web/res/metadataplayer/CurrentSegmentInfobox.js
changeset 1304 10974bff4dae
equal deleted inserted replaced
1303:20e00017dd60 1304:10974bff4dae
       
     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 }