src/widgets/Markers.js
changeset 1045 b06345320ffb
child 1051 3820cf5fe29e
equal deleted inserted replaced
1044:d8339b45edc4 1045:b06345320ffb
       
     1 
       
     2 IriSP.Widgets.Markers = function(player, config) {
       
     3     IriSP.Widgets.Widget.call(this, player, config);
       
     4 };
       
     5 
       
     6 IriSP.Widgets.Markers.prototype = new IriSP.Widgets.Widget();
       
     7 
       
     8 IriSP.Widgets.Markers.prototype.defaults = {
       
     9     annotation_type: "markers",
       
    10     line_height: 8,
       
    11     background: "#e0e0e0",
       
    12     marker_color: "#ff80fc",
       
    13     hover_color: "#e15581",
       
    14     selected_color: "#74d600",
       
    15     ball_radius: 4,
       
    16     pause_on_write: true,
       
    17     api_serializer: "ldt_annotate",
       
    18     api_endpoint_template: "",
       
    19     api_method_create: "POST",
       
    20     api_method_editing: "PUT",
       
    21     project_id: "",
       
    22     creator_name: "",
       
    23     after_send_timeout: 0,
       
    24     close_after_send: false,
       
    25 };
       
    26 
       
    27 IriSP.Widgets.Markers.prototype.template = 
       
    28     '<div class="Ldt-Markers-Display" style="height:{{line_height}}px;">'
       
    29     +     '<div class="Ldt-Markers-List" style="height:{{line_height}}px; position: relative;"></div>'
       
    30     +     '<div class="Ldt-Markers-Position"></div>'
       
    31     + '</div>'
       
    32     + '<div class="Ldt-Markers-Inputs">'
       
    33     +     '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenMain">'
       
    34     +         '<div class="Ldt-Markers-Create">+</div>'
       
    35     +         '<div class="Ldt-Markers-Info"></div>'
       
    36     +     '</div>'
       
    37     +     '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenSending">'  
       
    38     +         '<div class="Ldt-Markers-Screen-InnerBox">{{l10n.wait_while_processing}}</div>'
       
    39     +     '</div>'
       
    40     +     '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenSuccess">'
       
    41     +         '<a title="{{l10n.close_widget}}" class="Ldt-Markers-Close" href="#"></a>'    
       
    42     +         '<div class="Ldt-Markers-Screen-InnerBox">{{l10n.annotation_saved}}</div>'
       
    43     +     '</div>'
       
    44     +     '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenFailure">'
       
    45     +         '<a title="{{l10n.close_widget}}" class="Ldt-Markers-Close" href="#"></a>'
       
    46     +         '<div class="Ldt-Markers-Screen-InnerBox">{{l10n.error_while_contacting}}</div>'
       
    47     +     '</div>'
       
    48     + '</div>';
       
    49 
       
    50 
       
    51 IriSP.Widgets.Markers.prototype.markerTemplate = 
       
    52     '<div class="Ldt-Markers-Marker" style="height:{{height}}px; left:{{left}}px; width: 2px; background-color: black;">' +
       
    53         '<div class="Ldt-Markers-MarkerBall" style="background-color: {{marker_color}}; position: relative; width: {{ball_diameter}}px; height: {{ball_diameter}}px; left: {{ball_left}}px; top: {{ball_top}}px; border: 1px solid; border-radius: {{ball_radius}}px"></div>' + 
       
    54     '</div>';   
       
    55 
       
    56 IriSP.Widgets.Markers.prototype.infoTemplate = 
       
    57     '{{^edit}}<div class="Ldt-Markers-MarkerDescription">{{marker_info}}</div>{{/edit}}' +
       
    58     '{{#edit}}<div class="Ldt-Markers-MarkerEdit">' + 
       
    59         '<textarea class="Ldt-Markers-MarkerTextArea" cols="60" rows="4">{{marker_info}}</textarea>' +
       
    60         '<div class="Ldt-Markers-Buttons">' +
       
    61             '<div class="Ldt-Markers-MarkerSend">{{send}}</div>' +
       
    62             '<div class="Ldt-Markers-MarkerCancel">{{cancel}}</div>' +
       
    63         '</div>' +
       
    64     '</div>{{/edit}}'
       
    65 
       
    66 IriSP.Widgets.Markers.prototype.messages = {
       
    67     en : {
       
    68         send : "Send",
       
    69         cancel : "Cancel",
       
    70         wait_while_processing: "Please wait while your annotation is being processed...",
       
    71         error_while_contacting: "An error happened while contacting the server. Your annotation has not been saved.",
       
    72         annotation_saved: "Thank you, your annotation has been saved.",
       
    73         close_widget: "Close",
       
    74     },
       
    75     fr : {
       
    76         send : "Envoyer",
       
    77         cancel : "Annuler",
       
    78         wait_while_processing: "Veuillez patienter pendant le traitement de votre annotation...",
       
    79         error_while_contacting: "Une erreur s'est produite en contactant le serveur. Votre annotation n'a pas été enregistrée.",
       
    80         annotation_saved: "Merci, votre annotation a été enregistrée.",
       
    81         close_widget: "Fermer",
       
    82     }
       
    83 }
       
    84 
       
    85 IriSP.Widgets.Markers.prototype.draw = function(){
       
    86     var _this = this;
       
    87     
       
    88     this.renderTemplate();
       
    89     
       
    90     this.markers = this.getWidgetAnnotations().filter(function(_ann) {
       
    91         return ((_ann.getDuration() == 0) || (_ann.begin == _ann.end));
       
    92     });
       
    93     this.drawMarkers();
       
    94     
       
    95     this.$.find(".Ldt-Markers-Create").click(function(){
       
    96         if (!_this.selectedMarker){
       
    97             _this.toggleCreateMarker();
       
    98         }
       
    99         else {
       
   100             _this.selectedMarker = false;
       
   101             _this.$.find(".Ldt-Markers-Info").html("");
       
   102             _this.$.find(".Ldt-Markers-MarkerBall").css("background-color", _this.marker_color)
       
   103             _this.$.find(".Ldt-Markers-Create").html("+");
       
   104         }
       
   105     })
       
   106     this.$.find(".Ldt-Markers-Info").click(function(){
       
   107         if (_this.selectedMarker&&!_this.editing){
       
   108             _this.toggleCreateMarker();
       
   109         }
       
   110     })
       
   111     this.showScreen("Main");
       
   112     this.$.css({
       
   113         margin: "1px 0",
       
   114         height: this.line_height,
       
   115         background: this.background
       
   116     });
       
   117     
       
   118     this.$.find(".Ldt-Markers-Close").click(function() {
       
   119         _this.showScreen("Main");
       
   120     });
       
   121     
       
   122     this.onMediaEvent("timeupdate", "updatePosition");
       
   123     this.onMdpEvent("Markers.refresh", this.functionWrapper("drawMarkers"));
       
   124     
       
   125     this.editing = false;
       
   126     this.selectedMarker = false;
       
   127 }
       
   128 
       
   129 
       
   130 IriSP.Widgets.Markers.prototype.updatePosition = function(_time) {    
       
   131     var _x = Math.floor( this.width * _time / this.media.duration);
       
   132     this.$.find('.Ldt-Markers-Position').css({
       
   133         left: _x + "px"
       
   134     });
       
   135 };
       
   136 
       
   137 
       
   138 IriSP.Widgets.Markers.prototype.toggleCreateMarker = function(){
       
   139     if(!this.editing){
       
   140         this.editing = true
       
   141     }
       
   142     else {
       
   143         this.editing = false
       
   144     }
       
   145     var _divHtml = "";
       
   146     if (this.selectedMarker){       
       
   147         _divHtml = Mustache.to_html(this.infoTemplate, {
       
   148             edit: this.editing,
       
   149             marker_info: this.selectedMarker.description,
       
   150             send: this.l10n.send,
       
   151             cancel: this.l10n.cancel
       
   152         })
       
   153         
       
   154         this.$.find(".Ldt-Markers-Info").html(_divHtml);
       
   155      }
       
   156      else {
       
   157          if (this.editing) {
       
   158              _divHtml = Mustache.to_html(this.infoTemplate, {
       
   159                  edit: this.editing,
       
   160                  marker_info: "",
       
   161                  send: this.l10n.send,
       
   162                  cancel: this.l10n.cancel,
       
   163              })
       
   164          }
       
   165          this.$.find(".Ldt-Markers-Info").html(_divHtml);
       
   166      }
       
   167     
       
   168     if(this.editing){
       
   169         this.$.find(".Ldt-Markers-MarkerSend").click(this.functionWrapper("onSubmit"));
       
   170         this.$.find(".Ldt-Markers-MarkerCancel").click(this.functionWrapper("toggleCreateMarker"));
       
   171         this.$.find(".Ldt-Markers-MarkerTextArea").bind("change keyup input paste", this.functionWrapper("onDescriptionChange"));
       
   172         this.$.find(".Ldt-Markers-Create").html("-");
       
   173     }
       
   174     else {
       
   175         this.$.find(".Ldt-Markers-Create").html("+");
       
   176     }
       
   177 };
       
   178 
       
   179 IriSP.Widgets.Markers.prototype.onDescriptionChange = function(){
       
   180     var _field = this.$.find(".Ldt-Markers-MarkerTextArea"),
       
   181         _contents = _field.val();
       
   182     _field.css("border-color", !!_contents ? "#e87d9f" : "#ff0000");
       
   183     if (!!_contents) {
       
   184         _field.removeClass("empty");
       
   185     } else {
       
   186         _field.addClass("empty");
       
   187     }
       
   188     this.pauseOnWrite();
       
   189     return !!_contents;
       
   190 };
       
   191 
       
   192 IriSP.Widgets.Markers.prototype.pauseOnWrite = function(){
       
   193     if (this.pause_on_write && !this.media.getPaused()) {
       
   194         this.media.pause();
       
   195     }
       
   196 };
       
   197 
       
   198 IriSP.Widgets.Markers.prototype.showScreen = function(_screenName) {
       
   199     this.$.find('.Ldt-Markers-Screen' + _screenName).show()
       
   200         .siblings().hide();
       
   201     if ((_screenName=="Main")&&(this.editing)){
       
   202         this.toggleCreateMarker();
       
   203     };
       
   204 }
       
   205 
       
   206 IriSP.Widgets.Markers.prototype.drawMarkers = function(){
       
   207     this.$.remove("Ldt-Markers-Marker");
       
   208     var _this = this,
       
   209         _scale = this.width / this.source.getDuration(),
       
   210         list_$ = this.$.find('.Ldt-Markers-List');
       
   211     
       
   212     this.markers.forEach(function(_marker){
       
   213         var _left = _marker.begin * _scale -1;
       
   214         _data = {
       
   215             left: _left,
       
   216             height: _this.line_height-1,
       
   217             ball_top: (_this.ball_radius*2 > _this.line_height) ? 0 : ((_this.line_height - _this.ball_radius*2)/2)-1,
       
   218             ball_radius: (_this.ball_radius*2 > _this.line_height) ? _this.line_height/2 : _this.ball_radius,
       
   219             ball_diameter: (_this.ball_radius*2 > _this.line_height) ? _this.line_height/2 : _this.ball_radius*2,
       
   220             ball_left: -_this.ball_radius,
       
   221             marker_color: ((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))? _this.selected_color : _this.marker_color
       
   222         }
       
   223         var _html = Mustache.to_html(_this.markerTemplate, _data),
       
   224             _el = IriSP.jQuery(_html);
       
   225         _el.mouseover(function(){
       
   226                 if (!((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))){
       
   227                     _el.children().css("background-color", _this.hover_color);
       
   228                 };
       
   229             })
       
   230            .mouseout(function(){
       
   231               if (!((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))){
       
   232                   _el.children().css("background-color", _this.marker_color);
       
   233               };
       
   234            })
       
   235            .click(function(){
       
   236                _this.showScreen("Main");
       
   237                if (!((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))){
       
   238                   list_$.find(".Ldt-Markers-MarkerBall").css("background-color", _this.marker_color)
       
   239                   _el.children().css("background-color", _this.selected_color)
       
   240                   _this.selectedMarker = _marker;
       
   241                   _divHtml = Mustache.to_html(_this.infoTemplate, {
       
   242                       edit: _this.editing,
       
   243                       marker_info: _marker.description,
       
   244                       send: _this.l10n.send,
       
   245                       cancel: _this.l10n.cancel
       
   246                   })
       
   247                   
       
   248                   _this.$.find(".Ldt-Markers-Info").html(_divHtml);
       
   249 
       
   250                   if(_this.editing){
       
   251                       _this.$.find(".Ldt-Markers-MarkerSend").click(_this.functionWrapper("onSubmit"));
       
   252                       _this.$.find(".Ldt-Markers-MarkerCancel").click(_this.functionWrapper("toggleCreateMarker"));
       
   253                   }
       
   254                }
       
   255                else {
       
   256                    var _divHtml = ""
       
   257                    if (_this.editing){
       
   258                        _divHtml = Mustache.to_html(_this.infoTemplate, {
       
   259                            edit: _this.editing,
       
   260                            marker_info: "",
       
   261                            send: _this.l10n.send,
       
   262                            cancel: _this.l10n.cancel
       
   263                        });
       
   264                    }
       
   265                    _el.children().css("background-color", _this.hover_color);
       
   266                    _this.selectedMarker = false;
       
   267                    _this.$.find(".Ldt-Markers-Info").html(_divHtml);
       
   268                    
       
   269                    if(_this.editing){
       
   270                        _this.$.find(".Ldt-Markers-MarkerSend").click(_this.functionWrapper("onSubmit"));
       
   271                        _this.$.find(".Ldt-Markers-MarkerCancel").click(_this.functionWrapper("toggleCreateMarker"));
       
   272                    }
       
   273                }
       
   274                
       
   275                if (_this.selectedMarker){
       
   276                    _this.$.find(".Ldt-Markers-Create").html("-")
       
   277                }
       
   278                else {
       
   279                    _this.$.find(".Ldt-Markers-Create").html("+")
       
   280                }
       
   281                
       
   282                if (_this.selectedMarker) {
       
   283                    // If we unselect a marker we shouldn't trigger pause or time jump
       
   284                    _this.media.pause();
       
   285                    _marker.trigger("click");
       
   286                }
       
   287            })
       
   288            .appendTo(list_$);
       
   289     })
       
   290 }
       
   291 
       
   292 IriSP.Widgets.Markers.prototype.onSubmit = function(){
       
   293     
       
   294     /* Si les champs obligatoires sont vides, on annule l'envoi */
       
   295     if (!this.onDescriptionChange()) {
       
   296         return false;
       
   297     }
       
   298     
       
   299     /* On pause la vidéo si elle est encore en train de tourner */
       
   300     if (!this.media.getPaused()){
       
   301         this.media.pause();
       
   302     }
       
   303     
       
   304     var _this = this,
       
   305         _exportedAnnotations = new IriSP.Model.List(this.player.sourceManager), /* Création d'une liste d'annotations contenant une annotation afin de l'envoyer au serveur */
       
   306         _url = Mustache.to_html(this.api_endpoint_template, {annotation_id: this.selectedMarker ? this.selectedMarker.id : ""});
       
   307     if (this.selectedMarker){
       
   308         var _export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[this.api_serializer]})
       
   309             _annotation = this.selectedMarker;
       
   310         _annotation.source = _export
       
   311         _annotation.description = this.$.find(".Ldt-Markers-MarkerTextArea").val(), /* Champ description */
       
   312         _annotationTypes = this.source.getAnnotationTypes().searchByTitle(this.annotation_type, true), /* Récupération du type d'annotation dans lequel l'annotation doit être ajoutée */
       
   313         _annotationType = (_annotationTypes.length ? _annotationTypes[0] : new IriSP.Model.AnnotationType(false, _export)); /* Si le Type d'Annotation n'existe pas, il est créé à la volée */
       
   314     }
       
   315     else {
       
   316         var _export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[this.api_serializer]}), /* Création d'un objet source utilisant un sérialiseur spécifique pour l'export */
       
   317             _annotation = new IriSP.Model.Annotation(false, _export); /* Création d'une annotation dans cette source avec un ID généré à la volée (param. false) */
       
   318             _annotationTypes = this.source.getAnnotationTypes().searchByTitle(this.annotation_type, true), /* Récupération du type d'annotation dans lequel l'annotation doit être ajoutée */
       
   319             _annotationType = (_annotationTypes.length ? _annotationTypes[0] : new IriSP.Model.AnnotationType(false, _export)); /* Si le Type d'Annotation n'existe pas, il est créé à la volée */
       
   320         /* Si nous avons dû générer un ID d'annotationType à la volée... */
       
   321         if (!_annotationTypes.length) {
       
   322             /* Il ne faudra pas envoyer l'ID généré au serveur */
       
   323             _annotationType.dont_send_id = true;
       
   324             /* Il faut inclure le titre dans le type d'annotation */
       
   325             _annotationType.title = this.annotation_type;
       
   326         }
       
   327     
       
   328         _annotation.setMedia(this.source.currentMedia.id); /* Id du média annoté */
       
   329         _currentTime = this.media.getCurrentTime();
       
   330         _annotation.setBegin(_currentTime); /* Timecode de la lecture de la video */
       
   331         _annotation.setEnd(_currentTime); /* Timecode de fin du widget */
       
   332         _annotation.setAnnotationType(_annotationType.id); /* Id du type d'annotation */
       
   333         if (this.project_id != ""){
       
   334             /* Champ id projet, seulement si on l'a renseigné dans la config */
       
   335             _annotation.project_id = this.project_id;
       
   336         }
       
   337         _annotation.created = new Date(); /* Date de création de l'annotation */
       
   338         _annotation.description = this.$.find(".Ldt-Markers-MarkerTextArea").val(); /* Champ description */
       
   339         _annotation.creator = this.creator_name;
       
   340     }
       
   341     _annotation.project_id = this.project_id;
       
   342     
       
   343     /*
       
   344      * Nous remplissons les données de l'annotation générée à la volée
       
   345      * ATTENTION: Si nous sommes sur un MASHUP, ces éléments doivent se référer AU MEDIA D'ORIGINE
       
   346      * */
       
   347     
       
   348     _exportedAnnotations.push(_annotation); /* Ajout de l'annotation à la liste à exporter */
       
   349     _export.addList("annotation",_exportedAnnotations); /* Ajout de la liste à exporter à l'objet Source */
       
   350     
       
   351     /* Envoi de l'annotation via AJAX au serveur ! */
       
   352     IriSP.jQuery.ajax({
       
   353         url: _url,
       
   354         type: this.selectedMarker ? this.api_method_editing : this.api_method_create,
       
   355         contentType: 'application/json',
       
   356         data: _export.serialize(), /* L'objet Source est sérialisé */
       
   357         success: function(_data) {
       
   358             _this.showScreen('Success'); /* Si l'appel a fonctionné, on affiche l'écran "Annotation enregistrée" */
       
   359             window.setTimeout(function(){
       
   360                 _this.showScreen("Main")
       
   361             },
       
   362             (_this.after_send_timeout || 5000));
       
   363             _export.getAnnotations().removeElement(_annotation, true); /* Pour éviter les doublons, on supprime l'annotation qui a été envoyée */
       
   364             _export.deSerialize(_data); /* On désérialise les données reçues pour les réinjecter */
       
   365             _this.source.merge(_export); /* On récupère les données réimportées dans l'espace global des données */
       
   366             if (_this.pause_on_write && _this.media.getPaused()) {
       
   367                 _this.media.play();
       
   368             }
       
   369             _this.markers.push(_annotation);
       
   370             _this.selectedMarker = _annotation;
       
   371             _this.player.trigger("AnnotationsList.refresh"); /* On force le rafraîchissement du widget AnnotationsList */
       
   372             _this.player.trigger("Markers.refresh");
       
   373             _this.$.find(".Ldt-Markers-MarkerTextArea").val("")
       
   374         },
       
   375         error: function(_xhr, _error, _thrown) {
       
   376             IriSP.log("Error when sending annotation", _thrown);
       
   377             _export.getAnnotations().removeElement(_annotation, true);
       
   378             _this.showScreen('Failure');
       
   379             window.setTimeout(function(){
       
   380                 _this.showScreen("Main");
       
   381             },
       
   382             (_this.after_send_timeout || 5000));
       
   383         }
       
   384     });
       
   385     this.showScreen('Sending');
       
   386     
       
   387     return false;
       
   388 };