src/js/widgets/annotationsListWidget.js
changeset 843 75ba66457232
parent 842 4ae2247a59f4
child 852 eefb64f74a3f
equal deleted inserted replaced
53:7b55777486c3 843:75ba66457232
       
     1 IriSP.AnnotationsListWidget = function(Popcorn, config, Serializer) {
       
     2   IriSP.Widget.call(this, Popcorn, config, Serializer);
       
     3   this.__counter = 0;
       
     4   this.__oldList = [];
       
     5   this.searchRe = null;
       
     6   this._ajax_cache = [];
       
     7   var _this = this;
       
     8   
       
     9   this._Popcorn.listen("IriSP.search", function(searchString) {
       
    10       _this.searchHandler(searchString);
       
    11   });
       
    12   this._Popcorn.listen("IriSP.search.closed", function() {
       
    13       _this.searchHandler(false);
       
    14   });
       
    15   this._Popcorn.listen("IriSP.search.cleared", function() {
       
    16       _this.searchHandler(false);
       
    17   });
       
    18 };
       
    19 
       
    20 
       
    21 IriSP.AnnotationsListWidget.prototype = new IriSP.Widget();
       
    22 
       
    23 IriSP.AnnotationsListWidget.prototype.clear = function() {
       
    24 };
       
    25 
       
    26 IriSP.AnnotationsListWidget.prototype.clearWidget = function() {
       
    27 };
       
    28 
       
    29 IriSP.AnnotationsListWidget.prototype.searchHandler = function(searchString) {
       
    30   this.searchRe = (searchString && searchString.length) ? IriSP.regexpFromText(searchString) : null;
       
    31   if (this.ajax_mode && !this.cinecast_version) {
       
    32       var _this = this,
       
    33         _annotations = (
       
    34             this.searchRe === null
       
    35             ? this._ajax_cache
       
    36             : IriSP.underscore.filter(this._ajax_cache, function(_a) {
       
    37                return (_this.searchRe.test(_a.desc) || _this.searchRe.test(_a.title)); 
       
    38             })
       
    39         );
       
    40     this.do_redraw(_annotations);
       
    41     if (_annotations.length) {
       
    42         this._Popcorn.trigger("IriSP.search.matchFound");
       
    43       } else {
       
    44         this._Popcorn.trigger("IriSP.search.noMatchFound");
       
    45       }    
       
    46   } else {
       
    47       this.drawList();
       
    48   }
       
    49 }
       
    50 
       
    51 /** effectively redraw the widget - called by drawList */
       
    52 IriSP.AnnotationsListWidget.prototype.do_redraw = function(list) {
       
    53     var _html = IriSP.templToHTML(
       
    54         IriSP.annotationsListWidget_template, {
       
    55             annotations: list
       
    56         }),
       
    57         _this = this;
       
    58       
       
    59     this.selector.html(_html);
       
    60     
       
    61     this.selector.find('.Ldt-AnnotationsList-Tag-Li').click(function() {
       
    62         _this._Popcorn.trigger("IriSP.search.triggeredSearch", IriSP.jQuery(this).text().trim());
       
    63     })
       
    64     
       
    65     if (this.searchRe !== null) {
       
    66         this.selector.find(".Ldt-AnnotationsList-Title a, .Ldt-AnnotationsList-Description")
       
    67             .each(function()  {
       
    68                 var _$ = IriSP.jQuery(this);
       
    69                 _$.html(_$.text().trim().replace(_this.searchRe, '<span class="Ldt-AnnotationsList-highlight">$1</span>'))
       
    70             })
       
    71     }
       
    72 };
       
    73 
       
    74 IriSP.AnnotationsListWidget.prototype.transformAnnotation = function(a) {
       
    75     var _this = this;
       
    76     return {
       
    77         "id" : a.id,
       
    78         "title": this.cinecast_version ? IriSP.get_aliased(a.meta, ['creator_name', 'creator']) : a.content.title,
       
    79         "desc" : this.cinecast_version ? a.content.data : a.content.description,
       
    80         "begin": IriSP.msToTime(a.begin),
       
    81         "end" : IriSP.msToTime(a.end),
       
    82         "thumbnail" : (typeof a.meta == "object" && typeof a.meta.thumbnail == "string") ? a.meta.thumbnail : this.default_thumbnail,
       
    83         "url" : (typeof a.meta == "object" && typeof a.meta.url == "string") ? a.meta.url : null,
       
    84         "created_at" :(typeof a.meta == "object" && typeof a.meta.created == "string") ? Date.parse(a.meta.created.replace(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}\:\d{2}\:\d{2}).*$/,"$2/$3/$1 $4 UTC+0000")) : null,
       
    85         "tags": typeof a.tags == "object"
       
    86             ? IriSP.underscore(a.tags)
       
    87                 .chain()
       
    88                 .map(function(_t) {
       
    89                     if (typeof _t == "string") {
       
    90                         return _t.replace(/^.*:/,'#');
       
    91                     } else {
       
    92                         if (typeof _t['id-ref'] != "undefined") {
       
    93                             var _f = IriSP.underscore.find(_this._serializer._data.tags, function(_tag) {
       
    94                                 return _tag.id == _t['id-ref'];
       
    95                             });
       
    96                             if (typeof _f != "undefined") {
       
    97                                 return IriSP.get_aliased(_f.meta, ['dc:title', 'title']);
       
    98                             }
       
    99                         }
       
   100                     }
       
   101                     return null;
       
   102                 })
       
   103                 .filter(function(_t) {
       
   104                     return _t !== null && _t !== ""
       
   105                 })
       
   106                 .value()
       
   107             : []
       
   108     }    
       
   109 }
       
   110 
       
   111 /** draw the annotation list */
       
   112 IriSP.AnnotationsListWidget.prototype.drawList = function(force_redraw) {
       
   113   var _this = this;
       
   114   
       
   115 //  var view_type = this._serializer.getContributions();
       
   116   var annotations = this._serializer._data.annotations;
       
   117   var currentTime = this._Popcorn.currentTime();
       
   118   var list = [];
       
   119 
       
   120 /*  if (typeof(view_type) === "undefined") {    
       
   121     return;
       
   122 } */
       
   123   for (i = 0; i < annotations.length; i++) {
       
   124     var obj = this.transformAnnotation(annotations[i]);
       
   125     obj.iterator = i;
       
   126     obj.distance = Math.abs((annotations[i].end + annotations[i].begin) / 2000 - currentTime);
       
   127     if (!this.cinecast_version || annotations[i].type == "cinecast:UserAnnotation") {
       
   128         list.push(obj);
       
   129     }
       
   130     
       
   131   }
       
   132   
       
   133     if (this.searchRe !== null) {
       
   134         list = list.filter(function(_a) {
       
   135             return (_this.searchRe.test(_a.desc) || _this.searchRe.test(_a.title)); 
       
   136         });
       
   137         if (list.length) {
       
   138             this._Popcorn.trigger("IriSP.search.matchFound");
       
   139           } else {
       
   140             this._Popcorn.trigger("IriSP.search.noMatchFound");
       
   141           }
       
   142     }
       
   143   list = IriSP.underscore(list)
       
   144     .chain()
       
   145     .sortBy(function(_o) {
       
   146         return _o.distance;
       
   147     })
       
   148     .first(10)
       
   149     .sortBy(function(_o) {
       
   150         return (_this.cinecast_version ? - _o.created_at : _o.iterator);
       
   151     })
       
   152     .value();
       
   153   var idList = IriSP.underscore.pluck(list, "id").sort();
       
   154 
       
   155   
       
   156   if (!IriSP.underscore.isEqual(this.__oldList, idList) || this.lastSearch !== this.searchRe || typeof(force_redraw) !== "undefined") {
       
   157     this.do_redraw(list);
       
   158     this.__oldList = idList;
       
   159     this.lastSearch = this.searchRe;
       
   160   }
       
   161    /* save for next call */
       
   162   
       
   163   
       
   164 };
       
   165 
       
   166 IriSP.AnnotationsListWidget.prototype.ajaxRedraw = function(timecode) {
       
   167 
       
   168   /* the seeked signal sometimes passes an argument - depending on if we're using
       
   169      our popcorn lookalike or the real thing - if it's the case, use it as it's
       
   170      more precise than currentTime which sometimes contains the place we where at */
       
   171   if (IriSP.null_or_undefined(timecode) || typeof(timecode) != "number") {
       
   172      var tcode = this._Popcorn.currentTime();     
       
   173    } else {
       
   174      var tcode = timecode;     
       
   175   }
       
   176    
       
   177   
       
   178   /* the platform gives us a special url - of the type : http://path/{{media}}/{{begin}}/{{end}}
       
   179      we double the braces using regexps and we feed it to mustache to build the correct url
       
   180      we have to do that because the platform only knows at run time what view it's displaying.
       
   181   */
       
   182      
       
   183   var media_id = this.currentMedia()["id"];
       
   184   var duration = this.getDuration();
       
   185   
       
   186   var begin_timecode = (Math.floor(tcode) - 300) * 1000;
       
   187   if (begin_timecode < 0)
       
   188     begin_timecode = 0;
       
   189     
       
   190   var end_timecode = (Math.floor(tcode) + 300) * 1000;
       
   191   if (end_timecode > duration)
       
   192     end_timecode = duration;
       
   193   
       
   194   var templ = Mustache.to_html(this.ajax_url, {media: media_id, begin: begin_timecode,
       
   195                                  end: end_timecode});
       
   196 
       
   197   /* we create on the fly a serializer to get the ajax */
       
   198   var serializer = new IriSP.JSONSerializer(IriSP.__dataloader, templ);
       
   199   serializer.sync(IriSP.wrap(this, function(json) { this.processJson(json, serializer) }));
       
   200 };
       
   201 
       
   202 /** process the received json - it's a bit hackish */
       
   203 IriSP.AnnotationsListWidget.prototype.processJson = function(json, serializer) {
       
   204   /* FIXME: DRY the whole thing */
       
   205   var annotations = serializer._data.annotations;
       
   206   if (IriSP.null_or_undefined(annotations))
       
   207     return;
       
   208   
       
   209   /*
       
   210   commented in case we wanted to discriminate against some annotation types.
       
   211   var view_types = serializer.getIds("Contributions");
       
   212   */
       
   213   var l = [];
       
   214   
       
   215   var media = this.currentMedia()["id"];
       
   216   
       
   217   for (i = 0; i < annotations.length; i++) {
       
   218     var obj = this.transformAnnotation(annotations[i])
       
   219       if (typeof obj.url == "undefined" || !obj.url) {
       
   220           /* only if the annotation isn't present in the document create an
       
   221              external link */
       
   222           if (this.annotations_ids.indexOf(obj.id.toLowerCase()) == -1) {
       
   223             // braindead url; jacques didn't want to create a new one in the platform,
       
   224             // so we append the cutting id to the url.
       
   225             obj.url = this.project_url + "/" + media + "/" + 
       
   226                          annotations[i].meta.project + "/" +
       
   227                          annotations[i].meta["id-ref"] + '#id=' + annotations[i].id;
       
   228                          
       
   229             // obj.url = document.location.href.split("#")[0] + "/" + annotation.meta.project;
       
   230           }
       
   231           }
       
   232       l.push(obj);
       
   233   }
       
   234   this._ajax_cache = l;
       
   235   this.do_redraw(l);
       
   236 };
       
   237 IriSP.AnnotationsListWidget.prototype.draw = function() {
       
   238   
       
   239   /* build a table of the annotations present in the document for faster 
       
   240      lookup
       
   241   */
       
   242   this.annotations_ids = IriSP.underscore(this._serializer._data.annotations).map(function(_a) {
       
   243     return _a.id.toLowerCase();
       
   244   });
       
   245   
       
   246   var _this = this;
       
   247     
       
   248     if (!this.ajax_mode || this.cinecast_version) {
       
   249         var _throttled = IriSP.underscore.throttle(function() {
       
   250             _this.drawList();
       
   251         }, 1500);
       
   252         _throttled();
       
   253         this._Popcorn.listen("IriSP.createAnnotationWidget.addedAnnotation", _throttled);
       
   254         this._Popcorn.listen("timeupdate", _throttled);
       
   255         if (this.cinecast_version) {
       
   256             window.setInterval(function() {
       
   257                 var _tmpSerializer = new IriSP.JSONSerializer(IriSP.__dataloader,  _this._config.metadata.src, true);
       
   258                 _tmpSerializer.sync(function(json) {
       
   259                     IriSP.underscore(json.annotations).each(function(_a) {
       
   260                         var _j = _this.annotations_ids.indexOf(_a.id);
       
   261                         if (_j == -1) {
       
   262                             _this._serializer._data.annotations.push(_a);
       
   263                             _this.annotations_ids.push(_a.id);
       
   264                         } else {
       
   265                             _this._serializer._data.annotations[_j] = _a;
       
   266                         }
       
   267                         _throttled();
       
   268                     });
       
   269                 }, true); // true is for force_refresh
       
   270             },this.refresh_interval);
       
   271         }
       
   272   } else {
       
   273     /* update the widget when the video has finished loading and when it's seeked and paused */
       
   274     this._Popcorn.listen("seeked", IriSP.wrap(this, this.ajaxRedraw));
       
   275     this._Popcorn.listen("loadedmetadata", IriSP.wrap(this, this.ajaxRedraw));
       
   276     this._Popcorn.listen("paused", IriSP.wrap(this, this.ajaxRedraw));
       
   277     
       
   278     this._Popcorn.listen("IriSP.createAnnotationWidget.addedAnnotation", IriSP.wrap(this, this.ajaxRedraw));
       
   279   }
       
   280 
       
   281 };