src/widgets/AnnotationsList.js
changeset 1075 92cb33eb7a75
parent 1072 ac1eacb3aa33
child 1076 510fd2a482f4
equal deleted inserted replaced
1074:231ea5ea7de4 1075:92cb33eb7a75
     2 
     2 
     3 import Mustache from "mustache";
     3 import Mustache from "mustache";
     4 import _ from "lodash";
     4 import _ from "lodash";
     5 import jQuery from "jquery";
     5 import jQuery from "jquery";
     6 
     6 
       
     7 const IsImageOk = function (img) {
       
     8   // During the onload event, IE correctly identifies any images that
       
     9   // weren’t downloaded as not complete. Others should too. Gecko-based
       
    10   // browsers act like NS4 in that they report this incorrectly.
       
    11   if (!img.complete) {
       
    12       return false;
       
    13   }
       
    14 
       
    15   // However, they do have two very useful properties: naturalWidth and
       
    16   // naturalHeight. These give the true size of the image. If it failed
       
    17   // to load, either of these should be zero.
       
    18   if (img.naturalWidth === 0) {
       
    19       return false;
       
    20   }
       
    21 
       
    22   // No other way of checking: assume it’s ok.
       
    23   return true;
       
    24 }
       
    25 
     7 const AnnotationsList = function (ns) {
    26 const AnnotationsList = function (ns) {
       
    27 
       
    28   const thumbnailBuffer = {};
       
    29 
     8   return class extends ns.Widgets.Widget {
    30   return class extends ns.Widgets.Widget {
     9     constructor(player, config) {
    31     constructor(player, config) {
    10       super(player, config);
    32       super(player, config);
    11       this.lastIds = [];
    33       this.lastIds = [];
    12       var _this = this;
    34       var _this = this;
   276 
   298 
   277     static annotationTemplate =
   299     static annotationTemplate =
   278       '<li class="Ldt-AnnotationsList-li Ldt-Highlighter-Annotation Ldt-TraceMe" data-annotation="{{ id }}" data-begin="{{ begin_ms }}" data-end="{{ end_ms }}" trace-info="annotation-id:{{id}}, media-id:{{media_id}}" style="{{specific_style}}">' +
   300       '<li class="Ldt-AnnotationsList-li Ldt-Highlighter-Annotation Ldt-TraceMe" data-annotation="{{ id }}" data-begin="{{ begin_ms }}" data-end="{{ end_ms }}" trace-info="annotation-id:{{id}}, media-id:{{media_id}}" style="{{specific_style}}">' +
   279       '<div data-annotation="{{ id }}" class="Ldt-AnnotationsList-ThumbContainer Ldt-AnnotationsList-Annotation-Screen Ldt-AnnotationsList-Annotation-ScreenMain">' +
   301       '<div data-annotation="{{ id }}" class="Ldt-AnnotationsList-ThumbContainer Ldt-AnnotationsList-Annotation-Screen Ldt-AnnotationsList-Annotation-ScreenMain">' +
   280       '<a {{#url}}href="{{url}}"{{/url}} draggable="true">' +
   302       '<a {{#url}}href="{{url}}"{{/url}} draggable="true">' +
   281       '<img title="{{^external}}{{ begin }} - {{ end }}{{/external}}{{#external}}{{l10n.external_annotation}}{{/external}}" class="Ldt-AnnotationsList-Thumbnail" src="{{thumbnail}}" />' +
   303       '<img title="{{^external}}{{ begin }} - {{ end }}{{/external}}{{#external}}{{l10n.external_annotation}}{{/external}}" class="Ldt-AnnotationsList-Thumbnail" id="{{thumbnailId}}" />' +
   282       '{{#external}}<div title="{{l10n.external_annotation}}" class="Ldt-AnnotationsList-External-Icon"></div>{{/external}}' +
   304       '{{#external}}<div title="{{l10n.external_annotation}}" class="Ldt-AnnotationsList-External-Icon"></div>{{/external}}' +
   283       "</a>" +
   305       "</a>" +
   284       "</div>" +
   306       "</div>" +
   285       "{{#allow_annotations_deletion}}" +
   307       "{{#allow_annotations_deletion}}" +
   286       '<div data-annotation="{{ id }}" class="Ldt-AnnotationsList-DeleteButton">&#10006;</div>' +
   308       '<div data-annotation="{{ id }}" class="Ldt-AnnotationsList-DeleteButton">&#10006;</div>' +
   384      * Import annotations
   406      * Import annotations
   385      */
   407      */
   386     importAnnotations() {
   408     importAnnotations() {
   387       var widget = this;
   409       var widget = this;
   388       var $ = jQuery;
   410       var $ = jQuery;
   389       var textarea = $("<textarea>");
   411       var textarea = jQuery("<textarea>");
   390       var el = $("<div>")
   412       var el = jQuery("<div>")
   391         .append(
   413         .append(
   392           $("<span>")
   414           jQuery("<span>")
   393             .addClass("importAnnotationsLabel")
   415             .addClass("importAnnotationsLabel")
   394             .text(widget.messages.import_annotations)
   416             .text(widget.messages.import_annotations)
   395         )
   417         )
   396         .addClass("importContainer")
   418         .addClass("importContainer")
   397         .dialog({
   419         .dialog({
   402           height: 400,
   424           height: 400,
   403           buttons: [
   425           buttons: [
   404             {
   426             {
   405               text: "Close",
   427               text: "Close",
   406               click: function () {
   428               click: function () {
   407                 $(this).dialog("close");
   429                 jQuery(this).dialog("close");
   408               },
   430               },
   409             },
   431             },
   410             // { text: "Load", click: function () {
   432             // { text: "Load", click: function () {
   411             //     // TODO
   433             //     // TODO
   412             //     // http://www.html5rocks.com/en/tutorials/file/dndfiles/?redirect_from_locale=fr
   434             //     // http://www.html5rocks.com/en/tutorials/file/dndfiles/?redirect_from_locale=fr
   654                   _annotation.begin / 1000.0,
   676                   _annotation.begin / 1000.0,
   655             _external =
   677             _external =
   656               _annotation.project != _this.source.projectId ? true : false,
   678               _annotation.project != _this.source.projectId ? true : false,
   657             _title = "",
   679             _title = "",
   658             _description = _annotation.description,
   680             _description = _annotation.description,
       
   681             _thumbnailId = `thumb_${_annotation.id}`,
   659             _thumbnail =
   682             _thumbnail =
   660               typeof _annotation.thumbnail !== "undefined" &&
   683               typeof _annotation.thumbnail !== "undefined" &&
   661               _annotation.thumbnail
   684               _annotation.thumbnail
   662                 ? _annotation.thumbnail
   685                 ? _annotation.thumbnail
   663                 : _this.default_thumbnail;
   686                 : _this.default_thumbnail;
       
   687                     
   664           if (_this.show_creator) {
   688           if (_this.show_creator) {
   665             if (_annotation.creator) {
   689             if (_annotation.creator) {
   666               var _users = [],
   690               var _users = [],
   667                 _user = {},
   691                 _user = {},
   668                 _creator = "";
   692                 _creator = "";
   719             end: _annotation.end.toString(),
   743             end: _annotation.end.toString(),
   720             created: _created,
   744             created: _created,
   721             show_timecode: _this.show_timecode,
   745             show_timecode: _this.show_timecode,
   722             show_end_time: _this.show_end_time,
   746             show_end_time: _this.show_end_time,
   723             show_title: _this.show_title && _title,
   747             show_title: _this.show_title && _title,
   724             thumbnail: _thumbnail,
   748             thumbnailId: _thumbnailId,
   725             url: _url,
   749             url: _url,
   726             tags: _tags,
   750             tags: _tags,
   727             specific_style:
   751             specific_style:
   728               typeof _bgcolor !== "undefined"
   752               typeof _bgcolor !== "undefined"
   729                 ? "background-color: " + _bgcolor
   753                 ? "background-color: " + _bgcolor
   794             },
   818             },
   795             _onunselect = function () {
   819             _onunselect = function () {
   796               _this.$.find(".Ldt-AnnotationsList-li").removeClass("selected");
   820               _this.$.find(".Ldt-AnnotationsList-li").removeClass("selected");
   797             };
   821             };
   798           _el
   822           _el
   799             .mouseover(function () {
   823             .on("mouseover",function () {
   800               _annotation.trigger("select");
   824               _annotation.trigger("select");
   801             })
   825             })
   802             .mouseout(function () {
   826             .on("mouseout",function () {
   803               _annotation.trigger("unselect");
   827               _annotation.trigger("unselect");
   804             })
   828             })
   805             .click(function () {
   829             .on("click",function () {
   806               if (_this.filter_by_segments && _this.media.getTimeRange()) {
   830               if (_this.filter_by_segments && _this.media.getTimeRange()) {
   807                 _ann_time = (_annotation.begin + _annotation.end) / 2;
   831                 _ann_time = (_annotation.begin + _annotation.end) / 2;
   808                 if (
   832                 if (
   809                   _ann_time <= _this.media.getTimeRange()[0] ||
   833                   _ann_time <= _this.media.getTimeRange()[0] ||
   810                   _ann_time >= _this.media.getTimeRange()[1]
   834                   _ann_time >= _this.media.getTimeRange()[1]
   813                 }
   837                 }
   814               }
   838               }
   815               _annotation.trigger("click");
   839               _annotation.trigger("click");
   816             })
   840             })
   817             .appendTo(_this.list_$);
   841             .appendTo(_this.list_$);
       
   842 
       
   843           
       
   844           let img = thumbnailBuffer[_thumbnail];
       
   845           if(typeof(img) == "undefined") {
       
   846             img = new Image();
       
   847             thumbnailBuffer[_thumbnail] = img;
       
   848           }
       
   849           console.log("Thumnailimg", jQuery(`#${_thumbnailId}`,_el).attr('src'));
       
   850           if(img.src && IsImageOk(img)) {
       
   851             jQuery(`#${_thumbnailId}`,_el).attr('src', img.src);
       
   852           } else {
       
   853             img.onload = function() {
       
   854               jQuery(`#${_thumbnailId}`,_el).attr('src', img.src);
       
   855             };
       
   856             img.onerror = function() {
       
   857               img.src = _this.default_thumbnail;
       
   858               const elthumbnail = jQuery(`#${_thumbnailId}`,_el);
       
   859               elthumbnail.attr('src', _this.default_thumbnail);
       
   860 
       
   861             };
       
   862             img.src = _thumbnail;
       
   863           }
   818           ns.attachDndData(_el.find("[draggable]"), {
   864           ns.attachDndData(_el.find("[draggable]"), {
   819             title: _title,
   865             title: _title,
   820             description: _description,
   866             description: _description,
   821             uri: _url,
   867             uri: _url,
   822             image: _annotation.thumbnail,
   868             image: _annotation.thumbnail,
   853             // have to specify the ancestor before which we can
   899             // have to specify the ancestor before which we can
   854             // insert the input widget.
   900             // insert the input widget.
   855             if (insertion_point === undefined) insertion_point = _this;
   901             if (insertion_point === undefined) insertion_point = _this;
   856 
   902 
   857             // Insert input element
   903             // Insert input element
   858             var input_element = $(
   904             var input_element = jQuery(
   859               _this.dataset.editable_type === "multiline"
   905               _this.dataset.editable_type === "multiline"
   860                 ? "<textarea>"
   906                 ? "<textarea>"
   861                 : "<input>"
   907                 : "<input>"
   862             )
   908             )
   863               .addClass("editableInput")
   909               .addClass("editableInput")
   864               .insertBefore($(insertion_point));
   910               .insertBefore(jQuery(insertion_point));
   865             input_element[0].value = _this.dataset.editable_value;
   911             input_element[0].value = _this.dataset.editable_value;
   866             $(input_element).show().focus();
   912             jQuery(input_element).show().focus();
   867             $(_this).addClass("editing");
   913             jQuery(_this).addClass("editing");
   868 
   914 
   869             function feedback(color) {
   915             function feedback(color) {
   870               // Give some feedback
   916               // Give some feedback
   871               $(_this).removeClass("editing");
   917               jQuery(_this).removeClass("editing");
   872               input_element.remove();
   918               input_element.remove();
   873               var previous_color = $(_this).css("background-color");
   919               var previous_color = jQuery(_this).css("background-color");
   874               $(_this)
   920               jQuery(_this)
   875                 .stop()
   921                 .stop()
   876                 .css("background-color", color)
   922                 .css("background-color", color)
   877                 .animate({ backgroundColor: previous_color }, 1000);
   923                 .animate({ backgroundColor: previous_color }, 1000);
   878             }
   924             }
   879 
   925 
   906                     return;
   952                     return;
   907                   }
   953                   }
   908                 }
   954                 }
   909                 _this.dataset.editable_value = n;
   955                 _this.dataset.editable_value = n;
   910                 n = val;
   956                 n = val;
   911                 $(_this).text(val);
   957                 jQuery(_this).text(val);
   912               }
   958               }
   913 
   959 
   914               // We cannot use .getElement since it fetches
   960               // We cannot use .getElement since it fetches
   915               // elements from the global Directory
   961               // elements from the global Directory
   916               var an = get_local_annotation(_this.dataset.editable_id);
   962               var an = get_local_annotation(_this.dataset.editable_id);
   929                 widget.player.addLocalAnnotation(an);
   975                 widget.player.addLocalAnnotation(an);
   930                 widget.player.trigger("Annotation.update", an);
   976                 widget.player.trigger("Annotation.update", an);
   931                 feedback(feedback_ok);
   977                 feedback(feedback_ok);
   932               }
   978               }
   933             }
   979             }
   934             $(input_element)
   980             jQuery(input_element)
   935               .bind("keydown", function (e) {
   981               .bind("keydown", function (e) {
   936                 if (e.which == 13) {
   982                 if (e.which == 13) {
   937                   e.preventDefault();
   983                   e.preventDefault();
   938                   validateChanges();
   984                   validateChanges();
   939                 } else if (e.which == 27) {
   985                 } else if (e.which == 27) {
   979             if (widget.on_edit) {
  1025             if (widget.on_edit) {
   980               var _annotation = get_local_annotation(this.dataset.editable_id);
  1026               var _annotation = get_local_annotation(this.dataset.editable_id);
   981               widget.on_edit(_annotation);
  1027               widget.on_edit(_annotation);
   982             } else {
  1028             } else {
   983               // Edit annotation title. We have to specify the insertion point.
  1029               // Edit annotation title. We have to specify the insertion point.
   984               var element = $(this)
  1030               var element = jQuery(this)
   985                 .parents(".Ldt-AnnotationsList-li")
  1031                 .parents(".Ldt-AnnotationsList-li")
   986                 .find(".Ldt-AnnotationsList-TitleContent.Ldt-live-editable");
  1032                 .find(".Ldt-AnnotationsList-TitleContent.Ldt-live-editable");
   987               edit_element(element[0]);
  1033               edit_element(element[0]);
   988             }
  1034             }
   989           });
  1035           });
  1028                 url: _url,
  1074                 url: _url,
  1029                 type: widget.api_method,
  1075                 type: widget.api_method,
  1030                 contentType: "application/json",
  1076                 contentType: "application/json",
  1031                 data: _export.serialize(),
  1077                 data: _export.serialize(),
  1032                 success: function (_data) {
  1078                 success: function (_data) {
  1033                   $(this).addClass("published");
  1079                   jQuery(this).addClass("published");
  1034                   // Save the published information
  1080                   // Save the published information
  1035                   var an = get_local_annotation(_annotation.id);
  1081                   var an = get_local_annotation(_annotation.id);
  1036                   // FIXME: handle "published" tag
  1082                   // FIXME: handle "published" tag
  1037                   an.setTags(["published"]);
  1083                   an.setTags(["published"]);
  1038                   save_local_annotations();
  1084                   save_local_annotations();