From e846bca64d04b60eb7285312b2cbe5d3689b9f78 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 7 Oct 2015 15:01:12 +0200 Subject: [PATCH 001/204] Fix Image aspect ratio --- src/widgets/SlideVideoPlayer.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index 00d86632..2752cf25 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -23,9 +23,12 @@ z-index: 1; } +.Ldt-SlideVideoPlayer-pip-main .Ldt-ImageDisplay-Container { + min-height: 30vw; +} .Ldt-SlideVideoPlayer-pip-pip { position: absolute; - width: 30%; + width: 30% !important; height: 30%; right: 2px; bottom: 2px; From 4b9aaa09464725892fe76d36131a1361914a6a55 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 7 Oct 2015 15:01:34 +0200 Subject: [PATCH 002/204] Move pip-menu into the whole widget --- src/widgets/SlideVideoPlayer.css | 6 +++--- src/widgets/SlideVideoPlayer.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index 2752cf25..19fe2b48 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -40,12 +40,12 @@ } .Ldt-SlideVideoPlayer-pip-menu { position: absolute; - top: 0px; - right: 0px; + bottom: 2px; + right: 2px; z-index: 10; display: none; } -.Ldt-SlideVideoPlayer-pip-pip:hover .Ldt-SlideVideoPlayer-pip-menu { +.Ldt-SlideVideoPlayer:hover .Ldt-SlideVideoPlayer-pip-menu { background-color: #000; opacity: .5; display: inline-block; diff --git a/src/widgets/SlideVideoPlayer.js b/src/widgets/SlideVideoPlayer.js index 4a0313f3..f8753a89 100644 --- a/src/widgets/SlideVideoPlayer.js +++ b/src/widgets/SlideVideoPlayer.js @@ -43,7 +43,7 @@ IriSP.Widgets.SlideVideoPlayer.prototype.draw = function() { ); if (_this.mode == 'pip') { - _this.$.find(".Ldt-SlideVideoPlayer-panel").append('
'); + _this.$.find(".Ldt-SlideVideoPlayer").append('
'); _this.$.on("click", ".Ldt-SlideVideoPlayer-pip-menu-toggle", function () { _this.toggleMainDisplay(); }); From bc123b39bda6c863bf6aa43dee8149406257acd5 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 9 Oct 2015 18:29:33 +0200 Subject: [PATCH 003/204] Cosmetic fixes --- src/widgets/EnrichedPlan.js | 40 +++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index c26c2b82..4baee77d 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -2,14 +2,14 @@ - add callbacks */ -IriSP.Widgets.EnrichedPlan = function(player, config) { +IriSP.Widgets.EnrichedPlan = function (player, config) { IriSP.Widgets.Widget.call(this, player, config); } IriSP.Widgets.EnrichedPlan.prototype = new IriSP.Widgets.Widget(); IriSP.Widgets.EnrichedPlan.prototype.defaults = { - // Main type for slide segmentation + // Main type for toc segmentation annotation_type: "Slides", // If no annotation type list is specified, use all other types annotation_types: [], @@ -48,26 +48,26 @@ IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
{{{ text }}} {{ author }}
'; -IriSP.Widgets.EnrichedPlan.prototype.draw = function() { +IriSP.Widgets.EnrichedPlan.prototype.draw = function () { var _this = this; // Generate a unique prefix, so that ids of input fields // (necessary for label association) are unique too. _this.prefix = "TODO"; // slides content: title, level (for toc) - var _slides = this.getWidgetAnnotations().sortBy(function(_annotation) { + var _slides = this.getWidgetAnnotations().sortBy(function (_annotation) { return _annotation.begin; }); // All other annotations - var _annotations = this.media.getAnnotations().filter( function (a) { + var _annotations = this.media.getAnnotations().filter(function (a) { return a.getAnnotationType().title != _this.annotation_type; - }).sortBy(function(_annotation) { + }).sortBy(function (_annotation) { return _annotation.begin; }); // Reference annotations in each slide: assume that end time is // correctly set. - _slides.forEach( function (slide) { - slide.annotations = _annotations.filter( function (a) { + _slides.forEach(function (slide) { + slide.annotations = _annotations.filter(function (a) { return a.begin >= slide.begin && a.begin <= slide.end; }); }); @@ -81,7 +81,7 @@ IriSP.Widgets.EnrichedPlan.prototype.draw = function() { return a.title.indexOf('Anonyme') < 0 ? "Own" : "Other"; }; - _slides.forEach(function(slide) { + _slides.forEach(function (slide) { var _html = Mustache.to_html(_this.slideTemplate, { id : slide.id, atitle : IriSP.textFieldHtml(slide.title), @@ -90,7 +90,7 @@ IriSP.Widgets.EnrichedPlan.prototype.draw = function() { begintc: slide.begin.milliseconds, thumbnail: slide.thumbnail, show_slides: _this.show_slides, - notes: slide.annotations.map( function (a) { + notes: slide.annotations.map(function (a) { return Mustache.to_html(_this.annotationTemplate, { id: a.id, text: IriSP.textFieldHtml(a.description || a.title), @@ -100,9 +100,9 @@ IriSP.Widgets.EnrichedPlan.prototype.draw = function() { atitle: a.title.slice(0, 20), // FIXME: Temporary hack waiting for a proper metadata definition category: "Ldt-EnrichedPlan-Note-" + note_category(a), - filtered: ( (note_category(a) == 'Own' && ! _this.show_own_notes) - || (note_category(a) == 'Other' && ! _this.show_other_notes) - || (note_category(a) == 'Teacher' && ! _this.show_teacher_notes) ) ? 'filtered_out' : '' + filtered: ((note_category(a) == 'Own' && !_this.show_own_notes) + || (note_category(a) == 'Other' && !_this.show_other_notes) + || (note_category(a) == 'Teacher' && !_this.show_teacher_notes)) ? 'filtered_out' : '' }); }).join("\n") }); @@ -115,25 +115,27 @@ IriSP.Widgets.EnrichedPlan.prototype.draw = function() { }); container.on("click", ".Ldt-EnrichedPlan-Control-Checkbox", function () { - var classname = _.first(_.filter(this.classList, function (s) { return s != "Ldt-EnrichedPlan-Control-Checkbox"; })); + var classname = _.first(_.filter(this.classList, function (s) { + return s != "Ldt-EnrichedPlan-Control-Checkbox"; + })); if (classname !== undefined) { - if ($(this).is(':checked')) { + if (IriSP.jQuery(this).is(':checked')) { content.find(".Ldt-EnrichedPlan-Slide ." + classname).removeClass("filtered_out"); } else { content.find(".Ldt-EnrichedPlan-Slide ." + classname).addClass("filtered_out"); - } + } } }); container.find(".Ldt-EnrichedPlan-Search-Input").on("search", function () { - var q = $(this).val().toLocaleLowerCase(); + var q = IriSP.jQuery(this).val().toLocaleLowerCase(); if (q === "") { // Show all content.find(".Ldt-EnrichedPlan-Note").removeClass("non_matching"); } else { - $(".Ldt-EnrichedPlan-Note").each( function () { - var node = $(this); + content.find(".Ldt-EnrichedPlan-Note").each(function () { + var node = IriSP.jQuery(this); if (node.text().toLocaleLowerCase().indexOf(q) > -1) { node.removeClass("non_matching"); } else { From 9548116b2019590a20c28d693f66797e9ec104df Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 9 Oct 2015 18:29:54 +0200 Subject: [PATCH 004/204] Add BarSlider component --- src/widgets/BarSlider.css | 120 ++++++++++++++++++++++++++++++++++++++ src/widgets/BarSlider.js | 72 +++++++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100644 src/widgets/BarSlider.css create mode 100644 src/widgets/BarSlider.js diff --git a/src/widgets/BarSlider.css b/src/widgets/BarSlider.css new file mode 100644 index 00000000..52f7e445 --- /dev/null +++ b/src/widgets/BarSlider.css @@ -0,0 +1,120 @@ +/* */ +/* Slider Widget */ + +.Ldt-BarSlider { + width: 100%; + height: 36px; + padding: 0; + margin: 0; + background-color: black; + background-image: none; + border: none; + border-bottom: 1px dashed #666; + position: relative; + border-radius: 0; +} + +.Ldt-BarSlider .ui-slider-handle { + border-radius: 8px; + top: -2px; + background: #fc00ff; + border: 1px solid #ffffff; + width: 0px; + height: 0px; + border-style: solid; + border-color: transparent transparent transparent #ffffff; + border-width: 3px 0 3px 5px; +} + +.Ldt-BarSlider .ui-slider-range { + background-color: #fff !important; + position: absolute !important; + top: 14px; + left: 4px; + height: 8px; + width: 0px; +} + +.Ldt-BarSlider-Time { + position: absolute; + bottom: 32px; + background: #fff; + color: #000000; + border-radius: 0px; + z-index: 8; + font-size: 10px; + width: 34px; + border: 1px solid #999999; + padding: 1px; + margin-left: -20px; + display: none; + text-align: center; + font-weight: bold; + pointer-events: none; +} + +.videoslider { + background-color: black; + height: 36px; + width: 100%; + border-bottom: 1px dashed #666; + position: relative; +} +.Ldt-BarSlider-sliderbar { + background-color: #999; + position: absolute; + top: 12px; + left: 4px; + right: 4px; + bottom: 11px; +} +.Ldt-BarSlider-currentbar { + background-color: #fff; + position: absolute; + top: 14px; + left: 4px; + width: 0px; + height: 8px; +} +.Ldt-BarSlider .rightarrow { + width: 0px; + height: 0px; + border-style: solid; + border-color: transparent transparent transparent #ffffff; + border-width: 3px 0 3px 5px; +} +.Ldt-BarSlider .leftarrow { + width: 0px; + height: 0px; + border-style: solid; + border-color: transparent transparent transparent #ffffff; + border-width: 3px 5px 3px 0; +} +.Ldt-BarSlider-currentbarhead { + position: absolute; + top: 15px; + left: 0px; +} +.Ldt-BarSlider-barmark { + width: 1px; + position: absolute; + top: 4px; + bottom: 4px; + background-color: #ccc; +} + +.barmark:nth-of-type(4) { + left: 20px; +} +.barmark:nth-of-type(5) { + left: 50px; +} +.barmark:nth-of-type(6) { + left: 90px; +} +.barmark:nth-of-type(7) { + left: 140px; +} +.barmark:nth-of-type(8) { + left: 200px; +} diff --git a/src/widgets/BarSlider.js b/src/widgets/BarSlider.js new file mode 100644 index 00000000..5966e8ae --- /dev/null +++ b/src/widgets/BarSlider.js @@ -0,0 +1,72 @@ +/* + The BarSlider Widget fits right under the video + */ + +IriSP.Widgets.BarSlider = function (player, config) { + IriSP.Widgets.Widget.call(this, player, config); +}; + +IriSP.Widgets.BarSlider.prototype = new IriSP.Widgets.Widget(); + +IriSP.Widgets.BarSlider.prototype.defaults = { + annotation_types: "Slides" +}; + +IriSP.Widgets.BarSlider.prototype.template = + '
' + + '
' + + '
' + + '
' +// + '
' + + '
00:00
' + + '
'; + +IriSP.Widgets.BarSlider.prototype.draw = function () { + var _this = this; + + this.renderTemplate(); + this.$time = this.$.find(".Ldt-BarSlider-Time"); + this.$slider = this.$.find(".Ldt-BarSlider"); + this.$currentbar = this.$.find(".Ldt-BarSlider-currentbar"); + this.$currentbarhead = this.$.find(".Ldt-BarSlider-currentbarhead"); + + this.$slider.slider({ + range: "min", + value: 0, + min: 0, + max: this.source.getDuration().milliseconds, + slide: function (event, ui) { + _this.media.setCurrentTime(ui.value); + _this.player.trigger("Mediafragment.setHashToTime"); + } + }); + + this.$handle = this.$slider.find('.ui-slider-handle'); + + this.onMediaEvent("timeupdate", "onTimeupdate"); + this.onMdpEvent("Player.MouseOut", "onMouseout"); + + this.$slider + .mouseover(function () { + _this.$time.show(); + }) + .mouseout(this.functionWrapper("onMouseout")) + .mousemove(function (_e) { + var _x = _e.pageX - _this.$.offset().left, + _t = new IriSP.Model.Time(_this.media.duration * _x / _this.width); + _this.$time.text(_t.toString()).css("left", _x); + }); +}; + +IriSP.Widgets.BarSlider.prototype.onTimeupdate = function (_time) { + var _this = this, + pos = _this.width * _time / _this.media.duration; + this.$slider.slider("value", _time); + // Update bar position + this.$currentbar.css("width", pos); + this.$currentbarhead.css("left", pos + 4); +}; + +IriSP.Widgets.BarSlider.prototype.onMouseout = function () { + this.$time.hide(); +}; From 21c59476330ffe4620bfe71b1d986af48484db32 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 12 Oct 2015 11:25:22 +0200 Subject: [PATCH 005/204] Whitespace/semicolons fixes --- src/widgets/AnnotationsList.js | 523 ++++++++++++++++----------------- 1 file changed, 259 insertions(+), 264 deletions(-) diff --git a/src/widgets/AnnotationsList.js b/src/widgets/AnnotationsList.js index 16c6efd7..2d0f7c0b 100644 --- a/src/widgets/AnnotationsList.js +++ b/src/widgets/AnnotationsList.js @@ -1,8 +1,8 @@ -IriSP.Widgets.AnnotationsList = function(player, config) { +IriSP.Widgets.AnnotationsList = function (player, config) { IriSP.Widgets.Widget.call(this, player, config); this.lastIds = []; var _this = this; - this.throttledRefresh = IriSP._.throttle(function(full) { + this.throttledRefresh = IriSP._.throttle(function (full) { _this.refresh(full); }, 800); this.searchString = false; @@ -13,7 +13,7 @@ IriSP.Widgets.AnnotationsList = function(player, config) { IriSP.Widgets.AnnotationsList.prototype = new IriSP.Widgets.Widget(); IriSP.Widgets.AnnotationsList.prototype.defaults = { - pre_draw_callback: function(){ + pre_draw_callback: function () { return this.importUsers(); }, /* @@ -83,7 +83,7 @@ IriSP.Widgets.AnnotationsList.prototype.defaults = { api_delete_method: "DELETE", api_users_endpoint: "", api_users_method: "GET", - make_name_string_function: function(params){ + make_name_string_function: function (params) { return params.username ? params.username : "Anonymous"; }, filter_by_segments: false, @@ -101,50 +101,50 @@ IriSP.Widgets.AnnotationsList.prototype.defaults = { polemics : [{ keyword: "++", background_color: "#c9ecc6" - },{ + }, { keyword: "--", background_color: "#f9c5c6" - },{ + }, { keyword: "??", background_color: "#cec5f9" - },{ + }, { keyword: "==", background_color: "#f9f4c6" }] }; -IriSP.Widgets.AnnotationsList.prototype.importUsers = function(){ - if (!this.source.users_data && this.api_users_endpoint){ +IriSP.Widgets.AnnotationsList.prototype.importUsers = function () { + if (!this.source.users_data && this.api_users_endpoint) { this.usernames = Array(); var _this = this, _list = this.getWidgetAnnotations(), usernames_list_string = ""; - _list.forEach(function(_annotation){ - if(_this.usernames.indexOf(_annotation.creator) == -1){ + _list.forEach(function (_annotation) { + if (_this.usernames.indexOf(_annotation.creator) == -1) { _this.usernames.push(_annotation.creator); - } + }; + }); + this.usernames.forEach(function (_username) { + usernames_list_string += _username + ","; }); - this.usernames.forEach(function(_username){ - usernames_list_string+=_username+"," - }) usernames_list_string = usernames_list_string.substring(0, usernames_list_string.length - 1); - _url = Mustache.to_html(this.api_users_endpoint, {usernames_list_string: encodeURIComponent(usernames_list_string), usernames_list_length: this.usernames.length}); + var _url = Mustache.to_html(this.api_users_endpoint, {usernames_list_string: encodeURIComponent(usernames_list_string), usernames_list_length: this.usernames.length}); return IriSP.jQuery.ajax({ async: false, url: _url, type: "GET", - success: function(_data) { - _this.source.users_data = _data.objects + success: function (_data) { + _this.source.users_data = _data.objects; }, - error: function(_xhr, _error, _thrown) { - console.log(_xhr) - console.log(_error) - console.log(_thrown) + error: function (_xhr, _error, _thrown) { + console.log(_xhr); + console.log(_error); + console.log(_thrown); } - }) + }); } -} +}; IriSP.Widgets.AnnotationsList.prototype.messages = { en: { @@ -219,23 +219,23 @@ IriSP.Widgets.AnnotationsList.prototype.template = + '{{#show_audio}}
{{/show_audio}}' + '
    ' + '
' - + '' + + '' + '{{#allow_annotations_deletion}}' + '
' - + '' + + '' + '
    ' + '{{l10n.annotation_deletion_delete}} {{l10n.confirm}} {{l10n.cancel}}' + '
    ' + '
    ' - + '' + + '' + '{{l10n.annotation_deletion_sending}}' + '
    ' + '
    ' - + '' + + '' + '{{l10n.annotation_deletion_success}}' + '
    ' + '
    ' - + '' + + '' + '{{l10n.annotation_deletion_error}}' + '
    ' + '{{/allow_annotations_deletion}}' @@ -283,7 +283,7 @@ IriSP.Widgets.AnnotationsList.prototype.annotationTemplate = // obj.url = this.project_url + "/" + media + "/" + annotations[i].meta.project // + "/" + annotations[i].meta["id-ref"] + '#id=' + annotations[i].id; -IriSP.Widgets.AnnotationsList.prototype.ajaxSource = function() { +IriSP.Widgets.AnnotationsList.prototype.ajaxSource = function () { var _currentTime = this.media.getCurrentTime(), _duration = this.media.duration; this.lastAjaxQuery = _currentTime; @@ -297,12 +297,12 @@ IriSP.Widgets.AnnotationsList.prototype.ajaxSource = function() { }, this.metadata)); }; -IriSP.Widgets.AnnotationsList.prototype.showScreen = function(_screenName) { +IriSP.Widgets.AnnotationsList.prototype.showScreen = function (_screenName) { this.$.find('.Ldt-AnnotationsList-Screen' + _screenName).show() .siblings().hide(); -} +}; -IriSP.Widgets.AnnotationsList.prototype.ajaxMashup = function() { +IriSP.Widgets.AnnotationsList.prototype.ajaxMashup = function () { var _currentTime = this.media.getCurrentTime(); var _currentAnnotation = this.source.currentMedia.getAnnotationAtTime(_currentTime); if (typeof _currentAnnotation !== "undefined" && _currentAnnotation.id !== this.lastMashupAnnotation) { @@ -337,7 +337,7 @@ IriSP.Widgets.AnnotationsList.prototype.importAnnotations = function () { width: '80%', minHeight: '400', height: 400, - buttons: [ { text: "Close", click: function() { $( this ).dialog( "close" ); } }, + buttons: [ { text: "Close", click: function () { $(this).dialog("close"); } }, // { text: "Load", click: function () { // // TODO // // http://www.html5rocks.com/en/tutorials/file/dndfiles/?redirect_from_locale=fr @@ -351,7 +351,7 @@ IriSP.Widgets.AnnotationsList.prototype.importAnnotations = function () { // Dummy parsing for the moment var data = textarea[0].value .split(time_regexp) - .filter( function (s) { return ! s.match(/^\s*$/)}); + .filter(function (s) { return !s.match(/^\s*$/); }); var begin = null, end = null, content = null, @@ -389,9 +389,9 @@ IriSP.Widgets.AnnotationsList.prototype.importAnnotations = function () { } } ] }); -} +}; -IriSP.Widgets.AnnotationsList.prototype.refresh = function(_forceRedraw) { +IriSP.Widgets.AnnotationsList.prototype.refresh = function (_forceRedraw) { _forceRedraw = (typeof _forceRedraw !== "undefined" && _forceRedraw); if (this.currentSource.status !== IriSP.Model._SOURCE_STATUS_READY) { return 0; @@ -404,112 +404,110 @@ IriSP.Widgets.AnnotationsList.prototype.refresh = function(_forceRedraw) { if (typeof _currentAnnotation !== "undefined") { _currentTime = _currentTime - _currentAnnotation.begin + _currentAnnotation.annotation.begin; var _mediaId = _currentAnnotation.getMedia().id; - _list = _list.filter(function(_annotation) { + _list = _list.filter(function (_annotation) { return _annotation.getMedia().id === _mediaId; }); } } - _list = _list.filter(function(_annotation) { + _list = _list.filter(function (_annotation) { return _annotation.found !== false; }); - - if ((this.filter_by_segments)&&(!(this.show_filters && this.segment_filter && this.ignoresegmentcheckbox_$[0].checked))) { + + if ((this.filter_by_segments) && (!(this.show_filters && this.segment_filter && this.ignoresegmentcheckbox_$[0].checked))) { + var _currentSegments, + _segmentsAnnotation; /* - * A given annotation is considered "in" segment if the middle of it is between the segment beginning and the segment end. + * A given annotation is considered "in" segment if the middle of it is between the segment beginning and the segment end. * Note this is meant to be used for "markings" annotations (not segments) */ - _segmentsAnnotation = this.currentSource.getAnnotationsByTypeTitle(this.segments_annotation_type) - if (this.media.getTimeRange()){ - _currentSegments = _segmentsAnnotation.filter(function(_segment){ - return (_this.media.getTimeRange()[0] == _segment.begin && _this.media.getTimeRange()[1] == _segment.end) + _segmentsAnnotation = this.currentSource.getAnnotationsByTypeTitle(this.segments_annotation_type); + if (this.media.getTimeRange()) { + _currentSegments = _segmentsAnnotation.filter(function (_segment) { + return (_this.media.getTimeRange()[0] == _segment.begin && _this.media.getTimeRange()[1] == _segment.end); }); - } - else { - _currentSegments = _segmentsAnnotation.filter(function(_segment){ - return (_currentTime >= _segment.begin && _currentTime <= _segment.end) + } else { + _currentSegments = _segmentsAnnotation.filter(function (_segment) { + return (_currentTime >= _segment.begin && _currentTime <= _segment.end); }); } if (_currentSegments.length == 0) { - _list = _list.filter(function(_annotation){ + _list = _list.filter(function (_annotation) { return false; }); - } - else { - _list = _list.filter(function(_annotation){ - _annotation_time = (_annotation.begin+_annotation.end)/2; - return (_currentSegments[0].begin <= _annotation_time && _currentSegments[0].end >= _annotation_time) + } else { + _list = _list.filter(function (_annotation) { + var _annotation_time = (_annotation.begin + _annotation.end) / 2; + return (_currentSegments[0].begin <= _annotation_time && _currentSegments[0].end >= _annotation_time); }); } - if(this.annotations_count_header && this.annotations_count != _list.length){ + if (this.annotations_count_header && this.annotations_count != _list.length) { this.annotations_count = _list.length; this.refreshHeader(); } } - if (this.show_only_annotation_from_user){ - _list = _list.filter(function(_annotation){ - return _annotation.creator == _this.show_only_annotation_from_user; + if (this.show_only_annotation_from_user) { + _list = _list.filter(function (_annotation) { + return _annotation.creator == _this.show_only_annotation_from_user; }); } if (this.limit_count) { /* Get the n annotations closest to current timecode */ - _list = _list.sortBy(function(_annotation) { + _list = _list.sortBy(function (_annotation) { return Math.abs((_annotation.begin + _annotation.end) / 2 - _currentTime); }).slice(0, this.limit_count); } - + if (this.newest_first) { - _list = _list.sortBy(function(_annotation) { + _list = _list.sortBy(function (_annotation) { return -_annotation.created.valueOf(); }); } else { - _list = _list.sortBy(function(_annotation) { + _list = _list.sortBy(function (_annotation) { return _annotation.begin; }); } - - if (this.show_filters){ - if (this.user_filter){ - _username = this.userselect_$[0].options[this.userselect_$[0].selectedIndex].value; - if (_username != "false") - { - _list = _list.filter(function(_annotation){ - return _annotation.creator == _username - }) + + if (this.show_filters) { + if (this.user_filter) { + var _username = this.userselect_$[0].options[this.userselect_$[0].selectedIndex].value; + if (_username != "false") { + _list = _list.filter(function (_annotation) { + return _annotation.creator == _username; + }); } } - if (this.keyword_filter){ - _keyword = this.keywordinput_$[0].value; - if (_keyword != ""){ - _list = _list.filter(function(_annotation){ - return _annotation.description.toLowerCase().match(_keyword.toLowerCase()); + if (this.keyword_filter) { + var _keyword = this.keywordinput_$[0].value; + if (_keyword != "") { + _list = _list.filter(function (_annotation) { + return _annotation.description.toLowerCase().match(_keyword.toLowerCase()); }); } } - if (this.date_filter){ - if(this.datefilterinput_$[0].value != ""){ - _date = this.datefilterinput_$.datepicker("getDate"); - _list = _list.filter(function(_annotation){ - return ((_annotation.created.getDate() == _date.getDate())&&(_annotation.created.getMonth() == _date.getMonth())&&(_annotation.created.getFullYear() == _date.getFullYear())); + if (this.date_filter) { + if (this.datefilterinput_$[0].value != "") { + var _date = this.datefilterinput_$.datepicker("getDate"); + _list = _list.filter(function (_annotation) { + return ((_annotation.created.getDate() == _date.getDate()) && (_annotation.created.getMonth() == _date.getMonth()) && (_annotation.created.getFullYear() == _date.getFullYear())); }); } } - if (this.latest_contributions_filter && this.latestcontributionscheckbox_$[0].checked){ - _list = _list.sortBy(function(_annotation) { + if (this.latest_contributions_filter && this.latestcontributionscheckbox_$[0].checked) { + _list = _list.sortBy(function (_annotation) { return -_annotation.created.valueOf(); }); - this.usernames.forEach(function(_user){ - - latest_ann = _list.filter(function(_annotation){ + this.usernames.forEach(function (_user) { + var latest_ann = _list.filter(function (_annotation) { return _annotation.creator == _user; })[0]; - _list = _list.filter(function(_annotation){ + _list = _list.filter(function (_annotation) { return _annotation.id == (latest_ann ? latest_ann.id : false) || _annotation.creator != _user; }); }); } - + } - + var _ids = _list.idIndex; if (_forceRedraw || !IriSP._.isEqual(_ids, this.lastIds) || this.searchString !== this.lastSearch) { @@ -517,12 +515,12 @@ IriSP.Widgets.AnnotationsList.prototype.refresh = function(_forceRedraw) { this.lastSearch = this.searchString; this.lastIds = _ids; this.list_$.html(""); - _list.forEach(function(_annotation) { + _list.forEach(function (_annotation) { var _url = ( - ( typeof _annotation.url !== "undefined" && _annotation.url) + (typeof _annotation.url !== "undefined" && _annotation.url) ? _annotation.url : ( - ( typeof _this.source.projectId !== "undefined" && typeof _annotation.project !== "undefined" && _annotation.project && _this.source.projectId !== _annotation.project ) + (typeof _this.source.projectId !== "undefined" && typeof _annotation.project !== "undefined" && _annotation.project && _this.source.projectId !== _annotation.project) ? Mustache.to_html( _this.foreign_url, { @@ -532,50 +530,49 @@ IriSP.Widgets.AnnotationsList.prototype.refresh = function(_forceRedraw) { annotationType : _annotation.annotationType.id } ) - : document.location.href.replace(/#.*$/,'') + '#id=' + _annotation.id + '&t=' + (_annotation.begin / 1000.0) + : document.location.href.replace(/#.*$/, '') + '#id=' + _annotation.id + '&t=' + (_annotation.begin / 1000.0) ) ); var _title = "", _description = _annotation.description, _thumbnail = (typeof _annotation.thumbnail !== "undefined" && _annotation.thumbnail ? _annotation.thumbnail : _this.default_thumbnail); - if (_this.show_creator){ + if (_this.show_creator) { if (_annotation.creator) { var _users = [], _user = {}, _creator = ""; if (_this.source.users_data) { - _users = _this.source.users_data.filter(function(_user_data){ + _users = _this.source.users_data.filter(function (_user_data) { return _user_data.username == _annotation.creator; }); } - if (_users.length == 0){ - _user.username = _annotation.creator - } - else{ - _user = _users[0] + if (_users.length == 0) { + _user.username = _annotation.creator; + } else { + _user = _users[0]; } - _creator = _this.make_name_string_function(_user); + _creator = _this.make_name_string_function (_user); } } - if (_this.show_title && _annotation.title){ - var _title = _annotation.title; + if (_this.show_title && _annotation.title) { + _title = _annotation.title; } var _bgcolor; - IriSP._(_this.polemics).each(function(_polemic) { + IriSP._(_this.polemics).each(function (_polemic) { var _rgxp = IriSP.Model.regexpFromTextOrArray(_polemic.keyword, true); if (_rgxp.test(_title + " " + _description)) { _bgcolor = _polemic.background_color; } }); var _created = false; + var _tags; if (_this.show_creation_date) { - _created = _annotation.created.toLocaleDateString()+", "+_annotation.created.toLocaleTimeString(); + _created = _annotation.created.toLocaleDateString() + ", " + _annotation.created.toLocaleTimeString(); } - if(this.tags == true){ - var _tags = _annotation.getTagTexts(); - } - else { - var _tags = false; + if (this.tags == true) { + _tags = _annotation.getTagTexts(); + } else { + _tags = false; } var _data = { id : _annotation.id, @@ -620,10 +617,10 @@ IriSP.Widgets.AnnotationsList.prototype.refresh = function(_forceRedraw) { width: 1, height: 1, events: { - onPause: function() { + onPause: function () { _this.$.find(".Ldt-AnnotationsList-Play[data-annotation-id=" + _annotation.id + "]").text(_this.l10n.voice_annotation); }, - onPlay: function() { + onPlay: function () { _this.$.find(".Ldt-AnnotationsList-Play[data-annotation-id=" + _annotation.id + "]").text(_this.l10n.now_playing); } } @@ -632,31 +629,31 @@ IriSP.Widgets.AnnotationsList.prototype.refresh = function(_forceRedraw) { } var _html = Mustache.to_html(_this.annotationTemplate, _data), _el = IriSP.jQuery(_html), - _onselect = function() { + _onselect = function () { _this.$.find('.Ldt-AnnotationsList-li').removeClass("selected"); _el.addClass("selected"); }, - _onunselect = function() { + _onunselect = function () { _this.$.find('.Ldt-AnnotationsList-li').removeClass("selected"); }; - _el.mouseover(function() { + _el.mouseover(function () { _annotation.trigger("select"); }) - .mouseout(function() { + .mouseout(function () { _annotation.trigger("unselect"); }) - .click(function() { + .click(function () { _annotation.trigger("click"); }) .appendTo(_this.list_$); IriSP.attachDndData(_el.find("[draggable]"), { - title: _title, - description: _description, - uri: _url, + title: _title, + description: _description, + uri: _url, image: _annotation.thumbnail, text: '[' + _annotation.begin.toString() + '] ' + _title }); - _el.on("remove", function() { + _el.on("remove", function () { _annotation.off("select", _onselect); _annotation.off("unselect", _onunselect); }); @@ -665,9 +662,9 @@ IriSP.Widgets.AnnotationsList.prototype.refresh = function(_forceRedraw) { }); /* Correct the empty tag bug */ - this.$.find('.Ldt-AnnotationsList-Tag-Li').each(function() { + this.$.find('.Ldt-AnnotationsList-Tag-Li').each(function () { var _el = IriSP.jQuery(this); - if (!_el.text().replace(/(^\s+|\s+$)/g,'')) { + if (!_el.text().replace(/(^\s+|\s+$)/g, '')) { _el.remove(); } }); @@ -686,9 +683,9 @@ IriSP.Widgets.AnnotationsList.prototype.refresh = function(_forceRedraw) { // propagate mouse clicks. If _this is a then we // have to specify the ancestor before which we can // insert the input widget. - if (insertion_point === undefined) + if (insertion_point === undefined) { insertion_point = _this; - + } // Insert input element var input_element = $(_this.dataset.editable_type === 'multiline' ? "' + + ''; + +IriSP.Widgets.CocoCreateAnnotation.prototype.draw = function () { + var _this = this; + var timecodeField, + textField; + + this.previousInput = ""; + this.renderTemplate(); + + timecodeField = this.$.find(".Ldt-CocoCreateAnnotation-Timecode"); + textField = this.$.find(".Ldt-CocoCreateAnnotation-Text"); + + this.begin = new IriSP.Model.Time(); + textField.on("change keyup input paste", this.functionWrapper("onTextChange")); + this.$.find("form").submit(this.functionWrapper("onSubmit")); +}; + +IriSP.Widgets.CocoCreateAnnotation.prototype.setBegin = function (t) { + this.begin = new IriSP.Model.Time(t || 0); + this.$.find(".Ldt-CocoCreateAnnotation-Timecode").val(this.begin.toString()); +}; + +IriSP.Widgets.CocoCreateAnnotation.prototype.pauseOnWrite = function () { + if (this.pause_on_write && !this.media.getPaused()) { + this.media.pause(); + } +}; + +IriSP.Widgets.CocoCreateAnnotation.prototype.onTextChange = function (e) { + if (e !== undefined && e.keyCode == 13 && !e.shiftKey) { + // Return: submit. Use shift-Return to insert a LF + this.onSubmit(); + return true; + } + var _field = this.$.find(".Ldt-CocoCreateAnnotation-Text"), + _timecodeField = this.$.find(".Ldt-CocoCreateAnnotation-Timecode"), + _contents = _field.val(); + _field.css("border-color", !!_contents ? "#666666" : "#ff0000"); + if (!!_contents) { + if (!this.previousInput) { + // Inputing text from an empty field, initialize timecode + this.setBegin(this.media.getCurrentTime()); + } + _field.removeClass("empty"); + _timecodeField.addClass("Ldt-CocoCreateAnnotation-Timecode-Active"); + } else { + _field.addClass("empty"); + _timecodeField.removeClass("Ldt-CocoCreateAnnotation-Timecode-Active"); + } + this.pauseOnWrite(); + this.previousInput = _contents; + return !!_contents; +}; + +IriSP.Widgets.CocoCreateAnnotation.prototype.onSubmit = function () { + var _this = this, + _exportedAnnotations = new IriSP.Model.List(this.player.sourceManager), /* We create a List to send to the server that will contains the annotation */ + _export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[this.api_serializer]}), /* We create a source object using a specific serializer for export */ + _annotation = new IriSP.Model.Annotation(false, _export), /* We create an annotation in the source with a generated ID (param. false) */ + _annotationTypes = this.source.getAnnotationTypes().searchByTitle(this.annotation_type, true), /* We get the AnnotationType in which the annotation will be added */ + _annotationType = (_annotationTypes.length ? _annotationTypes[0] : new IriSP.Model.AnnotationType(false, _export)), /* If it doesn't already exists, we create it */ + _url = Mustache.to_html(this.api_endpoint_template, {id: this.source.projectId}); /* We make the url to send the request to, must include project id */ + + /* If we created an AnnotationType on the spot ... */ + if (!_annotationTypes.length) { + /* ... We must not send its id to the server ... */ + _annotationType.dont_send_id = true; + /* ... And we must include its title. */ + _annotationType.title = this.annotation_type; + } + + /* + * Will fill the generated annotation object's data + * WARNING: If we're on a MASHUP, these datas must refer the ORIGINAL MEDIA + * */ + _annotation.setMedia(this.source.currentMedia.id); /* Annotated media ID */ + + _annotation.setBeginEnd(this.begin, this.begin); + _annotation.setAnnotationType(_annotationType.id); /* Annotation type ID */ + + _annotation.created = new Date(); /* Annotation creation date */ + _annotation.description = this.$.find(".Ldt-CocoCreateAnnotation-Text").val().trim(); + _annotation.title = ""; + + if (this.project_id != "") { + /* Project id, only if it's been specifiec in the config */ + _annotation.project_id = this.project_id; + } + + _annotation.creator = this.creator_name; + _exportedAnnotations.push(_annotation); /* Ajout de l'annotation à la liste à exporter */ + + if (_url !== "") { + _exportedAnnotations.push(_annotation); /* We add the annotation in the list to export */ + _export.addList("annotation", _exportedAnnotations); /* We add the list to the source object */ + /* We send the AJAX request to the server ! */ + IriSP.jQuery.ajax({ + url: _url, + type: this.api_method, + contentType: 'application/json', + data: _export.serialize(), /* Source is serialized */ + success: function (_data) { + _this.showScreen('Saved'); + if (_this.after_send_timeout) { + window.setTimeout( + function () { + _this.close_after_send + ? _this.player.trigger("CocoCreateAnnotation.hide") + : _this.player.trigger("CocoCreateAnnotation.show"); + }, + _this.after_send_timeout + ); + } + _export.getAnnotations().removeElement(_annotation, true); /* We delete the sent annotation to avoid redundancy */ + _export.deSerialize(_data); /* Data deserialization */ + _this.source.merge(_export); /* We merge the deserialized data with the current source data */ + if (_this.pause_on_write && _this.media.getPaused()) { + _this.media.play(); + } + _this.player.trigger("AnnotationsList.refresh"); + }, + 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'); + }; + return false; +}; From c9ec475b91aa02171cdce646802fc78653552142 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 2 Nov 2015 16:15:28 +0100 Subject: [PATCH 066/204] Append video element to container rather than replacing all content --- src/js/html-player.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/html-player.js b/src/js/html-player.js index fca04d82..0b270717 100644 --- a/src/js/html-player.js +++ b/src/js/html-player.js @@ -42,7 +42,7 @@ IriSP.htmlPlayer = function (media, jqselector, options) { }); videoEl.append(_trackNode); } - jqselector.html(videoEl); + jqselector.append(videoEl); var mediaEl = videoEl[0]; From 3c4e35fefefe8c5701c9f50447da118bf772e451 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 2 Nov 2015 16:36:52 +0100 Subject: [PATCH 067/204] Allow to specify PIP position --- src/widgets/SlideVideoPlayer.css | 52 ++++++++++++++++++++++++++------ src/widgets/SlideVideoPlayer.js | 17 +++++++++-- 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index 19fe2b48..d6913309 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -26,13 +26,26 @@ .Ldt-SlideVideoPlayer-pip-main .Ldt-ImageDisplay-Container { min-height: 30vw; } +/* pip-pip is -br (bottom right) by default */ .Ldt-SlideVideoPlayer-pip-pip { position: absolute; width: 30% !important; height: 30%; + z-index: 3; + bottom: 2px; right: 2px; +} +.Ldt-SlideVideoPlayer-pip-bl { + left: 2px; bottom: 2px; - z-index: 3; +} +.Ldt-SlideVideoPlayer-pip-tr { + top: 2px; + right: 2px; +} +.Ldt-SlideVideoPlayer-pip-tl { + top: 2px; + left: 2px; } .Ldt-SlideVideoPlayer h2 { @@ -40,20 +53,41 @@ } .Ldt-SlideVideoPlayer-pip-menu { position: absolute; - bottom: 2px; - right: 2px; + bottom: 0; + top: 0; + right: 0; + left: 0; z-index: 10; display: none; } -.Ldt-SlideVideoPlayer:hover .Ldt-SlideVideoPlayer-pip-menu { - background-color: #000; - opacity: .5; - display: inline-block; -} - .Ldt-SlideVideoPlayer-pip-menu-toggle { + position: absolute; width: 18px; height: 18px; cursor: pointer; + z-index: 10; background-image: url(img/pip_toggle.svg); + display: none; +} +.Ldt-SlideVideoPlayer-pip-pip:hover .Ldt-SlideVideoPlayer-pip-menu-toggle { + background-color: #000; + opacity: .5; + display: inline-block; +} + +.Ldt-SlideVideoPlayer-pip-menu-toggle-br { + bottom: 2px; + right: 2px; +} +.Ldt-SlideVideoPlayer-pip-menu-toggle-tr { + top: 2px; + right: 2px; +} +.Ldt-SlideVideoPlayer-pip-menu-toggle-tl { + top: 2px; + left: 2px; +} +.Ldt-SlideVideoPlayer-pip-menu-toggle-bl { + bottom: 2px; + left: 2px; } diff --git a/src/widgets/SlideVideoPlayer.js b/src/widgets/SlideVideoPlayer.js index f8753a89..af4f2798 100644 --- a/src/widgets/SlideVideoPlayer.js +++ b/src/widgets/SlideVideoPlayer.js @@ -43,9 +43,14 @@ IriSP.Widgets.SlideVideoPlayer.prototype.draw = function() { ); if (_this.mode == 'pip') { - _this.$.find(".Ldt-SlideVideoPlayer").append('
    '); + _this.$.find(".Ldt-SlideVideoPlayer-panel").each(function () { + IriSP.jQuery(this).append('
    '); + }); + _this.$.find(".Ldt-SlideVideoPlayer-pip-menu-toggle").each(function() { + IriSP.jQuery(this).addClass("Ldt-SlideVideoPlayer-pip-menu-toggle-" + this.dataset.position); + }); _this.$.on("click", ".Ldt-SlideVideoPlayer-pip-menu-toggle", function () { - _this.toggleMainDisplay(); + _this.setPipPosition(this.dataset.position); }); window.setTimeout(function () { _this.setMainDisplay('video'); @@ -83,4 +88,10 @@ IriSP.Widgets.SlideVideoPlayer.prototype.setMainDisplay = function(video_or_slid }; main.removeClass('Ldt-SlideVideoPlayer-pip-pip').addClass('Ldt-SlideVideoPlayer-pip-main'); pip.removeClass('Ldt-SlideVideoPlayer-pip-main').addClass('Ldt-SlideVideoPlayer-pip-pip'); -} +}; + +IriSP.Widgets.SlideVideoPlayer.prototype.setPipPosition = function(position) { + var pip = this.$.find(".Ldt-SlideVideoPlayer-pip-pip"); + pip.removeClass('Ldt-SlideVideoPlayer-pip-tl Ldt-SlideVideoPlayer-pip-tr Ldt-SlideVideoPlayer-pip-bl Ldt-SlideVideoPlayer-pip-br') + .addClass('Ldt-SlideVideoPlayer-pip-' + position); +}; From e8f71f4dfc86a0c762bafcbf96e13731f51fc00e Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 2 Nov 2015 16:38:59 +0100 Subject: [PATCH 068/204] .Ldt-SlideVideoPlayer-pip-menu is not used anymore --- src/widgets/SlideVideoPlayer.css | 9 --------- src/widgets/SlideVideoPlayer.js | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index d6913309..81eebc4e 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -51,15 +51,6 @@ .Ldt-SlideVideoPlayer h2 { display: none; } -.Ldt-SlideVideoPlayer-pip-menu { - position: absolute; - bottom: 0; - top: 0; - right: 0; - left: 0; - z-index: 10; - display: none; -} .Ldt-SlideVideoPlayer-pip-menu-toggle { position: absolute; width: 18px; diff --git a/src/widgets/SlideVideoPlayer.js b/src/widgets/SlideVideoPlayer.js index af4f2798..afe8c31c 100644 --- a/src/widgets/SlideVideoPlayer.js +++ b/src/widgets/SlideVideoPlayer.js @@ -44,7 +44,7 @@ IriSP.Widgets.SlideVideoPlayer.prototype.draw = function() { if (_this.mode == 'pip') { _this.$.find(".Ldt-SlideVideoPlayer-panel").each(function () { - IriSP.jQuery(this).append('
    '); + IriSP.jQuery(this).append('
    '); }); _this.$.find(".Ldt-SlideVideoPlayer-pip-menu-toggle").each(function() { IriSP.jQuery(this).addClass("Ldt-SlideVideoPlayer-pip-menu-toggle-" + this.dataset.position); From 37f2ed4869a001d79fc1cd5000d38ce9eb750c6e Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 2 Nov 2015 16:44:15 +0100 Subject: [PATCH 069/204] Allow to toggle main display --- src/widgets/SlideVideoPlayer.css | 6 ++++++ src/widgets/SlideVideoPlayer.js | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index 81eebc4e..6132b1b1 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -82,3 +82,9 @@ bottom: 2px; left: 2px; } +.Ldt-SlideVideoPlayer-pip-menu-toggle-main { + top: 50%; + top: calc(50% - 9px); + left: 50%; + left: calc(50% - 9px); +} diff --git a/src/widgets/SlideVideoPlayer.js b/src/widgets/SlideVideoPlayer.js index afe8c31c..818ddbfc 100644 --- a/src/widgets/SlideVideoPlayer.js +++ b/src/widgets/SlideVideoPlayer.js @@ -44,7 +44,7 @@ IriSP.Widgets.SlideVideoPlayer.prototype.draw = function() { if (_this.mode == 'pip') { _this.$.find(".Ldt-SlideVideoPlayer-panel").each(function () { - IriSP.jQuery(this).append('
    '); + IriSP.jQuery(this).append('
    '); }); _this.$.find(".Ldt-SlideVideoPlayer-pip-menu-toggle").each(function() { IriSP.jQuery(this).addClass("Ldt-SlideVideoPlayer-pip-menu-toggle-" + this.dataset.position); @@ -91,6 +91,10 @@ IriSP.Widgets.SlideVideoPlayer.prototype.setMainDisplay = function(video_or_slid }; IriSP.Widgets.SlideVideoPlayer.prototype.setPipPosition = function(position) { + if (position == 'main') { + this.toggleMainDisplay(); + return; + }; var pip = this.$.find(".Ldt-SlideVideoPlayer-pip-pip"); pip.removeClass('Ldt-SlideVideoPlayer-pip-tl Ldt-SlideVideoPlayer-pip-tr Ldt-SlideVideoPlayer-pip-bl Ldt-SlideVideoPlayer-pip-br') .addClass('Ldt-SlideVideoPlayer-pip-' + position); From 4896a5c04d55d20f2e0cda3917dbc6978425e133 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 2 Nov 2015 16:51:58 +0100 Subject: [PATCH 070/204] Make pip toggle buttons 32x32 --- src/widgets/SlideVideoPlayer.css | 4 ++-- src/widgets/img/pip_toggle.svg | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index 6132b1b1..41cd0031 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -53,8 +53,8 @@ } .Ldt-SlideVideoPlayer-pip-menu-toggle { position: absolute; - width: 18px; - height: 18px; + width: 32px; + height: 32px; cursor: pointer; z-index: 10; background-image: url(img/pip_toggle.svg); diff --git a/src/widgets/img/pip_toggle.svg b/src/widgets/img/pip_toggle.svg index baa907a1..75278974 100644 --- a/src/widgets/img/pip_toggle.svg +++ b/src/widgets/img/pip_toggle.svg @@ -8,9 +8,9 @@ xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="5.0797176mm" - height="5.0799999mm" - viewBox="0 0 17.998999 18" + width="32px" + height="32px" + viewBox="0 0 18 18" id="svg19931" version="1.1" inkscape:version="0.91 r13725" From 96ac63de35cfeb18e745452822a2925cf18bd6fc Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 2 Nov 2015 17:04:02 +0100 Subject: [PATCH 071/204] l10nize EnrichedPlan --- src/widgets/EnrichedPlan.js | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 320dafec..7faddc0f 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -7,11 +7,21 @@ IriSP.Widgets.EnrichedPlan.prototype = new IriSP.Widgets.Widget(); IriSP.Widgets.EnrichedPlan.prototype.messages = { en: { delete_annotation: "Delete note", - confirm_delete_message: "You are about to delete {{ annotation.title }}. Are you sure you want to delete it?" + confirm_delete_message: "You are about to delete {{ annotation.title }}. Are you sure you want to delete it?", + teacher_notes: "Teacher notes", + other_notes: "Other Notes", + own_notes: "Pers. notes", + slides: "Slides", + search: "Search..." }, fr: { delete_annotation: "Supprimer la note", - confirm_delete_message: "Vous allez supprimer {{ annotation.title }}. Êtes-vous certain(e) ?" + confirm_delete_message: "Vous allez supprimer {{ annotation.title }}. Êtes-vous certain(e) ?", + teacher_notes: "Notes Enseignant", + other_notes: "Notes Autres", + own_notes: "Notes perso.", + slides: "Diapo", + search: "Recherchez..." } }; @@ -32,15 +42,15 @@ IriSP.Widgets.EnrichedPlan.prototype.template = + '
    ' + '{{#show_controls}}' + ' ' - + ' ' + + ' ' + ' ' - + ' ' - + ' ' - + ' ' + + ' ' + + ' ' + + ' ' + ' ' - + ' ' + + ' ' + '{{/show_controls}}' - + ' ' + + ' ' + '
    ' + '
    ' + '
    '; From f63a09340c79148a40703ac68324dd42ca3a47a2 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 2 Nov 2015 17:06:03 +0100 Subject: [PATCH 072/204] l10nize CocoCreateAnnotation. --- src/widgets/CocoCreateAnnotation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/CocoCreateAnnotation.js b/src/widgets/CocoCreateAnnotation.js index 71319ecd..24b4b501 100644 --- a/src/widgets/CocoCreateAnnotation.js +++ b/src/widgets/CocoCreateAnnotation.js @@ -20,7 +20,7 @@ IriSP.Widgets.CocoCreateAnnotation.prototype.messages = { IriSP.Widgets.CocoCreateAnnotation.prototype.template = '
    ' + ' ' + - ' ' + + ' ' + '
    '; IriSP.Widgets.CocoCreateAnnotation.prototype.draw = function () { From 1d1c11d49d2d4643dd3162beea12a81120546988 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 9 Nov 2015 14:51:28 +0100 Subject: [PATCH 073/204] Use absolute for filtered out elements so as to avoid line break between timecode and content --- src/widgets/EnrichedPlan.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 9516e281..989d1af5 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -11,6 +11,7 @@ .Ldt-EnrichedPlan-SlideItem.filtered_out { max-height: 0; + position: absolute; overflow: hidden; } From f9fd7290db15b1fb61ce61f15278b9c42ec11b0d Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 9 Nov 2015 15:56:31 +0100 Subject: [PATCH 074/204] Display timecode left of input --- src/widgets/CocoCreateAnnotation.css | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/widgets/CocoCreateAnnotation.css b/src/widgets/CocoCreateAnnotation.css index 832bbc12..67593338 100644 --- a/src/widgets/CocoCreateAnnotation.css +++ b/src/widgets/CocoCreateAnnotation.css @@ -5,27 +5,19 @@ position: relative; } .Ldt-CocoCreateAnnotation-Text { - width: 100%; + width: calc(100% - 32px); + position: relative; + left: 36px; } .Ldt-CocoCreateAnnotation-Timecode { position: absolute; - border-radius: 2px; + font-size: 12px; color: #999; width: 4em; border: none; background-color: #fff; background-color: rgba(255, 255, 255, 1); - max-height: 0; - top: 0; - -webkit-transition: all 1s ease; - -moz-transition: all 1s ease; - -ms-transition: all 1s ease; - -o-transition: all 1s ease; - transition: all 1s ease; } .Ldt-CocoCreateAnnotation-Timecode-Active { display: inline-block; - max-height: 1.1em; - top: -1.1em; - border: 1px solid #77e; } From 05d4f267e6bbec6ebaec8c8c3ebfd76efe1aac08 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 9 Nov 2015 15:59:57 +0100 Subject: [PATCH 075/204] Modify timecode font size --- src/widgets/CocoCreateAnnotation.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/widgets/CocoCreateAnnotation.css b/src/widgets/CocoCreateAnnotation.css index 67593338..7a158941 100644 --- a/src/widgets/CocoCreateAnnotation.css +++ b/src/widgets/CocoCreateAnnotation.css @@ -11,7 +11,7 @@ } .Ldt-CocoCreateAnnotation-Timecode { position: absolute; - font-size: 12px; + font-size: 9px; color: #999; width: 4em; border: none; @@ -20,4 +20,6 @@ } .Ldt-CocoCreateAnnotation-Timecode-Active { display: inline-block; + font-weight: bold; + font-size: 12px; } From 679f60f20c9d66382a8b400a6bd0ad11f51c307f Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 9 Nov 2015 16:00:06 +0100 Subject: [PATCH 076/204] Update timecode if there is no input --- src/widgets/CocoCreateAnnotation.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/widgets/CocoCreateAnnotation.js b/src/widgets/CocoCreateAnnotation.js index 24b4b501..4e7854cc 100644 --- a/src/widgets/CocoCreateAnnotation.js +++ b/src/widgets/CocoCreateAnnotation.js @@ -37,6 +37,13 @@ IriSP.Widgets.CocoCreateAnnotation.prototype.draw = function () { this.begin = new IriSP.Model.Time(); textField.on("change keyup input paste", this.functionWrapper("onTextChange")); this.$.find("form").submit(this.functionWrapper("onSubmit")); + + this.onMediaEvent("timeupdate", function (_time) { + // Update timecode if description is empty + if (textField.val().trim() == "") { + _this.setBegin(_time); + }; + }); }; IriSP.Widgets.CocoCreateAnnotation.prototype.setBegin = function (t) { From d2f6c48c367938e1ca610477d59400ebd5d3f366 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 9 Nov 2015 16:24:19 +0100 Subject: [PATCH 077/204] Use same font size for active timecode --- src/widgets/CocoCreateAnnotation.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/widgets/CocoCreateAnnotation.css b/src/widgets/CocoCreateAnnotation.css index 7a158941..a2fa4f53 100644 --- a/src/widgets/CocoCreateAnnotation.css +++ b/src/widgets/CocoCreateAnnotation.css @@ -21,5 +21,4 @@ .Ldt-CocoCreateAnnotation-Timecode-Active { display: inline-block; font-weight: bold; - font-size: 12px; } From d88b4dbf37dfd71d41412a72e6339e55b5515e07 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 9 Nov 2015 16:28:59 +0100 Subject: [PATCH 078/204] Display note timecodes if thumbnail is hidden --- src/widgets/EnrichedPlan.css | 20 +++++++++++++++++++- src/widgets/EnrichedPlan.js | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 989d1af5..7da1f8c6 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -15,7 +15,8 @@ overflow: hidden; } -.Ldt-EnrichedPlan-SlideTimecode { +.Ldt-EnrichedPlan-SlideTimecode, +.Ldt-EnrichedPlan-NoteTimecode { display: inline-block; width: 24px; color: #999 !important; @@ -23,6 +24,18 @@ vertical-align: top; } +.Ldt-EnrichedPlan-SlideNotes { + position: relative; +} + +.Ldt-EnrichedPlan-NoteTimecode { + left: -35px; + position: absolute; + font-family: Roboto !important; + padding-top: 8px; + display: none; +} + .Ldt-EnrichedPlan-SlideThumbnail { display: inline-block; width: 180px; @@ -47,6 +60,11 @@ .Ldt-EnrichedPlan-SlideThumbnail.filtered_out + .Ldt-EnrichedPlan-SlideContent { width: calc(100% - 40px); + margin-left: 8px; +} + +.Ldt-EnrichedPlan-SlideThumbnail.filtered_out + .Ldt-EnrichedPlan-SlideContent .Ldt-EnrichedPlan-NoteTimecode { + display: inline-block; } .Ldt-EnrichedPlan-SlideTitle { diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 7faddc0f..056e314d 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -65,7 +65,7 @@ IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = + ' ' + ''; -IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    {{{ text }}} {{ author }} {{#can_edit}}{{/can_edit}}
    '; +IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    {{ begin }}
    {{{ text }}} {{ author }} {{#can_edit}}{{/can_edit}}
    '; IriSP.Widgets.EnrichedPlan.prototype.draw = function () { var _this = this; From bbd555852ccf902696ccef69065b6957f0a23312 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 10 Nov 2015 16:01:03 +0100 Subject: [PATCH 079/204] Convert EnrichedPlan control menu to dropdown menu --- src/widgets/EnrichedPlan.css | 49 ++++++++++++++++++++++++++++++----- src/widgets/EnrichedPlan.js | 38 +++++++++++++++++++-------- src/widgets/img/hamburger.svg | 4 +++ 3 files changed, 74 insertions(+), 17 deletions(-) create mode 100644 src/widgets/img/hamburger.svg diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 7da1f8c6..e6dcb710 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -138,8 +138,6 @@ height: 36px; padding: 9px 0 6px 0; border-bottom: 1px solid #000; - overflow-y: hidden; - overflow-x: hidden; position: absolute; top: 0; left: 0; @@ -159,14 +157,53 @@ position: relative; } .Ldt-EnrichedPlan-Controls .Ldt-EnrichedPlan-Search-Input { - float: right; font-family: Roboto; font-size: 16px; - width: calc(100% - 340px); + width: 95%; + width: calc(100% - 32px); outline: none; } -.Ldt-EnrichedPlan-Controls .Ldt-EnrichedPlan-Search-Input-Full { - width: 95%; + +.Ldt-EnrichedPlan-ControlMenu { + margin: 0; + padding: 0; + display: inline-block; + position: absolute; + width: 24px; + height: 24px; + right: 4px; + background-color: #fff; +} + +.Ldt-EnrichedPlan-Toggle { + display: flex; + background-image: url(img/hamburger.svg); + background-size: cover; + width: 24px; + height: 24px; +} + +.Ldt-EnrichedPlan-ControlMenuHome + ul { + position: absolute; + display: none; +} +.Ldt-EnrichedPlan-ControlMenuHome:checked + ul { + display: flex; + flex-direction: column; + margin-top: -13px; +} +.Ldt-EnrichedPlan-ControlMenu ul { + float: right; + padding: 0; + margin: 0; + list-style: none; + position: relative; + background-color: #fff; +} + +.Ldt-EnrichedPlan-ControlMenu ul li { + margin: 4px 10px; + display: inline-block; } .Ldt-EnrichedPlan-Note.non_matching { diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 056e314d..c7c98b86 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -39,20 +39,36 @@ IriSP.Widgets.EnrichedPlan.prototype.defaults = { IriSP.Widgets.EnrichedPlan.prototype.template = '
    ' + + '
    ' + '
    ' + + '' + '{{#show_controls}}' - + ' ' - + ' ' - + ' ' - + ' ' - + ' ' - + ' ' - + ' ' - + ' ' + + '
    ' + + ' ' + + ' ' + + '
      ' + + '
    • ' + + ' ' + + ' ' + + '
    • ' + + '
    • ' + + ' ' + + ' ' + + '
    • ' + + '
    • ' + + ' ' + + ' ' + + '
    • ' + + '
    • ' + + ' ' + + ' ' + + '
    • ' + + '
    ' + + '' + + '' + + '
    ' + '{{/show_controls}}' - + ' ' - + '
    ' - + '
    ' + + '' + '
    '; IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = diff --git a/src/widgets/img/hamburger.svg b/src/widgets/img/hamburger.svg new file mode 100644 index 00000000..0960513c --- /dev/null +++ b/src/widgets/img/hamburger.svg @@ -0,0 +1,4 @@ + + + + From 4eca6c138f378f3ee096afd7cf77066c7ecc184d Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 10 Nov 2015 16:13:27 +0100 Subject: [PATCH 080/204] Hide input field --- src/widgets/EnrichedPlan.css | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index e6dcb710..da88f061 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -183,6 +183,11 @@ height: 24px; } +.Ldt-EnrichedPlan-ControlMenuHome { + position: absolute; + left: -9999px; +} + .Ldt-EnrichedPlan-ControlMenuHome + ul { position: absolute; display: none; @@ -190,7 +195,6 @@ .Ldt-EnrichedPlan-ControlMenuHome:checked + ul { display: flex; flex-direction: column; - margin-top: -13px; } .Ldt-EnrichedPlan-ControlMenu ul { float: right; From aa50aa92a6635db0dc888dafe00d15dc3dce6d4a Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 10 Nov 2015 16:57:49 +0100 Subject: [PATCH 081/204] Modify edit icon size --- src/widgets/EnrichedPlan.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index da88f061..abbaec2a 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -236,7 +236,7 @@ .Ldt-EnrichedPlan-Control-Checkbox:checked + label:before { content: ''; position: absolute; - left:0; + left: 0; top: 2px; width: 13px; height: 13px; @@ -293,8 +293,9 @@ label:hover:before { display: inline-block; width: 24px; height: 24px; - margin: 7px; + margin: 3px; background-position: center; + background-size: cover; background-repeat: no-repeat; } From 7ae824a72f6ea09b88004194ad6bae05c6e6a2fb Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 10 Nov 2015 17:16:10 +0100 Subject: [PATCH 082/204] Use svg file for checkboxes Relying on standard fonts is too random --- src/widgets/EnrichedPlan.css | 9 +++++++-- src/widgets/img/checked.svg | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 src/widgets/img/checked.svg diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index abbaec2a..c43403f2 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -245,12 +245,17 @@ /* checked mark aspect */ .Ldt-EnrichedPlan-Control-Checkbox:not(:checked) + label:after, .Ldt-EnrichedPlan-Control-Checkbox:checked + label:after { - content: '\2a2f'; + content: ''; + width: 11px; + height: 11px; + background-image: url(img/checked.svg); + background-size: cover; + background-position: center; font-size: 20px; font-style: normal; position: absolute; top: 3px; - left: -1px; + left: 1px; transition: all .2s; } /* checked mark aspect changes */ diff --git a/src/widgets/img/checked.svg b/src/widgets/img/checked.svg new file mode 100644 index 00000000..2e22cfef --- /dev/null +++ b/src/widgets/img/checked.svg @@ -0,0 +1,4 @@ + + + + From 451496771b16896b03e72d2b24de360917a1e67b Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 20 Nov 2015 14:53:27 +0100 Subject: [PATCH 083/204] Remove whitespace --- src/widgets/AdaptivePlayer.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/widgets/AdaptivePlayer.js b/src/widgets/AdaptivePlayer.js index 98b0bb4d..0e89ff83 100644 --- a/src/widgets/AdaptivePlayer.js +++ b/src/widgets/AdaptivePlayer.js @@ -11,17 +11,17 @@ IriSP.Widgets.AdaptivePlayer.prototype.defaults = { }; IriSP.Widgets.AdaptivePlayer.prototype.draw = function() { - + if (typeof this.video === "undefined") { this.video = this.media.video; } - + var _props = [ "autostart", "video", "height", "width", "url_transform" ], _opts = {}, _canPlayType = document.createElement('video').canPlayType(this.mime_type); - + _opts.type = (_canPlayType !== "no") ? this.normal_player : this.fallback_player; - + for (var i = 0; i < _props.length; i++) { if (typeof this[_props[i]] !== "undefined") { _opts[_props[i]] = this[_props[i]]; @@ -29,5 +29,4 @@ IriSP.Widgets.AdaptivePlayer.prototype.draw = function() { } this.insertSubwidget(this.$, _opts); - -}; \ No newline at end of file +}; From 49e5456dbe2745833d0d1199a4fb78dc783cba3b Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 26 Nov 2015 15:42:47 +0100 Subject: [PATCH 084/204] Define BaseElement.getTitleOrDescription --- src/js/model.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/js/model.js b/src/js/model.js index 4f6bf7f6..2af7018e 100644 --- a/src/js/model.js +++ b/src/js/model.js @@ -542,6 +542,16 @@ IriSP.Model = (function (ns) { }); }; + /** + * Return a short surrogate for the element: + * either its title or the first line of its description + */ + BaseElement.prototype.getTitleOrDescription = function () { + var t = this.title || this.description || ""; + t = t.split(/\n/)[0]; + return t; + }; + BaseElement.prototype.on = function(_event, _callback) { if (typeof this.__events[_event] === "undefined") { this.__events[_event] = []; From 0cb1a54089a8ef2ee8dd140a5ee38c6dec2a6988 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 26 Nov 2015 15:42:57 +0100 Subject: [PATCH 085/204] Use .getTitleOrDescription for notes --- src/widgets/EnrichedPlan.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index c7c98b86..728db8fb 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -138,7 +138,7 @@ IriSP.Widgets.EnrichedPlan.prototype.draw = function () { _slides.forEach(function (slide) { var _html = Mustache.to_html(_this.slideTemplate, { id : slide.id, - atitle : IriSP.textFieldHtml(slide.title), + atitle : IriSP.textFieldHtml(slide.getTitleOrDescription()), level: (slide.content !== undefined && slide.content.data !== undefined) ? (slide.content.data.level || 1) : 1, begin : slide.begin.toString(), begintc: slide.begin.milliseconds, @@ -147,12 +147,12 @@ IriSP.Widgets.EnrichedPlan.prototype.draw = function () { notes: slide.annotations.map(function (a) { return Mustache.to_html(_this.annotationTemplate, { id: a.id, - text: IriSP.textFieldHtml(a.description || a.title), + text: IriSP.textFieldHtml(a.getTitleOrDescription()), url: document.location.href.replace(/#.*$/, '') + '#id=' + a.id + '&t=' + (a.begin / 1000.0), author: a.creator, begin: a.begin.toString(), begintc: a.begin.milliseconds, - atitle: a.title.slice(0, 20), + atitle: a.getTitleOrDescription().slice(0, 20), can_edit: a.meta['coco:can_edit'], category: "Ldt-EnrichedPlan-Note-" + note_category(a), filtered: ((note_category(a) == 'Own' && !_this.show_own_notes) From d6269827ba83f2b1ab2109c5bac499bfabc6cdc7 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 26 Nov 2015 15:43:25 +0100 Subject: [PATCH 086/204] Specify method for posting annotation --- src/widgets/CocoCreateAnnotation.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/widgets/CocoCreateAnnotation.js b/src/widgets/CocoCreateAnnotation.js index 4e7854cc..571dcd12 100644 --- a/src/widgets/CocoCreateAnnotation.js +++ b/src/widgets/CocoCreateAnnotation.js @@ -18,7 +18,7 @@ IriSP.Widgets.CocoCreateAnnotation.prototype.messages = { }; IriSP.Widgets.CocoCreateAnnotation.prototype.template = - '
    ' + + '' + ' ' + ' ' + '
    '; @@ -83,6 +83,13 @@ IriSP.Widgets.CocoCreateAnnotation.prototype.onTextChange = function (e) { return !!_contents; }; +/** + * Display a feedback + */ +IriSP.Widgets.CocoCreateAnnotation.prototype.showScreen = function (screen) { + // FIXME: use notify? +}; + IriSP.Widgets.CocoCreateAnnotation.prototype.onSubmit = function () { var _this = this, _exportedAnnotations = new IriSP.Model.List(this.player.sourceManager), /* We create a List to send to the server that will contains the annotation */ @@ -160,7 +167,7 @@ IriSP.Widgets.CocoCreateAnnotation.prototype.onSubmit = function () { (_this.after_send_timeout || 5000)); } }); - this.showScreen('Wait'); + _this.showScreen('Wait'); }; return false; }; From 49ce48e6b732254ef9f023e542ff42cb4b3467b7 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 26 Nov 2015 15:47:41 +0100 Subject: [PATCH 087/204] Allow to publish a remote annotation --- src/widgets/AnnotationsList.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/widgets/AnnotationsList.js b/src/widgets/AnnotationsList.js index 658d24ce..b9ea9d73 100644 --- a/src/widgets/AnnotationsList.js +++ b/src/widgets/AnnotationsList.js @@ -822,6 +822,10 @@ IriSP.Widgets.AnnotationsList.prototype.refresh = function (_forceRedraw) { }); this.$.find('.Ldt-AnnotationsList-PublishAnnotation').click(function (e) { var _annotation = get_local_annotation(this.dataset.editable_id); + if (_annotation === undefined) { + // It may be a remote annotation + _annotation = widget.source.getElement(this.dataset.editable_id); + } // Publish annotation to the server if (!confirm(Mustache.to_html(widget.l10n.confirm_publish_message, { annotation: _annotation }))) { return; From 97d1b0af3527d9b226cb354f49e190485d639204 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 26 Nov 2015 15:58:17 +0100 Subject: [PATCH 088/204] Move config menu to the left of input field --- src/widgets/EnrichedPlan.css | 8 +++----- src/widgets/EnrichedPlan.js | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index c43403f2..8b7e059d 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -144,6 +144,7 @@ right: 0; z-index: 1; background-color: #fff; + display: flex; } .Ldt-EnrichedPlan-Control-Label { @@ -159,16 +160,13 @@ .Ldt-EnrichedPlan-Controls .Ldt-EnrichedPlan-Search-Input { font-family: Roboto; font-size: 16px; - width: 95%; - width: calc(100% - 32px); + flex: 1; outline: none; } .Ldt-EnrichedPlan-ControlMenu { margin: 0; padding: 0; - display: inline-block; - position: absolute; width: 24px; height: 24px; right: 4px; @@ -195,9 +193,9 @@ .Ldt-EnrichedPlan-ControlMenuHome:checked + ul { display: flex; flex-direction: column; + width: 100px; } .Ldt-EnrichedPlan-ControlMenu ul { - float: right; padding: 0; margin: 0; list-style: none; diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 728db8fb..b44843fd 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -41,7 +41,6 @@ IriSP.Widgets.EnrichedPlan.prototype.template = '
    ' + '
    ' + '
    ' - + '' + '{{#show_controls}}' + '
    ' + ' ' @@ -68,6 +67,7 @@ IriSP.Widgets.EnrichedPlan.prototype.template = + '' + '
    ' + '{{/show_controls}}' + + '' + '
    ' + '
    '; From f8cfddabef21bdae3508ec29aa6065bc677aaf04 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 26 Nov 2015 16:20:17 +0100 Subject: [PATCH 089/204] Enlarge edit control icon space --- src/widgets/EnrichedPlan.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 8b7e059d..d64add75 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -296,7 +296,7 @@ label:hover:before { display: inline-block; width: 24px; height: 24px; - margin: 3px; + margin: 5px; background-position: center; background-size: cover; background-repeat: no-repeat; From 36211207265e712cf3ff8044a54715c43aaba678 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 27 Nov 2015 10:57:58 +0100 Subject: [PATCH 090/204] Append video player as first child Due to initialization delays, the .append function may be called after other elements (Controller) are appended. We assume here that the most common way of using the HtmlPlayer is to have it either as a single child, or, if there are other components, that it should be the first one (common use cases: Controller, Slidebar, overlays...) --- src/js/html-player.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/html-player.js b/src/js/html-player.js index 0b270717..bfc14149 100644 --- a/src/js/html-player.js +++ b/src/js/html-player.js @@ -42,7 +42,7 @@ IriSP.htmlPlayer = function (media, jqselector, options) { }); videoEl.append(_trackNode); } - jqselector.append(videoEl); + jqselector.prepend(videoEl); var mediaEl = videoEl[0]; From 5568c140ad8dedc328ec2a89d87051ec3215b85d Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 27 Nov 2015 10:59:34 +0100 Subject: [PATCH 091/204] Add a shadow to the controller menu --- src/widgets/EnrichedPlan.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index d64add75..525caa6b 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -194,6 +194,7 @@ display: flex; flex-direction: column; width: 100px; + box-shadow: grey 2px 2px 2px; } .Ldt-EnrichedPlan-ControlMenu ul { padding: 0; From 66d69f2141edd9d2c2935640e54ca20f80c85e55 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 7 Dec 2015 14:52:40 +0100 Subject: [PATCH 092/204] Copy all annotation.meta data when deserializing annotation --- src/js/serializers/ldt_annotate.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/js/serializers/ldt_annotate.js b/src/js/serializers/ldt_annotate.js index 18f00546..047a68b1 100644 --- a/src/js/serializers/ldt_annotate.js +++ b/src/js/serializers/ldt_annotate.js @@ -44,6 +44,7 @@ IriSP.serializers.ldt_annotate = { _anntype.title = _anndata.type_title; _source.getAnnotationTypes().push(_anntype); } + _ann.meta = _anndata.meta; _ann.setAnnotationType(_anntype.id); var _tagIds = IriSP._(_anndata.tags).map(function(_title) { var _tags = _source.getTags(true).searchByTitle(_title, true); From 6cc1d796ee0ffe03e3ad5cdd179838bc6fd66a2d Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 7 Dec 2015 14:53:04 +0100 Subject: [PATCH 093/204] Factorize update_content method so that the component can update itself --- src/widgets/EnrichedPlan.js | 128 +++++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 46 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index b44843fd..34b9d8f9 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -1,5 +1,10 @@ IriSP.Widgets.EnrichedPlan = function (player, config) { + var _this = this; IriSP.Widgets.Widget.call(this, player, config); + this.throttledRefresh = IriSP._.throttle(function (full) { + _this.update_content(); + }, 800, {leading: false}); + }; IriSP.Widgets.EnrichedPlan.prototype = new IriSP.Widgets.Widget(); @@ -83,12 +88,70 @@ IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    {{ begin }}
    {{{ text }}} {{ author }} {{#can_edit}}{{/can_edit}}
    '; -IriSP.Widgets.EnrichedPlan.prototype.draw = function () { + +/** + * Initialize the component + */ +IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { var _this = this; // Generate a unique prefix, so that ids of input fields // (necessary for label association) are unique too. _this.prefix = IriSP.generateUuid(); - // slides content: title, level (for toc) + _this.renderTemplate(); + var container = _this.$.find('.Ldt-EnrichedPlan-Container'); + var content = _this.$.find('.Ldt-EnrichedPlan-Content'); + + container.on("click", "[data-timecode]", function () { + _this.media.setCurrentTime(Number(this.dataset.timecode)); + }); + + container.on("click", ".Ldt-EnrichedPlan-Control-Checkbox", function () { + var classname = _.first(_.filter(this.classList, function (s) { + return s != "Ldt-EnrichedPlan-Control-Checkbox"; + })); + if (classname !== undefined) { + if (IriSP.jQuery(this).is(':checked')) { + content.find(".Ldt-EnrichedPlan-Slide ." + classname).removeClass("filtered_out"); + } else { + content.find(".Ldt-EnrichedPlan-Slide ." + classname).addClass("filtered_out"); + } + } + + }); + + container.on("click", ".Ldt-EnrichedPlan-EditControl-Edit", function () { + _this.player.trigger("Annotation.edit", this.dataset.id); + }); + container.on("click", ".Ldt-EnrichedPlan-EditControl-Delete", function () { + var _annotation = _this.source.getElement(this.dataset.id); + if (confirm(Mustache.to_html(_this.l10n.confirm_delete_message, { annotation: _annotation }))) { + _this.source.getAnnotations().removeElement(_annotation); + _this.player.trigger("Annotation.delete", this.dataset.id); + } + }); + + container.find(".Ldt-EnrichedPlan-Search-Input").on("search", function () { + var q = IriSP.jQuery(this).val().toLocaleLowerCase(); + if (q === "") { + // Show all + content.find(".Ldt-EnrichedPlan-Note").removeClass("non_matching"); + } else { + content.find(".Ldt-EnrichedPlan-Note").each(function () { + var node = IriSP.jQuery(this); + if (node.text().toLocaleLowerCase().indexOf(q) > -1) { + node.removeClass("non_matching"); + } else { + node.addClass("non_matching"); + } + }); + } + }); + + return [container, content]; +}; + +IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { + var _this = this; var _slides = this.getWidgetAnnotations().sortBy(function (_annotation) { return _annotation.begin; }); @@ -118,9 +181,18 @@ IriSP.Widgets.EnrichedPlan.prototype.draw = function () { }); }); - _this.renderTemplate(); var container = _this.$.find('.Ldt-EnrichedPlan-Container'); var content = _this.$.find('.Ldt-EnrichedPlan-Content'); + if (!container.length) { + // Initialization, render the container template + var els = _this.init_component(); + container = els[0]; + content = els[1]; + } else { + // Update: empty the container + // (Should do an incremental update, TBD) + content.empty(); + } function capitalize(s) { // This function is defined in recent versions of _ @@ -164,50 +236,14 @@ IriSP.Widgets.EnrichedPlan.prototype.draw = function () { var _el = IriSP.jQuery(_html); content.append(_el); }); +}; - container.on("click", "[data-timecode]", function () { - _this.media.setCurrentTime(Number(this.dataset.timecode)); - }); - - container.on("click", ".Ldt-EnrichedPlan-Control-Checkbox", function () { - var classname = _.first(_.filter(this.classList, function (s) { - return s != "Ldt-EnrichedPlan-Control-Checkbox"; - })); - if (classname !== undefined) { - if (IriSP.jQuery(this).is(':checked')) { - content.find(".Ldt-EnrichedPlan-Slide ." + classname).removeClass("filtered_out"); - } else { - content.find(".Ldt-EnrichedPlan-Slide ." + classname).addClass("filtered_out"); - } - } - - }); - - container.on("click", ".Ldt-EnrichedPlan-EditControl-Edit", function () { - _this.player.trigger("Annotation.edit", this.dataset.id); - }); - container.on("click", ".Ldt-EnrichedPlan-EditControl-Delete", function () { - var _annotation = _this.source.getElement(this.dataset.id); - if (confirm(Mustache.to_html(_this.l10n.confirm_delete_message, { annotation: _annotation }))) { - _this.source.getAnnotations().removeElement(_annotation); - _this.player.trigger("Annotation.delete", this.dataset.id); - } - }); +IriSP.Widgets.EnrichedPlan.prototype.draw = function () { + var _this = this; + _this.init_component(); + _this.update_content(); - container.find(".Ldt-EnrichedPlan-Search-Input").on("search", function () { - var q = IriSP.jQuery(this).val().toLocaleLowerCase(); - if (q === "") { - // Show all - content.find(".Ldt-EnrichedPlan-Note").removeClass("non_matching"); - } else { - content.find(".Ldt-EnrichedPlan-Note").each(function () { - var node = IriSP.jQuery(this); - if (node.text().toLocaleLowerCase().indexOf(q) > -1) { - node.removeClass("non_matching"); - } else { - node.addClass("non_matching"); - } - }); - } + _this.onMdpEvent("AnnotationsList.refresh", function () { + _this.throttledRefresh(false); }); }; From 382b88414f2d778b9ab6a2e8f54c1f039270412a Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 7 Dec 2015 15:31:28 +0100 Subject: [PATCH 094/204] Clear input data after sending it --- src/widgets/CocoCreateAnnotation.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/widgets/CocoCreateAnnotation.js b/src/widgets/CocoCreateAnnotation.js index 571dcd12..199f5a00 100644 --- a/src/widgets/CocoCreateAnnotation.js +++ b/src/widgets/CocoCreateAnnotation.js @@ -57,6 +57,11 @@ IriSP.Widgets.CocoCreateAnnotation.prototype.pauseOnWrite = function () { } }; +IriSP.Widgets.CocoCreateAnnotation.prototype.resetInput = function (e) { + this.$.find(".Ldt-CocoCreateAnnotation-Text").val(""); + this.setBegin(this.media.getCurrentTime()); +}; + IriSP.Widgets.CocoCreateAnnotation.prototype.onTextChange = function (e) { if (e !== undefined && e.keyCode == 13 && !e.shiftKey) { // Return: submit. Use shift-Return to insert a LF @@ -138,6 +143,7 @@ IriSP.Widgets.CocoCreateAnnotation.prototype.onSubmit = function () { contentType: 'application/json', data: _export.serialize(), /* Source is serialized */ success: function (_data) { + _this.resetInput(); _this.showScreen('Saved'); if (_this.after_send_timeout) { window.setTimeout( From 5a1ee9bedf26d4e14b16ccc419a34a3fc7c08fb0 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 7 Dec 2015 15:31:51 +0100 Subject: [PATCH 095/204] Remove unused code --- src/widgets/CocoCreateAnnotation.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/widgets/CocoCreateAnnotation.js b/src/widgets/CocoCreateAnnotation.js index 199f5a00..185918fe 100644 --- a/src/widgets/CocoCreateAnnotation.js +++ b/src/widgets/CocoCreateAnnotation.js @@ -145,16 +145,6 @@ IriSP.Widgets.CocoCreateAnnotation.prototype.onSubmit = function () { success: function (_data) { _this.resetInput(); _this.showScreen('Saved'); - if (_this.after_send_timeout) { - window.setTimeout( - function () { - _this.close_after_send - ? _this.player.trigger("CocoCreateAnnotation.hide") - : _this.player.trigger("CocoCreateAnnotation.show"); - }, - _this.after_send_timeout - ); - } _export.getAnnotations().removeElement(_annotation, true); /* We delete the sent annotation to avoid redundancy */ _export.deSerialize(_data); /* Data deserialization */ _this.source.merge(_export); /* We merge the deserialized data with the current source data */ From 58e88e075e35ad15b962e17093e6e9b1e4be1db8 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 7 Dec 2015 15:44:46 +0100 Subject: [PATCH 096/204] Use a strict comparison for slide inclusion test --- src/widgets/EnrichedPlan.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 34b9d8f9..273d6db8 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -177,7 +177,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { // correctly set. _slides.forEach(function (slide) { slide.annotations = _annotations.filter(function (a) { - return a.begin >= slide.begin && a.begin <= slide.end; + return a.begin >= slide.begin && a.begin < slide.end; }); }); From 49dfc1d2efe6c416b70bb283187de151c6a1cf77 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 9 Dec 2015 11:38:50 +0100 Subject: [PATCH 097/204] Add translations --- src/widgets/EnrichedPlan.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 273d6db8..07c0bf40 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -17,7 +17,8 @@ IriSP.Widgets.EnrichedPlan.prototype.messages = { other_notes: "Other Notes", own_notes: "Pers. notes", slides: "Slides", - search: "Search..." + search: "Search...", + whole_video: "Whole video" }, fr: { delete_annotation: "Supprimer la note", @@ -26,7 +27,8 @@ IriSP.Widgets.EnrichedPlan.prototype.messages = { other_notes: "Notes Autres", own_notes: "Notes perso.", slides: "Diapo", - search: "Recherchez..." + search: "Recherchez...", + whole_video: "Vidéo entière" } }; @@ -158,12 +160,16 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { if (_slides.length == 0) { // No valid segmentation defined. Let's pretend there is a // unique global segment. + var title = _this.messages.whole_video; _slides = [ { id: "whole", - title: "Whole video", + title: title; begin: 0, end: _this.media.duration, - thumbnail: "" + thumbnail: "", + getTitleOrDescription: function () { + return title; + } } ]; }; // All other annotations From 750eea41400c7155b8b161e08a1a1a8e61d843b4 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 9 Dec 2015 11:38:59 +0100 Subject: [PATCH 098/204] Handle is_admin parameter --- src/widgets/EnrichedPlan.css | 4 ++++ src/widgets/EnrichedPlan.js | 12 +++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 525caa6b..8e66cfa5 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -310,3 +310,7 @@ label:hover:before { .Ldt-EnrichedPlan-EditControl-Delete { background: url(img/notes_delete.svg); } + +.adminactions { + display: inline-block; +} diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 07c0bf40..31bd9473 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -41,7 +41,8 @@ IriSP.Widgets.EnrichedPlan.prototype.defaults = { show_slides: true, show_teacher_notes: true, show_other_notes: true, - show_own_notes: true + show_own_notes: true, + is_admin: false }; IriSP.Widgets.EnrichedPlan.prototype.template = @@ -83,12 +84,12 @@ IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = + '
    {{ begin }}
    ' + '
    {{#thumbnail}}{{/thumbnail}}
    ' + '
    ' - + '
    {{ atitle }}
    ' + + '
    {{#is_admin}}{{/is_admin}}{{ atitle }}
    ' + '
    {{{ notes }}}
    ' + '
    ' + ''; -IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    {{ begin }}
    {{{ text }}} {{ author }} {{#can_edit}}{{/can_edit}}
    '; +IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    {{ begin }}
    {{{ text }}} {{ author }} {{#can_edit}}{{/can_edit}}{{#is_admin}}{{/is_admin}}
    '; /** @@ -222,6 +223,9 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { begintc: slide.begin.milliseconds, thumbnail: slide.thumbnail, show_slides: _this.show_slides, + is_admin: _this.is_admin, + // FIXME: find an appropriate way to pass admin_url + admin_url: '/admin/coco/annotation/' + slide.id, notes: slide.annotations.map(function (a) { return Mustache.to_html(_this.annotationTemplate, { id: a.id, @@ -232,6 +236,8 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { begintc: a.begin.milliseconds, atitle: a.getTitleOrDescription().slice(0, 20), can_edit: a.meta['coco:can_edit'], + is_admin: _this.is_admin, + admin_url: '/admin/coco/annotation/' + a.id, category: "Ldt-EnrichedPlan-Note-" + note_category(a), filtered: ((note_category(a) == 'Own' && !_this.show_own_notes) || (note_category(a) == 'Other' && !_this.show_other_notes) From a840897f82a20fece4cc43f1fdb60229cf24cec9 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 11 Dec 2015 15:37:21 +0100 Subject: [PATCH 099/204] Fix typo --- src/widgets/CocoController.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/CocoController.js b/src/widgets/CocoController.js index 92c167d4..633e8448 100644 --- a/src/widgets/CocoController.js +++ b/src/widgets/CocoController.js @@ -104,7 +104,7 @@ IriSP.Widgets.CocoController.prototype.draw = function () { this.timeDisplayUpdater(new IriSP.Model.Time(0)); }; -/* Update the elasped time div */ +/* Update the elapsed time div */ IriSP.Widgets.CocoController.prototype.timeDisplayUpdater = function (_time) { var _totalTime = this.media.duration; this.$timeElapsed.html(_time.toString()); From 2f7c2ac9b10a72be037e1b0af3fd68222fbbf341 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 14 Dec 2015 11:07:06 +0100 Subject: [PATCH 100/204] Add videoonly mode for SlideVideoPlayer --- src/widgets/SlideVideoPlayer.css | 3 +++ src/widgets/SlideVideoPlayer.js | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index 41cd0031..54526c8a 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -88,3 +88,6 @@ left: 50%; left: calc(50% - 9px); } +.Ldt-SlideVideoPlayer-hidden { + display: none; +} diff --git a/src/widgets/SlideVideoPlayer.js b/src/widgets/SlideVideoPlayer.js index 818ddbfc..33e7a080 100644 --- a/src/widgets/SlideVideoPlayer.js +++ b/src/widgets/SlideVideoPlayer.js @@ -8,7 +8,7 @@ IriSP.Widgets.SlideVideoPlayer.prototype = new IriSP.Widgets.Widget(); IriSP.Widgets.SlideVideoPlayer.prototype.defaults = { playerModule: "HtmlPlayer", - // mode is either "sidebyside" or "pip" + // mode is either "sidebyside", "pip" or "videoonly" mode: "sidebyside" }; @@ -55,6 +55,8 @@ IriSP.Widgets.SlideVideoPlayer.prototype.draw = function() { window.setTimeout(function () { _this.setMainDisplay('video'); }, 1500); + } else if (_this.mode == 'videoonly') { + this.$.find(".Ldt-SlideVideoPlayer-panel.Ldt-SlideVideoPlayer-slide").addClass("Ldt-SlideVideoPlayer-hidden"); } else { // Default : side by side // FIXME: this should be better implemented through a signal sent From c7967544b3eab9646333954e1fc9e51ef6073bb2 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 14 Dec 2015 11:08:05 +0100 Subject: [PATCH 101/204] Fix translation fetching --- src/widgets/EnrichedPlan.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 31bd9473..e3243edd 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -161,10 +161,10 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { if (_slides.length == 0) { // No valid segmentation defined. Let's pretend there is a // unique global segment. - var title = _this.messages.whole_video; + var title = _this.l10n.whole_video; _slides = [ { id: "whole", - title: title; + title: title, begin: 0, end: _this.media.duration, thumbnail: "", From f41eb823f3695b5f8c9b0bc6261b60c6754d53db Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 15 Dec 2015 16:39:12 +0100 Subject: [PATCH 102/204] Hide non appliable pip menu toggle items --- src/widgets/SlideVideoPlayer.css | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index 54526c8a..28a83aed 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -70,18 +70,30 @@ bottom: 2px; right: 2px; } +.Ldt-SlideVideoPlayer-pip-pip .Ldt-SlideVideoPlayer-pip-menu-toggle-br { + display: none !important; +} .Ldt-SlideVideoPlayer-pip-menu-toggle-tr { top: 2px; right: 2px; } +.Ldt-SlideVideoPlayer-pip-tr .Ldt-SlideVideoPlayer-pip-menu-toggle-tr { + display: none !important; +} .Ldt-SlideVideoPlayer-pip-menu-toggle-tl { top: 2px; left: 2px; } +.Ldt-SlideVideoPlayer-pip-tl .Ldt-SlideVideoPlayer-pip-menu-toggle-tl { + display: none !important; +} .Ldt-SlideVideoPlayer-pip-menu-toggle-bl { bottom: 2px; left: 2px; } +.Ldt-SlideVideoPlayer-pip-bl .Ldt-SlideVideoPlayer-pip-menu-toggle-bl { + display: none !important; +} .Ldt-SlideVideoPlayer-pip-menu-toggle-main { top: 50%; top: calc(50% - 9px); From 409e5572fc1af891d3159e75b30fd72d3e2bc259 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 15 Dec 2015 16:46:47 +0100 Subject: [PATCH 103/204] Highlight selected annotation --- src/widgets/EnrichedPlan.css | 4 ++++ src/widgets/EnrichedPlan.js | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 8e66cfa5..e3b467ee 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -314,3 +314,7 @@ label:hover:before { .adminactions { display: inline-block; } + +.Ldt-EnrichedPlan-Selected-Timecode { + border: 1px dashed #6cf; +} diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index e3243edd..76021ecf 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -106,6 +106,8 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { container.on("click", "[data-timecode]", function () { _this.media.setCurrentTime(Number(this.dataset.timecode)); + IriSP.jQuery(".Ldt-EnrichedPlan-Selected-Timecode").removeClass("Ldt-EnrichedPlan-Selected-Timecode"); + IriSP.jQuery(this).addClass("Ldt-EnrichedPlan-Selected-Timecode"); }); container.on("click", ".Ldt-EnrichedPlan-Control-Checkbox", function () { From 327e4b12bf855464858514a65256cfe7be93876e Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 15 Dec 2015 16:51:17 +0100 Subject: [PATCH 104/204] Show edit buttons only on selected annotation --- src/widgets/EnrichedPlan.css | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index e3b467ee..4f1cc724 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -311,10 +311,23 @@ label:hover:before { background: url(img/notes_delete.svg); } -.adminactions { +.Ldt-EnrichedPlan-Selected-Timecode { + border: 1px dashed #6cf; +} + +.Ldt-EnrichedPlan-EditControl { + display: none; +} + +.Ldt-EnrichedPlan-Selected-Timecode .Ldt-EnrichedPlan-EditControl { display: inline-block; } -.Ldt-EnrichedPlan-Selected-Timecode { - border: 1px dashed #6cf; +.adminactions { + display: none; } + +.Ldt-EnrichedPlan-Selected-Timecode .adminactions { + display: inline-block; +} + From 20c30ecfef2f59e2a8b8d130a86d7f29704a58ea Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 15 Dec 2015 17:08:51 +0100 Subject: [PATCH 105/204] Hide information for whole-slide mode --- src/widgets/EnrichedPlan.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 4f1cc724..80d856d8 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -92,6 +92,13 @@ font-size: 14px; } +[data-id=whole] .Ldt-EnrichedPlan-SlideTitle { + display: none; +} +[data-id=whole] .Ldt-EnrichedPlan-SlideTimecode { + color: #fff !important; +} + .Ldt-EnrichedPlan-Note { font-weight: normal; font-size: 14px; From 3140f75a1f7cae312dc3726e87f62513740465f7 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 15 Dec 2015 17:10:48 +0100 Subject: [PATCH 106/204] Define flat_mode It enforces a single virtual slide, which is hidden --- src/widgets/EnrichedPlan.css | 10 ++++++++-- src/widgets/EnrichedPlan.js | 34 ++++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 80d856d8..b02bc7ff 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -58,15 +58,21 @@ transition: width .4s; } -.Ldt-EnrichedPlan-SlideThumbnail.filtered_out + .Ldt-EnrichedPlan-SlideContent { +.Ldt-EnrichedPlan-SlideThumbnail.filtered_out + .Ldt-EnrichedPlan-SlideContent, +.Ldt-EnrichedPlan-FlatMode .Ldt-EnrichedPlan-SlideContent { width: calc(100% - 40px); margin-left: 8px; } -.Ldt-EnrichedPlan-SlideThumbnail.filtered_out + .Ldt-EnrichedPlan-SlideContent .Ldt-EnrichedPlan-NoteTimecode { +.Ldt-EnrichedPlan-SlideThumbnail.filtered_out + .Ldt-EnrichedPlan-SlideContent .Ldt-EnrichedPlan-NoteTimecode, +.Ldt-EnrichedPlan-FlatMode .Ldt-EnrichedPlan-SlideContent .Ldt-EnrichedPlan-NoteTimecode { display: inline-block; } +.Ldt-EnrichedPlan-FlatMode .Ldt-EnrichedPlan-SlideThumbnail { + display: none; +} + .Ldt-EnrichedPlan-SlideTitle { display: inline-block; font-size: 14px; diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 76021ecf..4c08e166 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -42,11 +42,12 @@ IriSP.Widgets.EnrichedPlan.prototype.defaults = { show_teacher_notes: true, show_other_notes: true, show_own_notes: true, - is_admin: false + is_admin: false, + flat_mode: false }; IriSP.Widgets.EnrichedPlan.prototype.template = - '
    ' + '
    ' + '
    ' + '
    ' + '{{#show_controls}}' @@ -66,10 +67,12 @@ IriSP.Widgets.EnrichedPlan.prototype.template = + ' ' + ' ' + ' ' + + '{{^flat_mode}}' + '
  • ' + ' ' + ' ' + '
  • ' + + '{{/flat_mode}}' + ' ' + '' + '' @@ -97,6 +100,11 @@ IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    Date: Wed, 16 Dec 2015 11:13:31 +0100 Subject: [PATCH 107/204] Use explicit Ldt-SlideVideoPlayer-pip-br class --- src/widgets/SlideVideoPlayer.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index 28a83aed..864b1016 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -32,6 +32,9 @@ width: 30% !important; height: 30%; z-index: 3; +} + +.Ldt-SlideVideoPlayer-pip-br { bottom: 2px; right: 2px; } @@ -70,7 +73,7 @@ bottom: 2px; right: 2px; } -.Ldt-SlideVideoPlayer-pip-pip .Ldt-SlideVideoPlayer-pip-menu-toggle-br { +.Ldt-SlideVideoPlayer-pip-br .Ldt-SlideVideoPlayer-pip-menu-toggle-br { display: none !important; } .Ldt-SlideVideoPlayer-pip-menu-toggle-tr { From ed3d765b301581137af0be6cc77ce57d418d9a8f Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 16 Dec 2015 15:42:43 +0100 Subject: [PATCH 108/204] Implement group filtering --- src/widgets/EnrichedPlan.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 4c08e166..ad2faff7 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -43,7 +43,8 @@ IriSP.Widgets.EnrichedPlan.prototype.defaults = { show_other_notes: true, show_own_notes: true, is_admin: false, - flat_mode: false + flat_mode: false, + group: undefined }; IriSP.Widgets.EnrichedPlan.prototype.template = @@ -196,6 +197,11 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { return _annotation.begin; }); + if (_this.group) { + _annotations = _annotations.filter(function (a) { + return a.meta['coco:group'] == _this.group; + }); + } // Reference annotations in each slide: assume that slide end time is // correctly set. _slides.forEach(function (slide) { From 51ea1dfd1c6ef0cc556b2c9b0330b54472c21c32 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 16 Dec 2015 15:45:39 +0100 Subject: [PATCH 109/204] Specify initial position for pip --- src/widgets/SlideVideoPlayer.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/widgets/SlideVideoPlayer.js b/src/widgets/SlideVideoPlayer.js index 33e7a080..fdecd693 100644 --- a/src/widgets/SlideVideoPlayer.js +++ b/src/widgets/SlideVideoPlayer.js @@ -53,7 +53,7 @@ IriSP.Widgets.SlideVideoPlayer.prototype.draw = function() { _this.setPipPosition(this.dataset.position); }); window.setTimeout(function () { - _this.setMainDisplay('video'); + _this.setMainDisplay('video', true); }, 1500); } else if (_this.mode == 'videoonly') { this.$.find(".Ldt-SlideVideoPlayer-panel.Ldt-SlideVideoPlayer-slide").addClass("Ldt-SlideVideoPlayer-hidden"); @@ -80,7 +80,7 @@ IriSP.Widgets.SlideVideoPlayer.prototype.toggleMainDisplay = function() { // Set main display (in case of a "switch" display mode) // main is either 'video' or 'slides' -IriSP.Widgets.SlideVideoPlayer.prototype.setMainDisplay = function(video_or_slides) { +IriSP.Widgets.SlideVideoPlayer.prototype.setMainDisplay = function(video_or_slides, initial_display) { var main = this.$.find(".Ldt-SlideVideoPlayer-panel.Ldt-SlideVideoPlayer-video"); var pip = this.$.find(".Ldt-SlideVideoPlayer-panel.Ldt-SlideVideoPlayer-slide"); if (video_or_slides == 'slides') { @@ -90,6 +90,10 @@ IriSP.Widgets.SlideVideoPlayer.prototype.setMainDisplay = function(video_or_slid }; main.removeClass('Ldt-SlideVideoPlayer-pip-pip').addClass('Ldt-SlideVideoPlayer-pip-main'); pip.removeClass('Ldt-SlideVideoPlayer-pip-main').addClass('Ldt-SlideVideoPlayer-pip-pip'); + if (initial_display) { + // Specify initial position + pip.addClass('Ldt-SlideVideoPlayer-pip-br'); + } }; IriSP.Widgets.SlideVideoPlayer.prototype.setPipPosition = function(position) { From 59dbaead941e83dba1231455c56afe5e41659b4a Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 16 Dec 2015 15:58:01 +0100 Subject: [PATCH 110/204] Add left margin to search box --- src/widgets/EnrichedPlan.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index b02bc7ff..a3c39c99 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -175,6 +175,7 @@ font-size: 16px; flex: 1; outline: none; + margin-left: 12px; } .Ldt-EnrichedPlan-ControlMenu { From bf6e4e15cd20a2894b3340cf03204c570ea48a4d Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 17 Dec 2015 16:47:07 +0100 Subject: [PATCH 111/204] Add data-level information --- src/widgets/EnrichedPlan.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index ad2faff7..d72ff625 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -88,7 +88,7 @@ IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = + '
    {{ begin }}
    ' + '
    {{#thumbnail}}{{/thumbnail}}
    ' + '
    ' - + '
    {{#is_admin}}{{/is_admin}}{{ atitle }}
    ' + + '
    {{#is_admin}}{{/is_admin}}{{ atitle }}
    ' + '
    {{{ notes }}}
    ' + '
    ' + '
    '; From 5277f8dbee4db2d7b4b27ad35bb347bcf0569be5 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 18 Dec 2015 10:34:19 +0100 Subject: [PATCH 112/204] Do not specify SlideTitle height --- src/widgets/EnrichedPlan.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index a3c39c99..70d6f4aa 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -77,7 +77,6 @@ display: inline-block; font-size: 14px; width: 100%; - height: 1em; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; From ec70133d50f865016563f17f333ef98cfb184850 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 18 Dec 2015 15:01:56 +0100 Subject: [PATCH 113/204] Implement slide level update controls --- src/widgets/EnrichedPlan.js | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index d72ff625..9ac56745 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -88,7 +88,7 @@ IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = + '
    {{ begin }}
    ' + '
    {{#thumbnail}}{{/thumbnail}}
    ' + '
    ' - + '
    {{#is_admin}}{{/is_admin}}{{ atitle }}
    ' + + '
    {{#is_admin}}{{/is_admin}}{{ atitle }}
    ' + '
    {{{ notes }}}
    ' + '
    ' + '
    '; @@ -143,6 +143,32 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { } }); + function update_level(el, inc) { + var an = _this.source.getElement(el.dataset.id); + console.log("Update ", an.title, " to ", an.content.data.level + inc); + an.content.data.level += inc; + IriSP.jQuery.ajax({ + url: "/annotation/" + el.dataset.id + "/level/", + timeout: 2000, + type: "POST", + contentType: 'application/json', + data: JSON.stringify({'level': an.content.data.level}), + dataType: 'json', + error: function(XMLHttpRequest, textStatus, errorThrown) { + alert("An error has occurred making the request: " + errorThrown); + }, + success: function(data) { + _this.player.trigger("AnnotationsList.refresh"); + } + }); + }; + + container.on("click", ".level_incr", function () { + update_level(this, +1); + }).on("click", ".level_decr", function () { + update_level(this, -1); + }); + container.find(".Ldt-EnrichedPlan-Search-Input").on("search", function () { var q = IriSP.jQuery(this).val().toLocaleLowerCase(); if (q === "") { From 324466ed6b7215338fbeaa42e8bfcf59b4ebe7e9 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 18 Dec 2015 16:21:20 +0100 Subject: [PATCH 114/204] Use action_url method to get URLs --- src/widgets/EnrichedPlan.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 9ac56745..fd627d50 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -44,7 +44,10 @@ IriSP.Widgets.EnrichedPlan.prototype.defaults = { show_own_notes: true, is_admin: false, flat_mode: false, - group: undefined + group: undefined, + // action_url should be a function (action, elementid) that returns a URL + // Possible actions: admin, edit, level + action_url: function (action, elementid) { return ""; } }; IriSP.Widgets.EnrichedPlan.prototype.template = @@ -148,7 +151,7 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { console.log("Update ", an.title, " to ", an.content.data.level + inc); an.content.data.level += inc; IriSP.jQuery.ajax({ - url: "/annotation/" + el.dataset.id + "/level/", + url: _this.action_url("level", el.dataset.id), timeout: 2000, type: "POST", contentType: 'application/json', @@ -272,8 +275,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { thumbnail: slide.thumbnail, show_slides: _this.show_slides, is_admin: _this.is_admin, - // FIXME: find an appropriate way to pass admin_url - admin_url: '/admin/coco/annotation/' + slide.id, + admin_url: _this.action_url('admin', slide.id), notes: slide.annotations.map(function (a) { return Mustache.to_html(_this.annotationTemplate, { id: a.id, @@ -285,7 +287,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { atitle: a.getTitleOrDescription().slice(0, 20), can_edit: a.meta['coco:can_edit'], is_admin: _this.is_admin, - admin_url: '/admin/coco/annotation/' + a.id, + admin_url: _this.action_url('admin', a.id), category: "Ldt-EnrichedPlan-Note-" + note_category(a), filtered: ((note_category(a) == 'Own' && !_this.show_own_notes) || (note_category(a) == 'Other' && !_this.show_other_notes) From 97640f7453af3a954a6d0e112ae28d60399ca7c2 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 22 Dec 2015 15:16:07 +0100 Subject: [PATCH 115/204] Specify pip-main class in videoonly mode --- src/widgets/SlideVideoPlayer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/SlideVideoPlayer.js b/src/widgets/SlideVideoPlayer.js index fdecd693..5609d8ae 100644 --- a/src/widgets/SlideVideoPlayer.js +++ b/src/widgets/SlideVideoPlayer.js @@ -57,6 +57,7 @@ IriSP.Widgets.SlideVideoPlayer.prototype.draw = function() { }, 1500); } else if (_this.mode == 'videoonly') { this.$.find(".Ldt-SlideVideoPlayer-panel.Ldt-SlideVideoPlayer-slide").addClass("Ldt-SlideVideoPlayer-hidden"); + this.$.find(".Ldt-SlideVideoPlayer-panel.Ldt-SlideVideoPlayer-video").addClass('Ldt-SlideVideoPlayer-pip-main'); } else { // Default : side by side // FIXME: this should be better implemented through a signal sent From e9a6270f0238f0b02dd06af72edb4971b1b330f9 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 4 Jan 2016 14:29:54 +0100 Subject: [PATCH 116/204] Make update_level more robust --- src/widgets/EnrichedPlan.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index fd627d50..f12fa1a3 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -148,8 +148,10 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { function update_level(el, inc) { var an = _this.source.getElement(el.dataset.id); - console.log("Update ", an.title, " to ", an.content.data.level + inc); - an.content.data.level += inc; + if (an.content.data === "") { + an.content.data = {level: 1}; + }; + an.content.data.level = (an.content.data.level || 1) + inc; IriSP.jQuery.ajax({ url: _this.action_url("level", el.dataset.id), timeout: 2000, From b5d7201d223725c6e945ca8fe698c9b38922acb0 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 5 Jan 2016 14:42:55 +0100 Subject: [PATCH 117/204] Add different pip toggles for pip positioning --- src/widgets/SlideVideoPlayer.css | 7 ++- src/widgets/img/pip_bl.svg | 9 ++++ src/widgets/img/pip_br.svg | 9 ++++ src/widgets/img/pip_tl.svg | 9 ++++ src/widgets/img/pip_toggle.svg | 89 +++++++------------------------- src/widgets/img/pip_tr.svg | 9 ++++ 6 files changed, 60 insertions(+), 72 deletions(-) create mode 100644 src/widgets/img/pip_bl.svg create mode 100644 src/widgets/img/pip_br.svg create mode 100644 src/widgets/img/pip_tl.svg create mode 100644 src/widgets/img/pip_tr.svg diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index 864b1016..0d23681c 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -64,14 +64,14 @@ display: none; } .Ldt-SlideVideoPlayer-pip-pip:hover .Ldt-SlideVideoPlayer-pip-menu-toggle { - background-color: #000; - opacity: .5; + opacity: .8; display: inline-block; } .Ldt-SlideVideoPlayer-pip-menu-toggle-br { bottom: 2px; right: 2px; + background-image: url(img/pip_br.svg); } .Ldt-SlideVideoPlayer-pip-br .Ldt-SlideVideoPlayer-pip-menu-toggle-br { display: none !important; @@ -79,6 +79,7 @@ .Ldt-SlideVideoPlayer-pip-menu-toggle-tr { top: 2px; right: 2px; + background-image: url(img/pip_tr.svg); } .Ldt-SlideVideoPlayer-pip-tr .Ldt-SlideVideoPlayer-pip-menu-toggle-tr { display: none !important; @@ -86,6 +87,7 @@ .Ldt-SlideVideoPlayer-pip-menu-toggle-tl { top: 2px; left: 2px; + background-image: url(img/pip_tl.svg); } .Ldt-SlideVideoPlayer-pip-tl .Ldt-SlideVideoPlayer-pip-menu-toggle-tl { display: none !important; @@ -93,6 +95,7 @@ .Ldt-SlideVideoPlayer-pip-menu-toggle-bl { bottom: 2px; left: 2px; + background-image: url(img/pip_bl.svg); } .Ldt-SlideVideoPlayer-pip-bl .Ldt-SlideVideoPlayer-pip-menu-toggle-bl { display: none !important; diff --git a/src/widgets/img/pip_bl.svg b/src/widgets/img/pip_bl.svg new file mode 100644 index 00000000..f9c20a42 --- /dev/null +++ b/src/widgets/img/pip_bl.svg @@ -0,0 +1,9 @@ + + + + + + + diff --git a/src/widgets/img/pip_br.svg b/src/widgets/img/pip_br.svg new file mode 100644 index 00000000..bc0a4cf3 --- /dev/null +++ b/src/widgets/img/pip_br.svg @@ -0,0 +1,9 @@ + + + + + + + diff --git a/src/widgets/img/pip_tl.svg b/src/widgets/img/pip_tl.svg new file mode 100644 index 00000000..47688efb --- /dev/null +++ b/src/widgets/img/pip_tl.svg @@ -0,0 +1,9 @@ + + + + + + + diff --git a/src/widgets/img/pip_toggle.svg b/src/widgets/img/pip_toggle.svg index 75278974..9ad04170 100644 --- a/src/widgets/img/pip_toggle.svg +++ b/src/widgets/img/pip_toggle.svg @@ -1,71 +1,20 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/src/widgets/img/pip_tr.svg b/src/widgets/img/pip_tr.svg new file mode 100644 index 00000000..70c90e99 --- /dev/null +++ b/src/widgets/img/pip_tr.svg @@ -0,0 +1,9 @@ + + + + + + + From 902748c0d01e7b0e0c765a9abe4b26ecae597201 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 5 Jan 2016 14:43:21 +0100 Subject: [PATCH 118/204] Force hide fullscreen icon --- src/widgets/CocoController.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/CocoController.css b/src/widgets/CocoController.css index d0850088..98d59809 100644 --- a/src/widgets/CocoController.css +++ b/src/widgets/CocoController.css @@ -73,5 +73,5 @@ } .Ldt-CocoCtrl-Disabled { - display: none; + display: none !important; } From 4bf4a491f8f03e6c582777f77b5874b5ad9cd7cb Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 6 Jan 2016 16:25:53 +0100 Subject: [PATCH 119/204] Define enable_add_question option, disabled by default --- src/widgets/Controller.js | 27 ++++++++++++--------------- src/widgets/Quiz.js | 8 ++++++-- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/widgets/Controller.js b/src/widgets/Controller.js index a391ff78..3e115540 100644 --- a/src/widgets/Controller.js +++ b/src/widgets/Controller.js @@ -15,7 +15,8 @@ IriSP.Widgets.Controller.prototype.defaults = { always_show_search: false, // Selector for the widget that needs to be fullscreened fullscreen_widget: undefined, - enable_quiz_toggle: undefined + enable_quiz_toggle: undefined, + enable_add_question: false }; IriSP.Widgets.Controller.prototype.template = @@ -106,17 +107,7 @@ IriSP.Widgets.Controller.prototype.draw = function () { this.$playButton.click(this.functionWrapper("playHandler")); if (this.enable_quiz_toggle !== undefined) { - if (this.enable_quiz_toggle) { - this.$.find(".Ldt-Ctrl-Quiz-Enable").addClass("Ldt-Ctrl-Quiz-Toggle-Active"); - this.$.find(".Ldt-Ctrl-Quiz-Create").addClass("Ldt-Ctrl-Quiz-Toggle-Active"); - // this.player.trigger("QuizCreator.show"); - this.$.find("#QuizEditContainer").show(); - } else { - this.$.find(".Ldt-Ctrl-Quiz-Enable").removeClass("Ldt-Ctrl-Quiz-Toggle-Active"); - this.$.find(".Ldt-Ctrl-Quiz-Create").removeClass("Ldt-Ctrl-Quiz-Toggle-Active"); - this.player.trigger("QuizCreator.hide"); - this.$.find("#QuizEditContainer").hide(); - } + this.toggleQuiz(this.enable_quiz_toggle); } else { this.$.find(".Ldt-Ctrl-Quiz-Enable").hide(); } @@ -267,11 +258,17 @@ IriSP.Widgets.Controller.prototype.createQuiz = function () { this.player.trigger("QuizCreator.create"); }; -IriSP.Widgets.Controller.prototype.toggleQuiz = function () { - this.enable_quiz_toggle = !this.enable_quiz_toggle; +IriSP.Widgets.Controller.prototype.toggleQuiz = function (force_state) { + if (force_state !== undefined) { + this.enable_quiz_toggle = force_state; + } else { + this.enable_quiz_toggle = !this.enable_quiz_toggle; + } if (this.enable_quiz_toggle) { $(".Ldt-Ctrl-Quiz-Enable").addClass("Ldt-Ctrl-Quiz-Toggle-Active"); - $(".Ldt-Ctrl-Quiz-Create").addClass("Ldt-Ctrl-Quiz-Toggle-Active"); + if (this.enable_add_question) { + $(".Ldt-Ctrl-Quiz-Create").addClass("Ldt-Ctrl-Quiz-Toggle-Active"); + } this.player.trigger("Quiz.activate"); } else { $(".Ldt-Ctrl-Quiz-Enable").removeClass("Ldt-Ctrl-Quiz-Toggle-Active"); diff --git a/src/widgets/Quiz.js b/src/widgets/Quiz.js index bd253454..c1dfcaf5 100644 --- a/src/widgets/Quiz.js +++ b/src/widgets/Quiz.js @@ -11,7 +11,8 @@ IriSP.Widgets.Quiz.prototype.defaults = { analytics_api: "", api_method: "POST", user: "", - userid:"" + userid:"", + enable_add_question: false }; IriSP.Widgets.Quiz.prototype.template = '
    ' @@ -245,7 +246,7 @@ IriSP.Widgets.Quiz.prototype.draw = function () { }); this.onMediaEvent("pause", function () { - if (!_this.quiz_displayed) { + if (!_this.quiz_displayed && this.enable_add_question) { $(".Ldt-Pause-Add-Question").show(); } }); @@ -260,6 +261,9 @@ IriSP.Widgets.Quiz.prototype.draw = function () { .on("click", function () { _this.player.trigger("QuizCreator.create"); }) .appendTo($('#' + _this.container)); _this.overlay.html(this.template); + if (!this.enable_add_question) { + $(".Ldt-Pause-Add-Question").hide(); + } $(".Ldt-Quiz-Overlay").hide(); From 38139cdf09c0dcde045d2d6600fff4c088fdca8e Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 7 Jan 2016 09:47:48 +0100 Subject: [PATCH 120/204] Specify white background for PIP --- src/widgets/SlideVideoPlayer.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index 0d23681c..317e40fb 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -32,6 +32,7 @@ width: 30% !important; height: 30%; z-index: 3; + background-color: #fff; } .Ldt-SlideVideoPlayer-pip-br { From de2c93c88d687c735d4b7750ff7c50aff51880cb Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 7 Jan 2016 11:15:26 +0100 Subject: [PATCH 121/204] Use grey background for selected annotations --- src/widgets/EnrichedPlan.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 70d6f4aa..ad69155b 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -325,7 +325,7 @@ label:hover:before { } .Ldt-EnrichedPlan-Selected-Timecode { - border: 1px dashed #6cf; + background-color: #cfcfcf; } .Ldt-EnrichedPlan-EditControl { @@ -343,4 +343,3 @@ label:hover:before { .Ldt-EnrichedPlan-Selected-Timecode .adminactions { display: inline-block; } - From 8ec5ed6b266c2588ecfb424e6d894c7d0a930287 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 7 Jan 2016 17:54:03 +0100 Subject: [PATCH 122/204] Specify fill/stroke for hamburger icon --- src/widgets/img/hamburger.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/img/hamburger.svg b/src/widgets/img/hamburger.svg index 0960513c..fd7cc888 100644 --- a/src/widgets/img/hamburger.svg +++ b/src/widgets/img/hamburger.svg @@ -1,4 +1,4 @@ - + From 3b7564ccc54f085a5f4d1bfeb1cf7bf82bf264fd Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 13 Jan 2016 16:48:22 +0100 Subject: [PATCH 123/204] Fix padding --- src/widgets/EnrichedPlan.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index ad69155b..c8cc3dfe 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -148,7 +148,7 @@ .Ldt-EnrichedPlan-Controls { height: 36px; - padding: 9px 0 6px 0; + padding: 9px 0 5px 0; border-bottom: 1px solid #000; position: absolute; top: 0; From 7c4ee329b5a54f410a194d17cf668a1e74c75a4d Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 13 Jan 2016 16:54:33 +0100 Subject: [PATCH 124/204] Tweak Selected-Timecode background-color --- src/widgets/EnrichedPlan.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index c8cc3dfe..417290e2 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -325,7 +325,7 @@ label:hover:before { } .Ldt-EnrichedPlan-Selected-Timecode { - background-color: #cfcfcf; + background-color: #e9e9e9; } .Ldt-EnrichedPlan-EditControl { From 59b40ca34d448fc41c71c6a21fce712eb3cad5de Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 14 Jan 2016 16:19:59 +0100 Subject: [PATCH 125/204] Display featured annotations (instead of hardcoded teacher) --- src/widgets/EnrichedPlan.css | 4 ++-- src/widgets/EnrichedPlan.js | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 417290e2..634f5814 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -118,8 +118,8 @@ color: inherit; } -.Ldt-EnrichedPlan-Note-Teacher, -.Ldt-EnrichedPlan-Note-Link.Ldt-EnrichedPlan-Note-Teacher { +.Ldt-EnrichedPlan-Note-Featured, +.Ldt-EnrichedPlan-Note-Link.Ldt-EnrichedPlan-Note-Featured { color: #e5007e; font-style: italic; } diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index f12fa1a3..babdafba 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -13,7 +13,7 @@ IriSP.Widgets.EnrichedPlan.prototype.messages = { en: { delete_annotation: "Delete note", confirm_delete_message: "You are about to delete {{ annotation.title }}. Are you sure you want to delete it?", - teacher_notes: "Teacher notes", + featured_notes: "Featured notes", other_notes: "Other Notes", own_notes: "Pers. notes", slides: "Slides", @@ -23,7 +23,7 @@ IriSP.Widgets.EnrichedPlan.prototype.messages = { fr: { delete_annotation: "Supprimer la note", confirm_delete_message: "Vous allez supprimer {{ annotation.title }}. Êtes-vous certain(e) ?", - teacher_notes: "Notes Enseignant", + featured_notes: "Notes Promues", other_notes: "Notes Autres", own_notes: "Notes perso.", slides: "Diapo", @@ -39,7 +39,7 @@ IriSP.Widgets.EnrichedPlan.prototype.defaults = { annotation_types: [], show_controls: true, show_slides: true, - show_teacher_notes: true, + show_featured_notes: true, show_other_notes: true, show_own_notes: true, is_admin: false, @@ -60,8 +60,8 @@ IriSP.Widgets.EnrichedPlan.prototype.template = + ' ' + '
      ' + '
    • ' - + ' ' - + ' ' + + ' ' + + ' ' + '
    • ' + '
    • ' + ' ' @@ -261,7 +261,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { }); }; - // Returns the note category: Own, Other, Teacher + // Returns the note category: Own, Other, Featured function note_category(a) { var category = a.meta["coco:category"] || 'other'; return capitalize(category); @@ -293,7 +293,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { category: "Ldt-EnrichedPlan-Note-" + note_category(a), filtered: ((note_category(a) == 'Own' && !_this.show_own_notes) || (note_category(a) == 'Other' && !_this.show_other_notes) - || (note_category(a) == 'Teacher' && !_this.show_teacher_notes)) ? 'filtered_out' : '' + || (note_category(a) == 'Featured' && !_this.show_featured_notes)) ? 'filtered_out' : '' }); }).join("\n") }); From d5543558578b8ea24dd51ec8279980f0503aa0b4 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 14 Jan 2016 16:44:03 +0100 Subject: [PATCH 126/204] Coding style fix --- src/js/serializers/ldt_annotate.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/js/serializers/ldt_annotate.js b/src/js/serializers/ldt_annotate.js index 047a68b1..745ba722 100644 --- a/src/js/serializers/ldt_annotate.js +++ b/src/js/serializers/ldt_annotate.js @@ -22,7 +22,7 @@ IriSP.serializers.ldt_annotate = { media: _data.getMedia().id, project: _data.project_id, type_title: _annType.title, - type: ( typeof _annType.dont_send_id !== "undefined" && _annType.dont_send_id ? "" : _annType.id ), + type: (typeof _annType.dont_send_id !== "undefined" && _annType.dont_send_id ? "" : _annType.id), meta: { created: _data.created, creator: _data.creator, @@ -50,9 +50,8 @@ IriSP.serializers.ldt_annotate = { var _tags = _source.getTags(true).searchByTitle(_title, true); if (_tags.length) { var _tag = _tags[0]; - } - else { - _tag = new IriSP.Model.Tag(_title.replace(/\W/g,'_'),_source); + } else { + _tag = new IriSP.Model.Tag(_title.replace(/\W/g, '_'), _source); _tag.title = _title; _source.getTags().push(_tag); } From 5497740d3722cd5807f047e9014c7e2b74193d71 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 14 Jan 2016 16:45:06 +0100 Subject: [PATCH 127/204] Serialize sharing attribute The deserialization is already effective since it is done through the meta.visibility attribute --- src/js/serializers/ldt_annotate.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/js/serializers/ldt_annotate.js b/src/js/serializers/ldt_annotate.js index 745ba722..e5b2cfbb 100644 --- a/src/js/serializers/ldt_annotate.js +++ b/src/js/serializers/ldt_annotate.js @@ -22,6 +22,7 @@ IriSP.serializers.ldt_annotate = { media: _data.getMedia().id, project: _data.project_id, type_title: _annType.title, + sharing: _data.sharing || "private", type: (typeof _annType.dont_send_id !== "undefined" && _annType.dont_send_id ? "" : _annType.id), meta: { created: _data.created, From fa0836215db902384d44c7e04780488c19723d65 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 14 Jan 2016 16:46:31 +0100 Subject: [PATCH 128/204] Use current_group information for sharing new annotations --- src/widgets/CocoCreateAnnotation.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/widgets/CocoCreateAnnotation.js b/src/widgets/CocoCreateAnnotation.js index 185918fe..cc4ae590 100644 --- a/src/widgets/CocoCreateAnnotation.js +++ b/src/widgets/CocoCreateAnnotation.js @@ -5,7 +5,9 @@ IriSP.Widgets.CocoCreateAnnotation = function (player, config) { IriSP.Widgets.CocoCreateAnnotation.prototype = new IriSP.Widgets.Widget(); IriSP.Widgets.CocoCreateAnnotation.prototype.defaults = { - pause_on_write : true + pause_on_write : true, + /* Function that should return the current group id (or "public" for public annotations) */ + current_group: undefined }; IriSP.Widgets.CocoCreateAnnotation.prototype.messages = { @@ -125,6 +127,14 @@ IriSP.Widgets.CocoCreateAnnotation.prototype.onSubmit = function () { _annotation.description = this.$.find(".Ldt-CocoCreateAnnotation-Text").val().trim(); _annotation.title = ""; + var g = this.current_group && this.current_group(); + if (g == -1) { + _annotation.sharing = "public"; + } else if (g !== undefined) { + _annotation.sharing = "shared-" + g; + } else { + _annotation.sharing = "private"; + } if (this.project_id != "") { /* Project id, only if it's been specifiec in the config */ _annotation.project_id = this.project_id; From 95289597e0a1bf93af98981fd3c9bfad211c3a26 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 14 Jan 2016 17:44:34 +0100 Subject: [PATCH 129/204] Display sharing icon next to annotation --- src/widgets/EnrichedPlan.css | 29 ++++++++++++++++++++++++++--- src/widgets/EnrichedPlan.js | 6 ++++-- src/widgets/img/icon_featured.svg | 14 ++++++++++++++ src/widgets/img/icon_group.svg | 11 +++++++++++ src/widgets/img/icon_public.svg | 22 ++++++++++++++++++++++ src/widgets/img/icon_question.svg | 24 ++++++++++++++++++++++++ 6 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 src/widgets/img/icon_featured.svg create mode 100644 src/widgets/img/icon_group.svg create mode 100644 src/widgets/img/icon_public.svg create mode 100644 src/widgets/img/icon_question.svg diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 634f5814..ffc25b1d 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -29,7 +29,7 @@ } .Ldt-EnrichedPlan-NoteTimecode { - left: -35px; + left: -52px; position: absolute; font-family: Roboto !important; padding-top: 8px; @@ -60,8 +60,8 @@ .Ldt-EnrichedPlan-SlideThumbnail.filtered_out + .Ldt-EnrichedPlan-SlideContent, .Ldt-EnrichedPlan-FlatMode .Ldt-EnrichedPlan-SlideContent { - width: calc(100% - 40px); - margin-left: 8px; + width: calc(100% - 60px); + margin-left: 28px; } .Ldt-EnrichedPlan-SlideThumbnail.filtered_out + .Ldt-EnrichedPlan-SlideContent .Ldt-EnrichedPlan-NoteTimecode, @@ -105,6 +105,7 @@ } .Ldt-EnrichedPlan-Note { + position: relative; font-weight: normal; font-size: 14px; font-family: Roboto-italic; @@ -343,3 +344,25 @@ label:hover:before { .Ldt-EnrichedPlan-Selected-Timecode .adminactions { display: inline-block; } + +.Ldt-EnrichedPlan-private { +} +.Ldt-EnrichedPlan-public:after { + content: ''; + position: absolute; + top: 0; + left: -20px; + width: 18px; + height: 18px; + background: url(img/icon_public.svg); +} + +.Ldt-EnrichedPlan-shared:after { + content: ''; + position: absolute; + top: 0; + left: -20px; + width: 18px; + height: 18px; + background: url(img/icon_group.svg); +} diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index babdafba..3f0a1272 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -96,7 +96,7 @@ IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = + '
    ' + '
    '; -IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    {{ begin }}
    {{{ text }}} {{ author }} {{#can_edit}}{{/can_edit}}{{#is_admin}}{{/is_admin}}
    '; +IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    {{ begin }}
    {{{ text }}} {{ author }} {{#can_edit}}{{/can_edit}}{{#is_admin}}{{/is_admin}}
    '; /** @@ -287,8 +287,10 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { begin: a.begin.toString(), begintc: a.begin.milliseconds, atitle: a.getTitleOrDescription().slice(0, 20), - can_edit: a.meta['coco:can_edit'], is_admin: _this.is_admin, + can_edit: a.meta['coco:can_edit'], + visibility: (a.meta['coco:visibility'] || "").indexOf('shared-') == 0 ? "shared" : (a.meta['coco:visibility'] || "private"), + featured: a.meta['coco:featured'], admin_url: _this.action_url('admin', a.id), category: "Ldt-EnrichedPlan-Note-" + note_category(a), filtered: ((note_category(a) == 'Own' && !_this.show_own_notes) diff --git a/src/widgets/img/icon_featured.svg b/src/widgets/img/icon_featured.svg new file mode 100644 index 00000000..c12e8452 --- /dev/null +++ b/src/widgets/img/icon_featured.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/src/widgets/img/icon_group.svg b/src/widgets/img/icon_group.svg new file mode 100644 index 00000000..c52991ff --- /dev/null +++ b/src/widgets/img/icon_group.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/src/widgets/img/icon_public.svg b/src/widgets/img/icon_public.svg new file mode 100644 index 00000000..472d8eec --- /dev/null +++ b/src/widgets/img/icon_public.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/src/widgets/img/icon_question.svg b/src/widgets/img/icon_question.svg new file mode 100644 index 00000000..3d1d7f9a --- /dev/null +++ b/src/widgets/img/icon_question.svg @@ -0,0 +1,24 @@ + + + + + + + + + + From 6925861014452040d0f1e6e142e571e93a47cafe Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 14 Jan 2016 17:56:10 +0100 Subject: [PATCH 130/204] Handle public notes --- src/widgets/EnrichedPlan.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 3f0a1272..78c73e63 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -44,6 +44,7 @@ IriSP.Widgets.EnrichedPlan.prototype.defaults = { show_own_notes: true, is_admin: false, flat_mode: false, + /* Group is either a group id, or -1 for public notes */ group: undefined, // action_url should be a function (action, elementid) that returns a URL // Possible actions: admin, edit, level @@ -228,11 +229,16 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { return _annotation.begin; }); - if (_this.group) { + if (_this.group > 0) { _annotations = _annotations.filter(function (a) { return a.meta['coco:group'] == _this.group; }); + } else if (_this.group == -1) { + _annotations = _annotations.filter(function (a) { + return a.meta['coco:visibility'] == "public"; + }); } + // Reference annotations in each slide: assume that slide end time is // correctly set. _slides.forEach(function (slide) { From 2da41cde68d8c780c64b7cdb7883f4e418b62645 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 15 Jan 2016 11:08:28 +0100 Subject: [PATCH 131/204] Move edit button to the right of the widget --- src/widgets/EnrichedPlan.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index ffc25b1d..79b45bbd 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -327,10 +327,15 @@ label:hover:before { .Ldt-EnrichedPlan-Selected-Timecode { background-color: #e9e9e9; + min-height: 34px; + padding-right: 32px; } .Ldt-EnrichedPlan-EditControl { display: none; + position: absolute; + top: 0; + right: 0; } .Ldt-EnrichedPlan-Selected-Timecode .Ldt-EnrichedPlan-EditControl { From 9d0617ab9f8881e75959e2f91a596c77ab2f6903 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 15 Jan 2016 17:51:30 +0100 Subject: [PATCH 132/204] Implement annotation bar display --- src/widgets/EnrichedPlan.css | 13 +++++++ src/widgets/EnrichedPlan.js | 68 +++++++++++++++++++++++------------- 2 files changed, 56 insertions(+), 25 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 79b45bbd..c83ef5f2 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -371,3 +371,16 @@ label:hover:before { height: 18px; background: url(img/icon_group.svg); } + +.Ldt-EnrichedPlan-BarContainer { + position: relative; + height: 20px; +} + +.Ldt-EnrichedPlan-Bar-Slide, +.Ldt-EnrichedPlan-Bar-Note { + width: 0px; + height: 100%; + border-left: 1px solid #fff; + position: absolute; +} diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 78c73e63..027a8f1e 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -48,7 +48,8 @@ IriSP.Widgets.EnrichedPlan.prototype.defaults = { group: undefined, // action_url should be a function (action, elementid) that returns a URL // Possible actions: admin, edit, level - action_url: function (action, elementid) { return ""; } + action_url: function (action, elementid) { return ""; }, + bar_container: undefined }; IriSP.Widgets.EnrichedPlan.prototype.template = @@ -87,6 +88,9 @@ IriSP.Widgets.EnrichedPlan.prototype.template = + '' + ''; +IriSP.Widgets.EnrichedPlan.prototype.barTemplate = + '
    '; + IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = '
    ' + '
    {{ begin }}
    ' @@ -97,14 +101,21 @@ IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = + '
    ' + ''; +IriSP.Widgets.EnrichedPlan.prototype.slideBarTemplate = + '
    ' + + '
    '; + IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    {{ begin }}
    {{{ text }}} {{ author }} {{#can_edit}}{{/can_edit}}{{#is_admin}}{{/is_admin}}
    '; +IriSP.Widgets.EnrichedPlan.prototype.annotationBarTemplate = '
    '; + /** * Initialize the component */ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { var _this = this; + _this.bar = undefined; // Get slides here so that it correctly initializes implicit // flat_mode if necessary (see template) @@ -114,32 +125,37 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { // (necessary for label association) are unique too. _this.prefix = IriSP.generateUuid(); _this.renderTemplate(); - var container = _this.$.find('.Ldt-EnrichedPlan-Container'); - var content = _this.$.find('.Ldt-EnrichedPlan-Content'); + if (_this.bar_container) { + // Container for the annotation bar + _this.bar = IriSP.jQuery(_this.templateToHtml(_this.barTemplate)); + IriSP.jQuery("#" + _this.bar_container).append(_this.bar); + } + _this.container = _this.$.find('.Ldt-EnrichedPlan-Container'); + _this.content = _this.$.find('.Ldt-EnrichedPlan-Content'); - container.on("click", "[data-timecode]", function () { + _this.container.on("click", "[data-timecode]", function () { _this.media.setCurrentTime(Number(this.dataset.timecode)); IriSP.jQuery(".Ldt-EnrichedPlan-Selected-Timecode").removeClass("Ldt-EnrichedPlan-Selected-Timecode"); IriSP.jQuery(this).addClass("Ldt-EnrichedPlan-Selected-Timecode"); }); - container.on("click", ".Ldt-EnrichedPlan-Control-Checkbox", function () { + _this.container.on("click", ".Ldt-EnrichedPlan-Control-Checkbox", function () { var classname = _.first(_.filter(this.classList, function (s) { return s != "Ldt-EnrichedPlan-Control-Checkbox"; })); if (classname !== undefined) { if (IriSP.jQuery(this).is(':checked')) { - content.find(".Ldt-EnrichedPlan-Slide ." + classname).removeClass("filtered_out"); + _this.content.find(".Ldt-EnrichedPlan-Slide ." + classname).removeClass("filtered_out"); } else { - content.find(".Ldt-EnrichedPlan-Slide ." + classname).addClass("filtered_out"); + _this.content.find(".Ldt-EnrichedPlan-Slide ." + classname).addClass("filtered_out"); } } }); - container.on("click", ".Ldt-EnrichedPlan-EditControl-Edit", function () { + _this.container.on("click", ".Ldt-EnrichedPlan-EditControl-Edit", function () { _this.player.trigger("Annotation.edit", this.dataset.id); }); - container.on("click", ".Ldt-EnrichedPlan-EditControl-Delete", function () { + _this.container.on("click", ".Ldt-EnrichedPlan-EditControl-Delete", function () { var _annotation = _this.source.getElement(this.dataset.id); if (confirm(Mustache.to_html(_this.l10n.confirm_delete_message, { annotation: _annotation }))) { _this.source.getAnnotations().removeElement(_annotation); @@ -169,19 +185,19 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { }); }; - container.on("click", ".level_incr", function () { + _this.container.on("click", ".level_incr", function () { update_level(this, +1); }).on("click", ".level_decr", function () { update_level(this, -1); }); - container.find(".Ldt-EnrichedPlan-Search-Input").on("search", function () { + _this.container.find(".Ldt-EnrichedPlan-Search-Input").on("search", function () { var q = IriSP.jQuery(this).val().toLocaleLowerCase(); if (q === "") { // Show all - content.find(".Ldt-EnrichedPlan-Note").removeClass("non_matching"); + _this.content.find(".Ldt-EnrichedPlan-Note").removeClass("non_matching"); } else { - content.find(".Ldt-EnrichedPlan-Note").each(function () { + _this.content.find(".Ldt-EnrichedPlan-Note").each(function () { var node = IriSP.jQuery(this); if (node.text().toLocaleLowerCase().indexOf(q) > -1) { node.removeClass("non_matching"); @@ -191,8 +207,6 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { }); } }); - - return [container, content]; }; IriSP.Widgets.EnrichedPlan.prototype.get_slides = function () { @@ -210,6 +224,7 @@ IriSP.Widgets.EnrichedPlan.prototype.get_slides = function () { title: title, begin: 0, end: this.media.duration, + media: this.media, thumbnail: "", getTitleOrDescription: function () { return title; @@ -247,17 +262,16 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { }); }); - var container = _this.$.find('.Ldt-EnrichedPlan-Container'); - var content = _this.$.find('.Ldt-EnrichedPlan-Content'); - if (!container.length) { + if (this.container === undefined) { // Initialization, render the container template var els = _this.init_component(); - container = els[0]; - content = els[1]; } else { // Update: empty the container // (Should do an incremental update, TBD) - content.empty(); + _this.content.empty(); + if (_this.bar) { + _this.bar.empty(); + } } function capitalize(s) { @@ -274,12 +288,13 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { }; _slides.forEach(function (slide) { - var _html = Mustache.to_html(_this.slideTemplate, { + var slideData = { id : slide.id, atitle : IriSP.textFieldHtml(slide.getTitleOrDescription()), level: (slide.content !== undefined && slide.content.data !== undefined) ? (slide.content.data.level || 1) : 1, begin : slide.begin.toString(), begintc: slide.begin.milliseconds, + position: 100 * slide.begin.milliseconds / _this.media.duration, thumbnail: slide.thumbnail, show_slides: _this.show_slides, is_admin: _this.is_admin, @@ -304,9 +319,12 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { || (note_category(a) == 'Featured' && !_this.show_featured_notes)) ? 'filtered_out' : '' }); }).join("\n") - }); - var _el = IriSP.jQuery(_html); - content.append(_el); + }; + _this.content.append(IriSP.jQuery(Mustache.to_html(_this.slideTemplate, slideData))); + if (_this.bar) { + var el = IriSP.jQuery(Mustache.to_html(_this.slideBarTemplate, slideData)); + _this.bar.append(el); + } }); }; From 053b4483a901d0dfef45ed9a92e5b0b2ae7bfed1 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 19 Jan 2016 17:40:18 +0100 Subject: [PATCH 133/204] Update icon_group and icon_public --- src/widgets/img/icon_group.svg | 33 ++++++++++++++------- src/widgets/img/icon_public.svg | 51 +++++++++++++++++++-------------- 2 files changed, 51 insertions(+), 33 deletions(-) diff --git a/src/widgets/img/icon_group.svg b/src/widgets/img/icon_group.svg index c52991ff..53161d9d 100644 --- a/src/widgets/img/icon_group.svg +++ b/src/widgets/img/icon_group.svg @@ -1,11 +1,22 @@ - - - - - - - - + + + + diff --git a/src/widgets/img/icon_public.svg b/src/widgets/img/icon_public.svg index 472d8eec..52a9e554 100644 --- a/src/widgets/img/icon_public.svg +++ b/src/widgets/img/icon_public.svg @@ -1,22 +1,29 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + From fdc0bf2cb477cb12e8341a18d9a244a877c4140d Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 19 Jan 2016 17:51:08 +0100 Subject: [PATCH 134/204] Display group/public icons only for own annotations --- src/widgets/EnrichedPlan.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 027a8f1e..3b35a153 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -300,6 +300,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { is_admin: _this.is_admin, admin_url: _this.action_url('admin', slide.id), notes: slide.annotations.map(function (a) { + var cat = note_category(a); return Mustache.to_html(_this.annotationTemplate, { id: a.id, text: IriSP.textFieldHtml(a.getTitleOrDescription()), @@ -310,13 +311,13 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { atitle: a.getTitleOrDescription().slice(0, 20), is_admin: _this.is_admin, can_edit: a.meta['coco:can_edit'], - visibility: (a.meta['coco:visibility'] || "").indexOf('shared-') == 0 ? "shared" : (a.meta['coco:visibility'] || "private"), + visibility: cat == 'Own' ? ((a.meta['coco:visibility'] || "").indexOf('shared-') == 0 ? "shared" : (a.meta['coco:visibility'] || "private")) : "none", featured: a.meta['coco:featured'], admin_url: _this.action_url('admin', a.id), - category: "Ldt-EnrichedPlan-Note-" + note_category(a), - filtered: ((note_category(a) == 'Own' && !_this.show_own_notes) - || (note_category(a) == 'Other' && !_this.show_other_notes) - || (note_category(a) == 'Featured' && !_this.show_featured_notes)) ? 'filtered_out' : '' + category: "Ldt-EnrichedPlan-Note-" + cat, + filtered: ((cat == 'Own' && !_this.show_own_notes) + || (cat == 'Other' && !_this.show_other_notes) + || (cat == 'Featured' && !_this.show_featured_notes)) ? 'filtered_out' : '' }); }).join("\n") }; From 032a5c958be30644cb51239242e8d97fcf2b9662 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 19 Jan 2016 18:02:00 +0100 Subject: [PATCH 135/204] Coding style fixes --- src/widgets/Shortcuts.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/widgets/Shortcuts.js b/src/widgets/Shortcuts.js index 55551501..52595ece 100644 --- a/src/widgets/Shortcuts.js +++ b/src/widgets/Shortcuts.js @@ -5,7 +5,7 @@ IriSP.Widgets.Shortcuts = function(player, config) { /** * Keyboard shortcuts widget * This widgets add global shortcuts for common actions. - * The default shortcuts are: + * The default shortcuts are: * - Control-space for play/pause * - Control-left for rewind (+shift to go faster) * - Control-right for forward (+shift to go faster) @@ -15,15 +15,15 @@ IriSP.Widgets.Shortcuts.prototype = new IriSP.Widgets.Widget(); IriSP.Widgets.Shortcuts.prototype.defaults = { // Time increment, in ms, for backward/forward navigation time_increment: 2000 -} +}; IriSP.Widgets.Shortcuts.prototype.draw = function() { var _this = this; - + /* Standard shortcuts */ Mousetrap.bindGlobal("ctrl+space", function (e) { e.preventDefault(); - if (! _this.media.getPaused()) { + if (!_this.media.getPaused()) { _this.media.pause(); } else { _this.media.play(); @@ -60,5 +60,4 @@ IriSP.Widgets.Shortcuts.prototype.draw = function() { _this.player.trigger("CreateAnnotation.toggle"); return false; }); - }; From 6d98b0202095c8018233b64a51d89aaa42f5900d Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 20 Jan 2016 14:07:59 +0100 Subject: [PATCH 136/204] Add tooltip to slide bar --- src/widgets/EnrichedPlan.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 3b35a153..6844d196 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -102,7 +102,7 @@ IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = + ''; IriSP.Widgets.EnrichedPlan.prototype.slideBarTemplate = - '
    ' + '
    ' + '
    '; IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    {{ begin }}
    {{{ text }}} {{ author }} {{#can_edit}}{{/can_edit}}{{#is_admin}}{{/is_admin}}
    '; From 872ba1c0d2f8771b98429fb66c3660a137b566a2 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 20 Jan 2016 14:08:10 +0100 Subject: [PATCH 137/204] Set focus on annotation zone on pause event --- src/widgets/CocoCreateAnnotation.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/widgets/CocoCreateAnnotation.js b/src/widgets/CocoCreateAnnotation.js index cc4ae590..8b508d84 100644 --- a/src/widgets/CocoCreateAnnotation.js +++ b/src/widgets/CocoCreateAnnotation.js @@ -46,6 +46,11 @@ IriSP.Widgets.CocoCreateAnnotation.prototype.draw = function () { _this.setBegin(_time); }; }); + this.onMediaEvent("pause", function () { + // Set focus on annotation zone + textField.focus(); + }); + }; IriSP.Widgets.CocoCreateAnnotation.prototype.setBegin = function (t) { From 01b88f6e352c8bac6c76f2b162fdeafa625e8eca Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 22 Jan 2016 16:52:54 +0100 Subject: [PATCH 138/204] Handle clicks on bar representation --- src/widgets/EnrichedPlan.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 6844d196..65930fe3 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -133,11 +133,15 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { _this.container = _this.$.find('.Ldt-EnrichedPlan-Container'); _this.content = _this.$.find('.Ldt-EnrichedPlan-Content'); - _this.container.on("click", "[data-timecode]", function () { + function go_to_timecode() { _this.media.setCurrentTime(Number(this.dataset.timecode)); IriSP.jQuery(".Ldt-EnrichedPlan-Selected-Timecode").removeClass("Ldt-EnrichedPlan-Selected-Timecode"); IriSP.jQuery(this).addClass("Ldt-EnrichedPlan-Selected-Timecode"); - }); + }; + _this.container.on("click", "[data-timecode]", go_to_timecode); + if (_this.bar) { + _this.bar.on("click", "[data-timecode]", go_to_timecode); + } _this.container.on("click", ".Ldt-EnrichedPlan-Control-Checkbox", function () { var classname = _.first(_.filter(this.classList, function (s) { From ddc8545f5d0f9487463b324da1eb8fc2ab116056 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 26 Jan 2016 10:34:52 +0100 Subject: [PATCH 139/204] Quick fix for a strange resizing issue --- src/widgets/SlideVideoPlayer.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index 317e40fb..61a0d8de 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -8,7 +8,7 @@ .Ldt-SlideVideoPlayer { width: 100%; max-width: 100%; - height: 100%; + height: 100% !important; max-height: 100%; } From 53cedc916f81747dccf045d6d7d86d295e658ce5 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 26 Jan 2016 10:47:57 +0100 Subject: [PATCH 140/204] Remove max-height (conflict with height) --- src/widgets/SlideVideoPlayer.css | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index 61a0d8de..9619a3a5 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -8,8 +8,11 @@ .Ldt-SlideVideoPlayer { width: 100%; max-width: 100%; - height: 100% !important; - max-height: 100%; +} + +.Ldt-SlideVideoPlayer-video video { + width: 100%; + height: 100%; } .Ldt-SlideVideoPlayer-pip-main { From b5bc8e612c459aaf43d027baa3af26d9d944ceb6 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 26 Jan 2016 11:52:05 +0100 Subject: [PATCH 141/204] Reorder css directives --- src/widgets/EnrichedPlan.css | 42 +++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index c83ef5f2..73d61640 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -69,6 +69,19 @@ display: inline-block; } +.Ldt-EnrichedPlan-BarContainer { + position: relative; + height: 20px; +} + +.Ldt-EnrichedPlan-Bar-Slide, +.Ldt-EnrichedPlan-Bar-Note { + width: 0; + height: 100%; + border-left: 1px solid #fff; + position: absolute; +} + .Ldt-EnrichedPlan-FlatMode .Ldt-EnrichedPlan-SlideThumbnail { display: none; } @@ -133,6 +146,16 @@ color: #996633; } +.Ldt-EnrichedPlan-Bar-Note.Ldt-EnrichedPlan-Note-Own { + border-color: #6cf; +} +.Ldt-EnrichedPlan-Bar-Note.Ldt-EnrichedPlan-Note-Featured { + border-color: #e5007e; +} +.Ldt-EnrichedPlan-Bar-Note.Ldt-EnrichedPlan-Note-Other { + border-color: #996633; +} + .Ldt-EnrichedPlan-Note-Text { line-height: 22px; word-wrap: break-word; @@ -325,7 +348,8 @@ label:hover:before { background: url(img/notes_delete.svg); } -.Ldt-EnrichedPlan-Selected-Timecode { +.Ldt-EnrichedPlan-Selected-Timecode, +.Ldt-EnrichedPlan-Note-Own:hover { background-color: #e9e9e9; min-height: 34px; padding-right: 32px; @@ -338,7 +362,8 @@ label:hover:before { right: 0; } -.Ldt-EnrichedPlan-Selected-Timecode .Ldt-EnrichedPlan-EditControl { +.Ldt-EnrichedPlan-Selected-Timecode .Ldt-EnrichedPlan-EditControl, +.Ldt-EnrichedPlan-Note:hover .Ldt-EnrichedPlan-EditControl { display: inline-block; } @@ -371,16 +396,3 @@ label:hover:before { height: 18px; background: url(img/icon_group.svg); } - -.Ldt-EnrichedPlan-BarContainer { - position: relative; - height: 20px; -} - -.Ldt-EnrichedPlan-Bar-Slide, -.Ldt-EnrichedPlan-Bar-Note { - width: 0px; - height: 100%; - border-left: 1px solid #fff; - position: absolute; -} From ec58051532e1a4b76e1799fd6d3386a473b95bc6 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 26 Jan 2016 16:17:30 +0100 Subject: [PATCH 142/204] Make filtered_out more generic --- src/widgets/EnrichedPlan.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 73d61640..15b4f200 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -9,7 +9,7 @@ transition: max-height .6s; } -.Ldt-EnrichedPlan-SlideItem.filtered_out { +.filtered_out { max-height: 0; position: absolute; overflow: hidden; From 6777f9f2a050a74e52ed4fe1a8866d10d0d6f90e Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 26 Jan 2016 16:39:08 +0100 Subject: [PATCH 143/204] Display notes in annotation bar --- src/widgets/EnrichedPlan.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 65930fe3..647f5940 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -107,7 +107,7 @@ IriSP.Widgets.EnrichedPlan.prototype.slideBarTemplate = IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    {{ begin }}
    {{{ text }}} {{ author }} {{#can_edit}}{{/can_edit}}{{#is_admin}}{{/is_admin}}
    '; -IriSP.Widgets.EnrichedPlan.prototype.annotationBarTemplate = '
    '; +IriSP.Widgets.EnrichedPlan.prototype.annotationBarTemplate = '
    '; /** @@ -150,8 +150,14 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { if (classname !== undefined) { if (IriSP.jQuery(this).is(':checked')) { _this.content.find(".Ldt-EnrichedPlan-Slide ." + classname).removeClass("filtered_out"); + if (_this.bar) { + _this.bar.find("." + classname).removeClass("filtered_out"); + } } else { _this.content.find(".Ldt-EnrichedPlan-Slide ." + classname).addClass("filtered_out"); + if (_this.bar) { + _this.bar.find("." + classname).addClass("filtered_out"); + } } } }); @@ -305,7 +311,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { admin_url: _this.action_url('admin', slide.id), notes: slide.annotations.map(function (a) { var cat = note_category(a); - return Mustache.to_html(_this.annotationTemplate, { + var annData = { id: a.id, text: IriSP.textFieldHtml(a.getTitleOrDescription()), url: document.location.href.replace(/#.*$/, '') + '#id=' + a.id + '&t=' + (a.begin / 1000.0), @@ -314,6 +320,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { begintc: a.begin.milliseconds, atitle: a.getTitleOrDescription().slice(0, 20), is_admin: _this.is_admin, + position: 100 * a.begin.milliseconds / _this.media.duration, can_edit: a.meta['coco:can_edit'], visibility: cat == 'Own' ? ((a.meta['coco:visibility'] || "").indexOf('shared-') == 0 ? "shared" : (a.meta['coco:visibility'] || "private")) : "none", featured: a.meta['coco:featured'], @@ -322,7 +329,11 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { filtered: ((cat == 'Own' && !_this.show_own_notes) || (cat == 'Other' && !_this.show_other_notes) || (cat == 'Featured' && !_this.show_featured_notes)) ? 'filtered_out' : '' - }); + }; + if (_this.bar) { + _this.bar.append(IriSP.jQuery(Mustache.to_html(_this.annotationBarTemplate, annData))); + } + return Mustache.to_html(_this.annotationTemplate, annData); }).join("\n") }; _this.content.append(IriSP.jQuery(Mustache.to_html(_this.slideTemplate, slideData))); From 3e95631a2525c546514a6e5549e7dc76695211d0 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 28 Jan 2016 14:06:51 +0100 Subject: [PATCH 144/204] Use relative positioning for slider --- src/widgets/BarSlider.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/widgets/BarSlider.js b/src/widgets/BarSlider.js index 5966e8ae..8a80c061 100644 --- a/src/widgets/BarSlider.js +++ b/src/widgets/BarSlider.js @@ -60,11 +60,11 @@ IriSP.Widgets.BarSlider.prototype.draw = function () { IriSP.Widgets.BarSlider.prototype.onTimeupdate = function (_time) { var _this = this, - pos = _this.width * _time / _this.media.duration; + pos = 100 * _time / _this.media.duration; this.$slider.slider("value", _time); // Update bar position - this.$currentbar.css("width", pos); - this.$currentbarhead.css("left", pos + 4); + this.$currentbar.css("width", pos + "%"); + this.$currentbarhead.css("left", "calc(" + pos + "% + 4px)"); }; IriSP.Widgets.BarSlider.prototype.onMouseout = function () { From c17bc08ccd02124172dabf344243656426951298 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 28 Jan 2016 15:31:48 +0100 Subject: [PATCH 145/204] Highlight hovered bar element --- src/widgets/EnrichedPlan.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 15b4f200..7dd237ee 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -81,6 +81,10 @@ border-left: 1px solid #fff; position: absolute; } +.Ldt-EnrichedPlan-Bar-Slide:hover, +.Ldt-EnrichedPlan-Bar-Note:hover { + border-width: 5px; +} .Ldt-EnrichedPlan-FlatMode .Ldt-EnrichedPlan-SlideThumbnail { display: none; @@ -352,7 +356,6 @@ label:hover:before { .Ldt-EnrichedPlan-Note-Own:hover { background-color: #e9e9e9; min-height: 34px; - padding-right: 32px; } .Ldt-EnrichedPlan-EditControl { From 80c3f927e6ac774c8cec330a79e3cf2d270f5c8e Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 2 Feb 2016 11:29:24 +0100 Subject: [PATCH 146/204] Use grey background for annotation bar --- src/widgets/EnrichedPlan.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 7dd237ee..794ab142 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -72,6 +72,7 @@ .Ldt-EnrichedPlan-BarContainer { position: relative; height: 20px; + background-color: #999; } .Ldt-EnrichedPlan-Bar-Slide, From 9537cca9ae40722955e5aae32e6aeb9c5bbc8d83 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 2 Feb 2016 11:30:58 +0100 Subject: [PATCH 147/204] Add horizontal padding for annotation bar --- src/widgets/EnrichedPlan.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 794ab142..c6c08651 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -73,6 +73,7 @@ position: relative; height: 20px; background-color: #999; + padding: 0 4px; } .Ldt-EnrichedPlan-Bar-Slide, From 5fa1dae633e39e5500c53043b4304dab097ac435 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 2 Feb 2016 11:32:05 +0100 Subject: [PATCH 148/204] Make pip bottom right by default --- src/widgets/SlideVideoPlayer.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index 9619a3a5..9d153fd5 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -36,6 +36,8 @@ height: 30%; z-index: 3; background-color: #fff; + bottom: 2px; + right: 2px; } .Ldt-SlideVideoPlayer-pip-br { From 1ef458ac66cb6ba5f93cd3bda0bd8c3537a19228 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 2 Feb 2016 11:34:52 +0100 Subject: [PATCH 149/204] Add border around PIP --- src/widgets/SlideVideoPlayer.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index 9d153fd5..c66d8431 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -38,6 +38,8 @@ background-color: #fff; bottom: 2px; right: 2px; + border: 1px solid #999; + box-shadow: #999 2px 2px 2px; } .Ldt-SlideVideoPlayer-pip-br { From 1cb5ebe9e7c7c58650af8f7e71779b628e809df3 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 2 Feb 2016 11:35:08 +0100 Subject: [PATCH 150/204] Trigger twitter/facebook events --- src/widgets/CocoController.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/widgets/CocoController.js b/src/widgets/CocoController.js index 633e8448..af6ff873 100644 --- a/src/widgets/CocoController.js +++ b/src/widgets/CocoController.js @@ -95,6 +95,12 @@ IriSP.Widgets.CocoController.prototype.draw = function () { fullscreenButton.addClass("Ldt-CocoCtrl-Disabled"); } + this.$.on("click touchstart", ".Ldt-CocoCtrl-Twitter-Button", function (e) { + _this.player.trigger("Player.tweet"); + }); + this.$.on("click touchstart", ".Ldt-CocoCtrl-Facebook-Button", function (e) { + _this.player.trigger("Player.facebook"); + }); this.$.on("click touchstart", ".Ldt-CocoCtrl-Sound", function (e) { e.stopPropagation(); e.preventDefault(); From 40919b46e43df1e517c5ae6a0284e1240edf854d Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 2 Feb 2016 14:52:12 +0100 Subject: [PATCH 151/204] Add classname to slide bars so that they react to visibility toggle --- src/widgets/EnrichedPlan.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 647f5940..55f5be66 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -102,7 +102,7 @@ IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = + '
    '; IriSP.Widgets.EnrichedPlan.prototype.slideBarTemplate = - '
    ' + '
    ' + '
    '; IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    {{ begin }}
    {{{ text }}} {{ author }} {{#can_edit}}{{/can_edit}}{{#is_admin}}{{/is_admin}}
    '; From d89339a68a0fe517040cc0bc8c6387c4cfafbe44 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 4 Feb 2016 14:23:20 +0100 Subject: [PATCH 152/204] Add "Configure tab display" menuitem This breaks encapsulation/separation of concerns. --- src/widgets/EnrichedPlan.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 55f5be66..878ee1f1 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -16,6 +16,7 @@ IriSP.Widgets.EnrichedPlan.prototype.messages = { featured_notes: "Featured notes", other_notes: "Other Notes", own_notes: "Pers. notes", + popup_tabconfig: "Configure tab display", slides: "Slides", search: "Search...", whole_video: "Whole video" @@ -26,6 +27,7 @@ IriSP.Widgets.EnrichedPlan.prototype.messages = { featured_notes: "Notes Promues", other_notes: "Notes Autres", own_notes: "Notes perso.", + popup_tabconfig: "Configurer les onglets", slides: "Diapo", search: "Recherchez...", whole_video: "Vidéo entière" @@ -61,6 +63,7 @@ IriSP.Widgets.EnrichedPlan.prototype.template = + ' ' + ' ' + '
    '; @@ -245,11 +246,21 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { if (q === "") { // Show all _this.content.find(".Ldt-EnrichedPlan-Note").removeClass("non_matching"); + _this.content.find(".Ldt-EnrichedPlan-Slide").removeClass("non_matching"); } else { - _this.content.find(".Ldt-EnrichedPlan-Note").each(function () { + _this.content.find(".Ldt-EnrichedPlan-Slide").each(function () { var node = IriSP.jQuery(this); if (node.text().toLocaleLowerCase().indexOf(q) > -1) { node.removeClass("non_matching"); + // Hide non-matching notes from the slide + node.find(".Ldt-EnrichedPlan-Note").each(function () { + var node = IriSP.jQuery(this); + if (node.text().toLocaleLowerCase().indexOf(q) > -1) { + node.removeClass("non_matching"); + } else { + node.addClass("non_matching"); + } + }); } else { node.addClass("non_matching"); } @@ -275,6 +286,7 @@ IriSP.Widgets.EnrichedPlan.prototype.get_slides = function () { end: this.media.duration, media: this.media, thumbnail: "", + description: "", getTitleOrDescription: function () { return title; } @@ -343,6 +355,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { var slideData = { id : slide.id, atitle : IriSP.textFieldHtml(slide.getTitleOrDescription()), + description: IriSP.textFieldHtml(slide.description), level: (slide.content !== undefined && slide.content.data !== undefined) ? (slide.content.data.level || 1) : 1, begin : slide.begin.toString(), begintc: slide.begin.milliseconds, From 2601f5be7925c8bcd8a22ab22ed0ccdc69f79f8f Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 7 Jun 2016 17:23:48 +0200 Subject: [PATCH 169/204] Add tracing information --- src/widgets/EnrichedPlan.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 4764722e..31d6adf1 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -104,23 +104,23 @@ IriSP.Widgets.EnrichedPlan.prototype.barTemplate = '
    '; IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = - '
    ' + '
    ' + '
    {{ begin }}
    ' - + '
    {{#thumbnail}}{{/thumbnail}}
    ' + + '
    {{#thumbnail}}{{/thumbnail}}
    ' + '
    ' - + '
    {{#is_admin}}{{/is_admin}}{{ atitle }}
    ' - + '
    {{description}}
    ' + + '
    {{#is_admin}}{{/is_admin}}{{ atitle }}
    ' + + '
    {{description}}
    ' + '
    {{{ notes }}}
    ' + '
    ' + '
    '; IriSP.Widgets.EnrichedPlan.prototype.slideBarTemplate = - '
    ' + '
    ' + '
    '; -IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    {{ begin }}
    {{{ text }}} {{ author }} {{#can_edit}}{{#is_admin}}{{/is_admin}}{{/can_edit}}{{#is_admin}}{{/is_admin}}
    '; +IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    {{ begin }}
    {{{ text }}} {{ author }} {{#can_edit}}{{#is_admin}}{{/is_admin}}{{/can_edit}}{{#is_admin}}{{/is_admin}}
    '; -IriSP.Widgets.EnrichedPlan.prototype.annotationBarTemplate = '
    '; +IriSP.Widgets.EnrichedPlan.prototype.annotationBarTemplate = '
    '; /** @@ -354,11 +354,13 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { _slides.forEach(function (slide) { var slideData = { id : slide.id, + media_id: slide.media.id, atitle : IriSP.textFieldHtml(slide.getTitleOrDescription()), description: IriSP.textFieldHtml(slide.description), level: (slide.content !== undefined && slide.content.data !== undefined) ? (slide.content.data.level || 1) : 1, begin : slide.begin.toString(), - begintc: slide.begin.milliseconds, + begin_ms: slide.begin.milliseconds, + end_ms: slide.end.milliseconds, position: 100 * slide.begin.milliseconds / _this.media.duration, thumbnail: slide.thumbnail, show_slides: _this.show_slides, @@ -368,11 +370,13 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { var cat = note_category(a); var annData = { id: a.id, + media_id: a.media.id, text: IriSP.textFieldHtml(a.getTitleOrDescription()), url: document.location.href.replace(/#.*$/, '') + '#id=' + a.id + '&t=' + (a.begin / 1000.0), author: a.creator, begin: a.begin.toString(), - begintc: a.begin.milliseconds, + begin_ms: a.begin.milliseconds, + end_ms: a.end.milliseconds, atitle: a.getTitleOrDescription().slice(0, 20), is_admin: _this.is_admin, position: 100 * a.begin.milliseconds / _this.media.duration, From be0704432e73bc9798f218dcce28b07386850145 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 8 Jun 2016 11:45:52 +0200 Subject: [PATCH 170/204] Display slides as rectangles in bar --- src/widgets/EnrichedPlan.css | 9 ++++++++- src/widgets/EnrichedPlan.js | 25 +++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index b8a76621..ea1453bf 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -83,7 +83,14 @@ border-left: 1px solid #fff; position: absolute; } -.Ldt-EnrichedPlan-Bar-Slide:hover, +.Ldt-EnrichedPlan-Bar-Slide { + background-color: rgba(200, 200, 200, .5); +} + +.Ldt-EnrichedPlan-Bar-Slide:hover { + background-color: #fff; +} + .Ldt-EnrichedPlan-Bar-Note:hover { border-width: 5px; } diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 31d6adf1..865e27e2 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -115,7 +115,7 @@ IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = + '
    '; IriSP.Widgets.EnrichedPlan.prototype.slideBarTemplate = - '
    ' + '
    ' + '
    '; IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    {{ begin }}
    {{{ text }}} {{ author }} {{#can_edit}}{{#is_admin}}{{/is_admin}}{{/can_edit}}{{#is_admin}}{{/is_admin}}
    '; @@ -247,22 +247,37 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { // Show all _this.content.find(".Ldt-EnrichedPlan-Note").removeClass("non_matching"); _this.content.find(".Ldt-EnrichedPlan-Slide").removeClass("non_matching"); + if (_this.bar) { + _this.bar.find(".Ldt-EnrichedPlan-Bar-Note").removeClass("non_matching"); + } } else { _this.content.find(".Ldt-EnrichedPlan-Slide").each(function () { var node = IriSP.jQuery(this); if (node.text().toLocaleLowerCase().indexOf(q) > -1) { node.removeClass("non_matching"); + if (_this.bar) { + _this.bar.find("[data-id=" + this.dataset.id + "]").removeClass("non_matching"); + } // Hide non-matching notes from the slide node.find(".Ldt-EnrichedPlan-Note").each(function () { var node = IriSP.jQuery(this); if (node.text().toLocaleLowerCase().indexOf(q) > -1) { node.removeClass("non_matching"); + if (_this.bar) { + _this.bar.find("[data-id=" + this.dataset.id + "]").removeClass("non_matching"); + } } else { node.addClass("non_matching"); + if (_this.bar) { + _this.bar.find("[data-id=" + this.dataset.id + "]").addClass("non_matching"); + } } }); } else { node.addClass("non_matching"); + if (_this.bar) { + _this.bar.find("[data-id=" + this.dataset.id + "]").addClass("non_matching"); + } } }); } @@ -351,6 +366,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { return capitalize(category); }; + var annotationBarData = []; _slides.forEach(function (slide) { var slideData = { id : slide.id, @@ -362,6 +378,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { begin_ms: slide.begin.milliseconds, end_ms: slide.end.milliseconds, position: 100 * slide.begin.milliseconds / _this.media.duration, + width: 100 * (slide.end.milliseconds - slide.begin.milliseconds) / _this.media.duration, thumbnail: slide.thumbnail, show_slides: _this.show_slides, is_admin: _this.is_admin, @@ -392,15 +409,19 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { ) ? 'filtered_out' : '' }; if (_this.bar) { - _this.bar.append(IriSP.jQuery(Mustache.to_html(_this.annotationBarTemplate, annData))); + annotationBarData.push(IriSP.jQuery(Mustache.to_html(_this.annotationBarTemplate, annData))); } return Mustache.to_html(_this.annotationTemplate, annData); }).join("\n") }; _this.content.append(IriSP.jQuery(Mustache.to_html(_this.slideTemplate, slideData))); + // Populate bar, starting with slides if (_this.bar) { var el = IriSP.jQuery(Mustache.to_html(_this.slideBarTemplate, slideData)); _this.bar.append(el); + annotationBarData.forEach(function (dom) { + _this.bar.append(dom); + }); } }); }; From f270c9bbbf4f9e87da1f95ff992b4e621792efca Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 8 Jun 2016 16:09:36 +0200 Subject: [PATCH 171/204] Handle accented search terms --- src/js/utils.js | 7 +++++++ src/widgets/EnrichedPlan.css | 7 +++++++ src/widgets/EnrichedPlan.js | 6 +++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/js/utils.js b/src/js/utils.js index 049febef..648a33f6 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -213,3 +213,10 @@ IriSP.generateUuid = function () { return v.toString(16); }); }; + +/** + * Return a non-accentuated version of the given string + */ +IriSP.unaccent = function (s) { + return s.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); +}; diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index ea1453bf..4aee7f59 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -95,6 +95,13 @@ border-width: 5px; } +.Ldt-EnrichedPlan-Bar-Slide.filtered_out, +.Ldt-EnrichedPlan-Bar-Note.filtered_out, +.Ldt-EnrichedPlan-Bar-Slide.non_matching, +.Ldt-EnrichedPlan-Bar-Note.non_matching { + display: none; +} + .Ldt-EnrichedPlan-FlatMode .Ldt-EnrichedPlan-SlideThumbnail { display: none; } diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 865e27e2..e1bbf9e3 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -242,7 +242,7 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { }); _this.container.find(".Ldt-EnrichedPlan-Search-Input").on("search", function () { - var q = IriSP.jQuery(this).val().toLocaleLowerCase(); + var q = IriSP.unaccent(IriSP.jQuery(this).val().toLocaleLowerCase()); if (q === "") { // Show all _this.content.find(".Ldt-EnrichedPlan-Note").removeClass("non_matching"); @@ -253,7 +253,7 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { } else { _this.content.find(".Ldt-EnrichedPlan-Slide").each(function () { var node = IriSP.jQuery(this); - if (node.text().toLocaleLowerCase().indexOf(q) > -1) { + if (IriSP.unaccent(node.text().toLocaleLowerCase()).indexOf(q) > -1) { node.removeClass("non_matching"); if (_this.bar) { _this.bar.find("[data-id=" + this.dataset.id + "]").removeClass("non_matching"); @@ -261,7 +261,7 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { // Hide non-matching notes from the slide node.find(".Ldt-EnrichedPlan-Note").each(function () { var node = IriSP.jQuery(this); - if (node.text().toLocaleLowerCase().indexOf(q) > -1) { + if (IriSP.unaccent(node.text().toLocaleLowerCase()).indexOf(q) > -1) { node.removeClass("non_matching"); if (_this.bar) { _this.bar.find("[data-id=" + this.dataset.id + "]").removeClass("non_matching"); From 229d876a51387f610eff724c74913fa13f40f575 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 8 Jun 2016 17:10:31 +0200 Subject: [PATCH 172/204] Add expander to show slide content --- src/widgets/EnrichedPlan.css | 28 +++++++++++++++++++++++++--- src/widgets/EnrichedPlan.js | 14 +++++++++++--- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 4aee7f59..9a00e346 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -107,13 +107,34 @@ } .Ldt-EnrichedPlan-SlideDescription { - display: none; + max-height: 0; + overflow: hidden; + font-size: 9px; +} + +.Ldt-EnrichedPlan-Expanded .Ldt-EnrichedPlan-SlideDescription { + max-height: 200px; + overflow: auto; +} + +.Ldt-EnrichedPlan-SlideExpander { + display: inline-block; + background: url(img/right_arrow.svg) center/80% no-repeat; + margin: 1px; + border: 1px solid grey; + width: 10px; + height: 10px; + cursor: zoom-in; +} + +.Ldt-EnrichedPlan-Expanded .Ldt-EnrichedPlan-SlideExpander { + background: url(img/checked.svg) center/80% no-repeat; } .Ldt-EnrichedPlan-SlideTitle { display: inline-block; font-size: 14px; - width: 100%; + width: calc(100% - 16px); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; @@ -134,7 +155,8 @@ font-size: 14px; } -[data-id=whole] .Ldt-EnrichedPlan-SlideTitle { +[data-id=whole] .Ldt-EnrichedPlan-SlideTitle, +[data-id=whole] .Ldt-EnrichedPlan-SlideExpander { display: none; } [data-id=whole] .Ldt-EnrichedPlan-SlideTimecode { diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index e1bbf9e3..fe56a24f 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -21,7 +21,8 @@ IriSP.Widgets.EnrichedPlan.prototype.messages = { popup_tabconfig: "Configure tab display", slides: "Slides", search: "Search...", - whole_video: "Whole video" + whole_video: "Whole video", + expand_slide: "Show the slide content" }, fr: { delete_annotation: "Supprimer la note", @@ -34,7 +35,8 @@ IriSP.Widgets.EnrichedPlan.prototype.messages = { popup_tabconfig: "Configurer les onglets", slides: "Diapo", search: "Recherchez...", - whole_video: "Vidéo entière" + whole_video: "Vidéo entière", + expand_slide: "Montrer le contenu de la diapo" } }; @@ -49,6 +51,8 @@ IriSP.Widgets.EnrichedPlan.prototype.defaults = { show_other_notes: true, show_own_notes: true, show_quiz_notes: false, + // Automatically scroll so that current slide is visible + autoscroll: true, is_admin: false, flat_mode: false, /* Group is either a group id, or -1 for public notes */ @@ -108,8 +112,9 @@ IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = + '
    {{ begin }}
    ' + '
    {{#thumbnail}}{{/thumbnail}}
    ' + '
    ' + + '
    ' + '
    {{#is_admin}}{{/is_admin}}{{ atitle }}
    ' - + '
    {{description}}
    ' + + '
    {{{description}}}
    ' + '
    {{{ notes }}}
    ' + '
    ' + '
    '; @@ -160,6 +165,9 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { _this.player.trigger("Player.tabconfig"); }); + _this.container.on("click", ".Ldt-EnrichedPlan-SlideExpander", function () { + IriSP.jQuery(this).parent().toggleClass("Ldt-EnrichedPlan-Expanded"); + }); _this.container.on("click", ".Ldt-EnrichedPlan-Control-Checkbox", function () { var classname = _.first(_.filter(this.classList, function (s) { return s != "Ldt-EnrichedPlan-Control-Checkbox"; From bef1bb3dcb64662e3f1f67a44b693224ef565365 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 8 Jun 2016 17:11:55 +0200 Subject: [PATCH 173/204] Coding style fixes --- src/widgets/Trace.js | 83 ++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/src/widgets/Trace.js b/src/widgets/Trace.js index 22552956..55f4e859 100644 --- a/src/widgets/Trace.js +++ b/src/widgets/Trace.js @@ -1,6 +1,5 @@ IriSP.Widgets.Trace = function(player, config) { - IriSP.Widgets.Widget.call(this, player, config); - + IriSP.Widgets.Widget.call(this, player, config); }; IriSP.Widgets.Trace.prototype = new IriSP.Widgets.Widget(); @@ -16,24 +15,24 @@ IriSP.Widgets.Trace.prototype.defaults = { }; IriSP.Widgets.Trace.prototype.draw = function() { - if (typeof window.tracemanager === "undefined") { - console.log("Tracemanager not found"); - return; - } - var _this = this, - _medialisteners = { - "play" : 0, - "pause" : 0, - "volumechange" : 0, - "seeked" : 0, - "play" : 0, - "pause" : 0, - "timeupdate" : 10000 - }, - _annlisteners = { - search: 0, - "search-cleared": 0 - }; + if (typeof window.tracemanager === "undefined") { + console.log("Tracemanager not found"); + return; + } + var _this = this, + _medialisteners = { + "play" : 0, + "pause" : 0, + "volumechange" : 0, + "seeked" : 0, + "play" : 0, + "pause" : 0, + "timeupdate" : 10000 + }, + _annlisteners = { + search: 0, + "search-cleared": 0 + }; IriSP._(_medialisteners).each(function(_ms, _listener) { var _f = function(_arg) { _this.eventHandler(_listener, _arg); @@ -53,20 +52,20 @@ IriSP.Widgets.Trace.prototype.draw = function() { } _annotations.on(_listener, _f); }); - + if (!this.tracer) { - + this.tracer = window.tracemanager.init_trace("test", { url: this.url, requestmode: this.requestmode, syncmode: this.syncmode, default_subject: this.default_subject }); - + } - - - + + + this.tracer.trace("TraceWidgetInit", {}); // Configure annotation creation/update/delete/publish tracing @@ -87,7 +86,7 @@ IriSP.Widgets.Trace.prototype.draw = function() { this.mouseLocation = ''; IriSP.jQuery(".Ldt-Widget").on("mousedown mouseenter mouseleave", ".Ldt-TraceMe", function(_e) { var _target = IriSP.jQuery(this); - + var _widget = _target.attr("widget-type") || _target.parents(".Ldt-Widget").attr("widget-type"), _data = { "type": _e.type, @@ -99,7 +98,7 @@ IriSP.Widgets.Trace.prototype.draw = function() { _id = _targetEl.id, _value = _target.val(), _traceInfo = _target.attr("trace-info"); - _data.target = _name + (_id && _id.length ? '#' + IriSP.jqEscape(_id) : '') + (_class && _class.length ? ('.' + IriSP.jqEscape(_class).replace(/\s/g,'.')).replace(/\.Ldt-(Widget|TraceMe)/g,'') : ''); + _data.target = _name + (_id && _id.length ? '#' + IriSP.jqEscape(_id) : '') + (_class && _class.length ? ('.' + IriSP.jqEscape(_class).replace(/\s/g, '.')).replace(/\.Ldt-(Widget|TraceMe)/g, '') : ''); if (typeof _traceInfo == "string" && _traceInfo) { _data.traceInfo = _traceInfo; } @@ -118,22 +117,22 @@ IriSP.Widgets.Trace.prototype.eventHandler = function(_listener, _arg) { if (typeof _arg == "undefined") { _arg = {}; } - switch(_listener) { - case 'UIEvent': - _traceName += _arg.widget + '_' + _arg.type; - delete _arg.widget; - delete _arg.type; + switch (_listener) { + case 'UIEvent': + _traceName += _arg.widget + '_' + _arg.type; + delete _arg.widget; + delete _arg.type; break; - case 'play': - case 'pause': - _arg.milliseconds = this.media.getCurrentTime().milliseconds; - case 'timeupdate': - case 'seeked': - case 'volumechange': - _traceName += 'media_' + _listener; + case 'play': + case 'pause': + _arg.milliseconds = this.media.getCurrentTime().milliseconds; + case 'timeupdate': + case 'seeked': + case 'volumechange': + _traceName += 'media_' + _listener; break; - default: - _traceName += _listener.replace('.','_'); + default: + _traceName += _listener.replace('.', '_'); } if (typeof this.extend === "object" && this.extend) { IriSP._(_arg).extend(this.extend); From 1f84bd3c0e3e6a1c5e11dd4c3500c06bad692c09 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 8 Jun 2016 17:23:06 +0200 Subject: [PATCH 174/204] Implement Media.togglePlayPause method --- src/js/model.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/js/model.js b/src/js/model.js index 2af7018e..94055d11 100644 --- a/src/js/model.js +++ b/src/js/model.js @@ -681,6 +681,14 @@ IriSP.Model = (function (ns) { this.trigger("setpause"); }; + Playable.prototype.togglePlayPause = function () { + if (this.getPaused()) { + this.play(); + } else { + this.pause(); + }; + }; + Playable.prototype.show = function() {}; Playable.prototype.hide = function() {}; From 7ef302a774ebdb24a8a436d5438d42950a191e29 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 9 Jun 2016 15:34:36 +0200 Subject: [PATCH 175/204] Pressing space with an empty input field toggles play/pause --- src/widgets/CocoCreateAnnotation.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/widgets/CocoCreateAnnotation.js b/src/widgets/CocoCreateAnnotation.js index 4fe1803d..9957cae1 100644 --- a/src/widgets/CocoCreateAnnotation.js +++ b/src/widgets/CocoCreateAnnotation.js @@ -39,7 +39,7 @@ IriSP.Widgets.CocoCreateAnnotation.prototype.draw = function () { textField = this.$.find(".Ldt-CocoCreateAnnotation-Text"); this.begin = new IriSP.Model.Time(); - textField.on("change keyup input paste", this.functionWrapper("onTextChange")); + textField.on("keyup paste", this.functionWrapper("onTextChange")); this.$.find("form").submit(this.functionWrapper("onSubmit")); this.onMediaEvent("timeupdate", function (_time) { @@ -92,6 +92,15 @@ IriSP.Widgets.CocoCreateAnnotation.prototype.onTextChange = function (e) { var _field = this.$.find(".Ldt-CocoCreateAnnotation-Text"), _timecodeField = this.$.find(".Ldt-CocoCreateAnnotation-Timecode"), _contents = _field.val(); + + if (!this.previousInput && e.keyCode == 32) { + // Let's consider it improbable to have a leading space in a note. + // Reset text entry + _contents = ""; + _field.val(""); + // Toggle play/pause + this.media.togglePlayPause(); + }; _field.css("border-color", !!_contents ? "#666666" : "#ff0000"); if (!!_contents) { if (!this.previousInput) { From 1a2a5b5ddcc711858f8e4ca2053af9bd6ca61c6a Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 9 Jun 2016 15:38:30 +0200 Subject: [PATCH 176/204] Allow text selection in slides It is disabled by TouchSplitter --- src/widgets/EnrichedPlan.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 9a00e346..11a98727 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -2,6 +2,8 @@ border-bottom: 2px dotted #ccc; padding-top: 4px; cursor: pointer; + -webkit-user-select: initial; + user-select: initial; } .Ldt-EnrichedPlan-SlideItem { @@ -74,6 +76,8 @@ height: 20px; background-color: #999; padding: 0 4px; + -webkit-user-select: initial; + user-select: initial; } .Ldt-EnrichedPlan-Bar-Slide, From 577186437a449e7e8f510213b8aab11e6c247678 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 9 Jun 2016 16:17:04 +0200 Subject: [PATCH 177/204] Use markjs.io for searching It allows to highlight matching text --- src/js/libs/jquery.mark.min.js | 7 +++ src/js/widgets-container/defaults.js | 6 ++- src/widgets/EnrichedPlan.js | 65 ++++++++++++++++------------ 3 files changed, 49 insertions(+), 29 deletions(-) create mode 100644 src/js/libs/jquery.mark.min.js diff --git a/src/js/libs/jquery.mark.min.js b/src/js/libs/jquery.mark.min.js new file mode 100644 index 00000000..402849ef --- /dev/null +++ b/src/js/libs/jquery.mark.min.js @@ -0,0 +1,7 @@ +/*!*************************************************** + * mark.js v6.3.0 + * https://github.com/julmot/mark.js + * Copyright (c) 2014–2016, Julian Motz + * Released under the MIT license https://git.io/vwTVl + *****************************************************/ +"use strict";function _classCallCheck(a,b){if(!(a instanceof b))throw new TypeError("Cannot call a class as a function")}var _extends=Object.assign||function(a){for(var b=1;b-1)return!1;a=a.replace(new RegExp("["+b+"]","gmi"),"["+b+"]"),c.push(b)}return!0})}),a}},{key:"createAccuracyRegExp",value:function(a){switch(this.opt.accuracy){case"partially":return"()("+a+")";case"complementary":return"()(\\S*"+a+"\\S*)";case"exactly":return"(^|\\s)("+a+")(?=\\s|$)"}}},{key:"getSeparatedKeywords",value:function(a){var b=this,c=[];return a.forEach(function(a){b.opt.separateWordSearch?a.split(" ").forEach(function(a){a.trim()&&c.push(a)}):a.trim()&&c.push(a)}),{keywords:c,length:c.length}}},{key:"getElements",value:function(){var a=void 0,b=[];return a="undefined"==typeof this.ctx?[]:this.ctx instanceof HTMLElement?[this.ctx]:Array.isArray(this.ctx)?this.ctx:Array.prototype.slice.call(this.ctx),a.forEach(function(a){b.push(a);var c=a.querySelectorAll("*");c.length&&(b=b.concat(Array.prototype.slice.call(c)))}),a.length||this.log("Empty context","warn"),{elements:b,length:b.length}}},{key:"matches",value:function(a,b){return(a.matches||a.matchesSelector||a.msMatchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.oMatchesSelector).call(a,b)}},{key:"matchesFilter",value:function(a,b){var c=this,d=!0,e=this.opt.filter.concat(["script","style","title"]);return this.opt.iframes||(e=e.concat(["iframe"])),b&&(e=e.concat(["*[data-markjs='true']"])),e.every(function(b){return c.matches(a,b)?d=!1:!0}),!d}},{key:"onIframeReady",value:function(a,b,c){try{!function(){var d=a.contentWindow,e="about:blank",f="complete",g=function(){try{if(null===d.document)throw new Error("iframe inaccessible");b(d.document)}catch(a){c()}},h=function(){var b=a.getAttribute("src").trim(),c=d.location.href;return c===e&&b!==e&&b},i=function(){var b=function b(){try{h()||(a.removeEventListener("load",b),g())}catch(a){c()}};a.addEventListener("load",b)};d.document.readyState===f?h()?i():g():i()}()}catch(a){c()}}},{key:"forEachElementInIframe",value:function(a,b){var c=this,d=arguments.length<=2||void 0===arguments[2]?function(){}:arguments[2],e=0,f=function(){--e<1&&d()};this.onIframeReady(a,function(a){var d=Array.prototype.slice.call(a.querySelectorAll("*"));0===(e=d.length)&&f(),d.forEach(function(a){"iframe"===a.tagName.toLowerCase()?!function(){var d=0;c.forEachElementInIframe(a,function(a,c){b(a,c),c-1===d&&f(),d++},f)}():(b(a,d.length),f())})},function(){var b=a.getAttribute("src");c.log("iframe '"+b+"' could not be accessed","warn"),f()})}},{key:"forEachElement",value:function(a){var b=this,c=arguments.length<=1||void 0===arguments[1]?function(){}:arguments[1],d=arguments.length<=2||void 0===arguments[2]?!0:arguments[2],e=this.getElements(),f=e.elements,g=e.length,h=function(){0===--g&&c()};h(++g),f.forEach(function(c){if(!b.matchesFilter(c,d)){if("iframe"===c.tagName.toLowerCase())return void b.forEachElementInIframe(c,function(c){b.matchesFilter(c,d)||a(c)},h);a(c)}h()})}},{key:"forEachNode",value:function(a){var b=arguments.length<=1||void 0===arguments[1]?function(){}:arguments[1];this.forEachElement(function(b){for(b=b.firstChild;b;b=b.nextSibling)3===b.nodeType&&b.textContent.trim()&&a(b)},b)}},{key:"wrapMatches",value:function(a,c,d,e){for(var f=this.opt.element?this.opt.element:"mark",g=d?0:2,h=void 0;null!==(h=c.exec(a.textContent));){var i=h.index;d||(i+=h[g-1].length);var j=a.splitText(i);if(a=j.splitText(h[g].length),null!==j.parentNode){var k=b.createElement(f);k.setAttribute("data-markjs","true"),this.opt.className&&k.setAttribute("class",this.opt.className),k.textContent=h[g],j.parentNode.replaceChild(k,j),e(k)}c.lastIndex=0}}},{key:"unwrapMatches",value:function(a){for(var c=a.parentNode,d=b.createDocumentFragment();a.firstChild;)d.appendChild(a.removeChild(a.firstChild));c.replaceChild(d,a),c.normalize()}},{key:"markRegExp",value:function(a,b){var c=this;this.opt=b,this.log('Searching with expression "'+a+'"');var d=0,e=function(a){d++,c.opt.each(a)};this.forEachNode(function(b){c.wrapMatches(b,a,!0,e)},function(){0===d&&c.opt.noMatch(a),c.opt.complete(d),c.opt.done(d)})}},{key:"mark",value:function(a,b){var c=this;this.opt=b,a="string"==typeof a?[a]:a;var d=this.getSeparatedKeywords(a),e=d.keywords,f=d.length,g=0;0===f&&(this.opt.complete(g),this.opt.done(g)),e.forEach(function(a){var b=new RegExp(c.createRegExp(a),"gmi"),d=0,h=function(a){d++,g++,c.opt.each(a)};c.log('Searching with expression "'+b+'"'),c.forEachNode(function(a){c.wrapMatches(a,b,!1,h)},function(){0===d&&c.opt.noMatch(a),e[f-1]===a&&(c.opt.complete(g),c.opt.done(g))})})}},{key:"unmark",value:function(a){var b=this;this.opt=a;var c=this.opt.element?this.opt.element:"*";c+="[data-markjs]",this.opt.className&&(c+="."+this.opt.className),this.log('Removal selector "'+c+'"'),this.forEachElement(function(a){b.matches(a,c)&&b.unwrapMatches(a)},function(){b.opt.complete(),b.opt.done()},!1)}},{key:"opt",set:function(b){this._opt=_extends({},{element:"",className:"",filter:[],iframes:!1,separateWordSearch:!0,diacritics:!0,synonyms:{},accuracy:"partially",each:function(){},noMatch:function(){},done:function(){},complete:function(){},debug:!1,log:a.console},b)},get:function(){return this._opt}}]),c}();c.fn.mark=function(a,b){return new d(this).mark(a,b),this},c.fn.markRegExp=function(a,b){return new d(this).markRegExp(a,b),this},c.fn.unmark=function(a){return new d(this).unmark(a),this}},window,document); \ No newline at end of file diff --git a/src/js/widgets-container/defaults.js b/src/js/widgets-container/defaults.js index 3738d259..f40576b9 100644 --- a/src/js/widgets-container/defaults.js +++ b/src/js/widgets-container/defaults.js @@ -29,7 +29,8 @@ IriSP.libFiles = { processing: "processing-1.3.6.min.js", recordMicSwf: "record_mic.swf", mousetrap: "mousetrap.min.js", - mousetrapGlobal: "mousetrap-global-bind.js" + mousetrapGlobal: "mousetrap-global-bind.js", + markjs: "jquery.mark.min.js" }, locations : { // use to define locations outside default_dir @@ -110,6 +111,9 @@ IriSP.widgetsRequirements = { }, Shortcuts: { requires: [ "mousetrap", "mousetrapGlobal" ] + }, + EnrichedPlan: { + requires: [ "markjs" ] } }; diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index fe56a24f..a4e2914c 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -250,43 +250,52 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { }); _this.container.find(".Ldt-EnrichedPlan-Search-Input").on("search", function () { - var q = IriSP.unaccent(IriSP.jQuery(this).val().toLocaleLowerCase()); + var q = IriSP.jQuery(this).val().toLocaleLowerCase(); if (q === "") { // Show all - _this.content.find(".Ldt-EnrichedPlan-Note").removeClass("non_matching"); - _this.content.find(".Ldt-EnrichedPlan-Slide").removeClass("non_matching"); + IriSP.jQuery(".Ldt-EnrichedPlan-Content").unmark().find(".non_matching").removeClass("non_matching"); if (_this.bar) { - _this.bar.find(".Ldt-EnrichedPlan-Bar-Note").removeClass("non_matching"); + _this.bar.find(".non_matching").removeClass("non_matching"); } } else { _this.content.find(".Ldt-EnrichedPlan-Slide").each(function () { var node = IriSP.jQuery(this); - if (IriSP.unaccent(node.text().toLocaleLowerCase()).indexOf(q) > -1) { - node.removeClass("non_matching"); - if (_this.bar) { - _this.bar.find("[data-id=" + this.dataset.id + "]").removeClass("non_matching"); - } - // Hide non-matching notes from the slide - node.find(".Ldt-EnrichedPlan-Note").each(function () { - var node = IriSP.jQuery(this); - if (IriSP.unaccent(node.text().toLocaleLowerCase()).indexOf(q) > -1) { - node.removeClass("non_matching"); - if (_this.bar) { - _this.bar.find("[data-id=" + this.dataset.id + "]").removeClass("non_matching"); - } - } else { - node.addClass("non_matching"); - if (_this.bar) { - _this.bar.find("[data-id=" + this.dataset.id + "]").addClass("non_matching"); - } + node.unmark().mark(q, { + filter: [ '.filtered_out' ], + diacritics: true, + noMatch: function () { + node.addClass("non_matching"); + if (_this.bar) { + _this.bar.find("[data-id=" + node[0].dataset.id + "]").addClass("non_matching"); + } + }, + each: function () { + node.removeClass("non_matching"); + if (_this.bar) { + _this.bar.find("[data-id=" + node[0].dataset.id + "]").removeClass("non_matching"); } - }); - } else { - node.addClass("non_matching"); - if (_this.bar) { - _this.bar.find("[data-id=" + this.dataset.id + "]").addClass("non_matching"); + // Hide non-matching notes from the slide + node.find(".Ldt-EnrichedPlan-Note").each(function () { + var note = IriSP.jQuery(this); + note.unmark().mark(q, { + filter: [ '.filtered_out' ], + diacritics: true, + noMatch: function () { + note.addClass("non_matching"); + if (_this.bar) { + _this.bar.find("[data-id=" + note[0].dataset.id + "]").addClass("non_matching"); + } + }, + each: function () { + note.removeClass('non_matching').removeClass('filtered_out'); + if (_this.bar) { + _this.bar.find("[data-id=" + note[0].dataset.id + "]").removeClass("non_matching").removeClass('filtered_out'); + } + } + }); + }); } - } + }); }); } }); From b2478e8c7e530e956ba42abd4e35641cf809784e Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 21 Jun 2016 15:51:01 +0200 Subject: [PATCH 178/204] Add slide content show/hide icons --- src/widgets/EnrichedPlan.css | 4 ++-- src/widgets/img/slide_content_hide.svg | 17 +++++++++++++++++ src/widgets/img/slide_content_show.svg | 19 +++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 src/widgets/img/slide_content_hide.svg create mode 100644 src/widgets/img/slide_content_show.svg diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 11a98727..d7d772c9 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -123,7 +123,7 @@ .Ldt-EnrichedPlan-SlideExpander { display: inline-block; - background: url(img/right_arrow.svg) center/80% no-repeat; + background: url(img/slide_content_show.svg) center/100% no-repeat; margin: 1px; border: 1px solid grey; width: 10px; @@ -132,7 +132,7 @@ } .Ldt-EnrichedPlan-Expanded .Ldt-EnrichedPlan-SlideExpander { - background: url(img/checked.svg) center/80% no-repeat; + background: url(img/slide_content_hide.svg) center/100% no-repeat; } .Ldt-EnrichedPlan-SlideTitle { diff --git a/src/widgets/img/slide_content_hide.svg b/src/widgets/img/slide_content_hide.svg new file mode 100644 index 00000000..f2a9dcf4 --- /dev/null +++ b/src/widgets/img/slide_content_hide.svg @@ -0,0 +1,17 @@ + + + + diff --git a/src/widgets/img/slide_content_show.svg b/src/widgets/img/slide_content_show.svg new file mode 100644 index 00000000..44858117 --- /dev/null +++ b/src/widgets/img/slide_content_show.svg @@ -0,0 +1,19 @@ + + + + + From 7ef9b2b4373463a22639b142a1e41643d867417a Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 23 Jun 2016 17:37:26 +0200 Subject: [PATCH 179/204] Implement Comment infrastructure. Add is_authenticated option --- src/widgets/EnrichedPlan.css | 26 ++++++++++++- src/widgets/EnrichedPlan.js | 75 +++++++++++++++++++++++++++++++++--- 2 files changed, 94 insertions(+), 7 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index d7d772c9..424bd640 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -55,7 +55,8 @@ } .Ldt-EnrichedPlan-SlideContent { - display: inline-block; + display: inline-flex; + flex-direction: column; width: calc(100% - 220px); transition: width .4s; } @@ -219,7 +220,8 @@ word-wrap: break-word; } -.Ldt-EnrichedPlan-Note-Author { +.Ldt-EnrichedPlan-Note-Author, +.Ldt-EnrichedPlan-Comment-Author { text-transform: uppercase; font-size: 10px; } @@ -457,3 +459,23 @@ label:hover:before { height: 18px; background: url(img/icon_group.svg); } + +.Ldt-EnrichedPlan-Comments { + display: none; +} +.Ldt-EnrichedPlan-Selected-Timecode .Ldt-EnrichedPlan-Comments { + display: inline-flex; + flex-direction: column; + width: 100%; + padding-top: 10px; +} + +.Ldt-EnrichedPlan-Comment-New.Ldt-EnrichedPlan-Expanded { + display: inline-flex; +} + +.Ldt-EnrichedPlan-Comment-New-Text { + font-family: Merriweather; + font-size: 12px; + width: 100%; +} diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index a4e2914c..8c69d63a 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -22,7 +22,9 @@ IriSP.Widgets.EnrichedPlan.prototype.messages = { slides: "Slides", search: "Search...", whole_video: "Whole video", - expand_slide: "Show the slide content" + expand_slide: "Show the slide content", + comment_count: "comment(s)", + new_comment: "Comment on this note" }, fr: { delete_annotation: "Supprimer la note", @@ -36,7 +38,9 @@ IriSP.Widgets.EnrichedPlan.prototype.messages = { slides: "Diapo", search: "Recherchez...", whole_video: "Vidéo entière", - expand_slide: "Montrer le contenu de la diapo" + expand_slide: "Montrer le contenu de la diapo", + comment_count: "commentaire(s)", + new_comment: "Commentez cette note" } }; @@ -54,6 +58,7 @@ IriSP.Widgets.EnrichedPlan.prototype.defaults = { // Automatically scroll so that current slide is visible autoscroll: true, is_admin: false, + is_authenticated: false, flat_mode: false, /* Group is either a group id, or -1 for public notes */ group: undefined, @@ -112,8 +117,10 @@ IriSP.Widgets.EnrichedPlan.prototype.slideTemplate = + '
    {{ begin }}
    ' + '
    {{#thumbnail}}{{/thumbnail}}
    ' + '
    ' - + '
    ' - + '
    {{#is_admin}}{{/is_admin}}{{ atitle }}
    ' + + '
    ' + + '
    ' + + ' {{#is_admin}}{{/is_admin}}{{ atitle }}' + + '
    ' + '
    {{{description}}}
    ' + '
    {{{ notes }}}
    ' + '
    ' @@ -123,7 +130,34 @@ IriSP.Widgets.EnrichedPlan.prototype.slideBarTemplate = '
    ' + '
    '; -IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    {{ begin }}
    {{{ text }}} {{ author }} {{#can_edit}}{{#is_admin}}{{/is_admin}}{{/can_edit}}{{#is_admin}}{{/is_admin}}
    '; +IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = + '
    \ +
    {{ begin }}
    \ + {{{ text }}} \ + {{ author }} \ + {{#can_edit}}\ + {{#is_admin}}{{/is_admin}}\ + \ + {{/can_edit}}\ + {{#is_admin}}
    \ + \ +
    {{/is_admin}}\ + {{#comments.length}}\ + {{comments.length}} {{l10n.comment_count}}\ + {{/comments.length}}\ +
    \ + {{#comments}}\ +
    \ + {{description}}\ + {{modified}}\ + {{creator}}\ +
    \ + {{/comments}}\ + {{#is_authenticated}}\ +
    \ +{{/is_authenticated}}\ +
    \ +
    '; IriSP.Widgets.EnrichedPlan.prototype.annotationBarTemplate = '
    '; @@ -199,6 +233,34 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { } }); + function add_comment(annotation_id, text) { + console.log("Commenting ", annotation_id, text); + IriSP.jQuery.ajax({ + url: _this.action_url("add_comment", annotation_id), + timeout: 2000, + type: "POST", + contentType: 'application/json', + data: JSON.stringify({ 'description': text }), + dataType: 'json', + error: function(XMLHttpRequest, textStatus, errorThrown) { + alert("An error has occurred making the request: " + errorThrown); + }, + success: function(data) { + // Update the local value. + var an = _this.source.getElement(annotation_id); + an.meta['coco:comments'].push(data.comment); + _this.player.trigger("AnnotationsList.refresh"); + } + }); + }; + + _this.container.on("keydown", ".Ldt-EnrichedPlan-Comment-New-Text", function (event) { + if (event.keyCode == 13) { + add_comment(this.dataset.id, IriSP.jQuery(this).val()); + return false; + } + }); + function toggle_featured(e) { var aid = e.target.dataset.id; e.preventDefault(); @@ -404,6 +466,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { var cat = note_category(a); var annData = { id: a.id, + l10n: _this.l10n, media_id: a.media.id, text: IriSP.textFieldHtml(a.getTitleOrDescription()), url: document.location.href.replace(/#.*$/, '') + '#id=' + a.id + '&t=' + (a.begin / 1000.0), @@ -413,12 +476,14 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { end_ms: a.end.milliseconds, atitle: a.getTitleOrDescription().slice(0, 20), is_admin: _this.is_admin, + is_authenticated: _this.is_authenticated, position: 100 * a.begin.milliseconds / _this.media.duration, can_edit: a.meta['coco:can_edit'], visibility: cat == 'Own' ? ((a.meta['coco:visibility'] || "").indexOf('shared-') == 0 ? "shared" : (a.meta['coco:visibility'] || "private")) : "none", featured: a.meta['coco:featured'], admin_url: _this.action_url('admin', a.id), category: "Ldt-EnrichedPlan-Note-" + cat, + comments: a.meta['coco:comments'], filtered: ((cat == 'Own' && !_this.show_own_notes) || (cat == 'Other' && !_this.show_other_notes) || (cat == 'Featured' && !_this.show_featured_notes) From f59e1f8d014ea897b61a11bcdb1483d15342a4a2 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 28 Jun 2016 14:51:57 +0200 Subject: [PATCH 180/204] Set pointer cursor for all menu labels --- src/widgets/EnrichedPlan.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 424bd640..632f2290 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -314,6 +314,10 @@ .Ldt-EnrichedPlan-Control- { font-style: normal; } +.Ldt-EnrichedPlan-Control-Label { + cursor: pointer; +} + /**********************************************************/ /* Base for label styling */ .Ldt-EnrichedPlan-Control-Checkbox:not(:checked), @@ -325,7 +329,6 @@ .Ldt-EnrichedPlan-Control-Checkbox:checked + label { position: relative; padding-left: 20px; - cursor: pointer; } /* checkbox aspect */ From b360e2a409e1547926a664bbb1fea644aa21b370 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 28 Jun 2016 17:09:29 +0200 Subject: [PATCH 181/204] Highlight current menu element --- src/widgets/EnrichedPlan.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 632f2290..a49128af 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -317,6 +317,9 @@ .Ldt-EnrichedPlan-Control-Label { cursor: pointer; } +.Ldt-EnrichedPlan-Control-Label:hover { + background-color: #ddd; +} /**********************************************************/ /* Base for label styling */ From f40cd2a141f6d30ceae33719afc4d1ed4926b13d Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 28 Jun 2016 17:09:42 +0200 Subject: [PATCH 182/204] Add show_comments option --- src/widgets/EnrichedPlan.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 8c69d63a..19f91093 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -55,6 +55,7 @@ IriSP.Widgets.EnrichedPlan.prototype.defaults = { show_other_notes: true, show_own_notes: true, show_quiz_notes: false, + show_comments: false, // Automatically scroll so that current slide is visible autoscroll: true, is_admin: false, @@ -142,6 +143,7 @@ IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = {{#is_admin}}
    \ \
    {{/is_admin}}\ + {{#show_comments}}\ {{#comments.length}}\ {{comments.length}} {{l10n.comment_count}}\ {{/comments.length}}\ @@ -155,8 +157,9 @@ IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = {{/comments}}\ {{#is_authenticated}}\
    \ -{{/is_authenticated}}\ + {{/is_authenticated}}\
    \ + {{/show_comments}}\ '; IriSP.Widgets.EnrichedPlan.prototype.annotationBarTemplate = '
    '; @@ -200,7 +203,7 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { }); _this.container.on("click", ".Ldt-EnrichedPlan-SlideExpander", function () { - IriSP.jQuery(this).parent().toggleClass("Ldt-EnrichedPlan-Expanded"); + IriSP.jQuery(this).parent().parent().toggleClass("Ldt-EnrichedPlan-Expanded"); }); _this.container.on("click", ".Ldt-EnrichedPlan-Control-Checkbox", function () { var classname = _.first(_.filter(this.classList, function (s) { @@ -477,6 +480,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { atitle: a.getTitleOrDescription().slice(0, 20), is_admin: _this.is_admin, is_authenticated: _this.is_authenticated, + show_comments: _this.show_comments, position: 100 * a.begin.milliseconds / _this.media.duration, can_edit: a.meta['coco:can_edit'], visibility: cat == 'Own' ? ((a.meta['coco:visibility'] || "").indexOf('shared-') == 0 ? "shared" : (a.meta['coco:visibility'] || "private")) : "none", From b1a341d205807758bca46315a1c7b215d46858d4 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 21 Jul 2016 13:24:24 +0200 Subject: [PATCH 183/204] Fallover for input type=search Firefox/IE do not generate search events --- src/widgets/EnrichedPlan.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 19f91093..e253bd69 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -314,7 +314,8 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { update_level(this, -1); }); - _this.container.find(".Ldt-EnrichedPlan-Search-Input").on("search", function () { + var inputField = _this.container.find(".Ldt-EnrichedPlan-Search-Input"); + inputField.on('onsearch' in inputField[0] ? "search" : "keyup", function () { var q = IriSP.jQuery(this).val().toLocaleLowerCase(); if (q === "") { // Show all From 149e373dffd4d05123bd1fc82a10e15b3de81270 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 21 Jul 2016 16:07:30 +0200 Subject: [PATCH 184/204] Hack source reference for created annotation --- src/widgets/CocoCreateAnnotation.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/widgets/CocoCreateAnnotation.js b/src/widgets/CocoCreateAnnotation.js index 9957cae1..e8f4fae0 100644 --- a/src/widgets/CocoCreateAnnotation.js +++ b/src/widgets/CocoCreateAnnotation.js @@ -144,7 +144,6 @@ IriSP.Widgets.CocoCreateAnnotation.prototype.onSubmit = function () { /* * Will fill the generated annotation object's data - * WARNING: If we're on a MASHUP, these datas must refer the ORIGINAL MEDIA * */ _annotation.setMedia(this.source.currentMedia.id); /* Annotated media ID */ @@ -184,7 +183,12 @@ IriSP.Widgets.CocoCreateAnnotation.prototype.onSubmit = function () { _this.resetInput(); _this.showScreen('Saved'); _export.getAnnotations().removeElement(_annotation, true); /* We delete the sent annotation to avoid redundancy */ + _export.source = _this.source; _export.deSerialize(_data); /* Data deserialization */ + _export.getAnnotations().forEach(function (a) { + // Set main source as reference for created annotation + a.source = _this.source; + }); _this.source.merge(_export); /* We merge the deserialized data with the current source data */ if (_this.pause_on_write && _this.media.getPaused()) { _this.media.play(); From 938ebfa75ad680bbf892682632aed19ad5e947b5 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 21 Jul 2016 17:03:54 +0200 Subject: [PATCH 185/204] Coding style fixes --- src/widgets/Mediafragment.js | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/widgets/Mediafragment.js b/src/widgets/Mediafragment.js index 36a50cac..1f1fa258 100644 --- a/src/widgets/Mediafragment.js +++ b/src/widgets/Mediafragment.js @@ -14,14 +14,14 @@ IriSP.Widgets.Mediafragment = function(player, config) { } }); }; - this.onMdpEvent("Mediafragment.setHashToAnnotation","setHashToAnnotation"); + this.onMdpEvent("Mediafragment.setHashToAnnotation", "setHashToAnnotation"); this.blocked = false; }; IriSP.Widgets.Mediafragment.prototype = new IriSP.Widgets.Widget(); IriSP.Widgets.Mediafragment.prototype.draw = function() { - this.onMediaEvent("setpause","setHashToTime"); + this.onMediaEvent("setpause", "setHashToTime"); var _this = this; this.getWidgetAnnotations().forEach(function(_annotation) { _annotation.on("click", function() { @@ -31,7 +31,7 @@ IriSP.Widgets.Mediafragment.prototype.draw = function() { if (this.media.loadedMetadata) { this.goToHash(); } else { - this.onMediaEvent("loadedmetadata","goToHash"); + this.onMediaEvent("loadedmetadata", "goToHash"); } }; @@ -44,7 +44,7 @@ IriSP.Widgets.Mediafragment.prototype.setWindowHash = function(_hash) { }; IriSP.Widgets.Mediafragment.prototype.getLastHash = function() { - var _tab = document.location.hash.replace(/^#/,'').split('&'); + var _tab = document.location.hash.replace(/^#/, '').split('&'); _tab = IriSP._(_tab).filter(function(_el) { return _el && !/^(id|t)=/.test(_el); }); @@ -59,7 +59,7 @@ IriSP.Widgets.Mediafragment.prototype.getLastHash = function() { IriSP.Widgets.Mediafragment.prototype.goToHash = function() { if (document.location.hash !== this.getLastHash()) { - var _tab = document.location.hash.replace(/^#/,'').split('&'); + var _tab = document.location.hash.replace(/^#/, '').split('&'); for (var _i = 0; _i < _tab.length; _i++) { var _subtab = _tab[_i].split("="); if (_subtab[0] == "id" || _subtab[0] == "t") { @@ -69,26 +69,24 @@ IriSP.Widgets.Mediafragment.prototype.goToHash = function() { var _annotation = this.source.getElement(this.last_hash_value); if (typeof _annotation !== "undefined") { this.media.setCurrentTime(_annotation.begin); - } else { - /* Proceed parsing elements, maybe a t was specified */ - continue; + break; } } if (this.last_hash_key == "t") { this.media.setCurrentTime(1000 * this.last_hash_value); + break; } - break; } } } }; IriSP.Widgets.Mediafragment.prototype.setHashToAnnotation = function(_annotation) { - this.setHash( 'id', _annotation.id, 't', _annotation.begin / 1000.0 ); + this.setHash('id', _annotation.id, 't', _annotation.begin / 1000.0); }; IriSP.Widgets.Mediafragment.prototype.setHashToTime = function() { - this.setHash( 't', this.media.getCurrentTime().getSeconds() ); + this.setHash('t', this.media.getCurrentTime().getSeconds()); }; IriSP.Widgets.Mediafragment.prototype.setHash = function(_key, _value, _key2, _value2) { @@ -101,7 +99,7 @@ IriSP.Widgets.Mediafragment.prototype.setHash = function(_key, _value, _key2, _v var _hash = this.getLastHash(); this.setWindowHash(_hash); if (window.parent !== window) { - window.parent.postMessage(_hash,"*"); + window.parent.postMessage(_hash, "*"); } this.block(); } From 7a63cc08a6b84fb2b7d78f4c5c0265d7782b044a Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 22 Jul 2016 17:49:04 +0200 Subject: [PATCH 186/204] Implement autoscroll --- src/widgets/EnrichedPlan.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index e253bd69..8bc89079 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -4,6 +4,9 @@ IriSP.Widgets.EnrichedPlan = function (player, config) { this.throttledRefresh = IriSP._.throttle(function (full) { _this.update_content(); }, 800, {leading: false}); + this.throttledAutoscroll = IriSP._.throttle(function (annotation) { + _this.do_autoscroll(annotation); + }, 800, {leading: true}); }; @@ -513,6 +516,16 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { }); }; +IriSP.Widgets.EnrichedPlan.prototype.do_autoscroll = function (a) { + var _this = this; + if (_this.autoscroll) { + _this.container.find("[data-id=" + a.id + "]").not(".filtered_out").each(function () { + this.scrollIntoView(true); + }); + } + return true; +}; + IriSP.Widgets.EnrichedPlan.prototype.draw = function () { var _this = this; _this.init_component(); @@ -521,4 +534,7 @@ IriSP.Widgets.EnrichedPlan.prototype.draw = function () { _this.onMdpEvent("AnnotationsList.refresh", function () { _this.throttledRefresh(false); }); + _this.media.on("enter-annotation", function(_a) { + _this.throttledAutoscroll(_a); + }); }; From 10e6f41a2d9f93c46fab0e3cd72c5e8954a49aeb Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 22 Jul 2016 18:02:49 +0200 Subject: [PATCH 187/204] Modify EnrichedPlan layout to avoid top margin --- src/widgets/EnrichedPlan.css | 16 ++++++++++------ src/widgets/EnrichedPlan.js | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index a49128af..90dee2a7 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -226,23 +226,27 @@ font-size: 10px; } -.Ldt-EnrichedPlan-Content { - margin-top: 37px; +.Ldt-EnrichedPlan-Container { + overflow-y: hidden; + height: 100%; } .Ldt-EnrichedPlan-Controls { height: 36px; padding: 9px 0 5px 0; border-bottom: 1px solid #000; - position: absolute; - top: 0; - left: 0; - right: 0; z-index: 1; background-color: #fff; display: flex; } +.Ldt-EnrichedPlan-Content { + overflow-y: auto; + overflow-x: hidden; + height: calc(100% - 37px); +} + + .Ldt-EnrichedPlan-Control-Label { display: inline-block; text-transform: uppercase; diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 8bc89079..342d0779 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -74,7 +74,6 @@ IriSP.Widgets.EnrichedPlan.prototype.defaults = { IriSP.Widgets.EnrichedPlan.prototype.template = '
    ' - + '
    ' + '
    ' + '{{#show_controls}}' + '
    ' @@ -111,6 +110,7 @@ IriSP.Widgets.EnrichedPlan.prototype.template = + '{{/show_controls}}' + '' + '' + + '
    ' + '
    '; IriSP.Widgets.EnrichedPlan.prototype.barTemplate = From 980ad8a76267177af7b30b6b95df1d474953f5ea Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 22 Jul 2016 18:06:53 +0200 Subject: [PATCH 188/204] Convert to unix EOL --- src/js/libs/tracemanager.js | 1085 +++++++++++++++++------------------ 1 file changed, 538 insertions(+), 547 deletions(-) diff --git a/src/js/libs/tracemanager.js b/src/js/libs/tracemanager.js index cc62d14d..ecd97e61 100644 --- a/src/js/libs/tracemanager.js +++ b/src/js/libs/tracemanager.js @@ -1,547 +1,538 @@ -/* - * Modelled Trace API - * - * This file is part of ktbs4js. - * - * ktbs4js is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * ktbs4js is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with ktbs4js. If not, see . - * - */ -/* FIXME: properly use require.js feature. This will do for debugging in the meantime */ -window.tracemanager = (function($) { - // If there are more than MAX_FAILURE_COUNT synchronisation - // failures, then disable synchronisation - var MAX_FAILURE_COUNT = 20; - - // If there are more than MAX_BUFFER_SIZE obsels in the buffer, - // then "compress" them as a single "ktbsFullBuffer" - var MAX_BUFFER_SIZE = 500; - - var _replacement = { - ';': '"', - '"': ';', - '#': '%23', - '&': '%26', - '?': '%3F' - }; - var BufferedService_prototype = { - /* - * Buffered service for traces - */ - // url: "", - // buffer: [], - // isReady: false, - // timer: null, - // failureCount: 0, - - /* Flush buffer */ - flush: function() { - // FIXME: add mutex on this.buffer - if (! this.isReady) - { - if (window.console) window.console.log("Sync service not ready"); - } else if (this.failureCount > MAX_FAILURE_COUNT) - { - // Disable synchronisation - this.set_sync_mode('none'); - } else if (this.buffer.length) { - var temp = this.buffer; - this.buffer = []; - - if (this.mode == 'GET') - { - // GET mode: do some data mangline. We mark the - // "compressed" nature of the generated JSON by - // prefixing it with c - var data = 'c' + JSON.stringify(temp.map(function (o) { return o.toCompactJSON(); })); - // Swap " (very frequent, which will be - // serialized into %22) and ; (rather rare), this - // saves some bytes - data = data.replace(/[;"#?&]/g, function(s){ return _replacement[s]; }); - // FIXME: check data length (< 2K is safe) - var request=$('').error( function() { this.failureCount += 1; }) - .load( function() { this.failureCount = 0; }) - .attr('src', this.url + 'trace/?data=' + data); - } - else - { - $.ajax({ url: this.url + 'trace/', - type: 'POST', - contentType: 'application/json', - data: JSON.stringify(temp.map(function (o) { return o.toJSON(); })), - processData: false, - // Type of the returned data. - dataType: "html", - error: function(jqXHR, textStatus, errorThrown) { - if (window.console) window.console.log("Error when sending buffer:", textStatus); - this.failureCount += 1; - }, - success: function(data, textStatus, jqXHR) { - // Reset failureCount to 0 as soon as there is 1 valid answer - this.failureCount = 0; - } - }); - } - } - }, - - /* Sync mode: delayed, sync (immediate sync), none (no - * synchronisation with server, the trace has to be explicitly saved - * if needed */ - set_sync_mode: function(mode, default_subject) { - this.sync_mode = mode; - if (! this.isReady && mode !== "none") - this.init(default_subject); - if (mode == 'delayed') { - this.start_timer(); - } else { - this.stop_timer(); - } - }, - - /* Enqueue an obsel */ - enqueue: function(obsel) { - if (this.buffer.length > MAX_BUFFER_SIZE) - { - obsel = new Obsel('ktbsFullBuffer', this.buffer[0].begin, - this.buffer[this.buffer.length - 1].end, this.buffer[0].subject); - obsel.trace = this.buffer[0].trace; - this.buffer = []; - } - this.buffer.push(obsel); - if (this.sync_mode === 'sync') { - // Immediate sync of the obsel. - this.flush(); - } - }, - - start_timer: function() { - var self = this; - if (this.timer === null) { - this.timer = window.setInterval(function() { - self.flush(); - }, this.timeOut); - } - }, - - stop_timer: function() { - if (this.timer !== null) { - window.clearInterval(this.timer); - this.timer = null; - } - }, - - /* - * Initialize the sync service - */ - init: function(default_subject) { - var self = this; - if (this.isReady) - /* Already initialized */ - return; - if (typeof default_subject === 'undefined') - default_subject = 'anonymous'; - if (this.mode == 'GET') - { - var request=$('').attr('src', this.url + 'login?userinfo={"default_subject": "' + default_subject + '"}'); - // Do not wait for the return, assume it is - // initialized. This assumption will not work anymore - // if login returns some necessary information - this.isReady = true; - } - else - { - $.ajax({ url: this.url + 'login', - type: 'POST', - data: 'userinfo={"default_subject":"' + default_subject + '"}', - success: function(data, textStatus, jqXHR) { - self.isReady = true; - if (self.buffer.length) { - self.flush(); - } - } - }); - } - } - }; - var BufferedService = function(url, mode) { - this.url = url; - this.buffer = []; - this.isReady = false; - this.timer = null; - this.failureCount = 0; - // sync_mode is either "none", "sync" or "buffered" - this.sync_mode = "none"; - /* mode can be either POST or GET */ - if (mode == 'POST' || mode == 'GET') - this.mode = mode; - else - this.mode = 'POST'; - /* Flush buffer every timeOut ms if the sync_mode is delayed */ - this.timeOut = 2000; - }; - BufferedService.prototype = BufferedService_prototype; - - var Trace_prototype = { - /* FIXME: We could/should use a sorted list such as - http://closure-library.googlecode.com/svn/docs/class_goog_structs_AvlTree.html - to speed up queries based on time */ - obsels: [], - /* Trace URI */ - uri: "", - default_subject: "", - /* baseuri is used as the base URI to resolve relative - * attribute-type names in obsels. Strictly speaking, this - * should rather be expressed as a reference to model, or - * more generically, as a qname/URI dict */ - baseuri: "", - /* Mapping of obsel type or property name to a compact - * representation (shorthands). - */ - shorthands: null, - syncservice: null, - - /* Define the trace URI */ - set_uri: function(uri) { - this.uri = uri; - }, - - /* Sync mode: delayed, sync (immediate sync), none (no - * synchronisation with server, the trace has to be explicitly saved - * if needed */ - set_sync_mode: function(mode) { - if (this.syncservice !== null) { - this.syncservice.set_sync_mode(mode, this.default_subject); - } - }, - - /* - * Return a list of the obsels of this trace matching the parameters - */ - list_obsels: function(_begin, _end, _reverse) { - var res; - if (typeof _begin !== 'undefined' || typeof _end !== 'undefined') { - /* - * Not optimized yet. - */ - res = []; - var l = this.obsels.length; - for (var i = 0; i < l; i++) { - var o = this.obsels[i]; - if ((typeof _begin !== 'undefined' && o.begin > _begin) && (typeof _end !== 'undefined' && o.end < _end)) { - res.push(o); - } - } - } - - if (typeof _reverse !== 'undefined') { - if (res !== undefined) { - /* Should reverse the whole list. Make a copy. */ - res = this.obsels.slice(0); - } - res.sort(function(a, b) { return b.begin - a.begin; }); - return res; - } - - if (res === undefined) { - res = this.obsels; - } - return res; - - }, - - /* - * Return the obsel of this trace identified by the URI, or undefined - */ - get_obsel: function(id) { - for (var i = 0; i < this.obsels.length; i++) { - /* FIXME: should check against variations of id/uri, take this.baseuri into account */ - if (this.obsels[i].uri === id) { - return this.obsels[i]; - } - } - return undefined; - }, - - set_default_subject: function(subject) { - // FIXME: if we call this method after the sync_service - // init method, then the default_subject will not be - // consistent anymore. Maybe we should then call init() again? - this.default_subject = subject; - }, - - get_default_subject: function() { - return this.default_subject; - }, - - /* (type:ObselType, begin:int, end:int?, subject:str?, attributes:[AttributeType=>any]?) */ - /* Create a new obsel and add it to the trace */ - create_obsel: function(type, begin, end, subject, _attributes) { - var o = new Obsel(type, begin, end, subject); - if (typeof _attributes !== 'undefined') { - o.attributes = _attributes; - } - o.trace = this; - this.obsels.push(o); - if (this.syncservice !== null) - this.syncservice.enqueue(o); - }, - - /* Helper methods */ - - /* Create a new obsel with the given attributes */ - trace: function(type, _attributes, _begin, _end, _subject) { - var t = (new Date()).getTime(); - if (typeof begin === 'undefined') { - _begin = t; - } - if (typeof end === 'undefined') { - _end = _begin; - } - if (typeof subject === 'undefined') { - _subject = this.default_subject; - } - if (typeof _attributes === 'undefined') { - _attributes = {}; - } - return this.create_obsel(type, _begin, _end, _subject, _attributes); - } - }; - - var Trace = function(uri, requestmode) { - /* FIXME: We could/should use a sorted list such as - http://closure-library.googlecode.com/svn/docs/class_goog_structs_AvlTree.html - to speed up queries based on time */ - this.obsels = []; - /* Trace URI */ - if (uri === undefined) - uri = ""; - this.uri = uri; - this.sync_mode = "none"; - this.default_subject = ""; - this.shorthands = {}; - /* baseuri is used a the base URI to resolve relative attribute names in obsels */ - this.baseuri = ""; - - this.syncservice = new BufferedService(uri, requestmode); - $(window).unload( function () { - if (this.syncservice && this.sync_mode !== 'none') { - this.syncservice.flush(); - this.syncservice.stop_timer(); - } - }); - }; - Trace.prototype = Trace_prototype; - - var Obsel_prototype = { - /* The following attributes are here for documentation - * purposes. They MUST be defined in the constructor - * function. */ - trace: undefined, - type: undefined, - begin: undefined, - end: undefined, - subject: undefined, - /* Dictionary indexed by ObselType URIs */ - attributes: {}, - - /* Method definitions */ - get_trace: function() { - return this.trace; - }, - - get_obsel_type: function() { - return this.type; - }, - get_begin: function() { - return this.begin; - }, - get_end: function() { - return this.end; - }, - get_subject: function() { - return this.subject; - }, - - list_attribute_types: function() { - var result = []; - for (var prop in this.attributes) { - if (this.attributes.hasOwnProperty(prop)) - result.push(prop); - } - /* FIXME: we return URIs here instead of AttributeType elements */ - return result; - }, - - list_relation_types: function() { - /* FIXME: not implemented yet */ - }, - - list_related_obsels: function (rt) { - /* FIXME: not implemented yet */ - }, - list_inverse_relation_types: function () { - /* FIXME: not implemented yet */ - }, - list_relating_obsels: function (rt) { - /* FIXME: not implemented yet */ - }, - /* - * Return the value of the given attribute type for this obsel - */ - get_attribute_value: function(at) { - if (typeof at === "string") - /* It is a URI */ - return this.attributes[at]; - else - /* FIXME: check that at is instance of AttributeType */ - return this.attributes[at.uri]; - }, - - - /* obsel modification (trace amendment) */ - - set_attribute_value: function(at, value) { - if (typeof at === "string") - /* It is a URI */ - this.attributes[at] = value; - /* FIXME: check that at is instance of AttributeType */ - else - this.attributes[at.uri] = value; - }, - - del_attribute_value: function(at) { - if (typeof at === "string") - /* It is a URI */ - delete this.attributes[at]; - /* FIXME: check that at is instance of AttributeType */ - else - delete this.attributes[at.uri]; - }, - - add_related_obsel: function(rt, value) { - /* FIXME: not implemented yet */ - }, - - del_related_obsel: function(rt, value) { - /* FIXME: not implemented yet */ - }, - - /* - * Return a JSON representation of the obsel - */ - toJSON: function() { - var r = { - "@id": this.id, - "@type": this.type, - "begin": this.begin, - "end": this.end, - "subject": this.subject - }; - for (var prop in this.attributes) { - if (this.attributes.hasOwnProperty(prop)) - r[prop] = this.attributes[prop]; - } - return r; - }, - - /* - * Return a compact JSON representation of the obsel. - * Use predefined + custom shorthands for types/properties - */ - toCompactJSON: function() { - var r = { - "@t": (this.trace.shorthands.hasOwnProperty(this.type) ? this.trace.shorthands[this.type] : this.type), - "@b": this.begin, - }; - // Transmit subject only if different from default_subject - if (this.subject !== this.trace.default_subject) - r["@s"] = this.subject; - - // Store duration (to save some bytes) and only if it is non-null - if (this.begin !== this.end) - r["@d"] = this.end - this.begin; - - // Store id only if != "" - if (this.id !== "") - r["@i"] = this.id; - - for (var prop in this.attributes) { - if (this.attributes.hasOwnProperty(prop)) - { - var v = this.attributes[prop]; - r[prop] = this.trace.shorthands.hasOwnProperty(v) ? this.trace.shorthands[v] : v; - } - } - return r; - }, - - toJSONstring: function() { - return JSON.stringify(this.toJSON()); - } - }; - - var Obsel = function(type, begin, end, subject, attributes) { - this.trace = undefined; - this.uri = ""; - this.id = ""; - this.type = type; - this.begin = begin; - this.end = end; - this.subject = subject; - /* Is the obsel synched with the server ? */ - this.sync_status = false; - /* Dictionary indexed by ObselType URIs */ - this.attributes = {}; - }; - Obsel.prototype = Obsel_prototype; - - var TraceManager_prototype = { - traces: [], - /* - * Return the trace with id name - * If it was not registered, return undefined. - */ - get_trace: function(name) { - return this.traces[name]; - }, - - /* - * Explicitly create and initialize a new trace with the given name. - * The optional uri parameter allows to initialize the trace URI. - * - * If another existed with the same name before, then it is replaced by a new one. - */ - init_trace: function(name, params) - { - if (window.console) window.console.log("init_trace", params); - url = params.url ? params.url : ""; - requestmode = params.requestmode ? params.requestmode : "POST"; - syncmode = params.syncmode ? params.syncmode : "none"; - default_subject = params.default_subject ? params.default_subject : "default"; - var t = new Trace(url, requestmode); - t.set_default_subject(default_subject); - t.set_sync_mode(syncmode); - this.traces[name] = t; - return t; - } - }; - - var TraceManager = function() { - this.traces = {}; - }; - TraceManager.prototype = TraceManager_prototype; - - var tracemanager = new TraceManager(); - return tracemanager; - })(jQuery); +/* + * Modelled Trace API + * + * This file is part of ktbs4js. + * + * ktbs4js is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * ktbs4js is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with ktbs4js. If not, see . + * + */ +/* FIXME: properly use require.js feature. This will do for debugging in the meantime */ +window.tracemanager = (function($) { + // If there are more than MAX_FAILURE_COUNT synchronisation + // failures, then disable synchronisation + var MAX_FAILURE_COUNT = 20; + + // If there are more than MAX_BUFFER_SIZE obsels in the buffer, + // then "compress" them as a single "ktbsFullBuffer" + var MAX_BUFFER_SIZE = 500; + + var _replacement = { + ';': '"', + '"': ';', + '#': '%23', + '&': '%26', + '?': '%3F' + }; + var BufferedService_prototype = { + /* + * Buffered service for traces + */ + // url: "", + // buffer: [], + // isReady: false, + // timer: null, + // failureCount: 0, + + /* Flush buffer */ + flush: function() { + // FIXME: add mutex on this.buffer + if (!this.isReady) { + if (window.console) { window.console.log("Sync service not ready"); }; + } else if (this.failureCount > MAX_FAILURE_COUNT) { + // Disable synchronisation + this.set_sync_mode('none'); + } else if (this.buffer.length) { + var temp = this.buffer; + this.buffer = []; + + if (this.mode == 'GET') { + // GET mode: do some data mangline. We mark the + // "compressed" nature of the generated JSON by + // prefixing it with c + var data = 'c' + JSON.stringify(temp.map(function (o) { return o.toCompactJSON(); })); + // Swap " (very frequent, which will be + // serialized into %22) and ; (rather rare), this + // saves some bytes + data = data.replace(/[;"#?&]/g, function(s) { return _replacement[s]; }); + // FIXME: check data length (< 2K is safe) + var request = $('').error(function() { this.failureCount += 1; }) + .load(function() { this.failureCount = 0; }) + .attr('src', this.url + 'trace/?data=' + data); + } else { + $.ajax({ url: this.url + 'trace/', + type: 'POST', + contentType: 'application/json', + data: JSON.stringify(temp.map(function (o) { return o.toJSON(); })), + processData: false, + // Type of the returned data. + dataType: "html", + error: function(jqXHR, textStatus, errorThrown) { + if (window.console) { window.console.log("Error when sending buffer:", textStatus); } + this.failureCount += 1; + }, + success: function(data, textStatus, jqXHR) { + // Reset failureCount to 0 as soon as there is 1 valid answer + this.failureCount = 0; + } + }); + } + } + }, + + /* Sync mode: delayed, sync (immediate sync), none (no + * synchronisation with server, the trace has to be explicitly saved + * if needed */ + set_sync_mode: function(mode, default_subject) { + this.sync_mode = mode; + if (! this.isReady && mode !== "none") + this.init(default_subject); + if (mode == 'delayed') { + this.start_timer(); + } else { + this.stop_timer(); + } + }, + + /* Enqueue an obsel */ + enqueue: function(obsel) { + if (this.buffer.length > MAX_BUFFER_SIZE) { + obsel = new Obsel('ktbsFullBuffer', this.buffer[0].begin, + this.buffer[this.buffer.length - 1].end, this.buffer[0].subject); + obsel.trace = this.buffer[0].trace; + this.buffer = []; + } + this.buffer.push(obsel); + if (this.sync_mode === 'sync') { + // Immediate sync of the obsel. + this.flush(); + } + }, + + start_timer: function() { + var self = this; + if (this.timer === null) { + this.timer = window.setInterval(function() { + self.flush(); + }, this.timeOut); + } + }, + + stop_timer: function() { + if (this.timer !== null) { + window.clearInterval(this.timer); + this.timer = null; + } + }, + + /* + * Initialize the sync service + */ + init: function(default_subject) { + var self = this; + if (this.isReady) + /* Already initialized */ + return; + if (typeof default_subject === 'undefined') + default_subject = 'anonymous'; + if (this.mode == 'GET') { + var request=$('').attr('src', this.url + 'login?userinfo={"default_subject": "' + default_subject + '"}'); + // Do not wait for the return, assume it is + // initialized. This assumption will not work anymore + // if login returns some necessary information + this.isReady = true; + } else { + $.ajax({ url: this.url + 'login', + type: 'POST', + data: 'userinfo={"default_subject":"' + default_subject + '"}', + success: function(data, textStatus, jqXHR) { + self.isReady = true; + if (self.buffer.length) { + self.flush(); + } + } + }); + } + } + }; + var BufferedService = function(url, mode) { + this.url = url; + this.buffer = []; + this.isReady = false; + this.timer = null; + this.failureCount = 0; + // sync_mode is either "none", "sync" or "buffered" + this.sync_mode = "none"; + /* mode can be either POST or GET */ + if (mode == 'POST' || mode == 'GET') + this.mode = mode; + else + this.mode = 'POST'; + /* Flush buffer every timeOut ms if the sync_mode is delayed */ + this.timeOut = 2000; + }; + BufferedService.prototype = BufferedService_prototype; + + var Trace_prototype = { + /* FIXME: We could/should use a sorted list such as + http://closure-library.googlecode.com/svn/docs/class_goog_structs_AvlTree.html + to speed up queries based on time */ + obsels: [], + /* Trace URI */ + uri: "", + default_subject: "", + /* baseuri is used as the base URI to resolve relative + * attribute-type names in obsels. Strictly speaking, this + * should rather be expressed as a reference to model, or + * more generically, as a qname/URI dict */ + baseuri: "", + /* Mapping of obsel type or property name to a compact + * representation (shorthands). + */ + shorthands: null, + syncservice: null, + + /* Define the trace URI */ + set_uri: function(uri) { + this.uri = uri; + }, + + /* Sync mode: delayed, sync (immediate sync), none (no + * synchronisation with server, the trace has to be explicitly saved + * if needed */ + set_sync_mode: function(mode) { + if (this.syncservice !== null) { + this.syncservice.set_sync_mode(mode, this.default_subject); + } + }, + + /* + * Return a list of the obsels of this trace matching the parameters + */ + list_obsels: function(_begin, _end, _reverse) { + var res; + if (typeof _begin !== 'undefined' || typeof _end !== 'undefined') { + /* + * Not optimized yet. + */ + res = []; + var l = this.obsels.length; + for (var i = 0; i < l; i++) { + var o = this.obsels[i]; + if ((typeof _begin !== 'undefined' && o.begin > _begin) && (typeof _end !== 'undefined' && o.end < _end)) { + res.push(o); + } + } + } + + if (typeof _reverse !== 'undefined') { + if (res !== undefined) { + /* Should reverse the whole list. Make a copy. */ + res = this.obsels.slice(0); + } + res.sort(function(a, b) { return b.begin - a.begin; }); + return res; + } + + if (res === undefined) { + res = this.obsels; + } + return res; + + }, + + /* + * Return the obsel of this trace identified by the URI, or undefined + */ + get_obsel: function(id) { + for (var i = 0; i < this.obsels.length; i++) { + /* FIXME: should check against variations of id/uri, take this.baseuri into account */ + if (this.obsels[i].uri === id) { + return this.obsels[i]; + } + } + return undefined; + }, + + set_default_subject: function(subject) { + // FIXME: if we call this method after the sync_service + // init method, then the default_subject will not be + // consistent anymore. Maybe we should then call init() again? + this.default_subject = subject; + }, + + get_default_subject: function() { + return this.default_subject; + }, + + /* (type:ObselType, begin:int, end:int?, subject:str?, attributes:[AttributeType=>any]?) */ + /* Create a new obsel and add it to the trace */ + create_obsel: function(type, begin, end, subject, _attributes) { + var o = new Obsel(type, begin, end, subject); + if (typeof _attributes !== 'undefined') { + o.attributes = _attributes; + } + o.trace = this; + this.obsels.push(o); + if (this.syncservice !== null) + this.syncservice.enqueue(o); + }, + + /* Helper methods */ + + /* Create a new obsel with the given attributes */ + trace: function(type, _attributes, _begin, _end, _subject) { + var t = (new Date()).getTime(); + if (typeof begin === 'undefined') { + _begin = t; + } + if (typeof end === 'undefined') { + _end = _begin; + } + if (typeof subject === 'undefined') { + _subject = this.default_subject; + } + if (typeof _attributes === 'undefined') { + _attributes = {}; + } + return this.create_obsel(type, _begin, _end, _subject, _attributes); + } + }; + + var Trace = function(uri, requestmode) { + /* FIXME: We could/should use a sorted list such as + http://closure-library.googlecode.com/svn/docs/class_goog_structs_AvlTree.html + to speed up queries based on time */ + this.obsels = []; + /* Trace URI */ + if (uri === undefined) + uri = ""; + this.uri = uri; + this.sync_mode = "none"; + this.default_subject = ""; + this.shorthands = {}; + /* baseuri is used a the base URI to resolve relative attribute names in obsels */ + this.baseuri = ""; + + this.syncservice = new BufferedService(uri, requestmode); + $(window).unload( function () { + if (this.syncservice && this.sync_mode !== 'none') { + this.syncservice.flush(); + this.syncservice.stop_timer(); + } + }); + }; + Trace.prototype = Trace_prototype; + + var Obsel_prototype = { + /* The following attributes are here for documentation + * purposes. They MUST be defined in the constructor + * function. */ + trace: undefined, + type: undefined, + begin: undefined, + end: undefined, + subject: undefined, + /* Dictionary indexed by ObselType URIs */ + attributes: {}, + + /* Method definitions */ + get_trace: function() { + return this.trace; + }, + + get_obsel_type: function() { + return this.type; + }, + get_begin: function() { + return this.begin; + }, + get_end: function() { + return this.end; + }, + get_subject: function() { + return this.subject; + }, + + list_attribute_types: function() { + var result = []; + for (var prop in this.attributes) { + if (this.attributes.hasOwnProperty(prop)) + result.push(prop); + } + /* FIXME: we return URIs here instead of AttributeType elements */ + return result; + }, + + list_relation_types: function() { + /* FIXME: not implemented yet */ + }, + + list_related_obsels: function (rt) { + /* FIXME: not implemented yet */ + }, + list_inverse_relation_types: function () { + /* FIXME: not implemented yet */ + }, + list_relating_obsels: function (rt) { + /* FIXME: not implemented yet */ + }, + /* + * Return the value of the given attribute type for this obsel + */ + get_attribute_value: function(at) { + if (typeof at === "string") + /* It is a URI */ + return this.attributes[at]; + else + /* FIXME: check that at is instance of AttributeType */ + return this.attributes[at.uri]; + }, + + + /* obsel modification (trace amendment) */ + + set_attribute_value: function(at, value) { + if (typeof at === "string") + /* It is a URI */ + this.attributes[at] = value; + /* FIXME: check that at is instance of AttributeType */ + else + this.attributes[at.uri] = value; + }, + + del_attribute_value: function(at) { + if (typeof at === "string") + /* It is a URI */ + delete this.attributes[at]; + /* FIXME: check that at is instance of AttributeType */ + else + delete this.attributes[at.uri]; + }, + + add_related_obsel: function(rt, value) { + /* FIXME: not implemented yet */ + }, + + del_related_obsel: function(rt, value) { + /* FIXME: not implemented yet */ + }, + + /* + * Return a JSON representation of the obsel + */ + toJSON: function() { + var r = { + "@id": this.id, + "@type": this.type, + "begin": this.begin, + "end": this.end, + "subject": this.subject + }; + for (var prop in this.attributes) { + if (this.attributes.hasOwnProperty(prop)) + r[prop] = this.attributes[prop]; + } + return r; + }, + + /* + * Return a compact JSON representation of the obsel. + * Use predefined + custom shorthands for types/properties + */ + toCompactJSON: function() { + var r = { + "@t": (this.trace.shorthands.hasOwnProperty(this.type) ? this.trace.shorthands[this.type] : this.type), + "@b": this.begin, + }; + // Transmit subject only if different from default_subject + if (this.subject !== this.trace.default_subject) + r["@s"] = this.subject; + + // Store duration (to save some bytes) and only if it is non-null + if (this.begin !== this.end) + r["@d"] = this.end - this.begin; + + // Store id only if != "" + if (this.id !== "") + r["@i"] = this.id; + + for (var prop in this.attributes) { + if (this.attributes.hasOwnProperty(prop)) + { + var v = this.attributes[prop]; + r[prop] = this.trace.shorthands.hasOwnProperty(v) ? this.trace.shorthands[v] : v; + } + } + return r; + }, + + toJSONstring: function() { + return JSON.stringify(this.toJSON()); + } + }; + + var Obsel = function(type, begin, end, subject, attributes) { + this.trace = undefined; + this.uri = ""; + this.id = ""; + this.type = type; + this.begin = begin; + this.end = end; + this.subject = subject; + /* Is the obsel synched with the server ? */ + this.sync_status = false; + /* Dictionary indexed by ObselType URIs */ + this.attributes = {}; + }; + Obsel.prototype = Obsel_prototype; + + var TraceManager_prototype = { + traces: [], + /* + * Return the trace with id name + * If it was not registered, return undefined. + */ + get_trace: function(name) { + return this.traces[name]; + }, + + /* + * Explicitly create and initialize a new trace with the given name. + * The optional uri parameter allows to initialize the trace URI. + * + * If another existed with the same name before, then it is replaced by a new one. + */ + init_trace: function(name, params) + { + if (window.console) window.console.log("init_trace", params); + url = params.url ? params.url : ""; + requestmode = params.requestmode ? params.requestmode : "POST"; + syncmode = params.syncmode ? params.syncmode : "none"; + default_subject = params.default_subject ? params.default_subject : "default"; + var t = new Trace(url, requestmode); + t.set_default_subject(default_subject); + t.set_sync_mode(syncmode); + this.traces[name] = t; + return t; + } + }; + + var TraceManager = function() { + this.traces = {}; + }; + TraceManager.prototype = TraceManager_prototype; + + var tracemanager = new TraceManager(); + return tracemanager; + })(jQuery); From 641c94fe7fc50d44abcfcb2278dba6eade864a57 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 30 Aug 2016 14:54:59 +0200 Subject: [PATCH 189/204] Display creator --- src/widgets/EnrichedPlan.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 342d0779..edd16a6e 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -138,7 +138,7 @@ IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '
    \
    {{ begin }}
    \ {{{ text }}} \ - {{ author }} \ + {{ creator }} \ {{#can_edit}}\ {{#is_admin}}{{/is_admin}}\ \ @@ -152,9 +152,9 @@ IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = {{/comments.length}}\
    \ {{#comments}}\ -
    \ +
    \ {{description}}\ - {{modified}}\ + {{modified|slice:10}}\ {{creator}}\
    \ {{/comments}}\ @@ -477,7 +477,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { media_id: a.media.id, text: IriSP.textFieldHtml(a.getTitleOrDescription()), url: document.location.href.replace(/#.*$/, '') + '#id=' + a.id + '&t=' + (a.begin / 1000.0), - author: a.creator, + creator: a.creator, begin: a.begin.toString(), begin_ms: a.begin.milliseconds, end_ms: a.end.milliseconds, From 275ad71e0eeef541c5717715b3805ce6658e90d1 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Tue, 30 Aug 2016 14:55:16 +0200 Subject: [PATCH 190/204] Adjust padding --- src/widgets/EnrichedPlan.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 90dee2a7..7f802217 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -478,6 +478,7 @@ label:hover:before { flex-direction: column; width: 100%; padding-top: 10px; + padding-left: 1em; } .Ldt-EnrichedPlan-Comment-New.Ldt-EnrichedPlan-Expanded { From 94ef46289d5b9d12f173559db23cba6f1420e1b6 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 2 Sep 2016 17:26:22 +0200 Subject: [PATCH 191/204] Handle non-defined input field --- src/widgets/EnrichedPlan.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index edd16a6e..39f81051 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -318,7 +318,7 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { }); var inputField = _this.container.find(".Ldt-EnrichedPlan-Search-Input"); - inputField.on('onsearch' in inputField[0] ? "search" : "keyup", function () { + inputField.length && inputField.on('onsearch' in inputField[0] ? "search" : "keyup", function () { var q = IriSP.jQuery(this).val().toLocaleLowerCase(); if (q === "") { // Show all From 498c4c269b7e32784bdbee91a2a0738f9b6b08d9 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Mon, 5 Sep 2016 14:42:40 +0200 Subject: [PATCH 192/204] Rename Search to Filter --- src/widgets/EnrichedPlan.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 39f81051..9c3aa514 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -23,7 +23,7 @@ IriSP.Widgets.EnrichedPlan.prototype.messages = { quiz_notes: "Quiz questions", popup_tabconfig: "Configure tab display", slides: "Slides", - search: "Search...", + search: "Filter...", whole_video: "Whole video", expand_slide: "Show the slide content", comment_count: "comment(s)", @@ -39,7 +39,7 @@ IriSP.Widgets.EnrichedPlan.prototype.messages = { quiz_notes: "Questions de quiz", popup_tabconfig: "Configurer les onglets", slides: "Diapo", - search: "Recherchez...", + search: "Filtrer...", whole_video: "Vidéo entière", expand_slide: "Montrer le contenu de la diapo", comment_count: "commentaire(s)", From 630d6d6c1922cdcb886f85142d1e48e1bb5c0b18 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 7 Sep 2016 00:42:41 +0200 Subject: [PATCH 193/204] Trace settings checkboxes --- src/widgets/EnrichedPlan.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 9c3aa514..3409100e 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -78,7 +78,7 @@ IriSP.Widgets.EnrichedPlan.prototype.template = + '{{#show_controls}}' + '
    ' + ' ' - + ' ' + + ' ' + '
      ' + '
    • {{l10n.popup_tabconfig}}
    • ' + '
    • ' @@ -86,20 +86,20 @@ IriSP.Widgets.EnrichedPlan.prototype.template = + ' ' + '
    • ' + '
    • ' - + ' ' + + ' ' + ' ' + '
    • ' + '
    • ' - + ' ' + + ' ' + ' ' + '
    • ' + '
    • ' - + ' ' + + ' ' + ' ' + '
    • ' + '{{^flat_mode}}' + '
    • ' - + ' ' + + ' ' + ' ' + '
    • ' + '{{/flat_mode}}' @@ -210,7 +210,7 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { }); _this.container.on("click", ".Ldt-EnrichedPlan-Control-Checkbox", function () { var classname = _.first(_.filter(this.classList, function (s) { - return s != "Ldt-EnrichedPlan-Control-Checkbox"; + return s != "Ldt-EnrichedPlan-Control-Checkbox" && s.indexOf("Ldt-EnrichedPlan") == 0; })); if (classname !== undefined) { if (IriSP.jQuery(this).is(':checked')) { @@ -320,6 +320,7 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { var inputField = _this.container.find(".Ldt-EnrichedPlan-Search-Input"); inputField.length && inputField.on('onsearch' in inputField[0] ? "search" : "keyup", function () { var q = IriSP.jQuery(this).val().toLocaleLowerCase(); + _this.player.trigger("EnrichedPlan.filter", q); if (q === "") { // Show all IriSP.jQuery(".Ldt-EnrichedPlan-Content").unmark().find(".non_matching").removeClass("non_matching"); From 21e5576875f54e1b4ab7d98a1356ab3b301cf419 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 7 Sep 2016 00:48:57 +0200 Subject: [PATCH 194/204] Trigger player event when changing setting --- src/widgets/EnrichedPlan.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 3409100e..ada90019 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -86,20 +86,20 @@ IriSP.Widgets.EnrichedPlan.prototype.template = + ' ' + ' ' + '
    • ' - + ' ' + + ' ' + ' ' + '
    • ' + '
    • ' - + ' ' + + ' ' + ' ' + '
    • ' + '
    • ' - + ' ' + + ' ' + ' ' + '
    • ' + '{{^flat_mode}}' + '
    • ' - + ' ' + + ' ' + ' ' + '
    • ' + '{{/flat_mode}}' @@ -218,11 +218,13 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { if (_this.bar) { _this.bar.find("." + classname).removeClass("filtered_out"); } + _this.player.trigger("EnrichedPlan.SettingCheck", classname); } else { _this.content.find(".Ldt-EnrichedPlan-Slide ." + classname).addClass("filtered_out"); if (_this.bar) { _this.bar.find("." + classname).addClass("filtered_out"); } + _this.player.trigger("EnrichedPlan.SettingUncheck", classname); } } }); From 5ec15de3e8b87decf5cfcd14d39838ad2efd7cf3 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 28 Sep 2016 17:28:29 +0200 Subject: [PATCH 195/204] Add Comment Edit icon --- src/widgets/EnrichedPlan.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index ada90019..58fb6cc5 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -156,6 +156,9 @@ IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = {{description}}\ {{modified|slice:10}}\ {{creator}}\ + {{#can_edit}}\ + \ + {{/can_edit}}\
    \ {{/comments}}\ {{#is_authenticated}}\ From 00c6cfdc36a4b24b7538bd04ecb37b35eb78f0d3 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 29 Sep 2016 12:02:26 +0200 Subject: [PATCH 196/204] Make PIP view transparent --- src/widgets/SlideVideoPlayer.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index c66d8431..5dc656fe 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -40,6 +40,7 @@ right: 2px; border: 1px solid #999; box-shadow: #999 2px 2px 2px; + opacity: 50%; } .Ldt-SlideVideoPlayer-pip-br { From 5e1cb27993560e715bfccdedf02229fd701e6365 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 12 Oct 2016 09:25:41 +0200 Subject: [PATCH 197/204] Right align comment edit icon --- src/widgets/EnrichedPlan.css | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 7f802217..13cac2f3 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -401,6 +401,7 @@ label:hover:before { background-color: #ededed; } +.Ldt-EnrichedPlan-Comment-Edit, .Ldt-EnrichedPlan-EditControl span { display: inline-block; width: 24px; @@ -411,15 +412,21 @@ label:hover:before { background-repeat: no-repeat; } +.Ldt-EnrichedPlan-Comment-Edit { + position: absolute; + right: 2px; +} + +.Ldt-EnrichedPlan-Comment-Edit, .Ldt-EnrichedPlan-EditControl-Edit { - background: url(img/notes_edit.svg); + background-image: url(img/notes_edit.svg); } .Ldt-EnrichedPlan-EditControl-Featured { - background: url(img/notes_featured.svg); + background-image: url(img/notes_featured.svg); } .Ldt-EnrichedPlan-EditControl-Delete { - background: url(img/notes_delete.svg); + background-image: url(img/notes_delete.svg); } .Ldt-EnrichedPlan-Selected-Timecode, From 19f127de1dc693275c493f1291677c99a22b2f8a Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 12 Oct 2016 09:25:47 +0200 Subject: [PATCH 198/204] Highlight comments --- src/widgets/EnrichedPlan.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 13cac2f3..289019c3 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -488,6 +488,12 @@ label:hover:before { padding-left: 1em; } +.Ldt-EnrichedPlan-Comment { + background-color: #fafafa; + margin: 3px; + min-height: 32px; +} + .Ldt-EnrichedPlan-Comment-New.Ldt-EnrichedPlan-Expanded { display: inline-flex; } From da0e3487180b383ed7a740f682641857e12f9b03 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 12 Oct 2016 09:26:17 +0200 Subject: [PATCH 199/204] Fix Comment.edit trigger --- src/widgets/EnrichedPlan.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 58fb6cc5..0c180f6f 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -157,7 +157,7 @@ IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = {{modified|slice:10}}\ {{creator}}\ {{#can_edit}}\ - \ + \ {{/can_edit}}\
    \ {{/comments}}\ @@ -243,9 +243,12 @@ IriSP.Widgets.EnrichedPlan.prototype.init_component = function () { _this.player.trigger("Annotation.delete", this.dataset.id); } }); + _this.container.on("click", ".Ldt-EnrichedPlan-Comment-Edit", function () { + _this.player.trigger("Comment.edit", { comment_id: this.dataset.id, + parent_annotation_id: this.dataset.annotation_id }); + }); function add_comment(annotation_id, text) { - console.log("Commenting ", annotation_id, text); IriSP.jQuery.ajax({ url: _this.action_url("add_comment", annotation_id), timeout: 2000, @@ -479,6 +482,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { var cat = note_category(a); var annData = { id: a.id, + annotation_id: a.id, l10n: _this.l10n, media_id: a.media.id, text: IriSP.textFieldHtml(a.getTitleOrDescription()), From 99ca3adbc3977a3ccb6ec850abe9b947f70b2c9e Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 12 Oct 2016 09:26:32 +0200 Subject: [PATCH 200/204] Get featured information from a.meta dict --- src/widgets/EnrichedPlan.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 0c180f6f..a3bf30c0 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -504,7 +504,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { comments: a.meta['coco:comments'], filtered: ((cat == 'Own' && !_this.show_own_notes) || (cat == 'Other' && !_this.show_other_notes) - || (cat == 'Featured' && !_this.show_featured_notes) + || (a.meta['coco:featured'] && !_this.show_featured_notes) || (cat == 'Quiz' && !_this.show_quiz_notes) ) ? 'filtered_out' : '' }; From b3166cf7dbe5b24ac251923120d7b9e3b0a3815d Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 12 Oct 2016 09:26:43 +0200 Subject: [PATCH 201/204] Fix PIP opacity value --- src/widgets/SlideVideoPlayer.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/SlideVideoPlayer.css b/src/widgets/SlideVideoPlayer.css index 5dc656fe..71d6dae0 100644 --- a/src/widgets/SlideVideoPlayer.css +++ b/src/widgets/SlideVideoPlayer.css @@ -40,7 +40,7 @@ right: 2px; border: 1px solid #999; box-shadow: #999 2px 2px 2px; - opacity: 50%; + opacity: .5; } .Ldt-SlideVideoPlayer-pip-br { From 86f37cf73d3f0c684f63b1a864b8ee6d7a8122b5 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Wed, 12 Oct 2016 09:37:34 +0200 Subject: [PATCH 202/204] Fix comment width when editable --- src/widgets/EnrichedPlan.css | 8 ++++++++ src/widgets/EnrichedPlan.js | 10 ++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 289019c3..23023049 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -401,6 +401,14 @@ label:hover:before { background-color: #ededed; } +.Ldt-EnrichedPlan-Comment-Content { + display: inline-block; + width: 100%; +} +.Ldt-EnrichedPlan-Comment-Content.editable { + width: calc(100% - 30px); +} + .Ldt-EnrichedPlan-Comment-Edit, .Ldt-EnrichedPlan-EditControl span { display: inline-block; diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index a3bf30c0..fb2f0cbf 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -153,11 +153,13 @@ IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate =
    \ {{#comments}}\
    \ - {{description}}\ - {{modified|slice:10}}\ - {{creator}}\ +
    \ + {{description}}\ + {{modified|slice:10}}\ + {{creator}}\ +
    \ {{#can_edit}}\ - \ + \ {{/can_edit}}\
    \ {{/comments}}\ From dec05e364d26eb8e0e1ccae6c2383dc27a52d235 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Thu, 13 Oct 2016 14:48:31 +0200 Subject: [PATCH 203/204] Modify display of annotation count --- src/widgets/EnrichedPlan.css | 23 +++++++++++++++++++++++ src/widgets/EnrichedPlan.js | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.css b/src/widgets/EnrichedPlan.css index 23023049..cd07b16a 100644 --- a/src/widgets/EnrichedPlan.css +++ b/src/widgets/EnrichedPlan.css @@ -225,6 +225,29 @@ text-transform: uppercase; font-size: 10px; } +.Ldt-EnrichedPlan-Comments-Count { + border: 1px solid; + min-width: 12px; + height: 17px; + border-radius: 3px; + display: inline-block; + font-family: roboto; + font-size: 10px; + padding: 1px 2px; +} + +.Ldt-EnrichedPlan-Note-Own .Ldt-EnrichedPlan-Comments-Count { + background-color: #66ccff; + color: #fff; +} +.Ldt-EnrichedPlan-Note-Other .Ldt-EnrichedPlan-Comments-Count { + background-color: #996633; + color: #fff; +} +.Ldt-EnrichedPlan-Note-Quiz .Ldt-EnrichedPlan-Comments-Count { + background-color: #669933; + color: #fff; +} .Ldt-EnrichedPlan-Container { overflow-y: hidden; diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index fb2f0cbf..88afd733 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -148,7 +148,7 @@ IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate =
    {{/is_admin}}\ {{#show_comments}}\ {{#comments.length}}\ - {{comments.length}} {{l10n.comment_count}}\ + {{comments.length}}\ {{/comments.length}}\
    \ {{#comments}}\ From e8db6c1143c787729944364d1dd728e08d54d91b Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 14 Oct 2016 10:28:25 +0200 Subject: [PATCH 204/204] Select annotation identified in the document fragment --- src/widgets/EnrichedPlan.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/widgets/EnrichedPlan.js b/src/widgets/EnrichedPlan.js index 88afd733..a9d5b706 100644 --- a/src/widgets/EnrichedPlan.js +++ b/src/widgets/EnrichedPlan.js @@ -135,7 +135,7 @@ IriSP.Widgets.EnrichedPlan.prototype.slideBarTemplate = + '
    '; IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = - '
    \ + '
    \
    {{ begin }}
    \ {{{ text }}} \ {{ creator }} \ @@ -410,7 +410,12 @@ IriSP.Widgets.EnrichedPlan.prototype.get_slides = function () { IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { var _this = this; var _slides = this.get_slides(); + var selected_annotation = null; + var match = document.location.hash.match(/id=([0-9a-f-]+)/); + if (match !== null) { + selected_annotation = match[1]; + } var _annotations = this.media.getAnnotations().filter(function (a) { return a.getAnnotationType().title != _this.annotation_type; }).sortBy(function (_annotation) { @@ -485,6 +490,7 @@ IriSP.Widgets.EnrichedPlan.prototype.update_content = function () { var annData = { id: a.id, annotation_id: a.id, + selected: (a.id == selected_annotation), l10n: _this.l10n, media_id: a.media.id, text: IriSP.textFieldHtml(a.getTitleOrDescription()),