diff -r d8339b45edc4 -r b06345320ffb src/widgets/Markers.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/widgets/Markers.js Tue Sep 01 15:24:26 2015 +0200 @@ -0,0 +1,388 @@ + +IriSP.Widgets.Markers = function(player, config) { + IriSP.Widgets.Widget.call(this, player, config); +}; + +IriSP.Widgets.Markers.prototype = new IriSP.Widgets.Widget(); + +IriSP.Widgets.Markers.prototype.defaults = { + annotation_type: "markers", + line_height: 8, + background: "#e0e0e0", + marker_color: "#ff80fc", + hover_color: "#e15581", + selected_color: "#74d600", + ball_radius: 4, + pause_on_write: true, + api_serializer: "ldt_annotate", + api_endpoint_template: "", + api_method_create: "POST", + api_method_editing: "PUT", + project_id: "", + creator_name: "", + after_send_timeout: 0, + close_after_send: false, +}; + +IriSP.Widgets.Markers.prototype.template = + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
+
' + + '
' + + '
' + + '
' + + '
{{l10n.wait_while_processing}}
' + + '
' + + '
' + + '' + + '
{{l10n.annotation_saved}}
' + + '
' + + '
' + + '' + + '
{{l10n.error_while_contacting}}
' + + '
' + + '
'; + + +IriSP.Widgets.Markers.prototype.markerTemplate = + '
' + + '
' + + '
'; + +IriSP.Widgets.Markers.prototype.infoTemplate = + '{{^edit}}
{{marker_info}}
{{/edit}}' + + '{{#edit}}
' + + '' + + '
' + + '
{{send}}
' + + '
{{cancel}}
' + + '
' + + '
{{/edit}}' + +IriSP.Widgets.Markers.prototype.messages = { + en : { + send : "Send", + cancel : "Cancel", + wait_while_processing: "Please wait while your annotation is being processed...", + error_while_contacting: "An error happened while contacting the server. Your annotation has not been saved.", + annotation_saved: "Thank you, your annotation has been saved.", + close_widget: "Close", + }, + fr : { + send : "Envoyer", + cancel : "Annuler", + wait_while_processing: "Veuillez patienter pendant le traitement de votre annotation...", + error_while_contacting: "Une erreur s'est produite en contactant le serveur. Votre annotation n'a pas été enregistrée.", + annotation_saved: "Merci, votre annotation a été enregistrée.", + close_widget: "Fermer", + } +} + +IriSP.Widgets.Markers.prototype.draw = function(){ + var _this = this; + + this.renderTemplate(); + + this.markers = this.getWidgetAnnotations().filter(function(_ann) { + return ((_ann.getDuration() == 0) || (_ann.begin == _ann.end)); + }); + this.drawMarkers(); + + this.$.find(".Ldt-Markers-Create").click(function(){ + if (!_this.selectedMarker){ + _this.toggleCreateMarker(); + } + else { + _this.selectedMarker = false; + _this.$.find(".Ldt-Markers-Info").html(""); + _this.$.find(".Ldt-Markers-MarkerBall").css("background-color", _this.marker_color) + _this.$.find(".Ldt-Markers-Create").html("+"); + } + }) + this.$.find(".Ldt-Markers-Info").click(function(){ + if (_this.selectedMarker&&!_this.editing){ + _this.toggleCreateMarker(); + } + }) + this.showScreen("Main"); + this.$.css({ + margin: "1px 0", + height: this.line_height, + background: this.background + }); + + this.$.find(".Ldt-Markers-Close").click(function() { + _this.showScreen("Main"); + }); + + this.onMediaEvent("timeupdate", "updatePosition"); + this.onMdpEvent("Markers.refresh", this.functionWrapper("drawMarkers")); + + this.editing = false; + this.selectedMarker = false; +} + + +IriSP.Widgets.Markers.prototype.updatePosition = function(_time) { + var _x = Math.floor( this.width * _time / this.media.duration); + this.$.find('.Ldt-Markers-Position').css({ + left: _x + "px" + }); +}; + + +IriSP.Widgets.Markers.prototype.toggleCreateMarker = function(){ + if(!this.editing){ + this.editing = true + } + else { + this.editing = false + } + var _divHtml = ""; + if (this.selectedMarker){ + _divHtml = Mustache.to_html(this.infoTemplate, { + edit: this.editing, + marker_info: this.selectedMarker.description, + send: this.l10n.send, + cancel: this.l10n.cancel + }) + + this.$.find(".Ldt-Markers-Info").html(_divHtml); + } + else { + if (this.editing) { + _divHtml = Mustache.to_html(this.infoTemplate, { + edit: this.editing, + marker_info: "", + send: this.l10n.send, + cancel: this.l10n.cancel, + }) + } + this.$.find(".Ldt-Markers-Info").html(_divHtml); + } + + if(this.editing){ + this.$.find(".Ldt-Markers-MarkerSend").click(this.functionWrapper("onSubmit")); + this.$.find(".Ldt-Markers-MarkerCancel").click(this.functionWrapper("toggleCreateMarker")); + this.$.find(".Ldt-Markers-MarkerTextArea").bind("change keyup input paste", this.functionWrapper("onDescriptionChange")); + this.$.find(".Ldt-Markers-Create").html("-"); + } + else { + this.$.find(".Ldt-Markers-Create").html("+"); + } +}; + +IriSP.Widgets.Markers.prototype.onDescriptionChange = function(){ + var _field = this.$.find(".Ldt-Markers-MarkerTextArea"), + _contents = _field.val(); + _field.css("border-color", !!_contents ? "#e87d9f" : "#ff0000"); + if (!!_contents) { + _field.removeClass("empty"); + } else { + _field.addClass("empty"); + } + this.pauseOnWrite(); + return !!_contents; +}; + +IriSP.Widgets.Markers.prototype.pauseOnWrite = function(){ + if (this.pause_on_write && !this.media.getPaused()) { + this.media.pause(); + } +}; + +IriSP.Widgets.Markers.prototype.showScreen = function(_screenName) { + this.$.find('.Ldt-Markers-Screen' + _screenName).show() + .siblings().hide(); + if ((_screenName=="Main")&&(this.editing)){ + this.toggleCreateMarker(); + }; +} + +IriSP.Widgets.Markers.prototype.drawMarkers = function(){ + this.$.remove("Ldt-Markers-Marker"); + var _this = this, + _scale = this.width / this.source.getDuration(), + list_$ = this.$.find('.Ldt-Markers-List'); + + this.markers.forEach(function(_marker){ + var _left = _marker.begin * _scale -1; + _data = { + left: _left, + height: _this.line_height-1, + ball_top: (_this.ball_radius*2 > _this.line_height) ? 0 : ((_this.line_height - _this.ball_radius*2)/2)-1, + ball_radius: (_this.ball_radius*2 > _this.line_height) ? _this.line_height/2 : _this.ball_radius, + ball_diameter: (_this.ball_radius*2 > _this.line_height) ? _this.line_height/2 : _this.ball_radius*2, + ball_left: -_this.ball_radius, + marker_color: ((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))? _this.selected_color : _this.marker_color + } + var _html = Mustache.to_html(_this.markerTemplate, _data), + _el = IriSP.jQuery(_html); + _el.mouseover(function(){ + if (!((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))){ + _el.children().css("background-color", _this.hover_color); + }; + }) + .mouseout(function(){ + if (!((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))){ + _el.children().css("background-color", _this.marker_color); + }; + }) + .click(function(){ + _this.showScreen("Main"); + if (!((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))){ + list_$.find(".Ldt-Markers-MarkerBall").css("background-color", _this.marker_color) + _el.children().css("background-color", _this.selected_color) + _this.selectedMarker = _marker; + _divHtml = Mustache.to_html(_this.infoTemplate, { + edit: _this.editing, + marker_info: _marker.description, + send: _this.l10n.send, + cancel: _this.l10n.cancel + }) + + _this.$.find(".Ldt-Markers-Info").html(_divHtml); + + if(_this.editing){ + _this.$.find(".Ldt-Markers-MarkerSend").click(_this.functionWrapper("onSubmit")); + _this.$.find(".Ldt-Markers-MarkerCancel").click(_this.functionWrapper("toggleCreateMarker")); + } + } + else { + var _divHtml = "" + if (_this.editing){ + _divHtml = Mustache.to_html(_this.infoTemplate, { + edit: _this.editing, + marker_info: "", + send: _this.l10n.send, + cancel: _this.l10n.cancel + }); + } + _el.children().css("background-color", _this.hover_color); + _this.selectedMarker = false; + _this.$.find(".Ldt-Markers-Info").html(_divHtml); + + if(_this.editing){ + _this.$.find(".Ldt-Markers-MarkerSend").click(_this.functionWrapper("onSubmit")); + _this.$.find(".Ldt-Markers-MarkerCancel").click(_this.functionWrapper("toggleCreateMarker")); + } + } + + if (_this.selectedMarker){ + _this.$.find(".Ldt-Markers-Create").html("-") + } + else { + _this.$.find(".Ldt-Markers-Create").html("+") + } + + if (_this.selectedMarker) { + // If we unselect a marker we shouldn't trigger pause or time jump + _this.media.pause(); + _marker.trigger("click"); + } + }) + .appendTo(list_$); + }) +} + +IriSP.Widgets.Markers.prototype.onSubmit = function(){ + + /* Si les champs obligatoires sont vides, on annule l'envoi */ + if (!this.onDescriptionChange()) { + return false; + } + + /* On pause la vidéo si elle est encore en train de tourner */ + if (!this.media.getPaused()){ + this.media.pause(); + } + + 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 */ + _url = Mustache.to_html(this.api_endpoint_template, {annotation_id: this.selectedMarker ? this.selectedMarker.id : ""}); + if (this.selectedMarker){ + var _export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[this.api_serializer]}) + _annotation = this.selectedMarker; + _annotation.source = _export + _annotation.description = this.$.find(".Ldt-Markers-MarkerTextArea").val(), /* Champ description */ + _annotationTypes = this.source.getAnnotationTypes().searchByTitle(this.annotation_type, true), /* Récupération du type d'annotation dans lequel l'annotation doit être ajoutée */ + _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 */ + } + else { + 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 */ + _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) */ + _annotationTypes = this.source.getAnnotationTypes().searchByTitle(this.annotation_type, true), /* Récupération du type d'annotation dans lequel l'annotation doit être ajoutée */ + _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 */ + /* Si nous avons dû générer un ID d'annotationType à la volée... */ + if (!_annotationTypes.length) { + /* Il ne faudra pas envoyer l'ID généré au serveur */ + _annotationType.dont_send_id = true; + /* Il faut inclure le titre dans le type d'annotation */ + _annotationType.title = this.annotation_type; + } + + _annotation.setMedia(this.source.currentMedia.id); /* Id du média annoté */ + _currentTime = this.media.getCurrentTime(); + _annotation.setBegin(_currentTime); /* Timecode de la lecture de la video */ + _annotation.setEnd(_currentTime); /* Timecode de fin du widget */ + _annotation.setAnnotationType(_annotationType.id); /* Id du type d'annotation */ + if (this.project_id != ""){ + /* Champ id projet, seulement si on l'a renseigné dans la config */ + _annotation.project_id = this.project_id; + } + _annotation.created = new Date(); /* Date de création de l'annotation */ + _annotation.description = this.$.find(".Ldt-Markers-MarkerTextArea").val(); /* Champ description */ + _annotation.creator = this.creator_name; + } + _annotation.project_id = this.project_id; + + /* + * Nous remplissons les données de l'annotation générée à la volée + * ATTENTION: Si nous sommes sur un MASHUP, ces éléments doivent se référer AU MEDIA D'ORIGINE + * */ + + _exportedAnnotations.push(_annotation); /* Ajout de l'annotation à la liste à exporter */ + _export.addList("annotation",_exportedAnnotations); /* Ajout de la liste à exporter à l'objet Source */ + + /* Envoi de l'annotation via AJAX au serveur ! */ + IriSP.jQuery.ajax({ + url: _url, + type: this.selectedMarker ? this.api_method_editing : this.api_method_create, + contentType: 'application/json', + data: _export.serialize(), /* L'objet Source est sérialisé */ + success: function(_data) { + _this.showScreen('Success'); /* Si l'appel a fonctionné, on affiche l'écran "Annotation enregistrée" */ + window.setTimeout(function(){ + _this.showScreen("Main") + }, + (_this.after_send_timeout || 5000)); + _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 */ + if (_this.pause_on_write && _this.media.getPaused()) { + _this.media.play(); + } + _this.markers.push(_annotation); + _this.selectedMarker = _annotation; + _this.player.trigger("AnnotationsList.refresh"); /* On force le rafraîchissement du widget AnnotationsList */ + _this.player.trigger("Markers.refresh"); + _this.$.find(".Ldt-Markers-MarkerTextArea").val("") + }, + error: function(_xhr, _error, _thrown) { + IriSP.log("Error when sending annotation", _thrown); + _export.getAnnotations().removeElement(_annotation, true); + _this.showScreen('Failure'); + window.setTimeout(function(){ + _this.showScreen("Main"); + }, + (_this.after_send_timeout || 5000)); + } + }); + this.showScreen('Sending'); + + return false; +}; \ No newline at end of file