# HG changeset patch # User durandn # Date 1435935529 -7200 # Node ID e78b889a75e1f774e76df2d232d2576f71e0b2b9 # Parent 5c0416e8bba175964fc62fe56125d4b910530108 CreateAnnotations new feature: hide/show functionality on signal trigger (tweaks), added config options to customize what is displayed more accurately diff -r 5c0416e8bba1 -r e78b889a75e1 src/widgets/CreateAnnotation.css --- a/src/widgets/CreateAnnotation.css Fri Jul 03 16:57:10 2015 +0200 +++ b/src/widgets/CreateAnnotation.css Fri Jul 03 16:58:49 2015 +0200 @@ -23,7 +23,7 @@ } .Ldt-CreateAnnotation-Main { - min-height: 100px; + min-height: 150px; } .Ldt-CreateAnnotation-Title, .Ldt-CreateAnnotation-Creator { @@ -47,7 +47,6 @@ position: absolute; bottom: 7px; right: 7px; - display: inline; color: #ffffff; cursor: pointer; background: url('img/submit_annotation.png'); @@ -164,18 +163,4 @@ a.Ldt-CreateAnnotation-Close:hover { background-position: -17px 0; -} - -.Ldt-CreateAnnotation-Controls { - position: absolute; - top: 7px; - right: 7px; -} - -span[class^='Ldt-CreateAnnotation-Control-'] { - background-color: #ddd; - padding: 2px; - margin: 4px; - border-radius: 3px; - border: 1px solid #888; -} +} \ No newline at end of file diff -r 5c0416e8bba1 -r e78b889a75e1 src/widgets/CreateAnnotation.js --- a/src/widgets/CreateAnnotation.js Fri Jul 03 16:57:10 2015 +0200 +++ b/src/widgets/CreateAnnotation.js Fri Jul 03 16:58:49 2015 +0200 @@ -1,16 +1,7 @@ /* TODO: Add Social Network Sharing */ IriSP.Widgets.CreateAnnotation = function(player, config) { - var _this = this; IriSP.Widgets.Widget.call(this, player, config); - if (_this.api_method == 'local' && window.localStorage[_this.api_endpoint_template]) { - this.source.onLoad(function () { - var _export = _this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[_this.api_serializer]}); - _export.deSerialize(window.localStorage[_this.api_endpoint_template]); - console.log("Loaded personal annotations", _export); - _this.source.merge(_export); - }); - }; }; IriSP.Widgets.CreateAnnotation.prototype = new IriSP.Widgets.Widget(); @@ -18,13 +9,14 @@ IriSP.Widgets.CreateAnnotation.prototype.defaults = { show_title_field : true, show_creator_field : true, + creator_field_readonly : false, start_visible : true, always_visible : false, show_slice : true, - show_controls: false, show_arrow : true, show_mic_record: false, show_mic_play: false, + show_time: true, minimize_annotation_widget : true, creator_name : "", creator_avatar : "", @@ -51,13 +43,15 @@ }], slice_annotation_type: "chap", annotation_type: "Contributions", + post_at_segment_time: false, + segment_annotation_type: "chap", api_serializer: "ldt_annotate", api_endpoint_template: "", api_method: "POST", + project_id: "", after_send_timeout: 0, close_after_send: false, - tag_prefix: "#", - slice_widget: null + tag_prefix: "#" }; IriSP.Widgets.CreateAnnotation.prototype.messages = { @@ -112,16 +106,11 @@ + '
' + '

{{l10n.annotate_video}}{{#show_title_field}}

' + '

{{/show_title_field}}' - + ' {{#show_slice}}{{l10n.from_time}} {{/show_slice}}{{^show_slice}}{{l10n.at_time}} {{/show_slice}} 00:00' + + '{{#show_time}} {{#show_slice}}{{l10n.from_time}} {{/show_slice}}{{^show_slice}}{{l10n.at_time}} {{/show_slice}} 00:00{{/show_time}}' + '{{#show_slice}} {{l10n.to_time}} {{end}}{{/show_slice}}' - + '{{#show_creator_field}}{{l10n.your_name_}} {{/show_creator_field}}

' - + '{{#show_controls}}
' - + 'IN' - + 'OUT' - + 'Play' - + '
{{/show_controls}}' + + '{{#show_creator_field}}{{l10n.your_name_}} {{/show_creator_field}}' + '' - + '{{#show_creator_field}}
{{/show_creator_field}}' + + '
' + '' + '{{#show_mic_record}}
Add voice annotation
' + ' ' @@ -146,7 +135,7 @@ + ' pluginspage="http://www.macromedia.com/go/getflashplayer">' + ' ' + ' ' - + '
{{/show_mic_record}}' + + '{{/show_mic_record}}' + '{{#tags.length}}
{{l10n.add_keywords_}}
{{/tags.length}}' + '{{#polemics.length}}
{{l10n.add_polemic_keywords_}}
'; - + IriSP.Widgets.CreateAnnotation.prototype.draw = function() { var _this = this; - + this.begin = new IriSP.Model.Time(); this.end = this.source.getDuration(); - + this.tag_prefix = this.tag_prefix || ""; - + if (this.tag_titles && !this.tags) { if(!(this.tag_titles.length==1 && this.tag_titles[0]=="")){ this.tags = IriSP._(this.tag_titles).map(function(_tag_title) { @@ -200,13 +189,13 @@ this.renderTemplate(); if (this.show_mic_record) { this.recorder = this.$.find("embed")[0]; - + window.setAudioUrl = function(_url) { _this.audio_url = _url; - }; + } } if (this.show_slice) { - this.slice_widget = this.insertSubwidget( + this.insertSubwidget( this.$.find(".Ldt-CreateAnnotation-Slice"), { type: "Slice", @@ -259,35 +248,17 @@ if (this.show_creator_field) { this.$.find(".Ldt-CreateAnnotation-Creator").bind("change keyup input paste", this.functionWrapper("onCreatorChange")); } - this.$.find("[class^='Ldt-CreateAnnotation-Control-']").click(function() { - var action = this.className.replace('Ldt-CreateAnnotation-Control-', ''); - switch (action) { - case "In": - // Set In bound to current player time - _this.begin = new IriSP.Model.Time(_this.media.getCurrentTime() || 0); - _this.$.find(".Ldt-CreateAnnotation-Begin").html(_this.begin.toString()); - break; - case "Out": - // Set In bound to current player time - _this.end = new IriSP.Model.Time(_this.media.getCurrentTime() || _this.media.duration); - _this.$.find(".Ldt-CreateAnnotation-End").html(_this.end.toString()); - break; - case "Play": - _this.media.setCurrentTime(_this.begin); - _this.media.play() - break; - } - return false; - }); - + if (this.start_visible) { this.show(); } else { this.$.hide(); this.hide(); } - + this.onMdpEvent("CreateAnnotation.toggle","toggle"); + this.onMdpEvent("CreateAnnotation.hide", "hide"); + this.onMdpEvent("CreateAnnotation.show", "show"); this.$.find("form").submit(this.functionWrapper("onSubmit")); }; @@ -297,51 +268,47 @@ } IriSP.Widgets.CreateAnnotation.prototype.show = function() { - this.visible = true; - this.showScreen('Main'); - this.$.find(".Ldt-CreateAnnotation-Description").val("").css("border-color", "#666666").addClass("empty"); - if (this.show_title_field) { - this.$.find(".Ldt-CreateAnnotation-Title").val("").css("border-color", "#666666").addClass("empty"); - } - if (this.show_creator_field) { - this.$.find(".Ldt-CreateAnnotation-Creator").val(this.creator_name).css("border-color", "#666666"); - if (!this.creator_name) { - this.$.find(".Ldt-CreateAnnotation-Creator").addClass("empty"); + if (!this.visible){ + this.visible = true; + this.showScreen('Main'); + this.$.find(".Ldt-CreateAnnotation-Description").val("").css("border-color", "#666666").addClass("empty"); + if (this.show_title_field) { + this.$.find(".Ldt-CreateAnnotation-Title").val("").css("border-color", "#666666").addClass("empty"); } - } - this.$.find(".Ldt-CreateAnnotation-TagLi, .Ldt-CreateAnnotation-PolemicLi").removeClass("selected"); - this.$.slideDown(); - if (this.minimize_annotation_widget) { - this.player.trigger("Annotation.minimize"); + if (this.show_creator_field) { + this.$.find(".Ldt-CreateAnnotation-Creator").val(this.creator_name).css("border-color", "#666666"); + if (!this.creator_name) { + this.$.find(".Ldt-CreateAnnotation-Creator").addClass("empty"); + } + } + this.$.find(".Ldt-CreateAnnotation-TagLi, .Ldt-CreateAnnotation-PolemicLi").removeClass("selected"); + this.$.slideDown(); + if (this.minimize_annotation_widget) { + this.player.trigger("Annotation.minimize"); + } } }; IriSP.Widgets.CreateAnnotation.prototype.hide = function() { - if (this.recorder) { - this.recorder.stopRecord(); - } - if (!this.always_visible) { - this.visible = false; - this.$.slideUp(); - if (this.minimize_annotation_widget) { - this.player.trigger("Annotation.maximize"); + if (this.visible){ + if (this.recorder) { + this.recorder.stopRecord(); + } + if (!this.always_visible) { + this.visible = false; + this.$.slideUp(); + if (this.minimize_annotation_widget) { + this.player.trigger("Annotation.maximize"); + } } } }; IriSP.Widgets.CreateAnnotation.prototype.toggle = function() { - var _this = this; if (!this.always_visible) { if (this.visible) { this.hide(); } else { - _this.begin = new IriSP.Model.Time(_this.media.getCurrentTime() || 0); - _this.end = new IriSP.Model.Time(_this.media.getCurrentTime() || 0); - _this.$.find(".Ldt-CreateAnnotation-Begin").html(_this.begin.toString()); - _this.$.find(".Ldt-CreateAnnotation-End").html(_this.end.toString()); - if (_this.slice_widget) { - _this.slice_widget.setBounds(_this.begin, _this.end); - } this.show(); } } @@ -419,11 +386,11 @@ if (!this.onDescriptionChange() || (this.show_title_field && !this.onTitleChange()) || (this.show_creator_field && !this.onCreatorChange())) { return false; } - + if (this.recorder) { this.recorder.stopRecord(); } - + 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]}), /* Création d'un objet source utilisant un sérialiseur spécifique pour l'export */ @@ -431,7 +398,7 @@ _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 */ _url = Mustache.to_html(this.api_endpoint_template, {id: this.source.projectId}); /* Génération de l'URL à laquelle l'annotation doit être envoyée, qui doit inclure l'ID du projet */ - + /* 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 */ @@ -439,30 +406,48 @@ /* Il faut inclure le titre dans le type d'annotation */ _annotationType.title = this.annotation_type; } - + /* * 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 * */ _annotation.setMedia(this.source.currentMedia.id); /* Id du média annoté */ - _annotation.setBegin(this.begin); /*Timecode de début */ - _annotation.setEnd(this.end); /* Timecode de fin */ - _annotation.created = new Date(); /* Date de création de l'annotation */ - + + if (this.post_at_segment_time){ + var _currentTime = this.media.getCurrentTime() + var _segmentsAnnotations = this.source.getAnnotationsByTypeTitle(this.segments_annotation_type) + var _currentSegments = _segmentsAnnotations.filter(function(_segment){ + return (_currentTime >= _segment.begin && _currentTime <= _segment.end) + }); + if (_currentSegments.length == 0){ + _annotation.setBegin(this.begin); /* Timecode de début du widget */ + _annotation.setEnd(this.end); /* Timecode de fin du widget */ + } + else { + _annotation.setBegin(_currentSegments[0].begin); /* Timecode de début du segment */ + _annotation.setEnd(_currentSegments[0].end); /* Timecode de fin du segment */ + } + } + else { + _annotation.setBegin(this.begin); /*Timecode de début du widget */ + _annotation.setEnd(this.end); /* Timecode de fin du widget */ + } _annotation.setAnnotationType(_annotationType.id); /* Id du type d'annotation */ - _annotation.description = this.$.find(".Ldt-CreateAnnotation-Description").val(); /* Champ description */ if (this.show_title_field) { /* Champ titre, seulement s'il est visible */ _annotation.title = this.$.find(".Ldt-CreateAnnotation-Title").val(); - } else { - _annotation.title = _annotation.description; + }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-CreateAnnotation-Description").val(); /* Champ description */ + var tagIds = Array.prototype.map.call( this.$.find(".Ldt-CreateAnnotation-TagLi.selected"), function(el) { return IriSP.jQuery(el).attr("tag-id")} ); - + IriSP._(_annotation.description.match(/#[^\s#.,;]+/g)).each(function(_tt) { var _tag, _tag_title = _tt.replace(/^#/,''), @@ -477,9 +462,9 @@ if (tagIds.indexOf(_tag.id) === -1) { tagIds.push(_tag.id); } - + }) - + _annotation.setTags(IriSP._(tagIds).uniq()); /*Liste des ids de tags */ if (this.audio_url) { _annotation.audio = { @@ -494,65 +479,46 @@ _annotation.creator = this.creator_name; } _exportedAnnotations.push(_annotation); /* Ajout de l'annotation à la liste à exporter */ - - if (this.api_method == 'local') { - // Append to existing localStorage annotations - // FIXME: handle movie ids - /* Use localStorage */ - /* Data will be serialized in the localStore property designated by api_endpoint_template */ - _export.addList("annotation", _exportedAnnotations); /* Ajout de la liste à exporter à l'objet Source */ - _this.source.merge(_export); /* On ajoute la nouvelle annotation au recueil original */ - // Import previously saved local annotations - if (window.localStorage[_this.api_endpoint_template]) { - _export.deSerialize(window.localStorage[_this.api_endpoint_template]); - } - // Save everything back - window.localStorage[_this.api_endpoint_template] = _export.serialize(); - if (_this.pause_on_write && _this.media.getPaused()) { - _this.media.play(); + _export.addList("annotation",_exportedAnnotations); /* Ajout de la liste à exporter à l'objet Source */ + var _this = this; + /* Envoi de l'annotation via AJAX au serveur ! */ + IriSP.jQuery.ajax({ + url: _url, + type: this.api_method, + contentType: 'application/json', + data: _export.serialize(), /* L'objet Source est sérialisé */ + success: function(_data) { + _this.showScreen('Saved'); /* Si l'appel a fonctionné, on affiche l'écran "Annotation enregistrée" */ + if (_this.after_send_timeout) { /* Selon les options de configuration, on revient à l'écran principal ou on ferme le widget, ou rien */ + window.setTimeout( + function() { + _this.close_after_send + ? _this.hide() + : _this.show(); + }, + _this.after_send_timeout + ); + } + _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.player.trigger("AnnotationsList.refresh"); /* On force le rafraîchissement du widget AnnotationsList */ + }, + error: function(_xhr, _error, _thrown) { + IriSP.log("Error when sending annotation", _thrown); + _export.getAnnotations().removeElement(_annotation, true); + _this.showScreen('Error'); + window.setTimeout(function(){ + _this.showScreen("Main") + }, + (_this.after_send_timeout || 5000)); } - _this.player.trigger("AnnotationsList.refresh"); /* On force le rafraîchissement du widget AnnotationsList */ - _this.$.find(".Ldt-CreateAnnotation-Description").val(""); - } else { - _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.api_method, - contentType: 'application/json', - data: _export.serialize(), /* L'objet Source est sérialisé */ - success: function(_data) { - _this.showScreen('Saved'); /* Si l'appel a fonctionné, on affiche l'écran "Annotation enregistrée" */ - if (_this.after_send_timeout) { /* Selon les options de configuration, on revient à l'écran principal ou on ferme le widget, ou rien */ - window.setTimeout( - function() { - _this.close_after_send - ? _this.hide() - : _this.show(); - }, - _this.after_send_timeout - ); - } - _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.player.trigger("AnnotationsList.refresh"); /* On force le rafraîchissement du widget AnnotationsList */ - }, - error: function(_xhr, _error, _thrown) { - IriSP.log("Error when sending annotation", _thrown); - _export.getAnnotations().removeElement(_annotation, true); - _this.showScreen('Error'); - window.setTimeout(function(){ - _this.showScreen("Main") - }, - (_this.after_send_timeout || 5000)); - } - }); - this.showScreen('Wait'); - } - + }); + this.showScreen('Wait'); + return false; }; +