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