|
1 /* Widget displays info on the current segment, with possibility of config for editing description and tags */ |
|
2 |
|
3 IriSP.Widgets.CurrentSegmentInfobox = function(player, config){ |
|
4 IriSP.Widgets.Widget.call(this, player, config); |
|
5 }; |
|
6 |
|
7 IriSP.Widgets.CurrentSegmentInfobox.prototype = new IriSP.Widgets.Widget(); |
|
8 |
|
9 IriSP.Widgets.CurrentSegmentInfobox.prototype.defaults = { |
|
10 annotation_type: "chap", |
|
11 editable_segments: false, |
|
12 empty_message: false, |
|
13 project_id: false, |
|
14 api_serializer: "ldt_annotate", |
|
15 api_method: "PUT", |
|
16 api_endpoint_template: "", |
|
17 new_tag_button: true, |
|
18 show_headers: false, |
|
19 custom_edit_text: false, |
|
20 empty_description_placeholder: false, |
|
21 }; |
|
22 |
|
23 IriSP.Widgets.CurrentSegmentInfobox.prototype.template = |
|
24 '<div class="Ldt-CurrentSegmentInfobox">' |
|
25 + '<div class="Ldt-CurrentSegmentInfobox-SelectedSegment">' |
|
26 + '{{#editable_segments}}<div class="Ldt-CurrentSegmentInfobox-EditButton">{{edit}}</div>{{/editable_segments}}' |
|
27 + '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Title">{{title}}</div>' |
|
28 + '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Description">{{description}}</div>' |
|
29 + '{{^description}}{{^tags.length}}{{#description_placeholder}}<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Description-placeholder">{{description_placeholder}}</div>{{/description_placeholder}}{{/tags.length}}{{/description}}' |
|
30 + '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Tags">' |
|
31 + '{{#tags.length}}' |
|
32 + '<ul class="Ldt-CurrentSegmentInfobox-Tags-Ul">' |
|
33 + '{{#tags}}' |
|
34 + '{{#.}}' |
|
35 + '<li class="Ldt-CurrentSegmentInfobox-Tags-Li">' |
|
36 + '<span>{{.}}</span>' |
|
37 + '</li>' |
|
38 + '{{/.}}' |
|
39 + '{{/tags}}' |
|
40 + '</ul>' |
|
41 + '{{/tags.length}}' |
|
42 + '</div>' |
|
43 + '</div>' |
|
44 + '</div>' |
|
45 |
|
46 IriSP.Widgets.CurrentSegmentInfobox.prototype.editTemplate = |
|
47 '<div class="Ldt-CurrentSegmentInfobox">' |
|
48 + '<div class="Ldt-CurrentSegmentInfobox-SelectedSegment">' |
|
49 + '{{#headers}}<div class="Ldt-CurrentSegmentInfobox-FieldsHeader">{{fields_header}}</div>{{/headers}}' |
|
50 + '<input type="text" class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-TitleInput Ldt-CurrentSegmentInfobox-Title" value="{{title}}"></input>' |
|
51 + '<textarea class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-DescriptionInput Ldt-CurrentSegmentInfobox-Description">{{description}}</textarea>' |
|
52 + '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Tags">' |
|
53 + '{{#headers}}<div class="Ldt-CurrentSegmentInfobox-TagsHeader">{{tags_header}}</div>{{/headers}}' |
|
54 + '{{#new_tag_button}}' |
|
55 + '<div class="Ldt-CurrentSegmentInfobox-CreateTagButton">{{new_tag}}</div>' |
|
56 + '{{/new_tag_button}}' |
|
57 + '{{^new_tag_button}}' |
|
58 + '<input class="Ldt-CurrentSegmentInfobox-CreateTagInput" placeholder="{{new_tag}}"></input>' |
|
59 + '<div class="Ldt-CurrentSegmentInfobox-CreateTagInput-Add">+</div>' |
|
60 + '{{/new_tag_button}}' |
|
61 + '<ul class="Ldt-CurrentSegmentInfobox-Tags-Ul">' |
|
62 + '{{#tags}}' |
|
63 + '{{#.}}' |
|
64 + '<li class="Ldt-CurrentSegmentInfobox-Tags-Li">' |
|
65 + '<input type="text" class="Ldt-CurrentSegmentInfobox-Tags-Li-Input" value="{{.}}"></input>' |
|
66 + '<div class="Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton">{{delete_tag}}</div>' |
|
67 + '</li>' |
|
68 + '{{/.}}' |
|
69 + '{{/tags}}' |
|
70 + '</ul>' |
|
71 + '</div>' |
|
72 + '<div class="Ldt-CurrentSegmentInfobox-SubmitButton">{{submit}}</div>' |
|
73 + '<div class="Ldt-CurrentSegmentInfobox-CancelButton">{{cancel}}</div>' |
|
74 + '</div>' |
|
75 + '</div>' |
|
76 |
|
77 IriSP.Widgets.CurrentSegmentInfobox.prototype.messages = { |
|
78 fr : { |
|
79 submit : "Soumettre", |
|
80 cancel : "Annuler", |
|
81 edit : "Editer", |
|
82 new_tag : "Nouveau tag", |
|
83 delete_tag : "Supprimer", |
|
84 fields_header : "Commentaire associé à ce segment", |
|
85 tags_header : "Mots-clés associés à ce segment", |
|
86 empty : "Le player vidéo ne lit actuellement aucun segment" |
|
87 }, |
|
88 en: { |
|
89 submit : "Submit", |
|
90 cancel : "Cancel", |
|
91 edit : "Edit", |
|
92 new_tag : "New tag", |
|
93 delete_tag : "Delete tag", |
|
94 fields_header : "Current segment content", |
|
95 tags_header : "Current segment tags", |
|
96 empty : "The player currently doesn't read any segment" |
|
97 } |
|
98 } |
|
99 |
|
100 IriSP.Widgets.CurrentSegmentInfobox.prototype.draw = function() { |
|
101 var _this = this; |
|
102 this.segments = this.getWidgetAnnotations(); |
|
103 this.renderTemplate(); |
|
104 this.currentSegment = false; |
|
105 this.clearBox(); |
|
106 this.refresh(); |
|
107 this.onMediaEvent("timeupdate", "refresh"); |
|
108 this.onMediaEvent("settimerange", function(_timeRange){ |
|
109 var _segmentBegin = _timeRange[0], |
|
110 _segmentEnd = _timeRange[1], |
|
111 _list = _this.segments.filter(function(_segment){ |
|
112 return _segment.begin.milliseconds == _segmentBegin.milliseconds && _segment.end.milliseconds == _segmentEnd.milliseconds |
|
113 }); |
|
114 if (_list.length >0){ |
|
115 _this.$.toggleClass("editing", false); |
|
116 if (_this.currentSegment.id != _list[0].id){ |
|
117 _this.currentSegment = _list[0]; |
|
118 _data = { |
|
119 editable_segments: _this.editable_segments, |
|
120 edit: _this.custom_edit_text ? _this.custom_edit_text : _this.l10n.edit, |
|
121 title: _this.currentSegment.title, |
|
122 description : _this.currentSegment.description, |
|
123 description_placeholder : _this.empty_description_placeholder, |
|
124 tags : _this.currentSegment.getTagTexts() |
|
125 } |
|
126 _this.$.html(Mustache.to_html(_this.template, _data)) |
|
127 if(_this.editable_segments&&_this.currentSegment){ |
|
128 _this.$.find(".Ldt-CurrentSegmentInfobox").click(_this.functionWrapper("enableEditMode")); |
|
129 } |
|
130 } |
|
131 } |
|
132 }); |
|
133 |
|
134 if(this.editable_segments&&this.currentSegment){ |
|
135 this.$.find(".Ldt-CurrentSegmentInfobox").click(_this.functionWrapper("enableEditMode")); |
|
136 } |
|
137 } |
|
138 |
|
139 IriSP.Widgets.CurrentSegmentInfobox.prototype.enableEditMode = function() { |
|
140 var _this = this; |
|
141 if(this.currentSegment){ |
|
142 _data = { |
|
143 title: this.currentSegment.title, |
|
144 description : this.currentSegment.description, |
|
145 tags : this.currentSegment.getTagTexts(), |
|
146 submit : this.l10n.submit, |
|
147 cancel : this.l10n.cancel, |
|
148 headers : this.show_headers, |
|
149 tags_header : this.custom_tags_header ? this.custom_tags_header : this.l10n.tags_header, |
|
150 fields_header : this.custom_fields_header ? this.custom_fields_header : this.l10n.fields_header, |
|
151 new_tag : this.l10n.new_tag, |
|
152 delete_tag : this.l10n.delete_tag, |
|
153 new_tag_button : this.new_tag_button, |
|
154 } |
|
155 this.$.toggleClass("editing", true); |
|
156 this.$.html(Mustache.to_html(this.editTemplate, _data)); |
|
157 this.$.find(".Ldt-CurrentSegmentInfobox-CancelButton").click(this.functionWrapper("disableEditMode")); |
|
158 if (this.new_tag_button){ |
|
159 this.$.find(".Ldt-CurrentSegmentInfobox-CreateTagButton").click(this.functionWrapper("insertTagInput")); |
|
160 } else { |
|
161 this.$.find(".Ldt-CurrentSegmentInfobox-CreateTagInput").keypress(this.functionWrapper("insertTagInputKeypress")); |
|
162 this.$.find(".Ldt-CurrentSegmentInfobox-CreateTagInput-Add").click(this.functionWrapper("insertTagInputKeypress")); |
|
163 } |
|
164 this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton").click(this.functionWrapper("deleteTagInput")); |
|
165 this.$.find(".Ldt-CurrentSegmentInfobox-SubmitButton").click(this.functionWrapper("onSubmit")) |
|
166 } |
|
167 } |
|
168 |
|
169 IriSP.Widgets.CurrentSegmentInfobox.prototype.disableEditMode = function() { |
|
170 if(this.currentSegment){ |
|
171 _data = { |
|
172 editable_segments: this.editable_segments, |
|
173 edit: this.custom_edit_text ? this.custom_edit_text : this.l10n.edit, |
|
174 title: this.currentSegment.title, |
|
175 description : this.currentSegment.description, |
|
176 description_placeholder : this.empty_description_placeholder, |
|
177 tags : this.currentSegment.getTagTexts() |
|
178 } |
|
179 this.$.toggleClass("editing", false); |
|
180 this.$.html(Mustache.to_html(this.template, _data)); |
|
181 this.$.find(".Ldt-CurrentSegmentInfobox").click(this.functionWrapper("enableEditMode")); |
|
182 } |
|
183 } |
|
184 |
|
185 IriSP.Widgets.CurrentSegmentInfobox.prototype.insertTagInput = function() { |
|
186 if((!this.currentSegment.getTagTexts().length)&&(!this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Ul").length)){ |
|
187 this.$.find(".Ldt-CurrentSegmentInfobox-Tags").prepend('<ul class="Ldt-CurrentSegmentInfobox-Tags-Ul"></ul>') |
|
188 } |
|
189 this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Ul").append( |
|
190 '<li class="Ldt-CurrentSegmentInfobox-Tags-Li">' |
|
191 +'<input type="text" class="Ldt-CurrentSegmentInfobox-Tags-Li-Input" value=""></input>' |
|
192 +'<div class="Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton">'+this.l10n.delete_tag+'</div>' |
|
193 +'</li>'); |
|
194 this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton").click(this.functionWrapper("deleteTagInput")); |
|
195 } |
|
196 |
|
197 IriSP.Widgets.CurrentSegmentInfobox.prototype.insertTagInputKeypress = function(event) { |
|
198 var keycode = (event.keyCode ? event.keyCode : event.which); |
|
199 if(keycode == '13' || event.type == 'click'){ |
|
200 if((!this.currentSegment.getTagTexts().length)&&(!this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Ul").length)){ |
|
201 this.$.find(".Ldt-CurrentSegmentInfobox-Tags").prepend('<ul class="Ldt-CurrentSegmentInfobox-Tags-Ul"></ul>') |
|
202 } |
|
203 this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Ul").append( |
|
204 '<li class="Ldt-CurrentSegmentInfobox-Tags-Li">' |
|
205 +'<input type="text" class="Ldt-CurrentSegmentInfobox-Tags-Li-Input" value="'+ this.$.find(".Ldt-CurrentSegmentInfobox-CreateTagInput").val() +'"></input>' |
|
206 +'<div class="Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton">'+this.l10n.delete_tag+'</div>' |
|
207 +'</li>'); |
|
208 this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton").click(this.functionWrapper("deleteTagInput")); |
|
209 this.$.find(".Ldt-CurrentSegmentInfobox-CreateTagInput").val(""); |
|
210 return false; |
|
211 } |
|
212 } |
|
213 |
|
214 IriSP.Widgets.CurrentSegmentInfobox.prototype.deleteTagInput = function(clickEvent) { |
|
215 $(clickEvent.currentTarget).parent().remove(); |
|
216 } |
|
217 |
|
218 IriSP.Widgets.CurrentSegmentInfobox.prototype.onSubmit = function() { |
|
219 new_tags_titles = this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Li-Input").map(function(){ |
|
220 if($(this).val()){ |
|
221 return $(this).val() |
|
222 } |
|
223 }); |
|
224 new_title = this.$.find(".Ldt-CurrentSegmentInfobox-TitleInput").val() |
|
225 new_description = this.$.find(".Ldt-CurrentSegmentInfobox-DescriptionInput").val() |
|
226 |
|
227 var _this = this, |
|
228 _exportedAnnotations = new IriSP.Model.List(this.player.sourceManager), /* We create an Annotations List to send to the server */ |
|
229 _export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[this.api_serializer]}), /* We create a source object using a specific serializer for export */ |
|
230 _annotation = new IriSP.Model.Annotation(this.currentSegment.id, _export); /* We create an annotation in the source with a generated ID (param. false) */ |
|
231 |
|
232 _annotation.setAnnotationType(this.currentSegment.getAnnotationType().id); |
|
233 _annotation.setMedia(this.currentSegment.getMedia().id); |
|
234 _annotation.setBegin(this.currentSegment.begin); |
|
235 _annotation.setEnd(this.currentSegment.end); |
|
236 _annotation.created = this.currentSegment.created; |
|
237 _annotation.creator = this.currentSegment.creator; |
|
238 _annotation.title = new_title /* Title field */ |
|
239 _annotation.description = new_description /* Description field */ |
|
240 var _tagIds = IriSP._(new_tags_titles).map(function(_title) { |
|
241 var _tags = _this.source.getTags(true).searchByTitle(_title, true); |
|
242 if (_tags.length) { |
|
243 var _tag = _tags[0]; |
|
244 } |
|
245 else { |
|
246 _tag = new IriSP.Model.Tag(_title.replace(/\W/g,'_'), _this.source); |
|
247 _tag.title = _title; |
|
248 _this.source.getTags().push(_tag); |
|
249 } |
|
250 return _tag.id; |
|
251 }); |
|
252 _annotation.setTags(_tagIds); |
|
253 _annotation.project_id = this.project_id; |
|
254 |
|
255 _exportedAnnotations.push(_annotation); /* We add the annotation in the list to export */ |
|
256 _export.addList("annotation",_exportedAnnotations); /* We add the list to the source object */ |
|
257 |
|
258 _url = Mustache.to_html(this.api_endpoint_template, {annotation_id: this.currentSegment.id}); |
|
259 |
|
260 IriSP.jQuery.ajax({ |
|
261 url: _url, |
|
262 type: this.api_method, |
|
263 contentType: 'application/json', |
|
264 data: _export.serialize(), /* Source is serialized */ |
|
265 success: function(_data) { |
|
266 _export.getAnnotations().removeElement(_annotation, true); /* We delete the sent annotation to avoid redundancy */ |
|
267 _export.deSerialize(_data); /* Data deserialization */ |
|
268 _this.source.merge(_export); /* We merge the deserialized data with the current source data */ |
|
269 _this.segments.forEach(function(_segment){ |
|
270 if (_segment.id == _annotation.id){ |
|
271 _this.segments.removeElement(_segment) |
|
272 } |
|
273 }) |
|
274 _this.segments.push(_annotation) |
|
275 _this.currentSegment = _annotation |
|
276 _data = { |
|
277 editable_segments: _this.editable_segments, |
|
278 edit: _this.custom_edit_text ? _this.custom_edit_text : _this.l10n.edit, |
|
279 title: _this.currentSegment.title, |
|
280 description : _this.currentSegment.description, |
|
281 description_placeholder : _this.empty_description_placeholder, |
|
282 tags : _this.currentSegment.getTagTexts() |
|
283 } |
|
284 _this.$.html(Mustache.to_html(_this.template, _data)) |
|
285 if(_this.editable_segments&&_this.currentSegment){ |
|
286 _this.$.find(".Ldt-CurrentSegmentInfobox").click(_this.functionWrapper("enableEditMode")); |
|
287 } |
|
288 _this.$.toggleClass("editing", false); |
|
289 }, |
|
290 error: function(_xhr, _error, _thrown) { |
|
291 IriSP.log("Error when sending annotation", _thrown); |
|
292 _export.getAnnotations().removeElement(_annotation, true); |
|
293 } |
|
294 }); |
|
295 } |
|
296 |
|
297 IriSP.Widgets.CurrentSegmentInfobox.prototype.refresh = function() { |
|
298 if(!this.media.getTimeRange()){ |
|
299 var _currentTime = this.media.getCurrentTime(); |
|
300 var _list = this.segments.filter(function(_segment){ |
|
301 return (_segment.begin <= _currentTime && _segment.end >= _currentTime); |
|
302 }) |
|
303 |
|
304 if (_list.length > 0){ |
|
305 if (this.currentSegment.id != _list[0].id){ |
|
306 this.currentSegment = _list[0]; |
|
307 _data = { |
|
308 editable_segments: this.editable_segments, |
|
309 edit: this.custom_edit_text ? this.custom_edit_text : this.l10n.edit, |
|
310 title: this.currentSegment.title, |
|
311 description : this.currentSegment.description, |
|
312 description_placeholder : this.empty_description_placeholder, |
|
313 tags : this.currentSegment.getTagTexts() |
|
314 } |
|
315 this.$.html(Mustache.to_html(this.template, _data)) |
|
316 if(this.editable_segments&&this.currentSegment){ |
|
317 this.$.find(".Ldt-CurrentSegmentInfobox").click(this.functionWrapper("enableEditMode")); |
|
318 } |
|
319 } |
|
320 } |
|
321 else { |
|
322 this.currentSegment = false; |
|
323 this.clearBox(); |
|
324 } |
|
325 } |
|
326 } |
|
327 |
|
328 IriSP.Widgets.CurrentSegmentInfobox.prototype.clearBox = function(){ |
|
329 var _empty_message = this.l10n.empty |
|
330 if (this.empty_message) { |
|
331 _empty_message = this.empty_message |
|
332 } |
|
333 this.$.find(".Ldt-CurrentSegmentInfobox").html("<div class='Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-NoSegment'>"+_empty_message+"</div>"); |
|
334 } |