|
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 }; |