src/widgets/CurrentSegmentInfobox.js
author durandn
Tue, 22 Sep 2015 17:07:58 +0200
changeset 1062 f8adaa2caecb
parent 1060 3a4f2217a04f
child 1064 b9c816d95ab0
permissions -rw-r--r--
CurrentSegmentInfobox: fixed bug where editing a segment would not update the source correctly and mess up other widgets.

/* Widget displays info on the current segment, with possibility of config for editing description and tags */

IriSP.Widgets.CurrentSegmentInfobox = function(player, config){
    IriSP.Widgets.Widget.call(this, player, config);
};

IriSP.Widgets.CurrentSegmentInfobox.prototype = new IriSP.Widgets.Widget();

IriSP.Widgets.CurrentSegmentInfobox.prototype.defaults = {
    annotation_type: "chap",
    editable_segments: false,
    empty_message: false,
    project_id: false,
    api_serializer: "ldt_annotate",
    api_method: "PUT",
    api_endpoint_template: "",
    new_tag_button: true,
};

IriSP.Widgets.CurrentSegmentInfobox.prototype.template = 
      '<div class="Ldt-CurrentSegmentInfobox">'
    +     '{{#editable_segments}}<div class="Ldt-CurrentSegmentInfobox-EditButton">{{edit}}</div>{{/editable_segments}}'
    +     '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Title">{{title}}</div>'
    +     '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Description">{{description}}</div>' 
    +     '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Tags">'
    +         '{{#tags.length}}'
    +         '<ul class="Ldt-CurrentSegmentInfobox-Tags-Ul">'
    +         '{{#tags}}'
    +             '{{#.}}'
    +             '<li class="Ldt-CurrentSegmentInfobox-Tags-Li">'
    +                 '<span>{{.}}</span>'
    +             '</li>'
    +             '{{/.}}'
    +         '{{/tags}}'
    +         '</ul>'
    +         '{{/tags.length}}'
    +     '</div>'
    + '</div>'

IriSP.Widgets.CurrentSegmentInfobox.prototype.editTemplate = 
      '<div class="Ldt-CurrentSegmentInfobox">'
    +     '<input type="text" class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-TitleInput Ldt-CurrentSegmentInfobox-Title" value="{{title}}"></input>'   
    +     '<div class="Ldt-CurrentSegmentInfobox-CancelButton">{{cancel}}</div>'
    +     '<div class="Ldt-CurrentSegmentInfobox-SubmitButton">{{submit}}</div>'
    +     '<textarea class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-DescriptionInput Ldt-CurrentSegmentInfobox-Description">{{description}}</textarea>'
    +     '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Tags">'
    +     '{{#new_tag_button}}'
    +         '<div class="Ldt-CurrentSegmentInfobox-CreateTagButton">{{new_tag}}</div>'
    +     '{{/new_tag_button}}'
    +     '{{^new_tag_button}}'
    +         '<input class="Ldt-CurrentSegmentInfobox-CreateTagInput" placeholder="{{new_tag}}"></input>'
    +     '{{/new_tag_button}}'
    +         '{{#tags.length}}'
    +         '<ul class="Ldt-CurrentSegmentInfobox-Tags-Ul">'
    +         '{{#tags}}'
    +             '{{#.}}'
    +             '<li class="Ldt-CurrentSegmentInfobox-Tags-Li">'
    +                 '<input type="text" class="Ldt-CurrentSegmentInfobox-Tags-Li-Input" value="{{.}}"></input>'
    +                 '<div class="Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton">{{delete_tag}}</div>'
    +             '</li>'
    +             '{{/.}}'
    +         '{{/tags}}'
    +         '</ul>'
    +         '{{/tags.length}}'
    +     '</div>'
    + '</div>'
    
IriSP.Widgets.CurrentSegmentInfobox.prototype.messages = {
    fr : {
        submit : "Soumettre",
        cancel : "Annuler",
        edit : "Editer",
        new_tag : "Nouveau tag",
        delete_tag : "Supprimer",
        empty : "Le player vidéo ne lit actuellement aucun segment"
    },
    en: {
        submit : "Submit",
        cancel : "Cancel",
        edit : "Edit",
        new_tag : "New tag",
        delete_tag : "Delete tag",
        empty : "The player currently doesn't read any segment"
    }
}    
    
IriSP.Widgets.CurrentSegmentInfobox.prototype.draw = function() {
    var _this = this;
    this.segments = this.getWidgetAnnotations();
    this.renderTemplate();
    this.currentSegment = false;
    this.clearBox();
    this.refresh();
    this.onMediaEvent("timeupdate", "refresh");
    this.onMediaEvent("settimerange", function(_timeRange){
        var _segmentBegin = _timeRange[0],
            _segmentEnd = _timeRange[1],
            _list = _this.segments.filter(function(_segment){
                return _segment.begin.milliseconds == _segmentBegin.milliseconds && _segment.end.milliseconds == _segmentEnd.milliseconds
            });
        if (_list.length >0){
            _this.$.toggleClass("editing", false);
            if (_this.currentSegment.id != _list[0].id){
                _this.currentSegment = _list[0];
                _data = {
                        editable_segments: _this.editable_segments,
                        edit: _this.l10n.edit,
                        title: _this.currentSegment.title,
                        description : _this.currentSegment.description,
                        tags : _this.currentSegment.getTagTexts()
                }
                _this.$.html(Mustache.to_html(_this.template, _data))
                if(_this.editable_segments&&_this.currentSegment){
                    _this.$.find(".Ldt-CurrentSegmentInfobox").click(_this.functionWrapper("enableEditMode"));            
                }
            }
        }
    });
    
    if(this.editable_segments&&this.currentSegment){
        this.$.find(".Ldt-CurrentSegmentInfobox").click(_this.functionWrapper("enableEditMode"));        
    }
}

IriSP.Widgets.CurrentSegmentInfobox.prototype.enableEditMode = function() {
    var _this = this;
    if(this.currentSegment){
        _data = {
            title: this.currentSegment.title,
            description : this.currentSegment.description,
            tags : this.currentSegment.getTagTexts(),
            submit : this.l10n.submit,
            cancel : this.l10n.cancel,
            new_tag : this.l10n.new_tag,
            delete_tag : this.l10n.delete_tag,
            new_tag_button : this.new_tag_button,
        }
        this.$.toggleClass("editing", true);
        this.$.html(Mustache.to_html(this.editTemplate, _data));
        this.$.find(".Ldt-CurrentSegmentInfobox-CancelButton").click(this.functionWrapper("disableEditMode"));
        if (this.new_tag_button){
            this.$.find(".Ldt-CurrentSegmentInfobox-CreateTagButton").click(this.functionWrapper("insertTagInput"));            
        } else {
            this.$.find(".Ldt-CurrentSegmentInfobox-CreateTagInput").keypress(this.functionWrapper("insertTagInputKeypress"));            
        }
        this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton").click(this.functionWrapper("deleteTagInput"));
        this.$.find(".Ldt-CurrentSegmentInfobox-SubmitButton").click(this.functionWrapper("onSubmit"))
    }
}

IriSP.Widgets.CurrentSegmentInfobox.prototype.disableEditMode = function() {
    if(this.currentSegment){
        _data = {
                editable_segments: this.editable_segments,
                edit: this.l10n.edit,
                title: this.currentSegment.title,
                description : this.currentSegment.description,
                tags : this.currentSegment.getTagTexts()
            }
        this.$.toggleClass("editing", false);
        this.$.html(Mustache.to_html(this.template, _data));
        this.$.find(".Ldt-CurrentSegmentInfobox").click(this.functionWrapper("enableEditMode")); 
    }
}

IriSP.Widgets.CurrentSegmentInfobox.prototype.insertTagInput = function() {
    if((!this.currentSegment.getTagTexts().length)&&(!this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Ul").length)){
        this.$.find(".Ldt-CurrentSegmentInfobox-Tags").prepend('<ul class="Ldt-CurrentSegmentInfobox-Tags-Ul"></ul>')
    }
    this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Ul").append(
        '<li class="Ldt-CurrentSegmentInfobox-Tags-Li">'
        +'<input type="text" class="Ldt-CurrentSegmentInfobox-Tags-Li-Input" value=""></input>'
        +'<div class="Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton">'+this.l10n.delete_tag+'</div>'
        +'</li>');
    this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton").click(this.functionWrapper("deleteTagInput"));
}

IriSP.Widgets.CurrentSegmentInfobox.prototype.insertTagInputKeypress = function(event) {
    var keycode = (event.keyCode ? event.keyCode : event.which);
    if(keycode == '13'){
        if((!this.currentSegment.getTagTexts().length)&&(!this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Ul").length)){
            this.$.find(".Ldt-CurrentSegmentInfobox-Tags").prepend('<ul class="Ldt-CurrentSegmentInfobox-Tags-Ul"></ul>')
        }
        this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Ul").append(
            '<li class="Ldt-CurrentSegmentInfobox-Tags-Li">'
            +'<input type="text" class="Ldt-CurrentSegmentInfobox-Tags-Li-Input" value="'+ this.$.find(".Ldt-CurrentSegmentInfobox-CreateTagInput").val() +'"></input>'
            +'<div class="Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton">'+this.l10n.delete_tag+'</div>'
            +'</li>');
        this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton").click(this.functionWrapper("deleteTagInput"));
        this.$.find(".Ldt-CurrentSegmentInfobox-CreateTagInput").val("");
        return false;
    }
}

IriSP.Widgets.CurrentSegmentInfobox.prototype.deleteTagInput = function(clickEvent) {
    $(clickEvent.currentTarget).parent().remove();
}

IriSP.Widgets.CurrentSegmentInfobox.prototype.onSubmit = function() {
    new_tags_titles = this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Li-Input").map(function(){
        if($(this).val()){
            return $(this).val()
        }
    });
    new_title = this.$.find(".Ldt-CurrentSegmentInfobox-TitleInput").val()
    new_description = this.$.find(".Ldt-CurrentSegmentInfobox-DescriptionInput").val()
    
    var _this = this,
        _exportedAnnotations = new IriSP.Model.List(this.player.sourceManager), /* Création d'une liste d'annotations contenant une annotation afin de l'envoyer au serveur */
        _export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[this.api_serializer]}),
        _annotation = new IriSP.Model.Annotation(this.currentSegment.id, _export); /* Création d'une annotation dans cette source avec un ID généré à la volée (param. false) */
    
    _annotation.setAnnotationType(this.currentSegment.getAnnotationType().id);
    _annotation.setMedia(this.currentSegment.getMedia().id);
    _annotation.setBegin(this.currentSegment.begin);
    _annotation.setEnd(this.currentSegment.end);
    _annotation.created = this.currentSegment.created;
    _annotation.creator = this.currentSegment.creator;
    _annotation.title = new_title /* Champ titre */
    _annotation.description = new_description /* Champ description */
    var _tagIds = IriSP._(new_tags_titles).map(function(_title) {
        var _tags = _this.source.getTags(true).searchByTitle(_title, true);
        if (_tags.length) {
            var _tag = _tags[0];
        }
        else {
            _tag = new IriSP.Model.Tag(_title.replace(/\W/g,'_'), _this.source);
            _tag.title = _title;
            _this.source.getTags().push(_tag);
        }
        return _tag.id;
    });
    _annotation.setTags(_tagIds);
    _annotation.project_id = this.project_id;
    
    _exportedAnnotations.push(_annotation); /* Ajout de l'annotation à la liste à exporter */
    _export.addList("annotation",_exportedAnnotations); /* Ajout de la liste à exporter à l'objet Source */    
    
    _url = Mustache.to_html(this.api_endpoint_template, {annotation_id: this.currentSegment.id});
    
    IriSP.jQuery.ajax({
        url: _url,
        type: this.api_method,
        contentType: 'application/json',
        data: _export.serialize(), /* L'objet Source est sérialisé */
        success: function(_data) {
            _export.getAnnotations().removeElement(_annotation, true); /* Pour éviter les doublons, on supprime l'annotation qui a été envoyée */
            _export.deSerialize(_data); /* On désérialise les données reçues pour les réinjecter */
            _this.source.merge(_export); /* On récupère les données réimportées dans l'espace global des données */
            _this.segments.forEach(function(_segment){
                if (_segment.id == _annotation.id){
                    _this.segments.removeElement(_segment)
                }
            })
            _this.segments.push(_annotation)
            _this.currentSegment = _annotation
            _data = {
                    editable_segments: _this.editable_segments,
                    edit: _this.l10n.edit,
                    title: _this.currentSegment.title,
                    description : _this.currentSegment.description,
                    tags : _this.currentSegment.getTagTexts()
                }
            _this.$.html(Mustache.to_html(_this.template, _data))
            if(_this.editable_segments&&_this.currentSegment){
                _this.$.find(".Ldt-CurrentSegmentInfobox").click(_this.functionWrapper("enableEditMode"));             
            }
            _this.$.toggleClass("editing", false);
        },
        error: function(_xhr, _error, _thrown) {
            IriSP.log("Error when sending annotation", _thrown);
            _export.getAnnotations().removeElement(_annotation, true);
        }
    });
}

IriSP.Widgets.CurrentSegmentInfobox.prototype.refresh = function() {
    if(!this.media.getTimeRange()){
        var _currentTime = this.media.getCurrentTime();
        var _list = this.segments.filter(function(_segment){
            return (_segment.begin <= _currentTime && _segment.end >= _currentTime);
        })
        
        if (_list.length > 0){
            if (this.currentSegment.id != _list[0].id){
                this.currentSegment = _list[0];
                _data = {
                    editable_segments: this.editable_segments,
                    edit: this.l10n.edit,
                    title: this.currentSegment.title,
                    description : this.currentSegment.description,
                    tags : this.currentSegment.getTagTexts()
                }
                this.$.html(Mustache.to_html(this.template, _data))
                if(this.editable_segments&&this.currentSegment){
                    this.$.find(".Ldt-CurrentSegmentInfobox").click(this.functionWrapper("enableEditMode"));             
                }
            }
        }
        else {
            this.currentSegment = false;
            this.clearBox();
        }
    }
}

IriSP.Widgets.CurrentSegmentInfobox.prototype.clearBox = function(){
    var _empty_message = this.l10n.empty
    if (this.empty_message) {
        _empty_message = this.empty_message
    }
    this.$.find(".Ldt-CurrentSegmentInfobox").html("<div class='Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-NoSegment'>"+_empty_message+"</div>");
}