src/widgets/Markers.js
changeset 1051 3820cf5fe29e
parent 1045 b06345320ffb
child 1059 8158421193e3
equal deleted inserted replaced
1050:0b287ecbc2cb 1051:3820cf5fe29e
     8 IriSP.Widgets.Markers.prototype.defaults = {
     8 IriSP.Widgets.Markers.prototype.defaults = {
     9     annotation_type: "markers",
     9     annotation_type: "markers",
    10     line_height: 8,
    10     line_height: 8,
    11     background: "#e0e0e0",
    11     background: "#e0e0e0",
    12     marker_color: "#ff80fc",
    12     marker_color: "#ff80fc",
       
    13     placeholder_color: "#ffffff",
    13     hover_color: "#e15581",
    14     hover_color: "#e15581",
    14     selected_color: "#74d600",
    15     selected_color: "#74d600",
    15     ball_radius: 4,
    16     ball_radius: 4,
    16     pause_on_write: true,
    17     pause_on_write: true,
       
    18     play_on_submit: true,
    17     api_serializer: "ldt_annotate",
    19     api_serializer: "ldt_annotate",
    18     api_endpoint_template: "",
    20     api_endpoint_template_create: "",
       
    21     api_endpoint_template_edit: "",
       
    22     api_endpoint_template_delete: "",
    19     api_method_create: "POST",
    23     api_method_create: "POST",
    20     api_method_editing: "PUT",
    24     api_method_edit: "PUT",
       
    25     api_method_delete: "DELETE",
    21     project_id: "",
    26     project_id: "",
    22     creator_name: "",
    27     creator_name: "",
    23     after_send_timeout: 0,
    28     after_send_timeout: 0,
       
    29     markers_gap: 2000,
       
    30     allow_empty_markers: false,
    24     close_after_send: false,
    31     close_after_send: false,
       
    32     custom_send_button: false,
       
    33     custom_cancel_button: false,
    25 };
    34 };
    26 
    35 
    27 IriSP.Widgets.Markers.prototype.template = 
    36 IriSP.Widgets.Markers.prototype.template = 
    28     '<div class="Ldt-Markers-Display" style="height:{{line_height}}px;">'
    37     '<div class="Ldt-Markers-Display" style="height:{{line_height}}px;">'
    29     +     '<div class="Ldt-Markers-List" style="height:{{line_height}}px; position: relative;"></div>'
    38     +     '<div class="Ldt-Markers-List" style="height:{{line_height}}px; position: relative;"></div>'
    30     +     '<div class="Ldt-Markers-Position"></div>'
    39     +     '<div class="Ldt-Markers-Position"></div>'
    31     + '</div>'
    40     + '</div>'
    32     + '<div class="Ldt-Markers-Inputs">'
    41     + '<div class="Ldt-Markers-Inputs">'
    33     +     '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenMain">'
    42     +     '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenMain">'
    34     +         '<div class="Ldt-Markers-Create">+</div>'
    43     +         '<div class="Ldt-Markers-RoundButton Ldt-Markers-CannotCreate" title="{{l10n.cannot_create}}">+</div>'
       
    44     +         '<div class="Ldt-Markers-RoundButton Ldt-Markers-Create">+</div>'
       
    45     +         '<div class="Ldt-Markers-RoundButton Ldt-Markers-Delete">&#10006;</div>'
    35     +         '<div class="Ldt-Markers-Info"></div>'
    46     +         '<div class="Ldt-Markers-Info"></div>'
    36     +     '</div>'
    47     +     '</div>'
    37     +     '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenSending">'  
    48     +     '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenSending">'  
    38     +         '<div class="Ldt-Markers-Screen-InnerBox">{{l10n.wait_while_processing}}</div>'
    49     +         '<div class="Ldt-Markers-Screen-InnerBox">{{l10n.wait_while_processing}}</div>'
    39     +     '</div>'
    50     +     '</div>'
    40     +     '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenSuccess">'
    51     +     '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenSuccess">'
    41     +         '<a title="{{l10n.close_widget}}" class="Ldt-Markers-Close" href="#"></a>'    
    52     +         '<a title="{{l10n.close_widget}}" class="Ldt-Markers-Close" href="#"></a>'    
    42     +         '<div class="Ldt-Markers-Screen-InnerBox">{{l10n.annotation_saved}}</div>'
    53     +         '<div class="Ldt-Markers-Screen-InnerBox">{{l10n.annotation_saved}}</div>'
    43     +     '</div>'
    54     +     '</div>'
       
    55     +     '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenDeleteSuccess">'
       
    56     +         '<a title="{{l10n.close_widget}}" class="Ldt-Markers-Close" href="#"></a>'    
       
    57     +         '<div class="Ldt-Markers-Screen-InnerBox">{{l10n.delete_saved}}</div>'
       
    58     +     '</div>'
    44     +     '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenFailure">'
    59     +     '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenFailure">'
    45     +         '<a title="{{l10n.close_widget}}" class="Ldt-Markers-Close" href="#"></a>'
    60     +         '<a title="{{l10n.close_widget}}" class="Ldt-Markers-Close" href="#"></a>'
    46     +         '<div class="Ldt-Markers-Screen-InnerBox">{{l10n.error_while_contacting}}</div>'
    61     +         '<div class="Ldt-Markers-Screen-InnerBox">{{l10n.error_while_contacting}}</div>'
    47     +     '</div>'
    62     +     '</div>'
       
    63     +     '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenConfirmDelete">'
       
    64     +         '<a title="{{l10n.close_widget}}" class="Ldt-Markers-Close" href="#"></a>'
       
    65     +         '<div class="Ldt-Markers-Screen-InnerBox">'
       
    66     +           '{{l10n.delete_text}} '
       
    67     +           '<a class="Ldt-Markers-Screen-SubmitDelete">{{l10n.submit_delete}}</a> '
       
    68     +           '<a class="Ldt-Markers-Screen-CancelDelete">{{l10n.cancel}}</a>'
       
    69     +         '</div>'
       
    70     +     '</div>'
    48     + '</div>';
    71     + '</div>';
    49 
    72 
    50 
    73 
    51 IriSP.Widgets.Markers.prototype.markerTemplate = 
    74 IriSP.Widgets.Markers.prototype.markerTemplate = 
    52     '<div class="Ldt-Markers-Marker" style="height:{{height}}px; left:{{left}}px; width: 2px; background-color: black;">' +
    75     '<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>' + 
    76         '<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>';   
    77     '</div>';
       
    78 
       
    79 IriSP.Widgets.Markers.prototype.markerPlaceholderTemplate = 
       
    80     '<div class="Ldt-Markers-Marker Ldt-Markers-PlaceholderMarker" style="height:{{height}}px; left:{{left}}px; width: 2px; background-color: black;">' +
       
    81         '<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>' + 
       
    82     '</div>'; 
    55 
    83 
    56 IriSP.Widgets.Markers.prototype.infoTemplate = 
    84 IriSP.Widgets.Markers.prototype.infoTemplate = 
    57     '{{^edit}}<div class="Ldt-Markers-MarkerDescription">{{marker_info}}</div>{{/edit}}' +
    85     '{{^edit}}<div class="Ldt-Markers-MarkerDescription">{{marker_info}}</div>{{/edit}}' +
    58     '{{#edit}}<div class="Ldt-Markers-MarkerEdit">' + 
    86     '{{#edit}}<div class="Ldt-Markers-MarkerEdit">' + 
    59         '<textarea class="Ldt-Markers-MarkerTextArea" cols="60" rows="4">{{marker_info}}</textarea>' +
    87         '<textarea class="Ldt-Markers-MarkerTextArea" cols="60" rows="4">{{marker_info}}</textarea>' +
    64     '</div>{{/edit}}'
    92     '</div>{{/edit}}'
    65 
    93 
    66 IriSP.Widgets.Markers.prototype.messages = {
    94 IriSP.Widgets.Markers.prototype.messages = {
    67     en : {
    95     en : {
    68         send : "Send",
    96         send : "Send",
       
    97         submit_delete: "Delete",
    69         cancel : "Cancel",
    98         cancel : "Cancel",
    70         wait_while_processing: "Please wait while your annotation is being processed...",
    99         wait_while_processing: "Please wait while your annotation is being processed...",
       
   100         delete_text: "The selected marker will be deleted. Continue?",
    71         error_while_contacting: "An error happened while contacting the server. Your annotation has not been saved.",
   101         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.",
   102         annotation_saved: "Thank you, your annotation has been saved.",
       
   103         delete_saved: "Thank you, your annotation has been deleted",
    73         close_widget: "Close",
   104         close_widget: "Close",
       
   105         cannot_create: "Cannot create marker on this timecode"
    74     },
   106     },
    75     fr : {
   107     fr : {
    76         send : "Envoyer",
   108         send : "Envoyer",
       
   109         submit_delete: "Supprimer",
    77         cancel : "Annuler",
   110         cancel : "Annuler",
    78         wait_while_processing: "Veuillez patienter pendant le traitement de votre annotation...",
   111         wait_while_processing: "Veuillez patienter pendant le traitement de votre annotation...",
       
   112         delete_text: "Le marqueur sélectionné sera supprimé. Continuer?",
    79         error_while_contacting: "Une erreur s'est produite en contactant le serveur. Votre annotation n'a pas été enregistrée.",
   113         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.",
   114         annotation_saved: "Merci, votre annotation a été enregistrée.",
       
   115         delete_saved: "Merci, votre annotation a été supprimée",
    81         close_widget: "Fermer",
   116         close_widget: "Fermer",
       
   117         cannot_create: "Impossible de créer un marqueur sur ce timecode"
    82     }
   118     }
    83 }
   119 }
    84 
   120 
    85 IriSP.Widgets.Markers.prototype.draw = function(){
   121 IriSP.Widgets.Markers.prototype.draw = function(){
    86     var _this = this;
   122     var _this = this;
    90     this.markers = this.getWidgetAnnotations().filter(function(_ann) {
   126     this.markers = this.getWidgetAnnotations().filter(function(_ann) {
    91         return ((_ann.getDuration() == 0) || (_ann.begin == _ann.end));
   127         return ((_ann.getDuration() == 0) || (_ann.begin == _ann.end));
    92     });
   128     });
    93     this.drawMarkers();
   129     this.drawMarkers();
    94     
   130     
    95     this.$.find(".Ldt-Markers-Create").click(function(){
   131     this.$.find(".Ldt-Markers-Create").click(this.functionWrapper("onCreateClick"));
    96         if (!_this.selectedMarker){
   132     this.$.find(".Ldt-Markers-Delete").click(this.functionWrapper("onDeleteClick"));
    97             _this.toggleCreateMarker();
   133     this.$.find(".Ldt-Markers-RoundButton").hide()
    98         }
   134     this.updateCreateButtonState(this.media.getCurrentTime())
    99         else {
   135     this.$.find(".Ldt-Markers-Screen-SubmitDelete").click(this.functionWrapper("sendDelete"));
   100             _this.selectedMarker = false;
   136     this.$.find(".Ldt-Markers-Screen-CancelDelete").click(function(){
   101             _this.$.find(".Ldt-Markers-Info").html("");
   137         _this.showScreen("Main");
   102             _this.$.find(".Ldt-Markers-MarkerBall").css("background-color", _this.marker_color)
   138         _this.cancelEdit();
   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     })
   139     })
   111     this.showScreen("Main");
   140     this.showScreen("Main");
   112     this.$.css({
   141     this.$.css({
   113         margin: "1px 0",
   142         margin: "1px 0",
   114         height: this.line_height,
   143         height: this.line_height,
   115         background: this.background
   144         background: this.background
   116     });
   145     });
   117     
   146     
   118     this.$.find(".Ldt-Markers-Close").click(function() {
   147     this.$.find(".Ldt-Markers-Close").click(this.functionWrapper("revertToMainScreen"));
   119         _this.showScreen("Main");
   148     
   120     });
   149     this.onMediaEvent("timeupdate", this.functionWrapper("updatePosition"));
   121     
   150     this.onMediaEvent("timeupdate", this.functionWrapper("updateCreateButtonState"));
   122     this.onMediaEvent("timeupdate", "updatePosition");
   151     this.onMediaEvent("play", this.functionWrapper("clearSelectedMarker"));
   123     this.onMdpEvent("Markers.refresh", this.functionWrapper("drawMarkers"));
   152     this.onMdpEvent("Markers.refresh", this.functionWrapper("drawMarkers"));
   124     
   153    
   125     this.editing = false;
   154     this.newMarkerTimeCode = 0;
   126     this.selectedMarker = false;
   155     this.selectedMarker = false;
   127 }
   156 }
   128 
   157 
   129 
   158 
   130 IriSP.Widgets.Markers.prototype.updatePosition = function(_time) {    
   159 IriSP.Widgets.Markers.prototype.updatePosition = function(_time) {    
   131     var _x = Math.floor( this.width * _time / this.media.duration);
   160     var _x = Math.floor( this.width * _time / this.media.duration);
   132     this.$.find('.Ldt-Markers-Position').css({
   161     this.$.find('.Ldt-Markers-Position').css({
   133         left: _x + "px"
   162         left: _x + "px"
   134     });
   163     });
   135 };
   164 }
   136 
   165 
   137 
   166 IriSP.Widgets.Markers.prototype.updateCreateButtonState = function(_time){
   138 IriSP.Widgets.Markers.prototype.toggleCreateMarker = function(){
   167     _this = this
   139     if(!this.editing){
   168     var can_create = this.markers.every(function(_marker){   
   140         this.editing = true
   169         return ((_time < (_marker.begin-_this.markers_gap))||(_time > (_marker.begin+_this.markers_gap)))
       
   170     });
       
   171     if (can_create){
       
   172         if ((this.$.find(".Ldt-Markers-Create").is(":hidden"))&&(this.$.find(".Ldt-Markers-Delete").is(":hidden"))){
       
   173             this.$.find(".Ldt-Markers-RoundButton").hide();
       
   174             this.$.find(".Ldt-Markers-Create").show();
       
   175         }
   141     }
   176     }
   142     else {
   177     else {
   143         this.editing = false
   178         if ((this.$.find(".Ldt-Markers-CannotCreate").is(":hidden"))&&(this.$.find(".Ldt-Markers-Delete").is(":hidden"))){
   144     }
   179             this.$.find(".Ldt-Markers-RoundButton").hide();
   145     var _divHtml = "";
   180             this.$.find(".Ldt-Markers-CannotCreate").show();
   146     if (this.selectedMarker){       
   181         }
       
   182     }
       
   183 }
       
   184 
       
   185 IriSP.Widgets.Markers.prototype.onCreateClick = function(){
       
   186     this.pauseOnWrite();
       
   187     if (!this.selectedMarker){
       
   188         this.newMarkerCurrentTime = this.media.getCurrentTime();
       
   189         this.showPlaceholder(this.media.getCurrentTime());
       
   190         this.startEdit();
       
   191     }
       
   192 }
       
   193 
       
   194 IriSP.Widgets.Markers.prototype.onDeleteClick = function(){
       
   195     _this = this;
       
   196     this.pauseOnWrite();
       
   197     if(this.selectedMarker){
       
   198         this.showScreen("ConfirmDelete");
       
   199     }
       
   200     else {
       
   201         // Clic sur - sans marqueur sélectionné = retour à l'état initial
       
   202         this.cancelEdit();
       
   203     }
       
   204 }
       
   205 
       
   206 IriSP.Widgets.Markers.prototype.startEdit = function(){
       
   207     if (this.selectedMarker){
   147         _divHtml = Mustache.to_html(this.infoTemplate, {
   208         _divHtml = Mustache.to_html(this.infoTemplate, {
   148             edit: this.editing,
   209             edit: true,
   149             marker_info: this.selectedMarker.description,
   210             marker_info: this.selectedMarker.description,
   150             send: this.l10n.send,
   211             send: this.custom_send_button? this.custom_send_button : this.l10n.send,
   151             cancel: this.l10n.cancel
   212             cancel: this.custom_cancel_button? this.custom_cancel_button :this.l10n.cancel
   152         })
   213         })
   153         
   214     }
       
   215     else {
       
   216         _divHtml = Mustache.to_html(this.infoTemplate, {
       
   217             edit: true,
       
   218             marker_info: "",
       
   219             send: this.custom_send_button? this.custom_send_button : this.l10n.send,
       
   220             cancel: this.custom_cancel_button? this.custom_cancel_button :this.l10n.cancel
       
   221         })
       
   222     }
       
   223     this.$.find(".Ldt-Markers-Info").html(_divHtml);
       
   224     this.$.find(".Ldt-Markers-MarkerSend").click(this.functionWrapper("onSubmit"));
       
   225     this.$.find(".Ldt-Markers-MarkerCancel").click(this.functionWrapper("cancelEdit"));
       
   226     this.$.find(".Ldt-Markers-MarkerTextArea").bind("change keyup input paste", this.functionWrapper("onDescriptionChange"));
       
   227     this.$.find(".Ldt-Markers-RoundButton").hide();
       
   228     this.$.find(".Ldt-Markers-Delete").show();
       
   229     this.editing = true;
       
   230 }
       
   231 
       
   232 IriSP.Widgets.Markers.prototype.cancelEdit = function(){
       
   233     if (this.selectedMarker){
       
   234         // Clic sur "cancel" pendant édition d'un marqueur = retour à l'état visualisation
       
   235         _divHtml = Mustache.to_html(this.infoTemplate, {
       
   236             edit: false,
       
   237             marker_info: this.selectedMarker.description,
       
   238         })
   154         this.$.find(".Ldt-Markers-Info").html(_divHtml);
   239         this.$.find(".Ldt-Markers-Info").html(_divHtml);
   155      }
   240         this.$.find(".Ldt-Markers-MarkerDescription").click(this.functionWrapper("startEdit"));
   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     }
   241     }
   174     else {
   242     else {
   175         this.$.find(".Ldt-Markers-Create").html("+");
   243         // Clic sur "cancel" pendant la création d'un marqueur = retour à l'état initial
   176     }
   244         this.hidePlaceholder();
   177 };
   245         this.$.find(".Ldt-Markers-Info").html("");
       
   246         this.$.find(".Ldt-Markers-RoundButton").hide()
       
   247         this.$.find(".Ldt-Markers-Create").show()
       
   248         this.updateCreateButtonState(this.media.getCurrentTime())
       
   249     }
       
   250     this.editing = false;
       
   251 }
   178 
   252 
   179 IriSP.Widgets.Markers.prototype.onDescriptionChange = function(){
   253 IriSP.Widgets.Markers.prototype.onDescriptionChange = function(){
   180     var _field = this.$.find(".Ldt-Markers-MarkerTextArea"),
   254     // Returns false if the textarea is empty, true if there is text in it
   181         _contents = _field.val();
   255     if(!this.allow_empty_markers){
   182     _field.css("border-color", !!_contents ? "#e87d9f" : "#ff0000");
   256         var _field = this.$.find(".Ldt-Markers-MarkerTextArea"),
   183     if (!!_contents) {
   257             _contents = _field.val();
   184         _field.removeClass("empty");
   258         _field.css("border-color", !!_contents ? "#e87d9f" : "#ff0000");
   185     } else {
   259         if (!!_contents) {
   186         _field.addClass("empty");
   260             _field.removeClass("empty");
   187     }
   261         } else {
   188     this.pauseOnWrite();
   262             _field.addClass("empty");
   189     return !!_contents;
   263         }
       
   264         this.pauseOnWrite();
       
   265         return !!_contents;
       
   266     }
       
   267     else {
       
   268         // If the widget is configured to allow to post empty markers, it returns true
       
   269         return true
       
   270     }
   190 };
   271 };
   191 
   272 
   192 IriSP.Widgets.Markers.prototype.pauseOnWrite = function(){
   273 IriSP.Widgets.Markers.prototype.pauseOnWrite = function(){
   193     if (this.pause_on_write && !this.media.getPaused()) {
   274     if (this.pause_on_write && !this.media.getPaused()) {
   194         this.media.pause();
   275         this.media.pause();
   196 };
   277 };
   197 
   278 
   198 IriSP.Widgets.Markers.prototype.showScreen = function(_screenName) {
   279 IriSP.Widgets.Markers.prototype.showScreen = function(_screenName) {
   199     this.$.find('.Ldt-Markers-Screen' + _screenName).show()
   280     this.$.find('.Ldt-Markers-Screen' + _screenName).show()
   200         .siblings().hide();
   281         .siblings().hide();
   201     if ((_screenName=="Main")&&(this.editing)){
   282 }
   202         this.toggleCreateMarker();
   283 
   203     };
   284 IriSP.Widgets.Markers.prototype.revertToMainScreen = function(){
       
   285     if (this.$.find(".Ldt-Markers-ScreenMain").is(":hidden")){
       
   286         this.showScreen("Main");
       
   287         this.cancelEdit();
       
   288         if (this.selectedMarker){
       
   289             this.$.find(".Ldt-Markers-RoundButton").hide();
       
   290             this.$.find(".Ldt-Markers-Delete").show();
       
   291         }
       
   292         else {
       
   293             this.$.find(".Ldt-Markers-RoundButton").hide();
       
   294             this.$.find(".Ldt-Markers-Create").show();
       
   295             this.updateCreateButtonState();
       
   296         }
       
   297     }
       
   298 }
       
   299 
       
   300 IriSP.Widgets.Markers.prototype.hidePlaceholder = function(){
       
   301     this.$.find(".Ldt-Markers-PlaceholderMarker").remove();
       
   302 }
       
   303 
       
   304 IriSP.Widgets.Markers.prototype.showPlaceholder = function(_time){   
       
   305     var _scale = this.width / this.source.getDuration(),
       
   306         _left = _time * _scale -1,
       
   307         _data = {
       
   308             left: _left,
       
   309             height: this.line_height-1,
       
   310             ball_top: (this.ball_radius*2 > this.line_height) ? 0 : ((this.line_height - this.ball_radius*2)/2)-1,
       
   311             ball_radius: (this.ball_radius*2 > this.line_height) ? this.line_height/2 : this.ball_radius,
       
   312             ball_diameter: (this.ball_radius*2 > this.line_height) ? this.line_height/2 : this.ball_radius*2,
       
   313             ball_left: -this.ball_radius,
       
   314             marker_color: this.placeholder_color
       
   315         },
       
   316         _html = Mustache.to_html(this.markerPlaceholderTemplate, _data),
       
   317         _el = IriSP.jQuery(_html);
       
   318         
       
   319     list_$ = this.$.find(".Ldt-Markers-List");
       
   320     _el.appendTo(list_$);
       
   321 }
       
   322 
       
   323 IriSP.Widgets.Markers.prototype.clearSelectedMarker = function(){
       
   324     if (this.selectedMarker){
       
   325         var _divHtml = "";
       
   326         
       
   327         this.selectedMarker = false;
       
   328         this.$.find(".Ldt-Markers-Info").html(_divHtml);
       
   329         this.$.find(".Ldt-Markers-RoundButton").hide();
       
   330         this.$.find(".Ldt-Markers-Create").show();
       
   331         this.$.find(".Ldt-Markers-MarkerBall").toggleClass("selected", false);
       
   332         this.updateCreateButtonState(this.media.getCurrentTime())
       
   333     }
   204 }
   334 }
   205 
   335 
   206 IriSP.Widgets.Markers.prototype.drawMarkers = function(){
   336 IriSP.Widgets.Markers.prototype.drawMarkers = function(){
   207     this.$.remove("Ldt-Markers-Marker");
       
   208     var _this = this,
   337     var _this = this,
   209         _scale = this.width / this.source.getDuration(),
   338         _scale = this.width / this.source.getDuration(),
   210         list_$ = this.$.find('.Ldt-Markers-List');
   339         list_$ = this.$.find('.Ldt-Markers-List');
   211     
   340 
       
   341     this.$.remove("Ldt-Markers-Marker");
       
   342     list_$.html("");
   212     this.markers.forEach(function(_marker){
   343     this.markers.forEach(function(_marker){
   213         var _left = _marker.begin * _scale -1;
   344         var _left = _marker.begin * _scale -1,
   214         _data = {
   345             _data = {
   215             left: _left,
   346                 left: _left,
   216             height: _this.line_height-1,
   347                 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,
   348                 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,
   349                 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,
   350                 ball_diameter: (_this.ball_radius*2 > _this.line_height) ? _this.line_height/2 : _this.ball_radius*2,
   220             ball_left: -_this.ball_radius,
   351                 ball_left: -_this.ball_radius,
   221             marker_color: ((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))? _this.selected_color : _this.marker_color
   352                 marker_color: ((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))? _this.selected_color : _this.marker_color
   222         }
   353             },
   223         var _html = Mustache.to_html(_this.markerTemplate, _data),
   354             _html = Mustache.to_html(_this.markerTemplate, _data),
   224             _el = IriSP.jQuery(_html);
   355             _el = IriSP.jQuery(_html);
       
   356         
       
   357         if ((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id)){
       
   358             _el.children().toggleClass("selected", true);
       
   359         }
       
   360         
   225         _el.mouseover(function(){
   361         _el.mouseover(function(){
   226                 if (!((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))){
   362                 if (!((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))){
   227                     _el.children().css("background-color", _this.hover_color);
   363                     _el.children().css("background-color", _this.hover_color);
   228                 };
   364                 };
   229             })
   365             })
   232                   _el.children().css("background-color", _this.marker_color);
   368                   _el.children().css("background-color", _this.marker_color);
   233               };
   369               };
   234            })
   370            })
   235            .click(function(){
   371            .click(function(){
   236                _this.showScreen("Main");
   372                _this.showScreen("Main");
       
   373                _this.cancelEdit();
       
   374                _this.hidePlaceholder();
   237                if (!((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))){
   375                if (!((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))){
       
   376                   // if there either is no marker selected or we click a different marker
   238                   list_$.find(".Ldt-Markers-MarkerBall").css("background-color", _this.marker_color)
   377                   list_$.find(".Ldt-Markers-MarkerBall").css("background-color", _this.marker_color)
       
   378                   list_$.find(".Ldt-Markers-MarkerBall").toggleClass("selected", false);
       
   379                   _el.children().toggleClass("selected", true);
   239                   _el.children().css("background-color", _this.selected_color)
   380                   _el.children().css("background-color", _this.selected_color)
   240                   _this.selectedMarker = _marker;
   381                   _this.selectedMarker = _marker;
       
   382                   
   241                   _divHtml = Mustache.to_html(_this.infoTemplate, {
   383                   _divHtml = Mustache.to_html(_this.infoTemplate, {
   242                       edit: _this.editing,
   384                       edit: false,
   243                       marker_info: _marker.description,
   385                       marker_info: _marker.description,
   244                       send: _this.l10n.send,
       
   245                       cancel: _this.l10n.cancel
       
   246                   })
   386                   })
   247                   
   387                   
   248                   _this.$.find(".Ldt-Markers-Info").html(_divHtml);
   388                   _this.$.find(".Ldt-Markers-Info").html(_divHtml);
   249 
   389                   _this.$.find(".Ldt-Markers-MarkerDescription").click(_this.functionWrapper("startEdit"));
   250                   if(_this.editing){
   390                   _this.$.find(".Ldt-Markers-RoundButton").hide();
   251                       _this.$.find(".Ldt-Markers-MarkerSend").click(_this.functionWrapper("onSubmit"));
   391                   _this.$.find(".Ldt-Markers-Delete").show();
   252                       _this.$.find(".Ldt-Markers-MarkerCancel").click(_this.functionWrapper("toggleCreateMarker"));
   392 
   253                   }
       
   254                }
   393                }
   255                else {
   394                else {
   256                    var _divHtml = ""
   395                    // if we click the currently selected marker, we unselect it
   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);
   396                    _el.children().css("background-color", _this.hover_color);
   266                    _this.selectedMarker = false;
   397                    _this.clearSelectedMarker();
   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                }
   398                }
   281                
   399                
   282                if (_this.selectedMarker) {
   400                if (_this.selectedMarker) {
   283                    // If we unselect a marker we shouldn't trigger pause or time jump
   401                    // Only if we select a new marker do we pause video and time jump
   284                    _this.media.pause();
   402                    _this.media.pause();
   285                    _marker.trigger("click");
   403                    _marker.trigger("click");
   286                }
   404                }
   287            })
   405            })
   288            .appendTo(list_$);
   406            .appendTo(list_$);
   289     })
   407     })
   290 }
   408 }
   291 
   409 
       
   410 
   292 IriSP.Widgets.Markers.prototype.onSubmit = function(){
   411 IriSP.Widgets.Markers.prototype.onSubmit = function(){
   293     
   412     
   294     /* Si les champs obligatoires sont vides, on annule l'envoi */
   413     /* Si les champs obligatoires sont vides, on annule l'envoi */
   295     if (!this.onDescriptionChange()) {
   414     if (!this.allow_empty_markers && !this.onDescriptionChange()){
   296         return false;
   415         return false;
   297     }
   416     }
   298     
   417     
   299     /* On pause la vidéo si elle est encore en train de tourner */
   418     /* On pause la vidéo si elle est encore en train de tourner */
   300     if (!this.media.getPaused()){
   419     if (!this.media.getPaused()){
   301         this.media.pause();
   420         this.media.pause();
   302     }
   421     }
   303     
   422     
   304     var _this = this,
   423     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 */
   424         _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){
   425     if (this.selectedMarker){
   308         var _export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[this.api_serializer]})
   426         var _export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[this.api_serializer]})
   309             _annotation = this.selectedMarker;
   427             _annotation = this.selectedMarker,
       
   428             _url = Mustache.to_html(this.api_endpoint_template_edit, {annotation_id: this.selectedMarker ? this.selectedMarker.id : ""});
   310         _annotation.source = _export
   429         _annotation.source = _export
   311         _annotation.description = this.$.find(".Ldt-Markers-MarkerTextArea").val(), /* Champ description */
   430         _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 */
   431         _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 */
   432         _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     }
   433     }
   315     else {
   434     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 */
   435         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) */
   436             _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 */
   437             _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 */
   438             _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 */
       
   439             _url = Mustache.to_html(this.api_endpoint_template_create);
   320         /* Si nous avons dû générer un ID d'annotationType à la volée... */
   440         /* Si nous avons dû générer un ID d'annotationType à la volée... */
   321         if (!_annotationTypes.length) {
   441         if (!_annotationTypes.length) {
   322             /* Il ne faudra pas envoyer l'ID généré au serveur */
   442             /* Il ne faudra pas envoyer l'ID généré au serveur */
   323             _annotationType.dont_send_id = true;
   443             _annotationType.dont_send_id = true;
   324             /* Il faut inclure le titre dans le type d'annotation */
   444             /* Il faut inclure le titre dans le type d'annotation */
   325             _annotationType.title = this.annotation_type;
   445             _annotationType.title = this.annotation_type;
   326         }
   446         }
   327     
   447         
   328         _annotation.setMedia(this.source.currentMedia.id); /* Id du média annoté */
   448         _annotation.setMedia(this.source.currentMedia.id); /* Id du média annoté */
   329         _currentTime = this.media.getCurrentTime();
   449         if (!this.selectedMarker){
   330         _annotation.setBegin(_currentTime); /* Timecode de la lecture de la video */
   450             _annotation.setBegin(this.newMarkerCurrentTime);
   331         _annotation.setEnd(_currentTime); /* Timecode de fin du widget */
   451             _annotation.setEnd(this.newMarkerCurrentTime);
       
   452         }
   332         _annotation.setAnnotationType(_annotationType.id); /* Id du type d'annotation */
   453         _annotation.setAnnotationType(_annotationType.id); /* Id du type d'annotation */
   333         if (this.project_id != ""){
   454         if (this.project_id != ""){
   334             /* Champ id projet, seulement si on l'a renseigné dans la config */
   455             /* Champ id projet, seulement si on l'a renseigné dans la config */
   335             _annotation.project_id = this.project_id;
   456             _annotation.project_id = this.project_id;
   336         }
   457         }
   349     _export.addList("annotation",_exportedAnnotations); /* Ajout de la liste à exporter à l'objet Source */
   470     _export.addList("annotation",_exportedAnnotations); /* Ajout de la liste à exporter à l'objet Source */
   350     
   471     
   351     /* Envoi de l'annotation via AJAX au serveur ! */
   472     /* Envoi de l'annotation via AJAX au serveur ! */
   352     IriSP.jQuery.ajax({
   473     IriSP.jQuery.ajax({
   353         url: _url,
   474         url: _url,
   354         type: this.selectedMarker ? this.api_method_editing : this.api_method_create,
   475         type: this.selectedMarker ? this.api_method_edit : this.api_method_create,
   355         contentType: 'application/json',
   476         contentType: 'application/json',
   356         data: _export.serialize(), /* L'objet Source est sérialisé */
   477         data: _export.serialize(), /* L'objet Source est sérialisé */
   357         success: function(_data) {
   478         success: function(_data) {
   358             _this.showScreen('Success'); /* Si l'appel a fonctionné, on affiche l'écran "Annotation enregistrée" */
   479             _this.showScreen('Success'); /* Si l'appel a fonctionné, on affiche l'écran "Annotation enregistrée" */
   359             window.setTimeout(function(){
   480             window.setTimeout(_this.functionWrapper("revertToMainScreen"),(_this.after_send_timeout || 5000));
   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 */
   481             _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 */
   482             _export.deSerialize(_data); /* On désérialise les données reçues pour les réinjecter */
       
   483             _annotation.id = _data.id;
   365             _this.source.merge(_export); /* On récupère les données réimportées dans l'espace global des données */
   484             _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()) {
   485             if (_this.pause_on_write && _this.media.getPaused() && _this.play_on_submit) {
   367                 _this.media.play();
   486                 _this.media.play();
   368             }
   487             }
   369             _this.markers.push(_annotation);
   488             _this.markers.push(_annotation);
   370             _this.selectedMarker = _annotation;
   489             _this.selectedMarker = _annotation;
       
   490             _this.drawMarkers();
   371             _this.player.trigger("AnnotationsList.refresh"); /* On force le rafraîchissement du widget AnnotationsList */
   491             _this.player.trigger("AnnotationsList.refresh"); /* On force le rafraîchissement du widget AnnotationsList */
   372             _this.player.trigger("Markers.refresh");
   492             _this.player.trigger("Markers.refresh");
   373             _this.$.find(".Ldt-Markers-MarkerTextArea").val("")
       
   374         },
   493         },
   375         error: function(_xhr, _error, _thrown) {
   494         error: function(_xhr, _error, _thrown) {
   376             IriSP.log("Error when sending annotation", _thrown);
   495             IriSP.log("Error when sending annotation", _thrown);
   377             _export.getAnnotations().removeElement(_annotation, true);
   496             _export.getAnnotations().removeElement(_annotation, true);
   378             _this.showScreen('Failure');
   497             _this.showScreen('Failure');
   379             window.setTimeout(function(){
   498             window.setTimeout(_this.functionWrapper("revertToMainScreen"),(_this.after_send_timeout || 5000));
   380                 _this.showScreen("Main");
       
   381             },
       
   382             (_this.after_send_timeout || 5000));
       
   383         }
   499         }
   384     });
   500     });
   385     this.showScreen('Sending');
   501     this.showScreen('Sending');
   386     
   502     
   387     return false;
   503     return false;
   388 };
   504 };
       
   505 
       
   506 IriSP.Widgets.Markers.prototype.sendDelete = function(){
       
   507     _this = this;
       
   508     _url = Mustache.to_html(this.api_endpoint_template_delete, {annotation_id: this.selectedMarker ? this.selectedMarker.id : ""});
       
   509     IriSP.jQuery.ajax({
       
   510         url: _url,
       
   511         type: this.api_method_delete,
       
   512         contentType: 'application/json',
       
   513         success: function(_data) {
       
   514             _this.showScreen('DeleteSuccess'); /* Si l'appel a fonctionné, on affiche l'écran "Annotation enregistrée" */
       
   515             window.setTimeout(_this.functionWrapper("revertToMainScreen"),(_this.after_send_timeout || 5000));
       
   516             if (_this.pause_on_write && _this.media.getPaused() && _this.play_on_submit) {
       
   517                 _this.media.play();
       
   518             }
       
   519             _this.markers.removeElement(_this.selectedMarker);
       
   520             _this.selectedMarker = false
       
   521             _this.player.trigger("AnnotationsList.refresh"); /* On force le rafraîchissement du widget AnnotationsList */
       
   522             _this.player.trigger("Markers.refresh");
       
   523         },
       
   524         error: function(_xhr, _error, _thrown) {
       
   525             IriSP.log("Error when sending annotation", _thrown);
       
   526             _this.showScreen('Failure');
       
   527             window.setTimeout(_this.functionWrapper("revertToMainScreen"),(_this.after_send_timeout || 5000));
       
   528         }
       
   529     });
       
   530     this.showScreen("Sending")
       
   531 }