From 7114b25a40ad88c2d87be680cb71b3e0544d7cbf Mon Sep 17 00:00:00 2001 From: lduarte1991 Date: Mon, 11 Aug 2014 17:01:15 -0400 Subject: [PATCH 1/2] Annotation Tools: Explicit typecasting === changes and reorganizing plugins --- common/static/js/vendor/ova/catch/js/catch.js | 18 +++++++++--------- common/static/js/vendor/ova/ova.js | 8 ++++---- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/common/static/js/vendor/ova/catch/js/catch.js b/common/static/js/vendor/ova/catch/js/catch.js index b76b2e67ed..a5da7106a8 100644 --- a/common/static/js/vendor/ova/catch/js/catch.js +++ b/common/static/js/vendor/ova/catch/js/catch.js @@ -352,7 +352,7 @@ CatchAnnotation.prototype = { // if the default tab is instructor, we must refresh the catch to pull the ones // under the instructor's email. Calling changeUserId will update this.options.userId // and most importantly refresh not only the highlights (from Annotator) - // but also the table below from the annotations database server (called Catch). + // but also the table below from the annotations database server (called Catch). if(this.options.default_tab.toLowerCase() === 'instructor') { this.changeUserId(this.options.instructor_email); } @@ -717,7 +717,7 @@ CatchAnnotation.prototype = { var isInList = false; var list = $('#mainCatch .annotationList .annotationRow.item'); for (_i = 0, _len = list.length; _i < _len; _i++) { - if ($(list[_i]).parent().attr('annotationid') === an.id) + if (parseInt($(list[_i]).parent().attr('annotationid'), 10) === an.id) isInList = true; } return isInList; @@ -800,7 +800,7 @@ CatchAnnotation.prototype = { $(evt.target).parents('.detailHeader:first').find('#myLocationMap .map').html(imgSrc); }, _onPlaySelectionClick: function(evt) { - var id = $(evt.target).find('.idAnnotation').html(); + var id = parseInt($(evt.target).find('.idAnnotation').html(), 10); var uri = $(evt.target).find('.uri').html(); var container = $(evt.target).find('.container').html(); if (this.options.externalLink) { @@ -858,7 +858,7 @@ CatchAnnotation.prototype = { }, _onZoomToImageBoundsButtonClick: function(evt){ var zoomToBounds = $(evt.target).hasClass('zoomToImageBounds')?$(evt.target):$(evt.target).parents('.zoomToImageBounds:first'); - var osdaId = zoomToBounds.find('.idAnnotation').html(); + var osdaId = parseInt(zoomToBounds.find('.idAnnotation').html(), 10); var uri = zoomToBounds.find('.uri').html(); var allannotations = this.annotator.plugins['Store'].annotations; @@ -887,7 +887,7 @@ CatchAnnotation.prototype = { }, _onQuoteMediaButton: function(evt) { var quote = $(evt.target).hasClass('quote')?$(evt.target):$(evt.target).parents('.quote:first'); - var id = quote.find('.idAnnotation').html(); + var id = parseInt(quote.find('.idAnnotation').html(), 10); var uri = quote.find('.uri').html(); if (typeof id === 'undefined' || id === ''){ this.refreshCatch(); @@ -927,7 +927,7 @@ CatchAnnotation.prototype = { }, _refreshReplies: function(evt) { var item = $(evt.target).parents('.annotationItem:first'); - var anId = item.attr('annotationId'); + var anId = parseInt(item.attr('annotationId'), 10); var replyElem = $(evt.target).parents('.annotationItem:first').find('.replies'); var annotator = this.annotator; @@ -954,7 +954,7 @@ CatchAnnotation.prototype = { if (typeof replyItems !== 'undefined' && replyItems.length > 0) { annotations.forEach(function(ann) { replyItems.each(function(item) { - var id = $(replyItems[item]).attr('annotationid'); + var id = parseInt($(replyItems[item]).attr('annotationid'), 10); if (id === ann.id) { var perm = self.annotator.plugins.Permissions; if (!perm.options.userAuthorize('delete', ann, perm.user)) { @@ -1031,7 +1031,7 @@ CatchAnnotation.prototype = { if (confirm("Would you like to delete the annotation?")) { var annotator = this.annotator; var item = $(evt.target).parents('.annotationItem:first'); - var id = item.attr('annotationId'); + var id = parseInt(item.attr('annotationId'), 10); var store = annotator.plugins.Store; var annotations = store.annotations; var permissions = annotator.plugins.Permissions; @@ -1048,7 +1048,7 @@ CatchAnnotation.prototype = { var annotator = this.annotator; var item = $(evt.target).parents('.annotationItem:first'); - var id = item.attr('annotationId'); + var id = parseInt(item.attr('annotationId'), 10); var store = annotator.plugins.Store; var annotations = store.annotations; var permissions = annotator.plugins.Permissions; diff --git a/common/static/js/vendor/ova/ova.js b/common/static/js/vendor/ova/ova.js index fc5bda3d36..0170aca97a 100644 --- a/common/static/js/vendor/ova/ova.js +++ b/common/static/js/vendor/ova/ova.js @@ -2385,9 +2385,6 @@ OpenVideoAnnotation.Annotator = function (element, options) { if (typeof options.optionsAnnotator.store!='undefined') this.annotator.addPlugin("Store", options.optionsAnnotator.store); - - if (typeof options.optionsAnnotator.highlightTags!='undefined') - this.annotator.addPlugin("HighlightTags", options.optionsAnnotator.highlightTags); if (typeof options.optionsAnnotator.diacriticMarks != 'undefined' && typeof Annotator.Plugin["Diacritics"] === 'function') this.annotator.addPlugin("Diacritics", options.optionsAnnotator.diacriticMarks); @@ -2408,7 +2405,10 @@ OpenVideoAnnotation.Annotator = function (element, options) { if (typeof Annotator.Plugin["Flagging"] === 'function') this.annotator.addPlugin("Flagging"); - + + if (typeof options.optionsAnnotator.highlightTags!='undefined') + this.annotator.addPlugin("HighlightTags", options.optionsAnnotator.highlightTags); + //Will be add the player and the annotations plugin for video-js in the annotator this.annotator.mplayer = this.mplayer; this.annotator.editor.VideoJS=-1; From 63f1d9834d8b40efe04018f3d74458f4b8244710 Mon Sep 17 00:00:00 2001 From: lduarte1991 Date: Tue, 12 Aug 2014 13:35:42 -0400 Subject: [PATCH 2/2] - replaced tabs with 4 spaces - fixed spaces after commas, if conditions, braces, operators - fixed some typecasting issues as well - added missing semicolons --- common/static/js/vendor/ova/ova.js | 4837 ++++++++++++++-------------- 1 file changed, 2420 insertions(+), 2417 deletions(-) diff --git a/common/static/js/vendor/ova/ova.js b/common/static/js/vendor/ova/ova.js index 0170aca97a..d82569d4a4 100644 --- a/common/static/js/vendor/ova/ova.js +++ b/common/static/js/vendor/ova/ova.js @@ -17,12 +17,29 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -//----------------Utilities----------------// -var _ref, - __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, - __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, - createDateFromISO8601 = function(string) { +// ----------------Utilities---------------- // +var _ref; +var __bind = function(fn, me) { + return function() { + return fn.apply(me, arguments); + }; +}; +var __hasProp = {}.hasOwnProperty; +var __extends = function(child, parent) { + for (var key in parent) { + if (__hasProp.call(parent, key)) + child[key] = parent[key]; + } + function ctor() { + this.constructor = child; + } + + ctor.prototype = parent.prototype; + child.prototype = new ctor(); + child.__super__ = parent.prototype; + return child; +}; +var createDateFromISO8601 = function(string) { var d, date, offset, regexp, time, _ref; regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" + "(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\\.([0-9]+))?)?" + "(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?"; d = string.match(new RegExp(regexp)); @@ -57,7 +74,7 @@ var _ref, date.setTime(Number(time)); return date; }; -var Util = typeof Util !='undefined'? Util:{}; +var Util = typeof Util != 'undefined' ? Util : {}; Util.mousePosition = function(e, offsetEl) { var offset, _ref1; if ((_ref1 = $(offsetEl).css('position')) !== 'absolute' && _ref1 !== 'fixed' && _ref1 !== 'relative') { @@ -73,2472 +90,2458 @@ Util.mousePosition = function(e, offsetEl) { -//----------------Load videojs-Annotation Plugin----------------// -(function (){ -//-- Load Annotation plugin in videojs -function vjsAnnotation_(options){ - var player = this; - - //variables to know if it is ready - - player.annotations=new vjsAnnotation(player, options); - - //When the DOM, Range Slider and the video media is loaded - function initialVideoFinished(event) { - //-- wait for plugins --// - var wrapper = $('.annotator-wrapper').parent()[0], - annotator = $.data(wrapper, 'annotator'); - //wait for Annotator and the Share plugin - if (typeof Annotator.Plugin["Share"] === 'function') { - if (typeof annotator.isShareLoaded!='undefined' && annotator.isShareLoaded){ - annotator.unsubscribe('shareloaded',initialVideoFinished); - }else{ - annotator.subscribe('shareloaded',initialVideoFinished); - return false; - } - } - - var plugin = player.annotations; - - //All components will be initialize after they have been loaded by videojs - for (var index in plugin.components) { - plugin.components[index].init_(); - } +// ----------------Load videojs-Annotation Plugin---------------- // +(function () { + // -- Load Annotation plugin in videojs + function vjsAnnotation_(options){ + var player = this; + + // variables to know if it is ready + + player.annotations = new vjsAnnotation(player, options); + + // When the DOM, Range Slider and the video media is loaded + function initialVideoFinished(event) { + // -- wait for plugins -- // + var wrapper = $('.annotator-wrapper').parent()[0]; + var annotator = $.data(wrapper, 'annotator'); + + // wait for Annotator and the Share plugin + if (typeof Annotator.Plugin["Share"] === 'function') { + if (typeof annotator.isShareLoaded != 'undefined' && annotator.isShareLoaded) { + annotator.unsubscribe('shareloaded', initialVideoFinished); + } else { + annotator.subscribe('shareloaded', initialVideoFinished); + return false; + } + } + + var plugin = player.annotations; + + // All components will be initialize after they have been loaded by videojs + for (var index in plugin.components) { + plugin.components[index].init_(); + } - player.annotations.BigNewAn.show(); - - //set the position of the big buttom - plugin.setposBigNew(plugin.options.posBigNew); - - if(!options.showDisplay) plugin.hideDisplay(); - if(!options.showStatistics) plugin.hideStatistics(); - - - //Get current instance of annotator - player.annotator = annotator; - plugin.annotator = annotator; - - //get annotations - var allannotations = annotator.plugins['Store'].annotations; - plugin.refreshDisplay(); - - //-- Listener to Range Slider Plugin - player.rangeslider.rstb.on('mousedown', function(){plugin._onMouseDownRS(event)}); - //Open the autoPlay from the API - if (player.autoPlayAPI){ - var OnePlay = function (){ - player.annotations.showAnnotation(player.autoPlayAPI); - $('html,body').animate({ - scrollTop: $("#"+player.id_).offset().top}, - 'slow'); - } - if (player.techName == 'Youtube') - setTimeout(OnePlay, 100);//fix the delay playing youtube - else - OnePlay(); - } - - //set the number of Annotations to display - plugin.refreshDesignPanel(); - - //check full-screen change - player.on('fullscreenchange',function() { - if (player.isFullScreen) { - $(player.annotator.wrapper[0]).addClass('vjs-fullscreen'); - } else { - $(player.annotator.wrapper[0]).removeClass('vjs-fullscreen'); - } - plugin.refreshDesignPanel(); - }); - - //loaded plugin - plugin.loaded = true; - } - player.one('loadedRangeSlider', initialVideoFinished);//Loaded RangeSlider - - console.log("Loaded Annotation Plugin"); -} -videojs.plugin('annotations', vjsAnnotation_); + player.annotations.BigNewAn.show(); + + // set the position of the big buttom + plugin.setposBigNew(plugin.options.posBigNew); + + if(!options.showDisplay) + plugin.hideDisplay(); + if(!options.showStatistics) + plugin.hideStatistics(); + + + // Get current instance of annotator + player.annotator = annotator; + plugin.annotator = annotator; + + // get annotations + var allannotations = annotator.plugins['Store'].annotations; + plugin.refreshDisplay(); + + // -- Listener to Range Slider Plugin + player.rangeslider.rstb.on('mousedown', function(){plugin._onMouseDownRS(event)}); + // Open the autoPlay from the API + if (player.autoPlayAPI) { + var OnePlay = function () { + player.annotations.showAnnotation(player.autoPlayAPI); + $('html, body').animate({ + scrollTop: $("#" + player.id_).offset().top}, + 'slow'); + }; + if (player.techName == 'Youtube') + setTimeout(OnePlay, 100); // fix the delay playing youtube + else + OnePlay(); + } + + // set the number of Annotations to display + plugin.refreshDesignPanel(); + + // check full-screen change + player.on('fullscreenchange', function() { + if (player.isFullScreen) { + $(player.annotator.wrapper[0]).addClass('vjs-fullscreen'); + } else { + $(player.annotator.wrapper[0]).removeClass('vjs-fullscreen'); + } + plugin.refreshDesignPanel(); + }); + + // loaded plugin + plugin.loaded = true; + } + player.one('loadedRangeSlider', initialVideoFinished); // Loaded RangeSlider + + console.log("Loaded Annotation Plugin"); + } + videojs.plugin('annotations', vjsAnnotation_); -//-- Plugin -function vjsAnnotation(player,options){ - var player = player || this; - - this.player = player; - - this.components = {}; // holds any custom components we add to the player + // -- Plugin + function vjsAnnotation(player, options) { + var player = player || this; + + this.player = player; + + this.components = {}; // holds any custom components we add to the player - options = options || {}; // plugin options - - if(!options.hasOwnProperty('posBigNew')) - options.posBigNew = 'none'; // ul = up left || ur = up right || bl = below left || br = below right || c = center - if(!options.hasOwnProperty('showDisplay')) - options.showDisplay = false; - /*if(!options.hasOwnProperty('NumAnnotations')) - options.NumAnnotations = 16; */ - if(!options.hasOwnProperty('showStatistics')) - options.showStatistics = false; - - this.options = options; - - this.init(); -} + options = options || {}; // plugin options + + if(!options.hasOwnProperty('posBigNew')) + options.posBigNew = 'none'; // ul = up left || ur = up right || bl = below left || br = below right || c = center + if(!options.hasOwnProperty('showDisplay')) + options.showDisplay = false; + if(!options.hasOwnProperty('showStatistics')) + options.showStatistics = false; + + this.options = options; + + this.init(); + } -//-- Methods -vjsAnnotation.prototype = { - /*Constructor*/ - init:function(){ - var player = this.player || {}, - controlBar = player.controlBar, - seekBar = player.controlBar.progressControl.seekBar; - - this.updatePrecision = 3; - - //Components and Quick Aliases - this.BigNewAn = this.components.BigNewAnnotation = player.BigNewAnnotation; - this.AnConBut = this.components.AnContainerButtons = controlBar.AnContainerButtons; - this.ShowSt = this.components.ShowStatistics = this.AnConBut.ShowStatistics; - this.NewAn = this.components.NewAnnotation = this.AnConBut.NewAnnotation; - this.ShowAn =this.components.ShowAnnotations = this.AnConBut.ShowAnnotations; - this.BackAnDisplay = this.components.BackAnDisplay = controlBar.BackAnDisplay;//Background of the panel - this.AnDisplay = this.components.AnDisplay = controlBar.BackAnDisplay.AnDisplay;//Panel with all the annotations - this.AnStat = this.components.AnStat = controlBar.BackAnDisplay.AnStat;//Panel with statistics of the number of annotations - this.BackAnDisplayScroll = this.components.BackAnDisplayScroll = controlBar.BackAnDisplayScroll;//Back Panel with all the annotations - this.backDSBar = this.components.BackAnDisplayScrollBar = this.BackAnDisplayScroll.BackAnDisplayScrollBar;//Scroll Bar - this.backDSBarSel = this.components.ScrollBarSelector = this.backDSBar.ScrollBarSelector;//Scroll Bar Selector - this.backDSTime = this.components.BackAnDisplayScrollTime = this.BackAnDisplayScroll.BackAnDisplayScrollTime;//Back Panel with time of the annotations in the scroll - this.rsd = this.components.RangeSelectorDisplay = controlBar.BackAnDisplay.RangeSelectorDisplay;//Selection the time to display the annotations - this.rsdl = this.components.RangeSelectorLeft = this.rsd.RangeSelectorLeft; - this.rsdr = this.components.RangeSelectorRight = this.rsd.RangeSelectorRight; - this.rsdb = this.components.RangeSelectorBar = this.rsd.RangeSelectorBar; - this.rsdbl = this.components.RangeSelectorBarL = this.rsdb.RangeSelectorBarL; - this.rsdbr = this.components.RangeSelectorBarR = this.rsdb.RangeSelectorBarR; - this.rs = player.rangeslider; - - //local variables - this.editing = false; - - var wrapper = $('.annotator-wrapper').parent()[0], - annotator = $.data(wrapper, 'annotator'), - self = this; - //Subscribe to Annotator changes - annotator.subscribe("annotationsLoaded", function (annotations){ - if(self.loaded) - self.refreshDisplay(); - }); - annotator.subscribe("annotationUpdated", function (annotation){ - if(self.loaded) - self.refreshDisplay(); - }); - annotator.subscribe("annotationDeleted", function (annotation){ - var annotations = annotator.plugins['Store'].annotations, - tot = typeof annotations !='undefined'?annotations.length:0, - attempts = 0; // max 100 - //This is to watch the annotations object, to see when is deleted the annotation - var ischanged = function(){ - var new_tot = annotator.plugins['Store'].annotations.length; - if (attempts<100) - setTimeout(function(){ - if (new_tot != tot){ - if(self.loaded) - self.refreshDisplay(); - }else{ - attempts++; - ischanged(); - } - },100); //wait for the change in the annotations + // -- Methods + vjsAnnotation.prototype = { + /* Constructor */ + init: function() { + var player = this.player || {}; + var controlBar = player.controlBar; + var seekBar = player.controlBar.progressControl.seekBar; + + this.updatePrecision = 3; + + // Components and Quick Aliases + this.BigNewAn = this.components.BigNewAnnotation = player.BigNewAnnotation; + this.AnConBut = this.components.AnContainerButtons = controlBar.AnContainerButtons; + this.ShowSt = this.components.ShowStatistics = this.AnConBut.ShowStatistics; + this.NewAn = this.components.NewAnnotation = this.AnConBut.NewAnnotation; + this.ShowAn =this.components.ShowAnnotations = this.AnConBut.ShowAnnotations; + this.BackAnDisplay = this.components.BackAnDisplay = controlBar.BackAnDisplay; // Background of the panel + this.AnDisplay = this.components.AnDisplay = controlBar.BackAnDisplay.AnDisplay; // Panel with all the annotations + this.AnStat = this.components.AnStat = controlBar.BackAnDisplay.AnStat; // Panel with statistics of the number of annotations + this.BackAnDisplayScroll = this.components.BackAnDisplayScroll = controlBar.BackAnDisplayScroll; // Back Panel with all the annotations + this.backDSBar = this.components.BackAnDisplayScrollBar = this.BackAnDisplayScroll.BackAnDisplayScrollBar; // Scroll Bar + this.backDSBarSel = this.components.ScrollBarSelector = this.backDSBar.ScrollBarSelector; // Scroll Bar Selector + this.backDSTime = this.components.BackAnDisplayScrollTime = this.BackAnDisplayScroll.BackAnDisplayScrollTime; // Back Panel with time of the annotations in the scroll + this.rsd = this.components.RangeSelectorDisplay = controlBar.BackAnDisplay.RangeSelectorDisplay; // Selection the time to display the annotations + this.rsdl = this.components.RangeSelectorLeft = this.rsd.RangeSelectorLeft; + this.rsdr = this.components.RangeSelectorRight = this.rsd.RangeSelectorRight; + this.rsdb = this.components.RangeSelectorBar = this.rsd.RangeSelectorBar; + this.rsdbl = this.components.RangeSelectorBarL = this.rsdb.RangeSelectorBarL; + this.rsdbr = this.components.RangeSelectorBarR = this.rsdb.RangeSelectorBarR; + this.rs = player.rangeslider; + + // local variables + this.editing = false; + + var wrapper = $('.annotator-wrapper').parent()[0]; + var annotator = $.data(wrapper, 'annotator'); + var self = this; + // Subscribe to Annotator changes + annotator.subscribe("annotationsLoaded", function (annotations) { + if(self.loaded) + self.refreshDisplay(); + }); + annotator.subscribe("annotationUpdated", function (annotation) { + if(self.loaded) + self.refreshDisplay(); + }); + annotator.subscribe("annotationDeleted", function (annotation) { + var annotations = annotator.plugins['Store'].annotations; + var tot = typeof annotations !== 'undefined' ? annotations.length : 0; + var attempts = 0; // max 100 + // This is to watch the annotations object, to see when is deleted the annotation + var ischanged = function() { + var new_tot = annotator.plugins['Store'].annotations.length; + if (attempts < 100) + setTimeout(function(){ + if (new_tot !== tot) { + if(self.loaded) + self.refreshDisplay(); + } else { + attempts++; + ischanged(); + } + }, 100); // wait for the change in the annotations + }; + ischanged(); + }); + + this.BigNewAn.hide(); // Hide until the video is load + }, + newan: function(start, end) { + var player = this.player; + var annotator = this.annotator; + var sumPercent = 10; // percentage for the last mark + var currentTime = player.currentTime(); + var lastTime = this._sumPercent(currentTime, sumPercent); + + var start = typeof start !== 'undefined' ? start : currentTime; + var end = typeof end !== 'undefined' ? end : lastTime; + + this._reset(); + + // set position RS and pause the player + player.showSlider(); + player.pause(); + + player.setValueSlider(start, end); + + // This variable is to say the editor that we want create a VideoJS annotation + annotator.editor.VideoJS = this.player.id_; + + annotator.adder.show(); + + this._setOverRS(annotator.adder); + + // Open a new annotator dialog + annotator.onAdderClick(); + }, + showDisplay: function() { + this._reset(); + // show + this.BackAnDisplay.removeClass('disable'); // show the Container + this.BackAnDisplayScroll.removeClass('disable'); // show the scroll + // active button + this.ShowAn.addClass('active'); + this.options.showDisplay =true; + }, + hideDisplay: function() { + // hide + this.BackAnDisplay.addClass('disable'); // hide the Container + this.BackAnDisplayScroll.addClass('disable'); // hide the scroll + // no active button + videojs.removeClass(this.ShowAn.el_, 'active'); + this.options.showDisplay =false; + }, + showStatistics: function() { + this._reset(); + // show + this.BackAnDisplay.removeClass('disable'); // show the Container + this.AnStat.removeClass('disable'); // show Statistics + // mode (this mode will hide the annotations to show the statistics in the container) + this.BackAnDisplay.addClass('statistics'); // mode statistics + // paint + this.AnStat.paintCanvas(); // refresh canvas + // active button + this.ShowSt.addClass('active'); + this.options.showStatistics =true; + }, + hideStatistics: function() { + // hide + this.BackAnDisplay.addClass('disable'); // hide the Container + this.AnStat.addClass('disable'); // hide Statistics + // remove mode statistics + this.BackAnDisplay.removeClass('statistics'); + // no active button + this.ShowSt.removeClass('active'); + this.options.showStatistics = false; + }, + showAnnotation: function(annotation) { + var isVideo = this._isVideoJS(annotation); + if (isVideo) { + var start = annotation.rangeTime.start; + var end = annotation.rangeTime.end; + var duration = this.player.duration(); + var isPoint = videojs.round(start, 3) == videojs.round(end, 3); + + this._reset(); + + // show the range slider + this.rs.show(); + + // set the slider position + this.rs.setValues(start, end); + + // lock the player + this.rs.lock(); + + // play + if (!isPoint) + this.rs.playBetween(start, end); + + // fix small bar + var width = Math.min(1, Math.max(0.005, (this.rs._percent(end - start)))) * 100; + this.rs.bar.el_.style.width = width + '%'; + + // Add the annotation object to the bar + var bar = isPoint ? this.rs[((duration - start) / duration < 0.1) ? 'left' : 'right'].el_ : this.rs.bar.el_; + var holder = $(this.rs.left.el_).parent()[0]; + $(holder).append(''); + $(bar).appendTo( $(holder).find('.annotator-hl')); + + var span = $(bar).parent()[0]; + $.data(span, 'annotation', annotation); // Set the object in the span + + // set the editor over the range slider + this._setOverRS(this.annotator.editor.element); + this.annotator.editor.checkOrientation(); + + // hide the panel + this.rs.hidePanel(); + } + }, + hideAnnotation: function() { + this.rs.hide(); + this.rs.showPanel(); + + // remove the last single showed annotation + var holder = $(this.rs.left.el_).parent()[0]; + var holderRight = $(this.rs.right.el_).parent()[0]; + if ($(holder).find('.annotator-hl').length > 0) { + $($(holder).find('.annotator-hl')[0].children[0]).appendTo(holder); + $(holder).find('.annotator-hl').remove(); + } else if ($(holderRight).find('.annotator-hl').length > 0) { + $($(holderRight).find('.annotator-hl')[0].children[0]).appendTo(holderRight); + $(holderRight).find('.annotator-hl').remove(); + } + }, + editAnnotation: function(annotation, editor) { + // This will be usefull when we are going to edit an annotation. + if (this._isVideoJS(annotation)) { + this.hideDisplay(); + var player = this.player; + var editor = editor || this.annotator.editor; + + // show the slider and set in the position + player.showSlider(); + player.unlockSlider(); + player.setValueSlider(annotation.rangeTime.start, annotation.rangeTime.end); + + // show the time panel + player.showSliderPanel(); + + // set the editor over the range slider + this._setOverRS(editor.element); + editor.checkOrientation(); + + // set the VideoJS variable + editor.VideoJS = player.id_; + } + }, + refreshDisplay: function() { + var count = 0; + var allannotations = this.annotator.plugins['Store'].annotations; + + // Sort by date the Array + this._sortByDate(allannotations); + + // reset the panel + $(this.AnDisplay.el_).find('span').remove(); // remove the last html items + $(this.player.el_).find('.vjs-anpanel-annotation .annotation').remove(); // remove a deleted annotation without span wrapper + + for (var item in allannotations) { + var an = allannotations[item]; + + // check if the annotation is a video annotation + if (this._isVideoJS(an)){ + var div = document.createElement('div'); + var span = document.createElement('span'); + var start = this.rs._percent(an.rangeTime.start) * 100; + var end = this.rs._percent(an.rangeTime.end) * 100; + var width; + span.appendChild(div); + span.className = "annotator-hl"; + width = Math.min(100, Math.max(0.2, end - start)); + div.className = "annotation"; + div.id = count; + div.style.top = count + "em"; + div.style.left = start + '%'; + div.style.width = width + '%'; + div.start = an.rangeTime.start; + div.end = an.rangeTime.end; + this.AnDisplay.el_.appendChild(span); + + // detect point annotations + if (videojs.round(start, 0) == videojs.round(end, 0)) { + $(div).css('width', ''); + $(div).addClass("point"); + } + + // Set the object in the div + $.data(span, 'annotation', an); + // Add the highlights to the annotation + an.highlights = $(span); + + count++; + } }; - ischanged(); + var start = this.rs._seconds(parseFloat(this.rsdl.el_.style.left) / 100); + var end = this.rs._seconds(parseFloat(this.rsdr.el_.style.left) / 100); + + this.showBetween(start, end, this.rsdl.include, this.rsdr.include); + }, + showBetween: function (start, end, includeLeft, includeRight) { + var duration = this.player.duration(); + var start = start || 0; + var end = end || duration; + var annotationsHTML = $.makeArray($(this.player.el_).find('.vjs-anpanel-annotation .annotator-hl')); + var count = 0; + for (var index in annotationsHTML) { + var an = $.data(annotationsHTML[index], 'annotation'); + var expressionLeft = includeLeft ? (an.rangeTime.end >= start) : (an.rangeTime.start >= start); + var expressionRight = includeRight ? (an.rangeTime.start <= end) : (an.rangeTime.end <= end); + if (this._isVideoJS(an) && expressionLeft && expressionRight && typeof an.highlights[0] !== 'undefined') { + var annotationHTML = an.highlights[0].children[0]; + annotationHTML.style.marginTop = (-1 * parseFloat(annotationHTML.style.top) + count) + 'em'; + $(an.highlights[0]).show(); + count++; + } else if (this._isVideoJS(an) && typeof an.highlights[0] !== 'undefined') { + $(an.highlights[0]).hide(); + an.highlights[0].children[0].style.marginTop = ''; + } + } + // Set the times in the scroll time panel + this.backDSTime.setTimes(); + }, + setposBigNew: function(pos) { + var pos = pos || 'ul'; + var el = this.player.BigNewAnnotation.el_; + videojs.removeClass(el, 'ul'); + videojs.removeClass(el, 'ur'); + videojs.removeClass(el, 'c'); + videojs.removeClass(el, 'bl'); + videojs.removeClass(el, 'br'); + videojs.addClass(el, pos); + }, + pressedKey: function (key) { + var player = this.player; + var rs = this.player.rs; + if (typeof key !== 'undefined' && key == 73) { // -- i key + this._reset(); + + // show slider + this.rs.show(); + // hide other elements + this.rs._reset(); + this.rs.setValue(0, player.currentTime()); + this.rs.right.el_.style.visibility = 'hidden'; + this.rs.tpr.el_.style.visibility = 'hidden'; + this.rs.ctpr.el_.style.visibility = 'hidden'; + this.rs.bar.el_.style.visibility = 'hidden'; + this.lastStartbyKey = player.currentTime(); + } else if (typeof key!='undefined' && key==79) { // -- o key + if (this.rs.bar.el_.style.visibility == 'hidden') { // the last action was to type the i key + var start = this.lastStartbyKey != 'undefined' ? this.lastStartbyKey:0; + this.newan(start, player.currentTime()); + } else { + this.newan(player.currentTime(), player.currentTime()); + } + } + }, + refreshDesignPanel: function() { + var player = this.player; + var emtoPx = parseFloat($(this.backDSBar.el_).css('width')); + var playerHeight = parseFloat($(player.el_).css('height')); + var controlBarHeight = parseFloat($(player.controlBar.el_).css('height')); + var newHeight = (playerHeight - controlBarHeight) / emtoPx - 5; + this.BackAnDisplay.el_.style.height = this.backDSBar.el_.style.height = (newHeight + 'em'); + this.BackAnDisplay.el_.style.top = this.backDSBar.el_.style.top = "-" + (newHeight + 3 + 'em'); + this.BackAnDisplayScroll.el_.children[0].style.top = "-" + (newHeight + 5 + 'em'); + this.backDSTime.el_.children[0].style.top = "-" + (newHeight + 5 + 'em'); + }, + _reset: function() { + // Hide all the components + this.hideDisplay(); + this.hideAnnotation(); + this.hideStatistics(); + this.player.annotator.adder.hide(); + this.player.annotator.editor.hide(); + this.player.annotator.viewer.hide(); + + // make visible all the range slider element that maybe were hidden in pressedKey event + this.rs.right.el_.style.visibility = ''; + this.rs.tpr.el_.style.visibility = ''; + this.rs.ctpr.el_.style.visibility = ''; + this.rs.bar.el_.style.visibility = ''; + + // by default the range slider must be unlocked + this.rs.unlock(); + + // whether there is a playing selection + this.rs.bar.suspendPlay(); + + // refresh the design + this.refreshDesignPanel(); + }, + _setOverRS: function(elem) { + var annotator = this.player.annotator; + var wrapper = $('.annotator-wrapper')[0]; + var positionLeft = videojs.findPosition(this.rs.left.el_); + var positionRight = videojs.findPosition(this.rs.right.el_); + var positionAnnotator = videojs.findPosition(wrapper); + var positionAdder = {}; + + elem[0].style.display = 'block'; // Show the adder + + if (this.player.isFullScreen) { + positionAdder.top = positionLeft.top; + positionAdder.left = positionLeft.left + (positionRight.left - positionLeft.left) / 2; + } else { + positionAdder.left = positionLeft.left + (positionRight.left - positionLeft.left) / 2 - positionAnnotator.left; + positionAdder.top = positionLeft.top - positionAnnotator.top; + } + + elem.css(positionAdder); + }, + _onMouseDownRS: function(event) { + event.preventDefault(); + + if (!this.rs.options.locked) { + videojs.on(document, "mousemove", videojs.bind(this, this._onMouseMoveRS)); + videojs.on(document, "mouseup", videojs.bind(this, this._onMouseUpRS)); + } + }, + _onMouseMoveRS: function(event) { + var player = this.player; + var annotator = player.annotator; + var rs = player.rangeslider; + annotator.editor.element[0].style.display = 'none'; + rs.show(); + this._setOverRS(annotator.adder); + }, + _onMouseUpRS: function(event) { + videojs.off(document, "mousemove", this._onMouseMoveRS, false); + videojs.off(document, "mouseup", this._onMouseUpRS, false); + + var player = this.player; + var annotator = player.annotator; + var rs = player.rangeslider; + annotator.editor.element[0].style.display = 'block'; + + this._setOverRS(annotator.editor.element); + }, + _sumPercent: function(seconds, percent) { + // the percentage is in % + var duration = this.player.duration(); + var seconds = seconds || 0; + var percent = percent || 10; + percent = Math.min(100, Math.max(0, percent)); + + if (isNaN(duration)) { + return 0; + } + return Math.min(duration, Math.max(0, seconds + duration * percent / 100)); + }, + // Detect if we are creating or editing a video-js annotation + _EditVideoAn: function () { + var annotator = this.annotator; + var isOpenVideojs = (typeof this.player != 'undefined'); + var VideoJS = annotator.editor.VideoJS; + return (isOpenVideojs && typeof VideoJS!='undefined' && VideoJS!==-1); + }, + // Detect if the annotation is a video-js annotation + _isVideoJS: function (an) { + var player = this.player; + var rt = an.rangeTime; + var isOpenVideojs = (typeof this.player !== 'undefined'); + var isVideo = (typeof an.media !== 'undefined' && (an.media === 'video' || an.media === 'audio')); + var isContainer = (typeof an.target !== 'undefined' && an.target.container == player.id_ ); + var isNumber = (typeof rt !== 'undefined' && !isNaN(parseFloat(rt.start)) && isFinite(rt.start) && !isNaN(parseFloat(rt.end)) && isFinite(rt.end)); + var isSource = false; + if (isContainer) { + // Compare without extension + var isYoutube = (isOpenVideojs && typeof this.player.techName !== 'undefined') ? (this.player.techName === 'Youtube') : false; + var targetSrc = isYoutube ? an.target.src : an.target.src.substring(0, an.target.src.lastIndexOf(".")); + var playerSrc = isYoutube ? player.options_.sources[0].src : player.options_.sources[0].src.substring(0, player.options_.sources[0].src.lastIndexOf(".")); + isSource = (targetSrc === playerSrc); + } + return (isOpenVideojs && isVideo && isContainer && isSource && isNumber); + }, + _sortByDate: function (annotations, type) { + var type = type || 'asc'; // asc => The value [0] will be the most recent date + annotations.sort(function(a, b) { + a = new Date(typeof a.updated !== 'undefined' ? createDateFromISO8601(a.updated) : ''); + b = new Date(typeof b.updated !== 'undefined' ? createDateFromISO8601(b.updated) : ''); + if (type == 'asc') + return (b < a) ? -1 : ((b > a) ? 1 : 0); + else + return (a < b) ? -1 : ((a > b) ? 1 : 0); + }); + } + }; + + // ----------------CREATE new Components for video-js---------------- // + + // --Charge the new Component into videojs + videojs.ControlBar.prototype.options_.children.AnContainerButtons = {}; // Container with the css for the buttons + videojs.ControlBar.prototype.options_.children.BackAnDisplay = {}; // Range Slider Time Bar + videojs.ControlBar.prototype.options_.children.BackAnDisplayScroll = {}; // Range Slider Time Bar + videojs.options.children.BigNewAnnotation = {}; // Big Button New Annotation + + + + // -- Player--> BigNewAnnotation + + /** + * Create a New Annotation with big Button + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + videojs.BigNewAnnotation = videojs.Button.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Button.call(this, player, options); + } + }); + + videojs.BigNewAnnotation.prototype.init_ = function() { + this.an = this.player_.annotations; + // Hide Button if the user has selected readOnly in the Annotator options + var opts = this.an.options.optionsAnnotator; + if (typeof opts !== 'undefined' && typeof opts.readOnly !== 'undefined' && opts.readOnly) + this.hide(); + }; + + videojs.BigNewAnnotation.prototype.createEl = function() { + return videojs.Button.prototype.createEl.call(this, 'div', { + className: 'vjs-big-new-annotation vjs-menu-button vjs-control', + innerHTML: '
A
', + title: 'New Annotation', }); - - this.BigNewAn.hide(); //Hide until the video is load - }, - newan: function(start,end){ - var player = this.player, - annotator = this.annotator, - sumPercent = 10,//percentage for the last mark - currentTime = player.currentTime(), - lastTime = this._sumPercent(currentTime,sumPercent); - - var start = typeof start!='undefined'?start:currentTime, - end = typeof end!='undefined'?end:lastTime; - - this._reset(); - - //set position RS and pause the player - player.showSlider(); - player.pause(); - - player.setValueSlider(start,end); - - //This variable is to say the editor that we want create a VideoJS annotation - annotator.editor.VideoJS = this.player.id_; - - annotator.adder.show(); - - this._setOverRS(annotator.adder); - - //Open a new annotator dialog - annotator.onAdderClick(); - }, - showDisplay: function(){ - this._reset(); - //show - this.BackAnDisplay.removeClass('disable');//show the Container - this.BackAnDisplayScroll.removeClass('disable');//show the scroll - //active button - this.ShowAn.addClass('active'); - this.options.showDisplay =true; - }, - hideDisplay: function(){ - //hide - this.BackAnDisplay.addClass('disable');//hide the Container - this.BackAnDisplayScroll.addClass('disable');//hide the scroll - //no active button - videojs.removeClass(this.ShowAn.el_, 'active'); - this.options.showDisplay =false; - }, - showStatistics: function(){ - this._reset(); - //show - this.BackAnDisplay.removeClass('disable');//show the Container - this.AnStat.removeClass('disable');//show Statistics - //mode (this mode will hide the annotations to show the statistics in the container) - this.BackAnDisplay.addClass('statistics');//mode statistics - //paint - this.AnStat.paintCanvas();//refresh canvas - //active button - this.ShowSt.addClass('active'); - this.options.showStatistics =true; - }, - hideStatistics: function(){ - //hide - this.BackAnDisplay.addClass('disable');//hide the Container - this.AnStat.addClass('disable');//hide Statistics - //remove mode statistics - this.BackAnDisplay.removeClass('statistics'); - //no active button - this.ShowSt.removeClass('active'); - this.options.showStatistics =false; - }, - showAnnotation: function(annotation){ - var isVideo = this._isVideoJS(annotation); - if (isVideo){ - var start = annotation.rangeTime.start, - end = annotation.rangeTime.end, - duration = this.player.duration(), - isPoint = videojs.round(start,3)==videojs.round(end,3); - - this._reset(); - - //show the range slider - this.rs.show(); - - //set the slider position - this.rs.setValues(start,end); - - //lock the player - this.rs.lock(); - - //play - if(!isPoint) - this.rs.playBetween(start,end); - - //fix small bar - var width = Math.min(1, Math.max(0.005, (this.rs._percent(end-start))))*100; - this.rs.bar.el_.style.width = width+'%'; - - //Add the annotation object to the bar - var bar = isPoint?this.rs[((duration-start)/duration<0.1)?'left':'right'].el_:this.rs.bar.el_, - holder = $(this.rs.left.el_).parent()[0]; - $(holder).append(''); - $(bar).appendTo( $(holder).find('.annotator-hl')); - - var span = $(bar).parent()[0]; - $.data(span, 'annotation', annotation);//Set the object in the span - - //set the editor over the range slider - this._setOverRS(this.annotator.editor.element); - this.annotator.editor.checkOrientation(); - - //hide the panel - this.rs.hidePanel(); - } - }, - hideAnnotation: function(){ - this.rs.hide(); - this.rs.showPanel(); - - //remove the last single showed annotation - var holder = $(this.rs.left.el_).parent()[0]; - var holderRight = $(this.rs.right.el_).parent()[0]; - if ($(holder).find('.annotator-hl').length > 0){ - $($(holder).find('.annotator-hl')[0].children[0]).appendTo(holder); - $(holder).find('.annotator-hl').remove(); - }else if ($(holderRight).find('.annotator-hl').length > 0){ - $($(holderRight).find('.annotator-hl')[0].children[0]).appendTo(holderRight); - $(holderRight).find('.annotator-hl').remove(); - } - }, - editAnnotation: function(annotation,editor){ - //This will be usefull when we are going to edit an annotation. - if (this._isVideoJS(annotation)){ - this.hideDisplay(); - var player = this.player, - editor = editor || this.annotator.editor; - - //show the slider and set in the position - player.showSlider(); - player.unlockSlider(); - player.setValueSlider(annotation.rangeTime.start,annotation.rangeTime.end); - - //show the time panel - player.showSliderPanel(); - - //set the editor over the range slider - this._setOverRS(editor.element); - editor.checkOrientation(); - - //set the VideoJS variable - editor.VideoJS = player.id_; - } - }, - refreshDisplay: function(){ - console.log("loadingAnnotations"); - var count = 0, - allannotations = this.annotator.plugins['Store'].annotations; - - //Sort by date the Array - this._sortByDate(allannotations); - - //reset the panel - $(this.AnDisplay.el_).find('span').remove();//remove the last html items - $(this.player.el_).find('.vjs-anpanel-annotation .annotation').remove();//remove a deleted annotation without span wrapper - - for (var item in allannotations) { - var an = allannotations[item]; - - //check if the annotation is a video annotation - if (this._isVideoJS(an)){ - var div = document.createElement('div'), - span = document.createElement('span'), - start = this.rs._percent(an.rangeTime.start) * 100, - end = this.rs._percent(an.rangeTime.end) * 100, - width; - span.appendChild(div); - span.className = "annotator-hl"; - width = Math.min(100, Math.max(0.2, end - start)); - div.className = "annotation"; - div.id = count; - div.style.top = count+"em"; - div.style.left = start+'%'; - div.style.width = width+'%'; - div.start = an.rangeTime.start; - div.end = an.rangeTime.end; - this.AnDisplay.el_.appendChild(span); - - //detect point annotations - if(videojs.round(start,0)==videojs.round(end,0)){ - $(div).css('width',''); - $(div).addClass("point"); - } - - //Set the object in the div - $.data(span, 'annotation', an); - //Add the highlights to the annotation - an.highlights = $(span); - - count++; - } - }; - var start = this.rs._seconds(parseFloat(this.rsdl.el_.style.left)/100), - end = this.rs._seconds(parseFloat(this.rsdr.el_.style.left)/100); - - this.showBetween(start,end,this.rsdl.include,this.rsdr.include); - }, - showBetween: function (start,end,includeLeft,includeRight){ - var duration = this.player.duration(), - start = start || 0, - end = end || duration, - annotationsHTML = $.makeArray($(this.player.el_).find('.vjs-anpanel-annotation .annotator-hl')), - count = 0; - for (var index in annotationsHTML){ - var an = $.data(annotationsHTML[index], 'annotation'), - expressionLeft = includeLeft?(an.rangeTime.end >= start):(an.rangeTime.start >= start), - expressionRight = includeRight?(an.rangeTime.start <= end):(an.rangeTime.end <= end); - if (this._isVideoJS(an) && expressionLeft && expressionRight && typeof an.highlights[0]!='undefined'){ - var annotationHTML = an.highlights[0].children[0]; - annotationHTML.style.marginTop = (-1*parseFloat(annotationHTML.style.top)+count) + 'em'; - $(an.highlights[0]).show(); - count++; - }else if(this._isVideoJS(an) && typeof an.highlights[0]!='undefined'){ - $(an.highlights[0]).hide(); - an.highlights[0].children[0].style.marginTop = ''; - } - } - //Set the times in the scroll time panel - this.backDSTime.setTimes(); - }, - setposBigNew: function(pos){ - var pos = pos || 'ul', - el = this.player.BigNewAnnotation.el_; - videojs.removeClass(el, 'ul'); - videojs.removeClass(el, 'ur'); - videojs.removeClass(el, 'c'); - videojs.removeClass(el, 'bl'); - videojs.removeClass(el, 'br'); - videojs.addClass(el, pos); - }, - pressedKey: function (key){ - var player = this.player, - rs = this.player.rs; - if (typeof key!='undefined' && key==73){ //-- i key - this._reset(); - - //show slider - this.rs.show(); - //hide other elements - this.rs._reset(); - this.rs.setValue(0,player.currentTime()); - this.rs.right.el_.style.visibility = 'hidden'; - this.rs.tpr.el_.style.visibility = 'hidden'; - this.rs.ctpr.el_.style.visibility = 'hidden'; - this.rs.bar.el_.style.visibility = 'hidden'; - this.lastStartbyKey = player.currentTime(); - }else if (typeof key!='undefined' && key==79){ //-- o key - if (this.rs.bar.el_.style.visibility == 'hidden'){//the last action was to type the i key - var start = this.lastStartbyKey!='undefined'?this.lastStartbyKey:0; - this.newan(start,player.currentTime()); - }else{ - this.newan(player.currentTime(),player.currentTime()); - } - } - }, - refreshDesignPanel: function(){ - var player = this.player, - emtoPx = parseFloat($(this.backDSBar.el_).css('width')), - playerHeight = parseFloat($(player.el_).css('height')), - controlBarHeight = parseFloat($(player.controlBar.el_).css('height')), - newHeight = (playerHeight - controlBarHeight)/emtoPx-5; - /*this.BackAnDisplay.el_.style.height = this.backDSBar.el_.style.height = (this.options.NumAnnotations+'em'); - this.BackAnDisplay.el_.style.top = this.backDSBar.el_.style.top = "-"+(this.options.NumAnnotations+3+'em'); - this.BackAnDisplayScroll.el_.children[0].style.top = "-"+(this.options.NumAnnotations+5+'em'); - this.backDSTime.el_.children[0].style.top = "-"+(this.options.NumAnnotations+5+'em');*/ - this.BackAnDisplay.el_.style.height = this.backDSBar.el_.style.height = (newHeight+'em'); - this.BackAnDisplay.el_.style.top = this.backDSBar.el_.style.top = "-"+(newHeight+3+'em'); - this.BackAnDisplayScroll.el_.children[0].style.top = "-"+(newHeight+5+'em'); - this.backDSTime.el_.children[0].style.top = "-"+(newHeight+5+'em'); - }, - _reset: function(){ - //Hide all the components - this.hideDisplay(); - this.hideAnnotation(); - this.hideStatistics(); - this.player.annotator.adder.hide(); - this.player.annotator.editor.hide(); - this.player.annotator.viewer.hide(); - - //make visible all the range slider element that maybe were hidden in pressedKey event - this.rs.right.el_.style.visibility = ''; - this.rs.tpr.el_.style.visibility = ''; - this.rs.ctpr.el_.style.visibility = ''; - this.rs.bar.el_.style.visibility = ''; - - //by default the range slider must be unlocked - this.rs.unlock(); - - //whether there is a playing selection - this.rs.bar.suspendPlay(); - - //refresh the design - this.refreshDesignPanel(); - }, - _setOverRS: function(elem){ - var annotator = this.player.annotator, - wrapper = $('.annotator-wrapper')[0], - positionLeft = videojs.findPosition(this.rs.left.el_), - positionRight = videojs.findPosition(this.rs.right.el_), - positionAnnotator = videojs.findPosition(wrapper), - positionAdder = {}; - - elem[0].style.display = 'block'; //Show the adder - - if (this.player.isFullScreen){ - positionAdder.top = positionLeft.top; - positionAdder.left = positionLeft.left + (positionRight.left - positionLeft.left) / 2; - }else{ - positionAdder.left = positionLeft.left + (positionRight.left - positionLeft.left) / 2 - positionAnnotator.left; - positionAdder.top = positionLeft.top - positionAnnotator.top; - } - - elem.css(positionAdder); - }, - _onMouseDownRS: function(event){ - event.preventDefault(); - //videojs.blockTextSelection(); - - if(!this.rs.options.locked) { - videojs.on(document, "mousemove", videojs.bind(this,this._onMouseMoveRS)); - videojs.on(document, "mouseup", videojs.bind(this,this._onMouseUpRS)); - } - }, - _onMouseMoveRS: function(event) { - var player = this.player, - annotator = player.annotator, - rs = player.rangeslider; - annotator.editor.element[0].style.display = 'none'; - rs.show(); - this._setOverRS(annotator.adder); - }, - _onMouseUpRS: function(event){ - videojs.off(document, "mousemove", this._onMouseMoveRS, false); - videojs.off(document, "mouseup", this._onMouseUpRS, false); - - var player = this.player, - annotator = player.annotator, - rs = player.rangeslider; - annotator.editor.element[0].style.display = 'block'; - - this._setOverRS(annotator.editor.element); - }, - _sumPercent: function(seconds,percent) { - //the percentage is in % - var duration = this.player.duration(); - var seconds = seconds || 0; - var percent = percent || 10; - percent = Math.min(100, Math.max(0, percent)); - - if(isNaN(duration)) { - return 0; - } - return Math.min(duration, Math.max(0, seconds + duration * percent / 100)); - }, - //Detect if we are creating or editing a video-js annotation - _EditVideoAn: function (){ - var annotator = this.annotator, - isOpenVideojs = (typeof this.player != 'undefined'), - VideoJS = annotator.editor.VideoJS; - return (isOpenVideojs && typeof VideoJS!='undefined' && VideoJS!==-1); - }, - //Detect if the annotation is a video-js annotation - _isVideoJS: function (an){ - var player = this.player, - rt = an.rangeTime, - isOpenVideojs = (typeof this.player != 'undefined'), - isVideo = (typeof an.media!='undefined' && (an.media=='video' || an.media=='audio')), - isContainer = (typeof an.target!='undefined' && an.target.container==player.id_ ), - isNumber = (typeof rt!='undefined' && !isNaN(parseFloat(rt.start)) && isFinite(rt.start) && !isNaN(parseFloat(rt.end)) && isFinite(rt.end)), - isSource = false; - if(isContainer){ - //Compare without extension - var isYoutube = (isOpenVideojs && typeof this.player.techName!='undefined')?(this.player.techName == 'Youtube'):false, - targetSrc = isYoutube?an.target.src:an.target.src.substring(0,an.target.src.lastIndexOf(".")), - playerSrc = isYoutube?player.options_.sources[0].src:player.options_.sources[0].src.substring(0,player.options_.sources[0].src.lastIndexOf(".")); - isSource = (targetSrc == playerSrc); - } - return (isOpenVideojs && isVideo && isContainer && isSource && isNumber); - }, - _sortByDate: function (annotations,type){ - var type = type || 'asc'; //asc => The value [0] will be the most recent date - annotations.sort(function(a,b){ - a = new Date(typeof a.updated!='undefined'?createDateFromISO8601(a.updated):''); - b = new Date(typeof b.updated!='undefined'?createDateFromISO8601(b.updated):''); - if (type == 'asc') - return ba?1:0; - else - return ab?1:0; - }); - } -}; - - - - -//----------------CREATE new Components for video-js----------------// - -//--Charge the new Component into videojs -videojs.ControlBar.prototype.options_.children.AnContainerButtons={}; //Container with the css for the buttons -videojs.ControlBar.prototype.options_.children.BackAnDisplay={}; //Range Slider Time Bar -videojs.ControlBar.prototype.options_.children.BackAnDisplayScroll={}; //Range Slider Time Bar -videojs.options.children.BigNewAnnotation={}; //Big Button New Annotation - - - -//-- Player--> BigNewAnnotation - -/** - * Create a New Annotation with big Button - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ -videojs.BigNewAnnotation = videojs.Button.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Button.call(this, player, options); - } -}); - -videojs.BigNewAnnotation.prototype.init_ = function(){ - this.an = this.player_.annotations; - //Hide Button if the user has selected readOnly in the Annotator options - var opts = this.an.options.optionsAnnotator; - if (typeof opts!='undefined' && typeof opts.readOnly!='undefined' && opts.readOnly) - this.hide(); -}; - -videojs.BigNewAnnotation.prototype.createEl = function(){ - return videojs.Button.prototype.createEl.call(this, 'div', { - className: 'vjs-big-new-annotation vjs-menu-button vjs-control', - innerHTML: '
A
', - title: 'New Annotation', - }); -}; - -videojs.BigNewAnnotation.prototype.onClick = function(){ - this.an.newan(); -}; - - - -//-- Player--> ControlBar--> AnContainerButtons - -/** - * Container for the button CSS - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ - -videojs.AnContainerButtons = videojs.Component.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Component.call(this, player, options); - } -}); - -videojs.AnContainerButtons.prototype.init_ = function(){}; - - -videojs.AnContainerButtons.prototype.options_ = { - children: { - 'ShowStatistics': {}, - 'ShowAnnotations': {}, - 'NewAnnotation': {}, - } -}; - -videojs.AnContainerButtons.prototype.createEl = function(){ - return videojs.Component.prototype.createEl.call(this, 'div', { - className: 'vjs-container-button-annotation vjs-menu-button vjs-control', - }); -}; - - - -//-- Player--> ControlBar--> AnContainerButtons--> ShowStatistics - -/** - * Button for show/hide the chart with statistics of the annotation's number - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ - -videojs.ShowStatistics = videojs.Button.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Button.call(this, player, options); - } -}); - -videojs.ShowStatistics.prototype.init_ = function(){ - this.an = this.player_.annotations; -}; - -videojs.ShowStatistics.prototype.createEl = function(){ - return videojs.Button.prototype.createEl.call(this, 'div', { - className: 'vjs-statistics-annotation vjs-menu-button vjs-control', - title: 'Show the Statistics', - }); -}; - -videojs.ShowStatistics.prototype.onClick = function(){ - if (!this.an.options.showStatistics) this.an.showStatistics(); - else this.an.hideStatistics(); -}; - - - -//-- Player--> ControlBar--> AnContainerButtons--> ShowAnnotations - -/** - * Button for show/hide the annotation panel - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ - -videojs.ShowAnnotations = videojs.Button.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Button.call(this, player, options); - } -}); - -videojs.ShowAnnotations.prototype.init_ = function(){ - this.an = this.player_.annotations; -}; - -videojs.ShowAnnotations.prototype.createEl = function(){ - return videojs.Button.prototype.createEl.call(this, 'div', { - className: 'vjs-showannotations-annotation vjs-menu-button vjs-control', - title: 'Show Annotations', - }); -}; - -videojs.ShowAnnotations.prototype.onClick = function(){ - if (!this.an.options.showDisplay) this.an.showDisplay(); - else this.an.hideDisplay(); -}; - - - -//-- Player--> ControlBar--> AnContainerButtons--> NewAnnotation - -/** - * Create a New Annotation - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ -videojs.NewAnnotation = videojs.Button.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Button.call(this, player, options); - } -}); - -videojs.NewAnnotation.prototype.init_ = function(){ - this.an = this.player_.annotations; - //Hide Button if the user has selected readOnly in the Annotator options - var opts = this.an.options.optionsAnnotator; - if (typeof opts!='undefined' && typeof opts.readOnly!='undefined' && opts.readOnly) - this.hide(); -}; - -videojs.NewAnnotation.prototype.createEl = function(){ - return videojs.Button.prototype.createEl.call(this, 'div', { - className: 'vjs-new-annotation vjs-menu-button vjs-control', - title: 'New Annotation', - }); -}; - -videojs.NewAnnotation.prototype.onClick = function(){ - this.an.newan(); -}; - - - -//-- Player--> ControlBar--> BackAnDisplay - -/** - * The background annotations panel - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ -videojs.BackAnDisplay = videojs.Component.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Component.call(this, player, options); - } -}); - -videojs.BackAnDisplay.prototype.init_ = function(){ - this.an = this.player_.annotations - self = this; - //Fix error resizing the display panel. The scroll always went up. - $(this.el_).watch('font-size', function(){ - self.an.backDSBarSel.setPosition(self.an.BackAnDisplayScroll.currentValue,false); - }); - -}; - -videojs.BackAnDisplay.prototype.options_ = { - children: { - 'RangeSelectorDisplay': {}, - 'AnDisplay': {}, - 'AnStat': {}, - } -}; - -videojs.BackAnDisplay.prototype.createEl = function(){ - return videojs.Component.prototype.createEl.call(this, 'div', { - className: 'vjs-back-anpanel-annotation', - }); -}; - - - -//-- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay - -/** - * The selector to show the annotations in a time selection - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ - -videojs.RangeSelectorDisplay = videojs.Component.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Component.call(this, player, options); - this.on('mousedown', this.onMouseDown); - } -}); - -videojs.RangeSelectorDisplay.prototype.init_ = function(){ - this.rs = this.player_.rangeslider; - this.an = this.player_.annotations; - var duration = this.an.player.duration(); - this.start = 0; - this.end = duration; - - //set the selection area in the extreme position - this.setPosition(0,0,false); - this.setPosition(1,this.rs._percent(duration),false); -}; - -videojs.RangeSelectorDisplay.prototype.options_ = { - children: { - 'RangeSelectorLeft': {}, - 'RangeSelectorRight': {}, - 'RangeSelectorBar': {}, - } -}; - -videojs.RangeSelectorDisplay.prototype.createEl = function(){ - return videojs.Component.prototype.createEl.call(this, 'div', { - className: 'vjs-rangeselector-anpanel-annotation', - }); -}; - -videojs.RangeSelectorDisplay.prototype.onMouseDown = function(event) { - event.preventDefault(); - //videojs.blockTextSelection(); - - videojs.on(document, "mousemove", videojs.bind(this,this.onMouseMove)); - videojs.on(document, "mouseup", videojs.bind(this,this.onMouseUp)); - - videojs.removeClass(this.an.rsdb.el_,'disable'); -}; - -videojs.RangeSelectorDisplay.prototype.onMouseUp = function(event) { - videojs.off(document, "mousemove", this.onMouseMove, false); - videojs.off(document, "mouseup", this.onMouseUp, false); - - videojs.addClass(this.an.rsdb.el_,'disable'); -}; - -videojs.RangeSelectorDisplay.prototype.onMouseMove = function(event) { - var left = this.calculateDistance(event); - if (this.an.rsdl.pressed) - this.setPosition(0,left); - else if (this.an.rsdr.pressed) - this.setPosition(1,left); - - //move the frame to the position of the arrow - this.an.player.currentTime(this.rs._seconds(left)); -}; - -videojs.RangeSelectorDisplay.prototype.calculateDistance = function(event){ - var rstbX = this.getRSTBX(); - var rstbW = this.getRSTBWidth(); - var handleW = this.getWidth(); - - // Adjusted X and Width, so handle doesn't go outside the bar - rstbX = rstbX + (handleW / 2); - rstbW = rstbW - handleW; - - // Percent that the click is through the adjusted area - return Math.max(0, Math.min(1, (event.pageX - rstbX) / rstbW)); -}; - -videojs.RangeSelectorDisplay.prototype.getRSTBWidth = function() { - return this.el_.offsetWidth; -}; -videojs.RangeSelectorDisplay.prototype.getRSTBX = function() { - return videojs.findPosition(this.el_).left; -}; -videojs.RangeSelectorDisplay.prototype.getWidth = function() { - var arrow = $(this.an.rsdl.el_).find('.vjs-selector-arrow')[0]; - return arrow.offsetWidth;//does not matter left or right -}; - -videojs.RangeSelectorDisplay.prototype.setPosition = function(index,left,changeTime) { - //index = 0 for left side, index = 1 for right side - var index = index || 0, - changeTime = typeof changeTime!='undefined'?changeTime:true; - - // Check for invalid position - if(isNaN(left)) - return false; - - // Check index between 0 and 1 - if(!(index === 0 || index === 1)) - return false; - // Alias - var ObjLeft = this.an.rsdl.el_, - ObjRight = this.an.rsdr.el_, - Obj = this.an[index === 0 ? 'rsdl' : 'rsdr'].el_; - - //Check if left arrow is over the right arrow - if ((index === 0 ?this.updateLeft(left):this.updateRight(left))){ - if (index===1){//right - Obj.style.left = (left * 100)+'%'; - Obj.style.width = ((1-left) * 100)+'%'; - }else{//left - Obj.style.left = (left * 100)+'%'; - Obj.style.width = ((left) * 100)+'%'; - } - - this[index === 0 ? 'start' : 'end'] = this.rs._seconds(left); - - //Fix the problem when you press the button and the two arrow are underhand - //left.zIndex = 10 and right.zIndex=20. This is always less in this case: - if (index === 0 && (left * 100) >= 90) - $(ObjLeft).find('.vjs-selector-arrow')[0].style.zIndex = 25; - else - $(ObjLeft).find('.vjs-selector-arrow')[0].style.zIndex = 10; - - - //-- Panel - /*var MaxP,MinP,MaxDisP; - MaxP = this.player_.isFullScreen?96:92; - MinP = this.player_.isFullScreen?0.1:0.5; - MaxDisP = this.player_.isFullScreen?3.75:7.5;*/ - var rsdbl = this.an.rsdbl.el_, - rsdbr = this.an.rsdbr.el_, - distance = parseFloat(ObjRight.style.left)-parseFloat(ObjLeft.style.left); - if (index===0) - rsdbl.children[0].innerHTML = videojs.formatTime(this.rs._seconds(left)); - else - rsdbr.children[0].innerHTML = videojs.formatTime(this.rs._seconds(left)); - if (typeof distance!='undefined' && distance <= 12.5){ - if(parseFloat(ObjLeft.style.left)<7){ - rsdbl.style.top = (-1.5) + 'em';rsdbl.style.left = 1 + 'em'; - }else{ - rsdbl.style.left = (-2.5) + 'em';rsdbl.style.top = ''; - } - - if(parseFloat(ObjRight.style.left)>93){ - rsdbr.style.top = (-1.5) + 'em';rsdbr.style.right = 1 + 'em'; - }else{ - rsdbr.style.right = (-2.5) + 'em';rsdbr.style.top = ''; - } - }else{ - rsdbl.style.left = 1 + 'em'; - rsdbr.style.right = 1 + 'em'; - rsdbl.style.top = ''; - rsdbr.style.top = ''; - } - - - var start = this.rs._seconds(parseFloat(ObjLeft.style.left)/100), - end = this.rs._seconds(parseFloat(ObjRight.style.left)/100); - - if(changeTime) - this.an.showBetween(start,end,this.an.rsdl.include,this.an.rsdr.include); - } - return true; -}; - -videojs.RangeSelectorDisplay.prototype.updateLeft = function(left) { - var rightVal = this.an.rsdr.el_.style.left!=''?this.an.rsdr.el_.style.left:100; - var right = parseFloat(rightVal) / 100, - bar = this.an.rsdb.el_; - - var width = videojs.round((right - left),this.an.updatePrecision); //round necessary for not get 0.6e-7 for example that it's not able for the html css width - //(right+0.00001) is to fix the precision of the css in html - if(left <= (right+0.00001)) { - bar.style.left = (left * 100) + '%'; - bar.style.width = (width * 100) + '%'; - return true; - } - return false; -}; - -videojs.RangeSelectorDisplay.prototype.updateRight = function(right) { - var leftVal = this.an.rsdl.el_.style.left!=''?this.an.rsdl.el_.style.left:0; - var left = parseFloat(leftVal) / 100, - bar = this.an.rsdb.el_; - - var width = videojs.round((right - left),this.an.updatePrecision); //round necessary for not get 0.6e-7 for example that it's not able for the html css width - - //(right+0.00001) is to fix the precision of the css in html - if((right+0.00001) >= left) { - bar.style.width = (width * 100) + '%'; - bar.style.left = ((right - width) * 100) + '%'; - return true; - } - return false; -}; - - - -//-- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay--> RangeSelectorLeft - -/** - * Left Time selector - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ -videojs.RangeSelectorLeft = videojs.Component.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Component.call(this, player, options); - this.on('mousedown', this.onMouseDown); - this.on('dblclick', this.ondblclick); - this.pressed = false;//to know when is mousedown - this.include = true;//to know when we want to include the boundary time in the selection or not - } -}); - -videojs.RangeSelectorLeft.prototype.init_ = function(){ - this.rs = this.player_.rangeslider; - this.an = this.player_.annotations; - videojs.addClass(this.el_, 'include'); -}; - -videojs.RangeSelectorLeft.prototype.createEl = function(){ - return videojs.Component.prototype.createEl.call(this, 'div', { - className: 'vjs-leftselector-anpanel-annotation', - innerHTML: '
' - }); -}; - - -videojs.RangeSelectorLeft.prototype.onMouseDown = function(event) { - event.preventDefault(); - //videojs.blockTextSelection(); - - this.pressed = true; - videojs.on(document, "mouseup", videojs.bind(this,this.onMouseUp)); - videojs.addClass(this.el_, 'active'); - videojs.addClass(this.el_.parentNode, 'active'); -}; - -videojs.RangeSelectorLeft.prototype.onMouseUp = function(event) { - videojs.off(document, "mouseup", this.onMouseUp, false); - videojs.removeClass(this.el_, 'active'); - videojs.removeClass(this.el_.parentNode, 'active'); - this.pressed = false; -}; - -videojs.RangeSelectorLeft.prototype.ondblclick = function(event) { - if (this.include){ - this.include = false; - videojs.removeClass(this.el_, 'include'); - }else{ - this.include = true; - videojs.addClass(this.el_, 'include'); - } - var left = this.an.rsd.calculateDistance(event); - this.an.rsd.setPosition(0,left); -}; - - - -//-- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay--> RangeSelectorRight - -/** - * Right Time selector - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ -videojs.RangeSelectorRight = videojs.Component.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Component.call(this, player, options); - this.on('mousedown', this.onMouseDown); - this.on('dblclick', this.ondblclick); - this.pressed = false;//to know when is mousedown - this.include = true;//to know when we want to include the boundary time in the selection or not - } -}); - -videojs.RangeSelectorRight.prototype.init_ = function(){ - this.rs = this.player_.rangeslider; - this.an = this.player_.annotations; - videojs.addClass(this.el_, 'include'); -}; - -videojs.RangeSelectorRight.prototype.createEl = function(){ - return videojs.Component.prototype.createEl.call(this, 'div', { - className: 'vjs-rightselector-anpanel-annotation', - innerHTML: '
' - }); -}; - -videojs.RangeSelectorRight.prototype.onMouseDown = function(event) { - event.preventDefault(); - //videojs.blockTextSelection(); - - this.pressed = true; - videojs.on(document, "mouseup", videojs.bind(this,this.onMouseUp)); - videojs.addClass(this.el_, 'active'); - videojs.addClass(this.el_.parentNode, 'active'); -}; - -videojs.RangeSelectorRight.prototype.onMouseUp = function(event) { - videojs.off(document, "mouseup", this.onMouseUp, false); - videojs.removeClass(this.el_, 'active'); - videojs.removeClass(this.el_.parentNode, 'active'); - this.pressed = false; -}; - -videojs.RangeSelectorRight.prototype.ondblclick = function(event) { - if (this.include){ - this.include = false; - videojs.removeClass(this.el_, 'include'); - }else{ - this.include = true; - videojs.addClass(this.el_, 'include'); - } - var left = this.an.rsd.calculateDistance(event); - this.an.rsd.setPosition(1,left); -}; - - - -//-- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay--> RangeSelectorBar - -/** - * Bar to display the selected Time - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ - -videojs.RangeSelectorBar = videojs.Component.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Component.call(this, player, options); - } -}); - -videojs.RangeSelectorBar.prototype.init_ = function(){ - videojs.addClass(this.el_,'disable'); -}; - -videojs.RangeSelectorBar.prototype.options_ = { - children: { - 'RangeSelectorBarL': {}, - 'RangeSelectorBarR': {}, - } -}; - -videojs.RangeSelectorBar.prototype.createEl = function(){ - return videojs.Component.prototype.createEl.call(this, 'div', { - className: 'vjs-barselector-anpanel-annotation', - }); -}; - - - -//-- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay--> RangeSelectorBar--> RangeSelectorBarL - -/** - * This is the left time panel for RangeSelectorBar - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ -videojs.RangeSelectorBarL = videojs.Component.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Component.call(this, player, options); - } -}); - -videojs.RangeSelectorBarL.prototype.init_ = function(){}; - -videojs.RangeSelectorBarL.prototype.createEl = function(){ - return videojs.Component.prototype.createEl.call(this, 'div', { - className: 'vjs-barselector-left', - innerHTML: '00:00', - }); -}; - - - -//-- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay--> RangeSelectorBar--> RangeSelectorBarR -/** - * This is the right time panel for RangeSelectorBar - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ -videojs.RangeSelectorBarR = videojs.Component.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Component.call(this, player, options); - } -}); - -videojs.RangeSelectorBarR.prototype.init_ = function(){}; - -videojs.RangeSelectorBarR.prototype.createEl = function(){ - return videojs.Component.prototype.createEl.call(this, 'div', { - className: 'vjs-barselector-right', - innerHTML: '00:00' - }); -}; - - - -//-- Player--> ControlBar--> BackAnDisplay--> AnDisplay - -/** - * Show the annotations in a panel - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ - -videojs.AnDisplay = videojs.Component.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Component.call(this, player, options); - this.on('mousedown', this.onMouseDown); - this.on('mouseover', this.onMouseOver); - } -}); - -videojs.AnDisplay.prototype.init_ = function(){ - this.rs = this.player_.rangeslider; - this.an = this.player_.annotations; - this.transition = false; -}; - -videojs.AnDisplay.prototype.createEl = function(){ - return videojs.Component.prototype.createEl.call(this, 'div', { - className: 'vjs-anpanel-annotation', - }); -}; - -videojs.AnDisplay.prototype.onMouseDown = function(event){ - var elem = $(event.target).parents('.annotator-hl').andSelf(), - _self = this; - if (elem.hasClass("annotator-hl")){ - videojs.on(document, "mouseup", videojs.bind(this,this.onMouseUp)); - //Clone the bar box to make the animation - var boxup = document.createElement('div'), - ElemTop = parseFloat(elem[1].style.top), - ElemMargin = parseFloat(elem[1].style.marginTop), - emtoPx = parseFloat($(elem[1]).css('height')), - isPoint = $(elem[1]).hasClass("point"); - - boxup.className = isPoint?"boxup-dashed-line point":"boxup-dashed-line"; - boxup.style.left = elem[1].style.left; - boxup.style.width = elem[1].style.width; - - boxup.style.top = (ElemTop+ElemMargin-this.el_.scrollTop/emtoPx)+'em'; - elem[0].parentNode.parentNode.appendChild(boxup); - } -} - -videojs.AnDisplay.prototype.onMouseUp = function(event){ - if (typeof this.lastelem == 'undefined') - return false; - var elem = this.lastelem, - _self = this; - if (elem.hasClass("annotator-hl")){ - var annotation = elem.map(function() { - return $(this).data("annotation"); - })[0]; - var displayHeight = (-1)*parseFloat($(this.el_).parent()[0].style.top), - emtoPx = parseFloat($(elem[1]).css('height')); - if (typeof $(elem).parent().parent().find('.boxup-dashed-line')[0]!='undefined'){ - $(elem).parent().parent().find('.boxup-dashed-line')[0].style.top=(displayHeight-2)+'em'; - } - - this.an.player.pause(); - this.transition = true; - window.setTimeout(function () { - _self.an.showAnnotation(annotation); - _self.transition = false; - _self.onCloseViewer(); - }, 900); - } - videojs.off(document, "mouseup", this.onMouseUp, false); -}; - -videojs.AnDisplay.prototype.onMouseOver = function(event){ - if (!this.transition && !this.an.rsdl.pressed && !this.an.rsdr.pressed){ - var annotator = this.an.annotator; - var elem = $(event.target).parents('.annotator-hl').andSelf(); - - //if there is a opened annotation then show the new annotation mouse over - if (typeof annotator!='undefined' && annotator.viewer.isShown() && elem.hasClass("annotator-hl")){ - //hide the last open viewer - annotator.viewer.hide(); - //get the annotation over the mouse - var annotations = elem.map(function() { - return $(this).data("annotation"); - }); - //show the annotation in the viewer - annotator.showViewer($.makeArray(annotations), Util.mousePosition(event, annotator.wrapper[0])); - } - - //create dashed line - elem.addClass('active'); - if (typeof elem != 'undefined' && $(elem[1]).hasClass('annotation')){ - //create dashed line under the bar - var dashed = document.createElement('div'), - boxdown = document.createElement('div'), - DisplayHeight = parseFloat(this.an.BackAnDisplay.el_.style.height), - ElemMarginTop = elem[1].style.marginTop!=''?parseFloat(elem[1].style.marginTop):0; - ElemTop = parseFloat(elem[1].style.top)+ElemMarginTop, - emtoPx = parseFloat($(elem[1]).css('height')), - isPoint = $(elem[1]).hasClass("point"); - dashed.className = isPoint?'dashed-line point':'dashed-line'; - boxdown.className = "box-dashed-line"; - dashed.style.left = boxdown.style.left = elem[1].style.left; - dashed.style.width = boxdown.style.width = isPoint?'0':elem[1].style.width; - dashed.style.top = ((ElemTop+1)-this.el_.scrollTop/emtoPx)+'em'; - dashed.style.height = ((DisplayHeight-ElemTop+2)+this.el_.scrollTop/emtoPx)+'em';//get the absolute value of the top to put in the height - boxdown.style.top = (DisplayHeight+2)+'em'; - elem[0].parentNode.parentNode.appendChild(dashed); - elem[0].parentNode.parentNode.appendChild(boxdown); - - $(this.player).find('.vjs-play-progress').css('z-index', 2); - $(this.player).find('.vjs-seek-handle').css('z-index', 2); - } - - //store the last selected item - if (elem.hasClass("annotator-hl")) - this.lastelem = elem; - } -}; - -videojs.AnDisplay.prototype.onCloseViewer = function(){ - if (!this.transition){ - if (typeof this.lastelem != 'undefined') - this.lastelem.removeClass('active'); - //remove dashed line - if (typeof this.lastelem != 'undefined' && this.lastelem.hasClass("annotator-hl")){ - $(this.lastelem).parent().parent().find('.dashed-line').remove(); - $(this.lastelem).parent().parent().find('.box-dashed-line').remove(); - $(this.lastelem).parent().parent().find('.boxup-dashed-line').remove(); - $(this.player).find('.vjs-play-progress').css('z-index', ""); - $(this.player).find('.vjs-seek-handle').css('z-index', ""); - } - } -}; - - -videojs.AnDisplay.prototype.countVisibles = function() { - var AnArray = $.makeArray(this.el_.children); - //Count visible annotations in Panel - var count = 0; - for (var index in AnArray){ - var an = AnArray[index]; - if (an.style.display!='none'){ - count++; - } - } - return count; -}; - - - -//-- Player--> ControlBar--> BackAnDisplay--> AnStat - -/** - * Display with a chart with the statistics of the number of Annotations - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ - -videojs.AnStat = videojs.Component.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Component.call(this, player, options); - this.marginTop = 20; - this.marginBottom = 0; - } -}); - -videojs.AnStat.prototype.init_ = function(){ - this.rs = this.player_.rangeslider; - this.an = this.player_.annotations; - this.canvas = this.el_.children[0]; -}; - -videojs.AnStat.prototype.createEl = function(){ - return videojs.Component.prototype.createEl.call(this, 'div', { - className: 'vjs-anstat-annotation', - innerHTML: 'Your browser does not support the HTML5 canvas tag.', - }); -}; - -videojs.AnStat.prototype.paintCanvas = function(){ - var ctx=this.canvas.getContext("2d"), - points = this._getPoints(), - w = this._getWeights(points), - maxEn = this._getMaxArray(points,'entries'), - TotAn = this.an.AnDisplay.el_.children.length; - duration = this.an.player.duration(); - - //set the position of the canvas - this.canvas.style.marginTop = Math.round(this.marginTop)+'px'; - - //Add the Max Concentration and Number of annotations - if($(this.canvas).parent().find('.vjs-totan-anstat-annotation').length==0){ - $(this.canvas).parent().append('
'); - $(this.canvas).parent().append('
'); - } - var textCanvas = $(this.canvas).parent().find('.vjs-totan-anstat-annotation')[0]; - textCanvas.innerHTML = TotAn+' total annotations'; - var textCanvas = $(this.canvas).parent().find('.vjs-maxcon-anstat-annotation')[0]; - textCanvas.innerHTML = 'Max Annotations = '+maxEn; - - //Added dashed line function to paint - if (window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype.lineTo) { - CanvasRenderingContext2D.prototype.dashedLine = function(x1, y1, x2, y2, dashLen) { - if (dashLen == undefined) dashLen = 2; - - this.beginPath(); - this.moveTo(x1, y1); - - var dX = x2 - x1; - var dY = y2 - y1; - var dashes = Math.floor(Math.sqrt(dX * dX + dY * dY) / dashLen); - var dashX = dX / dashes; - var dashY = dY / dashes; - - var q = 0; - while (q++ < dashes) { - x1 += dashX; - y1 += dashY; - this[q % 2 == 0 ? 'moveTo' : 'lineTo'](x1, y1); - } - this[q % 2 == 0 ? 'moveTo' : 'lineTo'](x2, y2); - - this.stroke(); - this.closePath(); - }; - }; - - - //set the canvas size - this.canvas.height = this.an.AnDisplay.el_.offsetHeight-(this.marginTop+this.marginBottom); - this.canvas.width = this.an.AnDisplay.el_.offsetWidth; - - ctx.beginPath(); - ctx.strokeStyle="rgb(255, 163, 0)"; - var lastSe = 0, lastEn = 0; - ctx.moveTo(0,maxEn*w.Y); //Move pointer to 0,0 - for (var index in points){ - var p = points[index], - x1 =lastSe*w.X, y1 =(maxEn-lastEn)*w.Y, // Old Point - x2 =p.second*w.X, y2 =(maxEn-p.entries)*w.Y; // New Point - //new line - ctx.lineTo(x2,y1); //move horizontally to the new point - ctx.moveTo(x2,y1); //Move pointer - ctx.lineTo(x2,y2); //move vertically to the new point height - ctx.moveTo(x2,y2); //Prepare pointer for a new instance - //new rectangle under the curve - ctx.fillStyle="rgba(0, 0, 0,0.5)"; - ctx.fillRect(x1,y1,(x2-x1),(maxEn*w.Y-y1)); - - //store the last point - lastSe = p.second; - lastEn = p.entries; - } - //set the graphic to the end of the video - ctx.lineTo(lastSe*w.X,maxEn*w.Y); - ctx.moveTo(lastSe*w.X,maxEn*w.Y); - ctx.lineTo(duration*w.X,maxEn*w.Y); - ctx.stroke(); - - //dashed line down - ctx.beginPath(); - ctx.dashedLine(0,maxEn*w.Y, duration*w.X, maxEn*w.Y, 8); - ctx.stroke(); - //dashed line top - ctx.beginPath(); - ctx.dashedLine(0,0, duration*w.X, 0, 8); - ctx.stroke(); -}; - -videojs.AnStat.prototype._getWeights = function(points){ - var weight = {}, - panel = $(this.an.AnDisplay.el_), - maxSe = this.an.player.duration(), - maxEn = this._getMaxArray(points,'entries'), - panelW = parseFloat(panel.css('width')), - panelH = parseFloat(panel.css('height'))-(this.marginTop+this.marginBottom); - weight.X = maxSe != 0? (panelW / maxSe):0; - weight.Y = maxEn != 0? (panelH / maxEn):0; - return weight; -}; - -videojs.AnStat.prototype._getMaxArray = function(points,variable){ - var highest = 0, - tmp; - for (var index in points){ - tmp = points[index][variable]; - if (tmp > highest) highest = tmp; - } - return highest; -}; - -videojs.AnStat.prototype._getPoints = function(){ - var points = [], - allannotations = this.an.annotator.plugins['Store'].annotations; - for (var index in allannotations){ - var an = allannotations[index], - start,end; - if (this.an._isVideoJS(an)){ - start = an.rangeTime.start; - end = an.rangeTime.end; - //start - if(!this._isFound(points,start)){ - points.push({ - second:an.rangeTime.start, - entries:this._getNumberAnnotations(start) - }); - if (an.rangeTime.start==an.rangeTime.end){//is a point - points.push({ - second:an.rangeTime.end, - entries:this._getNumberAnnotations(end,true) - }); - } - } - //end - if(!this._isFound(points,end)){ - points.push({ - second:an.rangeTime.end, - entries:this._getNumberAnnotations(end,true) - }); - } - - found = false; - } - } - points.sort(function(a,b) {return parseFloat(a.second) - parseFloat(b.second)}); - return points; -}; - -videojs.AnStat.prototype._isFound = function(array,elem){ - var found = false; - for (var indexA in array){ - if(typeof array[indexA].second!='undefined' && array[indexA].second == elem) - found = true; - } - return found; -}; - -videojs.AnStat.prototype._getNumberAnnotations = function(time,end){ - var num = (typeof end!='undefined' && end)?-1:0, - allannotations = this.an.annotator.plugins['Store'].annotations; - for (var index in allannotations){ - var an = allannotations[index]; - if (this.an._isVideoJS(an)){ - if(an.rangeTime.start<=time && an.rangeTime.end>=time) - num++; - } - } - return num; -}; - - - -//-- Player--> ControlBar--> BackAnDisplayScroll - -/** - * The background annotations panel - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ - -videojs.BackAnDisplayScroll = videojs.Component.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Component.call(this, player, options); - this.on('mousedown', this.onMouseDown); - this.UpValue = 0.1; - this.currentValue = 0; - } -}); - -videojs.BackAnDisplayScroll.prototype.init_ = function(){ - this.rs = this.player_.rangeslider; - this.an = this.player_.annotations; - this.mousedownID = -1; - var self = this, - direction; - - //Firefox - $(this.an.AnDisplay.el_).bind('DOMMouseScroll', function(e){ - if(e.originalEvent.detail > 0) - direction = self.UpValue; - else - direction = -self.UpValue; - self.an.backDSBarSel.setPosition(self.getPercentScroll()+direction); - return false; - }); - - //IE, Opera, Safari - $(this.an.AnDisplay.el_).bind('mousewheel', function(e){ - if(e.originalEvent.wheelDelta < 0) - direction = self.UpValue; - else - direction = -self.UpValue; - self.an.backDSBarSel.setPosition(self.getPercentScroll()+direction); - return false; - }); -}; - -videojs.BackAnDisplayScroll.prototype.options_ = { - children: { - 'BackAnDisplayScrollBar': {}, - 'BackAnDisplayScrollTime': {}, - } -}; - -videojs.BackAnDisplayScroll.prototype.createEl = function(){ - return videojs.Component.prototype.createEl.call(this, 'div', { - className: 'vjs-scroll-anpanel-annotation', - innerHTML: '
', - }); -}; - -videojs.BackAnDisplayScroll.prototype.onMouseDown = function(event){ - var self = this; - if (event.target.className == 'vjs-scrollbar-anpanel-annotation'){ - //change position with a click in the scrollbar - this.an.backDSBarSel.onMouseMove(event); - return false; - }else if (event.target.className == 'vjs-scrollbar-selector'){ - //change position with scrollbar - //this event is controlled by this.an.backDSBarSel - return false; - }else{ - //change position with arrows - var direction = event.target.className=='vjs-down-scroll-annotation'?this.UpValue:-this.UpValue; - videojs.on(document, "mouseup", videojs.bind(this,this.onMouseUp)); - if(this.mousedownID==-1) //Prevent multimple loops! - this.mousedownID = setInterval(function () { - var pos = Math.max(0,Math.min(1,self.getPercentScroll()+direction)); - self.an.backDSBarSel.setPosition(pos); - },100); - } -}; - -videojs.BackAnDisplayScroll.prototype.onMouseUp = function(event){ - videojs.off(document, "mouseup", this.onMouseUp, false); - var self = this; - if(this.mousedownID!=-1) { //Only stop if exists - clearInterval(this.mousedownID); - self.mousedownID=-1; - } -}; - -videojs.BackAnDisplayScroll.prototype.getPercentScroll = function(){ - var scroll = this.an.AnDisplay.el_, - maxscroll = scroll.scrollHeight-scroll.offsetHeight, - currentValue = scroll.scrollTop; - return Math.max(0, Math.min(1, maxscroll != 0 ?(currentValue / maxscroll):0)); -}; - -videojs.BackAnDisplayScroll.prototype.setPercentScroll = function(percent){ - var scroll = this.an.AnDisplay.el_, - maxscroll = scroll.scrollHeight-scroll.offsetHeight; - percent = Math.max(0, Math.min(1, percent?percent:0)); - scroll.scrollTop = Math.round(maxscroll*percent); -}; - - - -//-- Player--> ControlBar--> BackAnDisplayScroll--> BackAnDisplayScrollBar - -/** - * The Scroll bar for the display - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ - -videojs.BackAnDisplayScrollBar = videojs.Component.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Component.call(this, player, options); - } -}); - -videojs.BackAnDisplayScrollBar.prototype.init_ = function(){}; - -videojs.BackAnDisplayScrollBar.prototype.options_ = { - children: { - 'ScrollBarSelector': {}, - } -}; - -videojs.BackAnDisplayScrollBar.prototype.createEl = function(){ - return videojs.Component.prototype.createEl.call(this, 'div', { - className: 'vjs-scrollbar-anpanel-annotation', - }); -}; - - - -//-- Player--> ControlBar--> BackAnDisplayScroll--> BackAnDisplayScrollBar--> ScrollBarSelector - -/** - * The Scroll bar for the display - * @param {videojs.Player|Object} player - * @param {Object=} options - * @constructor - */ - -videojs.ScrollBarSelector = videojs.Component.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Component.call(this, player, options); - this.on('mousedown', this.onMouseDown); - } -}); - -videojs.ScrollBarSelector.prototype.init_ = function(){ - this.rs = this.player_.rangeslider; - this.an = this.player_.annotations; - videojs.addClass(this.an.backDSBar.el_, 'disable'); -}; - - -videojs.ScrollBarSelector.prototype.createEl = function(){ - return videojs.Component.prototype.createEl.call(this, 'div', { - className: 'vjs-scrollbar-selector', - }); -}; - -videojs.ScrollBarSelector.prototype.onMouseDown = function(event){ - event.preventDefault(); - //videojs.blockTextSelection(); - videojs.on(document, "mousemove", videojs.bind(this,this.onMouseMove)); - videojs.on(document, "mouseup", videojs.bind(this,this.onMouseUp)); -} - -videojs.ScrollBarSelector.prototype.onMouseUp = function(event){ - videojs.off(document, "mousemove", this.onMouseMove, false); - videojs.off(document, "mouseup", this.onMouseUp, false); -}; - -videojs.ScrollBarSelector.prototype.onMouseMove = function(event){ - var top = this.calculateDistance(event); - top = this.parseMaxPercent(top); //set the max value fixing the height of the handle - this.setPosition(top); -} - -videojs.ScrollBarSelector.prototype.calculateDistance = function(event){ - var scrollY = this.getscrollY(); - var scrollH = this.getscrollHeight(); - var handleH = this.getHeight(); - - // Adjusted X and Width, so handle doesn't go outside the bar - scrollY = scrollY + (handleH); - scrollH = scrollH - (handleH); - // Adjusted X and Width, so handle doesn't go outside the bar - // Percent that the click is through the adjusted area - return Math.max(0, Math.min(1, (event.pageY - scrollY) / scrollH)); -}; - -videojs.ScrollBarSelector.prototype.getscrollHeight = function() { - return this.el_.parentNode.offsetHeight; -}; -videojs.ScrollBarSelector.prototype.getscrollY = function() { - return videojs.findPosition(this.el_.parentNode).top; -}; -videojs.ScrollBarSelector.prototype.getHeight = function() { - return this.el_.offsetHeight; -}; -videojs.ScrollBarSelector.prototype.parseMaxHeight = function(top){ - var scrollH = this.getscrollHeight(), - handleH = this.getHeight(), - percent = handleH / scrollH; - return Math.max(0,Math.min(1-percent, top)); -}; - -videojs.ScrollBarSelector.prototype.parseMaxPercent = function(top){ - var scrollH = this.getscrollHeight(), - handleH = this.getHeight(), - percent = handleH / scrollH, - newTop = top; - if(top >= (1-percent)) - newTop = 1; - return newTop; -}; - -videojs.ScrollBarSelector.prototype.setPosition = function(top,showBar){ - var showBar = typeof showBar != 'undefined'?showBar:true; - - // Check for invalid position - if(isNaN(top)) - return false; - - //Check if there is enough annotations to scroll - if(!this.isScrollable()) - return false; - - // Show the Scrollbar - if(showBar){ - videojs.removeClass(this.an.backDSBar.el_, 'disable') - } - - // Alias - var Obj = this.el_, - scroll = this.an.BackAnDisplayScroll, - scrollTime = this.an.backDSTime; - - Obj.style.top = (this.parseMaxHeight(top) * 100) + '%'; - scroll.setPercentScroll(top); - - //Set the times in the scroll time panel - scrollTime.setTimes(); - - //Hide the Scrollbar in 1 sec - if(showBar){ - var _self = this; - if (typeof this.Timeout!='undefined') - clearTimeout(this.Timeout); - this.Timeout = window.setTimeout(function () { - videojs.addClass(_self.an.backDSBar.el_, 'disable'); - }, 1000); - } - - //set current position - this.an.BackAnDisplayScroll.currentValue = top; - return true; -} - -videojs.ScrollBarSelector.prototype.isScrollable = function(){ - var scroll = this.an.AnDisplay.el_, - emtoPx = parseFloat($(scroll).find('.annotation').css('height')), - minTop = parseInt(scroll.offsetHeight/emtoPx); - - //Count visible annotations in Panel - var count = this.an.AnDisplay.countVisibles(); - return (count>minTop); -} - - - -//-- Player--> ControlBar--> BackAnDisplayScroll--> BackAnDisplayScrollTime - -videojs.BackAnDisplayScrollTime = videojs.Component.extend({ - /** @constructor */ - init: function(player, options){ - videojs.Component.call(this, player, options); - } -}); - -videojs.BackAnDisplayScrollTime.prototype.init_ = function(){ - this.rs = this.player_.rangeslider; - this.an = this.player_.annotations; -}; - -videojs.BackAnDisplayScrollTime.prototype.createEl = function(){ - return videojs.Component.prototype.createEl.call(this, 'div', { - className: 'vjs-scrolltime-anpanel-annotation', - innerHTML: '
', - }); -}; - -videojs.BackAnDisplayScrollTime.prototype.setTimes = function(){ - var AnPos = this.getAnnotationPosition(), - AnEl = this.getElements(AnPos), - AnTimes = this.getTimes(AnEl); - if(AnTimes.top!='Invalid Date'){ - $(this.el_).find('.vjs-up-scrolltime-annotation')[0].style.visibility=''; - $(this.el_).find('.vjs-up-scrolltime-annotation span')[0].innerHTML = AnTimes.top; - }else{ - $(this.el_).find('.vjs-up-scrolltime-annotation')[0].style.visibility='hidden'; - } - if(AnTimes.bottom!='Invalid Date'){ - $(this.el_).find('.vjs-down-scrolltime-annotation')[0].style.visibility=''; - $(this.el_).find('.vjs-down-scrolltime-annotation span')[0].innerHTML = AnTimes.bottom; - }else{ - $(this.el_).find('.vjs-down-scrolltime-annotation')[0].style.visibility='hidden'; - } -}; - -videojs.BackAnDisplayScrollTime.prototype.getAnnotationPosition = function(){ - var backDSBarSel = this.an.backDSBarSel, - percent = backDSBarSel.parseMaxPercent(parseFloat(backDSBarSel.el_.style.top)/100), - scroll = this.an.AnDisplay.el_, - maxTop = scroll.scrollHeight, - minTop = scroll.offsetHeight, - maxBottom = maxTop-minTop, - minBottom = 0, - pos = {}; - percent = percent || 0; - pos.top = Math.max(minTop, Math.min(maxTop,maxBottom*percent+scroll.offsetHeight)); - pos.bottom = Math.max(minBottom, Math.min(maxBottom,maxBottom*percent)); - return pos; -}; - -videojs.BackAnDisplayScrollTime.prototype.getElements = function(AnPos){ - var AnPos = AnPos || {}, - scroll = this.an.AnDisplay.el_, - emtoPx = parseFloat($(scroll).find('.annotation').css('height')), - maxTop = parseInt(scroll.scrollHeight/emtoPx), - minTop = parseInt(scroll.offsetHeight/emtoPx), - maxBottom = (maxTop-minTop), - minBottom = 0, - AnEl = {}; - AnEl.top = Math.max(minTop, Math.min(maxTop,parseInt(AnPos.top/emtoPx))); - AnEl.bottom = Math.max(minBottom, Math.min(maxBottom,parseInt(AnPos.bottom/emtoPx))); - return AnEl; -}; - -videojs.BackAnDisplayScrollTime.prototype.getTimes = function(AnEl){ - var AnEl = AnEl || {}, - AnTimes = {}, - TopEl, BottomEl, AnTop, AnBottom, - AnArray = $.makeArray(this.an.AnDisplay.el_.children); - AnEl.top = AnEl.top || 0; - AnEl.bottom = AnEl.bottom || 0; - - //Get HTML Elements - var count = 0, lastEl; - for (var index in AnArray){ - var an = AnArray[index]; - if (an.style.display!='none'){ - if(count == AnEl.bottom){ - TopEl = an; - }else if(count == AnEl.top){ - BottomEl = an; - } - lastEl = an; - count++; - } - } - if (typeof BottomEl=='undefined') - BottomEl = lastEl; - - //Annotation Element - AnTop = typeof TopEl!='undefined'?$.data(TopEl, 'annotation'):undefined; - AnBottom = typeof BottomEl!='undefined'?$.data(BottomEl, 'annotation'):undefined; - //Update of the element - AnTimes.top = (typeof AnTop!='undefined' && typeof AnTop.updated!='undefined')?AnTop.updated:''; - AnTimes.bottom = (typeof AnBottom!='undefined' && typeof AnBottom.updated!='undefined')?AnBottom.updated:''; - //Format - AnTimes.top = new Date(AnTimes.top!=''?createDateFromISO8601(AnTimes.top):''); - AnTimes.bottom = new Date(AnTimes.bottom!=''?createDateFromISO8601(AnTimes.bottom):''); - return AnTimes; -}; - - -})(); - - - -//----------------Plugin for Annotator to setup videojs----------------// + }; + + videojs.BigNewAnnotation.prototype.onClick = function() { + this.an.newan(); + }; + + // -- Player--> ControlBar--> AnContainerButtons + + /** + * Container for the button CSS + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + + videojs.AnContainerButtons = videojs.Component.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Component.call(this, player, options); + } + }); + + videojs.AnContainerButtons.prototype.init_ = function() {}; + + + videojs.AnContainerButtons.prototype.options_ = { + children: { + 'ShowStatistics': {}, + 'ShowAnnotations': {}, + 'NewAnnotation': {}, + } + }; + + videojs.AnContainerButtons.prototype.createEl = function() { + return videojs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-container-button-annotation vjs-menu-button vjs-control', + }); + }; + + // -- Player--> ControlBar--> AnContainerButtons--> ShowStatistics + + /** + * Button for show/hide the chart with statistics of the annotation's number + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + + videojs.ShowStatistics = videojs.Button.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Button.call(this, player, options); + } + }); + + videojs.ShowStatistics.prototype.init_ = function() { + this.an = this.player_.annotations; + }; + + videojs.ShowStatistics.prototype.createEl = function() { + return videojs.Button.prototype.createEl.call(this, 'div', { + className: 'vjs-statistics-annotation vjs-menu-button vjs-control', + title: 'Show the Statistics', + }); + }; + + videojs.ShowStatistics.prototype.onClick = function() { + if (!this.an.options.showStatistics) this.an.showStatistics(); + else this.an.hideStatistics(); + }; + + + + // -- Player--> ControlBar--> AnContainerButtons--> ShowAnnotations + + /** + * Button for show/hide the annotation panel + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + + videojs.ShowAnnotations = videojs.Button.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Button.call(this, player, options); + } + }); + + videojs.ShowAnnotations.prototype.init_ = function() { + this.an = this.player_.annotations; + }; + + videojs.ShowAnnotations.prototype.createEl = function() { + return videojs.Button.prototype.createEl.call(this, 'div', { + className: 'vjs-showannotations-annotation vjs-menu-button vjs-control', + title: 'Show Annotations', + }); + }; + + videojs.ShowAnnotations.prototype.onClick = function() { + if (!this.an.options.showDisplay) this.an.showDisplay(); + else this.an.hideDisplay(); + }; + + + + // -- Player--> ControlBar--> AnContainerButtons--> NewAnnotation + + /** + * Create a New Annotation + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + videojs.NewAnnotation = videojs.Button.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Button.call(this, player, options); + } + }); + + videojs.NewAnnotation.prototype.init_ = function() { + this.an = this.player_.annotations; + // Hide Button if the user has selected readOnly in the Annotator options + var opts = this.an.options.optionsAnnotator; + if (typeof opts !== 'undefined' && typeof opts.readOnly !== 'undefined' && opts.readOnly) + this.hide(); + }; + + videojs.NewAnnotation.prototype.createEl = function() { + return videojs.Button.prototype.createEl.call(this, 'div', { + className: 'vjs-new-annotation vjs-menu-button vjs-control', + title: 'New Annotation', + }); + }; + + videojs.NewAnnotation.prototype.onClick = function() { + this.an.newan(); + }; + + + + // -- Player--> ControlBar--> BackAnDisplay + + /** + * The background annotations panel + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + videojs.BackAnDisplay = videojs.Component.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Component.call(this, player, options); + } + }); + + videojs.BackAnDisplay.prototype.init_ = function() { + this.an = this.player_.annotations + self = this; + // Fix error resizing the display panel. The scroll always went up. + $(this.el_).watch('font-size', function() { + self.an.backDSBarSel.setPosition(self.an.BackAnDisplayScroll.currentValue, false); + }); + + }; + + videojs.BackAnDisplay.prototype.options_ = { + children: { + 'RangeSelectorDisplay': {}, + 'AnDisplay': {}, + 'AnStat': {}, + } + }; + + videojs.BackAnDisplay.prototype.createEl = function() { + return videojs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-back-anpanel-annotation', + }); + }; + + + + // -- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay + + /** + * The selector to show the annotations in a time selection + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + + videojs.RangeSelectorDisplay = videojs.Component.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Component.call(this, player, options); + this.on('mousedown', this.onMouseDown); + } + }); + + videojs.RangeSelectorDisplay.prototype.init_ = function() { + this.rs = this.player_.rangeslider; + this.an = this.player_.annotations; + var duration = this.an.player.duration(); + this.start = 0; + this.end = duration; + + // set the selection area in the extreme position + this.setPosition(0, 0, false); + this.setPosition(1, this.rs._percent(duration), false); + }; + + videojs.RangeSelectorDisplay.prototype.options_ = { + children: { + 'RangeSelectorLeft': {}, + 'RangeSelectorRight': {}, + 'RangeSelectorBar': {}, + } + }; + + videojs.RangeSelectorDisplay.prototype.createEl = function(){ + return videojs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-rangeselector-anpanel-annotation', + }); + }; + + videojs.RangeSelectorDisplay.prototype.onMouseDown = function(event) { + event.preventDefault(); + // videojs.blockTextSelection(); + + videojs.on(document, "mousemove", videojs.bind(this, this.onMouseMove)); + videojs.on(document, "mouseup", videojs.bind(this, this.onMouseUp)); + + videojs.removeClass(this.an.rsdb.el_, 'disable'); + }; + + videojs.RangeSelectorDisplay.prototype.onMouseUp = function(event) { + videojs.off(document, "mousemove", this.onMouseMove, false); + videojs.off(document, "mouseup", this.onMouseUp, false); + + videojs.addClass(this.an.rsdb.el_, 'disable'); + }; + + videojs.RangeSelectorDisplay.prototype.onMouseMove = function(event) { + var left = this.calculateDistance(event); + if (this.an.rsdl.pressed) + this.setPosition(0, left); + else if (this.an.rsdr.pressed) + this.setPosition(1, left); + + // move the frame to the position of the arrow + this.an.player.currentTime(this.rs._seconds(left)); + }; + + videojs.RangeSelectorDisplay.prototype.calculateDistance = function(event) { + var rstbX = this.getRSTBX(); + var rstbW = this.getRSTBWidth(); + var handleW = this.getWidth(); + + // Adjusted X and Width, so handle doesn't go outside the bar + rstbX = rstbX + (handleW / 2); + rstbW = rstbW - handleW; + + // Percent that the click is through the adjusted area + return Math.max(0, Math.min(1, (event.pageX - rstbX) / rstbW)); + }; + + videojs.RangeSelectorDisplay.prototype.getRSTBWidth = function() { + return this.el_.offsetWidth; + }; + videojs.RangeSelectorDisplay.prototype.getRSTBX = function() { + return videojs.findPosition(this.el_).left; + }; + videojs.RangeSelectorDisplay.prototype.getWidth = function() { + var arrow = $(this.an.rsdl.el_).find('.vjs-selector-arrow')[0]; + return arrow.offsetWidth; // does not matter left or right + }; + + videojs.RangeSelectorDisplay.prototype.setPosition = function(index, left, changeTime) { + // index = 0 for left side, index = 1 for right side + var index = index || 0; + var changeTime = typeof changeTime !== 'undefined' ? changeTime : true; + + // Check for invalid position + if(isNaN(left)) + return false; + + // Check index between 0 and 1 + if (!(index === 0 || index === 1)) + return false; + // Alias + var ObjLeft = this.an.rsdl.el_; + var ObjRight = this.an.rsdr.el_; + var Obj = this.an[index === 0 ? 'rsdl' : 'rsdr'].el_; + + // Check if left arrow is over the right arrow + if ((index === 0 ? this.updateLeft(left) : this.updateRight(left))) { + if (index === 1) { // right + Obj.style.left = (left * 100) + '%'; + Obj.style.width = ((1 - left) * 100) + '%'; + } else { // left + Obj.style.left = (left * 100) + '%'; + Obj.style.width = ((left) * 100) + '%'; + } + + this[index === 0 ? 'start' : 'end'] = this.rs._seconds(left); + + // Fix the problem when you press the button and the two arrow are underhand + // left.zIndex = 10 and right.zIndex=20. This is always less in this case: + if (index === 0 && (left * 100) >= 90) + $(ObjLeft).find('.vjs-selector-arrow')[0].style.zIndex = 25; + else + $(ObjLeft).find('.vjs-selector-arrow')[0].style.zIndex = 10; + + + // -- Panel + var rsdbl = this.an.rsdbl.el_, + rsdbr = this.an.rsdbr.el_, + distance = parseFloat(ObjRight.style.left) - parseFloat(ObjLeft.style.left); + if (index === 0) + rsdbl.children[0].innerHTML = videojs.formatTime(this.rs._seconds(left)); + else + rsdbr.children[0].innerHTML = videojs.formatTime(this.rs._seconds(left)); + if (typeof distance !== 'undefined' && distance <= 12.5) { + if (parseFloat(ObjLeft.style.left) < 7) { + rsdbl.style.top = (-1.5) + 'em'; + rsdbl.style.left = 1 + 'em'; + } else { + rsdbl.style.left = (-2.5) + 'em'; + rsdbl.style.top = ''; + } + + if (parseFloat(ObjRight.style.left) > 93) { + rsdbr.style.top = (-1.5) + 'em'; + rsdbr.style.right = 1 + 'em'; + } else { + rsdbr.style.right = (-2.5) + 'em'; + rsdbr.style.top = ''; + } + } else { + rsdbl.style.left = 1 + 'em'; + rsdbr.style.right = 1 + 'em'; + rsdbl.style.top = ''; + rsdbr.style.top = ''; + } + + + var start = this.rs._seconds(parseFloat(ObjLeft.style.left) / 100); + var end = this.rs._seconds(parseFloat(ObjRight.style.left) / 100); + + if (changeTime) + this.an.showBetween(start, end, this.an.rsdl.include, this.an.rsdr.include); + } + return true; + }; + + videojs.RangeSelectorDisplay.prototype.updateLeft = function(left) { + var rightVal = this.an.rsdr.el_.style.left !== '' ? this.an.rsdr.el_.style.left : 100; + var right = parseFloat(rightVal) / 100; + var bar = this.an.rsdb.el_; + + var width = videojs.round((right - left), this.an.updatePrecision); // round necessary for not get 0.6e-7 for example that it's not able for the html css width + if(left <= (right+0.00001)) { + bar.style.left = (left * 100) + '%'; + bar.style.width = (width * 100) + '%'; + return true; + } + return false; + }; + + videojs.RangeSelectorDisplay.prototype.updateRight = function(right) { + var leftVal = this.an.rsdl.el_.style.left !== '' ? this.an.rsdl.el_.style.left : 0; + var left = parseFloat(leftVal) / 100; + var bar = this.an.rsdb.el_; + + var width = videojs.round((right - left), this.an.updatePrecision); // round necessary for not get 0.6e-7 for example that it's not able for the html css width + + if((right+0.00001) >= left) { + bar.style.width = (width * 100) + '%'; + bar.style.left = ((right - width) * 100) + '%'; + return true; + } + return false; + }; + + + + // -- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay--> RangeSelectorLeft + + /** + * Left Time selector + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + videojs.RangeSelectorLeft = videojs.Component.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Component.call(this, player, options); + this.on('mousedown', this.onMouseDown); + this.on('dblclick', this.ondblclick); + this.pressed = false; // to know when is mousedown + this.include = true; // to know when we want to include the boundary time in the selection or not + } + }); + + videojs.RangeSelectorLeft.prototype.init_ = function() { + this.rs = this.player_.rangeslider; + this.an = this.player_.annotations; + videojs.addClass(this.el_, 'include'); + }; + + videojs.RangeSelectorLeft.prototype.createEl = function() { + return videojs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-leftselector-anpanel-annotation', + innerHTML: '
' + }); + }; + + + videojs.RangeSelectorLeft.prototype.onMouseDown = function(event) { + event.preventDefault(); + + this.pressed = true; + videojs.on(document, "mouseup", videojs.bind(this, this.onMouseUp)); + videojs.addClass(this.el_, 'active'); + videojs.addClass(this.el_.parentNode, 'active'); + }; + + videojs.RangeSelectorLeft.prototype.onMouseUp = function(event) { + videojs.off(document, "mouseup", this.onMouseUp, false); + videojs.removeClass(this.el_, 'active'); + videojs.removeClass(this.el_.parentNode, 'active'); + this.pressed = false; + }; + + videojs.RangeSelectorLeft.prototype.ondblclick = function(event) { + if (this.include) { + this.include = false; + videojs.removeClass(this.el_, 'include'); + } else { + this.include = true; + videojs.addClass(this.el_, 'include'); + } + var left = this.an.rsd.calculateDistance(event); + this.an.rsd.setPosition(0, left); + }; + + + + // -- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay--> RangeSelectorRight + + /** + * Right Time selector + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + videojs.RangeSelectorRight = videojs.Component.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Component.call(this, player, options); + this.on('mousedown', this.onMouseDown); + this.on('dblclick', this.ondblclick); + this.pressed = false; // to know when is mousedown + this.include = true; // to know when we want to include the boundary time in the selection or not + } + }); + + videojs.RangeSelectorRight.prototype.init_ = function() { + this.rs = this.player_.rangeslider; + this.an = this.player_.annotations; + videojs.addClass(this.el_, 'include'); + }; + + videojs.RangeSelectorRight.prototype.createEl = function() { + return videojs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-rightselector-anpanel-annotation', + innerHTML: '
' + }); + }; + + videojs.RangeSelectorRight.prototype.onMouseDown = function(event) { + event.preventDefault(); + + this.pressed = true; + videojs.on(document, "mouseup", videojs.bind(this, this.onMouseUp)); + videojs.addClass(this.el_, 'active'); + videojs.addClass(this.el_.parentNode, 'active'); + }; + + videojs.RangeSelectorRight.prototype.onMouseUp = function(event) { + videojs.off(document, "mouseup", this.onMouseUp, false); + videojs.removeClass(this.el_, 'active'); + videojs.removeClass(this.el_.parentNode, 'active'); + this.pressed = false; + }; + + videojs.RangeSelectorRight.prototype.ondblclick = function(event) { + if (this.include){ + this.include = false; + videojs.removeClass(this.el_, 'include'); + }else{ + this.include = true; + videojs.addClass(this.el_, 'include'); + } + var left = this.an.rsd.calculateDistance(event); + this.an.rsd.setPosition(1, left); + }; + + + + // -- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay--> RangeSelectorBar + + /** + * Bar to display the selected Time + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + + videojs.RangeSelectorBar = videojs.Component.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Component.call(this, player, options); + } + }); + + videojs.RangeSelectorBar.prototype.init_ = function() { + videojs.addClass(this.el_, 'disable'); + }; + + videojs.RangeSelectorBar.prototype.options_ = { + children: { + 'RangeSelectorBarL': {}, + 'RangeSelectorBarR': {}, + } + }; + + videojs.RangeSelectorBar.prototype.createEl = function() { + return videojs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-barselector-anpanel-annotation', + }); + }; + + + + // -- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay--> RangeSelectorBar--> RangeSelectorBarL + + /** + * This is the left time panel for RangeSelectorBar + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + videojs.RangeSelectorBarL = videojs.Component.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Component.call(this, player, options); + } + }); + + videojs.RangeSelectorBarL.prototype.init_ = function() {}; + + videojs.RangeSelectorBarL.prototype.createEl = function() { + return videojs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-barselector-left', + innerHTML: '00:00', + }); + }; + + + + // -- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay--> RangeSelectorBar--> RangeSelectorBarR + /** + * This is the right time panel for RangeSelectorBar + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + videojs.RangeSelectorBarR = videojs.Component.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Component.call(this, player, options); + } + }); + + videojs.RangeSelectorBarR.prototype.init_ = function() {}; + + videojs.RangeSelectorBarR.prototype.createEl = function() { + return videojs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-barselector-right', + innerHTML: '00:00' + }); + }; + + + + // -- Player--> ControlBar--> BackAnDisplay--> AnDisplay + + /** + * Show the annotations in a panel + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + + videojs.AnDisplay = videojs.Component.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Component.call(this, player, options); + this.on('mousedown', this.onMouseDown); + this.on('mouseover', this.onMouseOver); + } + }); + + videojs.AnDisplay.prototype.init_ = function() { + this.rs = this.player_.rangeslider; + this.an = this.player_.annotations; + this.transition = false; + }; + + videojs.AnDisplay.prototype.createEl = function() { + return videojs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-anpanel-annotation', + }); + }; + + videojs.AnDisplay.prototype.onMouseDown = function(event) { + var elem = $(event.target).parents('.annotator-hl').andSelf(); + var _self = this; + if (elem.hasClass("annotator-hl")) { + videojs.on(document, "mouseup", videojs.bind(this, this.onMouseUp)); + // Clone the bar box to make the animation + var boxup = document.createElement('div'); + var ElemTop = parseFloat(elem[1].style.top); + var ElemMargin = parseFloat(elem[1].style.marginTop); + var emtoPx = parseFloat($(elem[1]).css('height')); + var isPoint = $(elem[1]).hasClass("point"); + + boxup.className = isPoint ? "boxup-dashed-line point" : "boxup-dashed-line"; + boxup.style.left = elem[1].style.left; + boxup.style.width = elem[1].style.width; + + boxup.style.top = (ElemTop + ElemMargin - this.el_.scrollTop / emtoPx) + 'em'; + elem[0].parentNode.parentNode.appendChild(boxup); + } + } + + videojs.AnDisplay.prototype.onMouseUp = function(event) { + if (typeof this.lastelem === 'undefined') + return false; + var elem = this.lastelem; + var _self = this; + if (elem.hasClass("annotator-hl")) { + var annotation = elem.map(function() { + return $(this).data("annotation"); + })[0]; + var displayHeight = (-1) * parseFloat($(this.el_).parent()[0].style.top); + var emtoPx = parseFloat($(elem[1]).css('height')); + if (typeof $(elem).parent().parent().find('.boxup-dashed-line')[0] !== 'undefined') { + $(elem).parent().parent().find('.boxup-dashed-line')[0].style.top = (displayHeight - 2) + 'em'; + } + + this.an.player.pause(); + this.transition = true; + window.setTimeout(function () { + _self.an.showAnnotation(annotation); + _self.transition = false; + _self.onCloseViewer(); + }, 900); + } + videojs.off(document, "mouseup", this.onMouseUp, false); + }; + + videojs.AnDisplay.prototype.onMouseOver = function(event) { + if (!this.transition && !this.an.rsdl.pressed && !this.an.rsdr.pressed) { + var annotator = this.an.annotator; + var elem = $(event.target).parents('.annotator-hl').andSelf(); + + // if there is a opened annotation then show the new annotation mouse over + if (typeof annotator !== 'undefined' && annotator.viewer.isShown() && elem.hasClass("annotator-hl")) { + // hide the last open viewer + annotator.viewer.hide(); + // get the annotation over the mouse + var annotations = elem.map(function() { + return $(this).data("annotation"); + }); + // show the annotation in the viewer + annotator.showViewer($.makeArray(annotations), Util.mousePosition(event, annotator.wrapper[0])); + } + + // create dashed line + elem.addClass('active'); + if (typeof elem !== 'undefined' && $(elem[1]).hasClass('annotation')) { + // create dashed line under the bar + var dashed = document.createElement('div'); + var boxdown = document.createElement('div'); + var DisplayHeight = parseFloat(this.an.BackAnDisplay.el_.style.height); + var ElemMarginTop = elem[1].style.marginTop !== '' ? parseFloat(elem[1].style.marginTop) : 0; + var ElemTop = parseFloat(elem[1].style.top) + ElemMarginTop; + var emtoPx = parseFloat($(elem[1]).css('height')); + var isPoint = $(elem[1]).hasClass("point"); + + dashed.className = isPoint ? 'dashed-line point' : 'dashed-line'; + boxdown.className = "box-dashed-line"; + dashed.style.left = boxdown.style.left = elem[1].style.left; + dashed.style.width = boxdown.style.width = isPoint ? '0' : elem[1].style.width; + dashed.style.top = ((ElemTop + 1) - this.el_.scrollTop / emtoPx) + 'em'; + dashed.style.height = ((DisplayHeight - ElemTop + 2) + this.el_.scrollTop / emtoPx) + 'em'; // get the absolute value of the top to put in the height + boxdown.style.top = (DisplayHeight + 2) + 'em'; + elem[0].parentNode.parentNode.appendChild(dashed); + elem[0].parentNode.parentNode.appendChild(boxdown); + + $(this.player).find('.vjs-play-progress').css('z-index', 2); + $(this.player).find('.vjs-seek-handle').css('z-index', 2); + } + + // store the last selected item + if (elem.hasClass("annotator-hl")) + this.lastelem = elem; + } + }; + + videojs.AnDisplay.prototype.onCloseViewer = function() { + if (!this.transition) { + if (typeof this.lastelem !== 'undefined') + this.lastelem.removeClass('active'); + // remove dashed line + if (typeof this.lastelem !== 'undefined' && this.lastelem.hasClass("annotator-hl")) { + $(this.lastelem).parent().parent().find('.dashed-line').remove(); + $(this.lastelem).parent().parent().find('.box-dashed-line').remove(); + $(this.lastelem).parent().parent().find('.boxup-dashed-line').remove(); + $(this.player).find('.vjs-play-progress').css('z-index', ""); + $(this.player).find('.vjs-seek-handle').css('z-index', ""); + } + } + }; + + + videojs.AnDisplay.prototype.countVisibles = function() { + var AnArray = $.makeArray(this.el_.children); + // Count visible annotations in Panel + var count = 0; + for (var index in AnArray) { + var an = AnArray[index]; + if (an.style.display !== 'none') { + count++; + } + } + return count; + }; + + + + // -- Player--> ControlBar--> BackAnDisplay--> AnStat + + /** + * Display with a chart with the statistics of the number of Annotations + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + + videojs.AnStat = videojs.Component.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Component.call(this, player, options); + this.marginTop = 20; + this.marginBottom = 0; + } + }); + + videojs.AnStat.prototype.init_ = function() { + this.rs = this.player_.rangeslider; + this.an = this.player_.annotations; + this.canvas = this.el_.children[0]; + }; + + videojs.AnStat.prototype.createEl = function() { + return videojs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-anstat-annotation', + innerHTML: 'Your browser does not support the HTML5 canvas tag.', + }); + }; + + videojs.AnStat.prototype.paintCanvas = function() { + var ctx = this.canvas.getContext("2d"); + var points = this._getPoints(); + var w = this._getWeights(points); + var maxEn = this._getMaxArray(points, 'entries'); + var TotAn = this.an.AnDisplay.el_.children.length; + var duration = this.an.player.duration(); + + // set the position of the canvas + this.canvas.style.marginTop = Math.round(this.marginTop) + 'px'; + + // Add the Max Concentration and Number of annotations + if($(this.canvas).parent().find('.vjs-totan-anstat-annotation').length === 0) { + $(this.canvas).parent().append('
'); + $(this.canvas).parent().append('
'); + } + var textCanvas = $(this.canvas).parent().find('.vjs-totan-anstat-annotation')[0]; + textCanvas.innerHTML = TotAn + ' total annotations'; + var textCanvas = $(this.canvas).parent().find('.vjs-maxcon-anstat-annotation')[0]; + textCanvas.innerHTML = 'Max Annotations = ' + maxEn; + + // Added dashed line function to paint + if (window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype.lineTo) { + CanvasRenderingContext2D.prototype.dashedLine = function(x1, y1, x2, y2, dashLen) { + if (dashLen === undefined) dashLen = 2; + + this.beginPath(); + this.moveTo(x1, y1); + + var dX = x2 - x1; + var dY = y2 - y1; + var dashes = Math.floor(Math.sqrt(dX * dX + dY * dY) / dashLen); + var dashX = dX / dashes; + var dashY = dY / dashes; + + var q = 0; + while (q++ < dashes) { + x1 += dashX; + y1 += dashY; + this[q % 2 == 0 ? 'moveTo' : 'lineTo'](x1, y1); + } + this[q % 2 == 0 ? 'moveTo' : 'lineTo'](x2, y2); + + this.stroke(); + this.closePath(); + }; + }; + + + // set the canvas size + this.canvas.height = this.an.AnDisplay.el_.offsetHeight - (this.marginTop + this.marginBottom); + this.canvas.width = this.an.AnDisplay.el_.offsetWidth; + + ctx.beginPath(); + ctx.strokeStyle = "rgb(255, 163, 0)"; + var lastSe = 0; + var lastEn = 0; + ctx.moveTo(0, maxEn * w.Y); // Move pointer to 0, 0 + for (var index in points) { + var p = points[index]; + var x1 = lastSe * w.X, y1 = (maxEn - lastEn) * w.Y; // Old Point + var x2 = p.second * w.X, y2 = (maxEn - p.entries) * w.Y; // New Point + // new line + ctx.lineTo(x2, y1); // move horizontally to the new point + ctx.moveTo(x2, y1); // Move pointer + ctx.lineTo(x2, y2); // move vertically to the new point height + ctx.moveTo(x2, y2); // Prepare pointer for a new instance + // new rectangle under the curve + ctx.fillStyle = "rgba(0, 0, 0, 0.5)"; + ctx.fillRect(x1, y1, (x2 - x1), (maxEn * w.Y - y1)); + + // store the last point + lastSe = p.second; + lastEn = p.entries; + } + // set the graphic to the end of the video + ctx.lineTo(lastSe * w.X, maxEn * w.Y); + ctx.moveTo(lastSe * w.X, maxEn * w.Y); + ctx.lineTo(duration * w.X, maxEn * w.Y); + ctx.stroke(); + + // dashed line down + ctx.beginPath(); + ctx.dashedLine(0, maxEn * w.Y, duration * w.X, maxEn * w.Y, 8); + ctx.stroke(); + // dashed line top + ctx.beginPath(); + ctx.dashedLine(0, 0, duration * w.X, 0, 8); + ctx.stroke(); + }; + + videojs.AnStat.prototype._getWeights = function(points){ + var weight = {}; + var panel = $(this.an.AnDisplay.el_); + var maxSe = this.an.player.duration(); + var maxEn = this._getMaxArray(points, 'entries'); + var panelW = parseFloat(panel.css('width')); + var panelH = parseFloat(panel.css('height')) - (this.marginTop + this.marginBottom); + weight.X = maxSe != 0 ? (panelW / maxSe) : 0; + weight.Y = maxEn != 0 ? (panelH / maxEn) : 0; + return weight; + }; + + videojs.AnStat.prototype._getMaxArray = function(points, variable) { + var highest = 0; + var tmp; + for (var index in points) { + tmp = points[index][variable]; + if (tmp > highest) highest = tmp; + } + return highest; + }; + + videojs.AnStat.prototype._getPoints = function() { + var points = []; + var allannotations = this.an.annotator.plugins.Store.annotations; + for (var index in allannotations) { + var an = allannotations[index]; + var start, end; + if (this.an._isVideoJS(an)) { + start = an.rangeTime.start; + end = an.rangeTime.end; + // start + if (!this._isFound(points, start)) { + points.push({ + second:an.rangeTime.start, + entries:this._getNumberAnnotations(start) + }); + if (an.rangeTime.start == an.rangeTime.end){ // is a point + points.push({ + second:an.rangeTime.end, + entries:this._getNumberAnnotations(end, true) + }); + } + } + // end + if (!this._isFound(points, end)) { + points.push({ + second:an.rangeTime.end, + entries:this._getNumberAnnotations(end, true) + }); + } + + found = false; + } + } + points.sort(function(a, b) { + return parseFloat(a.second) - parseFloat(b.second) + }); + return points; + }; + + videojs.AnStat.prototype._isFound = function(array, elem) { + var found = false; + for (var indexA in array) { + if(typeof array[indexA].second !== 'undefined' && array[indexA].second == elem) + found = true; + } + return found; + }; + + videojs.AnStat.prototype._getNumberAnnotations = function(time, end) { + var num = (typeof end !== 'undefined' && end) ? -1 : 0; + var allannotations = this.an.annotator.plugins['Store'].annotations; + for (var index in allannotations) { + var an = allannotations[index]; + if (this.an._isVideoJS(an)) { + if(an.rangeTime.start <= time && an.rangeTime.end >= time) + num++; + } + } + return num; + }; + + // -- Player--> ControlBar--> BackAnDisplayScroll + + /** + * The background annotations panel + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + + videojs.BackAnDisplayScroll = videojs.Component.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Component.call(this, player, options); + this.on('mousedown', this.onMouseDown); + this.UpValue = 0.1; + this.currentValue = 0; + } + }); + + videojs.BackAnDisplayScroll.prototype.init_ = function() { + this.rs = this.player_.rangeslider; + this.an = this.player_.annotations; + this.mousedownID = -1; + var self = this; + var direction; + + // Firefox + $(this.an.AnDisplay.el_).bind('DOMMouseScroll', function(e) { + if (e.originalEvent.detail > 0) + direction = self.UpValue; + else + direction = -self.UpValue; + self.an.backDSBarSel.setPosition(self.getPercentScroll() + direction); + return false; + }); + + // IE, Opera, Safari + $(this.an.AnDisplay.el_).bind('mousewheel', function(e) { + if (e.originalEvent.wheelDelta < 0) + direction = self.UpValue; + else + direction = -self.UpValue; + self.an.backDSBarSel.setPosition(self.getPercentScroll() + direction); + return false; + }); + }; + + videojs.BackAnDisplayScroll.prototype.options_ = { + children: { + 'BackAnDisplayScrollBar': {}, + 'BackAnDisplayScrollTime': {}, + } + }; + + videojs.BackAnDisplayScroll.prototype.createEl = function() { + return videojs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-scroll-anpanel-annotation', + innerHTML: '
', + }); + }; + + videojs.BackAnDisplayScroll.prototype.onMouseDown = function(event) { + var self = this; + if (event.target.className === 'vjs-scrollbar-anpanel-annotation') { + // change position with a click in the scrollbar + this.an.backDSBarSel.onMouseMove(event); + return false; + } else if (event.target.className === 'vjs-scrollbar-selector') { + // change position with scrollbar + // this event is controlled by this.an.backDSBarSel + return false; + } else { + // change position with arrows + var direction = event.target.className=='vjs-down-scroll-annotation' ? this.UpValue : -this.UpValue; + videojs.on(document, "mouseup", videojs.bind(this, this.onMouseUp)); + if(parseInt(this.mousedownID, 10) === -1) { // Prevent multimple loops! + this.mousedownID = setInterval(function () { + var pos = Math.max(0, Math.min(1, self.getPercentScroll() + direction)); + self.an.backDSBarSel.setPosition(pos); + }, 100); + } + } + }; + + videojs.BackAnDisplayScroll.prototype.onMouseUp = function(event) { + videojs.off(document, "mouseup", this.onMouseUp, false); + var self = this; + if(parseInt(this.mousedownID, 10) != -1) { // Only stop if exists + clearInterval(this.mousedownID); + self.mousedownID = -1; + } + }; + + videojs.BackAnDisplayScroll.prototype.getPercentScroll = function() { + var scroll = this.an.AnDisplay.el_; + var maxscroll = scroll.scrollHeight - scroll.offsetHeight; + var currentValue = scroll.scrollTop; + return Math.max(0, Math.min(1, maxscroll !== 0 ? (currentValue / maxscroll) : 0)); + }; + + videojs.BackAnDisplayScroll.prototype.setPercentScroll = function(percent) { + var scroll = this.an.AnDisplay.el_; + var maxscroll = scroll.scrollHeight-scroll.offsetHeight; + percent = Math.max(0, Math.min(1, percent ? percent : 0)); + scroll.scrollTop = Math.round(maxscroll * percent); + }; + + + + // -- Player--> ControlBar--> BackAnDisplayScroll--> BackAnDisplayScrollBar + + /** + * The Scroll bar for the display + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + + videojs.BackAnDisplayScrollBar = videojs.Component.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Component.call(this, player, options); + } + }); + + videojs.BackAnDisplayScrollBar.prototype.init_ = function() {}; + + videojs.BackAnDisplayScrollBar.prototype.options_ = { + children: { + 'ScrollBarSelector': {}, + } + }; + + videojs.BackAnDisplayScrollBar.prototype.createEl = function() { + return videojs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-scrollbar-anpanel-annotation', + }); + }; + + + + // -- Player--> ControlBar--> BackAnDisplayScroll--> BackAnDisplayScrollBar--> ScrollBarSelector + + /** + * The Scroll bar for the display + * @param {videojs.Player|Object} player + * @param {Object=} options + * @constructor + */ + + videojs.ScrollBarSelector = videojs.Component.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Component.call(this, player, options); + this.on('mousedown', this.onMouseDown); + } + }); + + videojs.ScrollBarSelector.prototype.init_ = function() { + this.rs = this.player_.rangeslider; + this.an = this.player_.annotations; + videojs.addClass(this.an.backDSBar.el_, 'disable'); + }; + + + videojs.ScrollBarSelector.prototype.createEl = function() { + return videojs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-scrollbar-selector', + }); + }; + + videojs.ScrollBarSelector.prototype.onMouseDown = function(event) { + event.preventDefault(); + videojs.on(document, "mousemove", videojs.bind(this, this.onMouseMove)); + videojs.on(document, "mouseup", videojs.bind(this, this.onMouseUp)); + } + + videojs.ScrollBarSelector.prototype.onMouseUp = function(event) { + videojs.off(document, "mousemove", this.onMouseMove, false); + videojs.off(document, "mouseup", this.onMouseUp, false); + }; + + videojs.ScrollBarSelector.prototype.onMouseMove = function(event) { + var top = this.calculateDistance(event); + top = this.parseMaxPercent(top); // set the max value fixing the height of the handle + this.setPosition(top); + } + + videojs.ScrollBarSelector.prototype.calculateDistance = function(event) { + var scrollY = this.getscrollY(); + var scrollH = this.getscrollHeight(); + var handleH = this.getHeight(); + + // Adjusted X and Width, so handle doesn't go outside the bar + scrollY = scrollY + (handleH); + scrollH = scrollH - (handleH); + // Adjusted X and Width, so handle doesn't go outside the bar + // Percent that the click is through the adjusted area + return Math.max(0, Math.min(1, (event.pageY - scrollY) / scrollH)); + }; + + videojs.ScrollBarSelector.prototype.getscrollHeight = function() { + return this.el_.parentNode.offsetHeight; + }; + videojs.ScrollBarSelector.prototype.getscrollY = function() { + return videojs.findPosition(this.el_.parentNode).top; + }; + videojs.ScrollBarSelector.prototype.getHeight = function() { + return this.el_.offsetHeight; + }; + videojs.ScrollBarSelector.prototype.parseMaxHeight = function(top) { + var scrollH = this.getscrollHeight(); + var handleH = this.getHeight(); + var percent = handleH / scrollH; + return Math.max(0, Math.min(1 - percent, top)); + }; + + videojs.ScrollBarSelector.prototype.parseMaxPercent = function(top) { + var scrollH = this.getscrollHeight(); + var handleH = this.getHeight(); + var percent = handleH / scrollH; + var newTop = top; + if (top >= (1 - percent)) + newTop = 1; + return newTop; + }; + + videojs.ScrollBarSelector.prototype.setPosition = function(top, showBar) { + var showBar = typeof showBar !== 'undefined' ? showBar : true; + + // Check for invalid position + if (isNaN(top)) + return false; + + // Check if there is enough annotations to scroll + if (!this.isScrollable()) + return false; + + // Show the Scrollbar + if (showBar) { + videojs.removeClass(this.an.backDSBar.el_, 'disable') + } + + // Alias + var Obj = this.el_; + var scroll = this.an.BackAnDisplayScroll; + var scrollTime = this.an.backDSTime; + + Obj.style.top = (this.parseMaxHeight(top) * 100) + '%'; + scroll.setPercentScroll(top); + + // Set the times in the scroll time panel + scrollTime.setTimes(); + + // Hide the Scrollbar in 1 sec + if(showBar) { + var _self = this; + if (typeof this.Timeout !== 'undefined') + clearTimeout(this.Timeout); + this.Timeout = window.setTimeout(function () { + videojs.addClass(_self.an.backDSBar.el_, 'disable'); + }, 1000); + } + + // set current position + this.an.BackAnDisplayScroll.currentValue = top; + return true; + } + + videojs.ScrollBarSelector.prototype.isScrollable = function() { + var scroll = this.an.AnDisplay.el_; + var emtoPx = parseFloat($(scroll).find('.annotation').css('height')); + var minTop = parseInt(scroll.offsetHeight/emtoPx); + + // Count visible annotations in Panel + var count = this.an.AnDisplay.countVisibles(); + return (count > minTop); + } + + + + // -- Player--> ControlBar--> BackAnDisplayScroll--> BackAnDisplayScrollTime + + videojs.BackAnDisplayScrollTime = videojs.Component.extend({ + /** @constructor */ + init: function(player, options) { + videojs.Component.call(this, player, options); + } + }); + + videojs.BackAnDisplayScrollTime.prototype.init_ = function() { + this.rs = this.player_.rangeslider; + this.an = this.player_.annotations; + }; + + videojs.BackAnDisplayScrollTime.prototype.createEl = function() { + return videojs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-scrolltime-anpanel-annotation', + innerHTML: '
', + }); + }; + + videojs.BackAnDisplayScrollTime.prototype.setTimes = function() { + var AnPos = this.getAnnotationPosition(); + var AnEl = this.getElements(AnPos); + var AnTimes = this.getTimes(AnEl); + if (AnTimes.top != 'Invalid Date') { + $(this.el_).find('.vjs-up-scrolltime-annotation')[0].style.visibility = ''; + $(this.el_).find('.vjs-up-scrolltime-annotation span')[0].innerHTML = AnTimes.top; + } else { + $(this.el_).find('.vjs-up-scrolltime-annotation')[0].style.visibility = 'hidden'; + } + if (AnTimes.bottom != 'Invalid Date') { + $(this.el_).find('.vjs-down-scrolltime-annotation')[0].style.visibility = ''; + $(this.el_).find('.vjs-down-scrolltime-annotation span')[0].innerHTML = AnTimes.bottom; + } else { + $(this.el_).find('.vjs-down-scrolltime-annotation')[0].style.visibility = 'hidden'; + } + }; + + videojs.BackAnDisplayScrollTime.prototype.getAnnotationPosition = function() { + var backDSBarSel = this.an.backDSBarSel; + var percent = backDSBarSel.parseMaxPercent(parseFloat(backDSBarSel.el_.style.top) / 100); + var scroll = this.an.AnDisplay.el_; + var maxTop = scroll.scrollHeight; + var minTop = scroll.offsetHeight; + var maxBottom = maxTop - minTop; + var minBottom = 0; + var pos = {}; + + percent = percent || 0; + pos.top = Math.max(minTop, Math.min(maxTop, maxBottom * percent + scroll.offsetHeight)); + pos.bottom = Math.max(minBottom, Math.min(maxBottom, maxBottom * percent)); + return pos; + }; + + videojs.BackAnDisplayScrollTime.prototype.getElements = function(AnPos) { + var AnPos = AnPos || {}; + var scroll = this.an.AnDisplay.el_; + var emtoPx = parseFloat($(scroll).find('.annotation').css('height')); + var maxTop = parseInt(scroll.scrollHeight / emtoPx); + var minTop = parseInt(scroll.offsetHeight / emtoPx); + var maxBottom = (maxTop - minTop); + var minBottom = 0; + var AnEl = {}; + AnEl.top = Math.max(minTop, Math.min(maxTop, parseInt(AnPos.top / emtoPx))); + AnEl.bottom = Math.max(minBottom, Math.min(maxBottom, parseInt(AnPos.bottom / emtoPx))); + return AnEl; + }; + + videojs.BackAnDisplayScrollTime.prototype.getTimes = function(AnEl) { + var AnEl = AnEl || {}; + var AnTimes = {}; + var TopEl, BottomEl, AnTop, AnBottom; + var AnArray = $.makeArray(this.an.AnDisplay.el_.children); + AnEl.top = AnEl.top || 0; + AnEl.bottom = AnEl.bottom || 0; + + // Get HTML Elements + var count = 0; + var lastEl; + for (var index in AnArray) { + var an = AnArray[index]; + if (an.style.display !== 'none') { + if (count == AnEl.bottom) { + TopEl = an; + } else if (count == AnEl.top) { + BottomEl = an; + } + lastEl = an; + count++; + } + } + if (typeof BottomEl === 'undefined') + BottomEl = lastEl; + + // Annotation Element + AnTop = typeof TopEl !== 'undefined' ? $.data(TopEl, 'annotation') : undefined; + AnBottom = typeof BottomEl !== 'undefined' ? $.data(BottomEl, 'annotation') : undefined; + // Update of the element + AnTimes.top = (typeof AnTop !== 'undefined' && typeof AnTop.updated !== 'undefined') ? AnTop.updated : ''; + AnTimes.bottom = (typeof AnBottom !=='undefined' && typeof AnBottom.updated !== 'undefined') ? AnBottom.updated : ''; + // Format + AnTimes.top = new Date(AnTimes.top !== '' ? createDateFromISO8601(AnTimes.top) : ''); + AnTimes.bottom = new Date(AnTimes.bottom != '' ? createDateFromISO8601(AnTimes.bottom) : ''); + return AnTimes; + }; +}) (); + +// ----------------Plugin for Annotator to setup videojs---------------- // Annotator.Plugin.VideoJS = (function(_super) { - __extends(VideoJS, _super); + __extends(VideoJS, _super); - //constructor - function VideoJS() { - this.pluginSubmit = __bind(this.pluginSubmit, this); - _ref = VideoJS.__super__.constructor.apply(this, arguments); - this.__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; } - return _ref; - } + // constructor + function VideoJS() { + this.pluginSubmit = __bind(this.pluginSubmit, this); + _ref = VideoJS.__super__.constructor.apply(this, arguments); + this.__indexOf = [].indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (i in this && this[i] === item) + return i; + } + return -1; + }; + return _ref; + }; - VideoJS.prototype.field = null; - VideoJS.prototype.input = null; + VideoJS.prototype.field = null; + VideoJS.prototype.input = null; - VideoJS.prototype.pluginInit = function() { - console.log("VideoJS-pluginInit"); - //Check that annotator is working - if (!Annotator.supported()) { - return; - } - - //-- Editor - this.field = this.annotator.editor.addField({ - id: 'vjs-input-rangeTime-annotations', - type: 'input', //options (textarea,input,select,checkbox) - submit: this.pluginSubmit, - EditVideoAn: this.EditVideoAn - }); - - //Modify the element created with annotator to be an invisible span - var select = '
  • ', - newfield = Annotator.$(select); - Annotator.$(this.field).replaceWith(newfield); - this.field=newfield[0]; - - //-- Listener for Open Video Annotator - this.initListeners(); - - return this.input = $(this.field).find(':input'); - }; - + VideoJS.prototype.pluginInit = function() { + console.log("VideoJS-pluginInit"); + // Check that annotator is working + if (!Annotator.supported()) { + return; + } + + // -- Editor + this.field = this.annotator.editor.addField({ + id: 'vjs-input-rangeTime-annotations', + type: 'input', // options (textarea, input, select, checkbox) + submit: this.pluginSubmit, + EditVideoAn: this.EditVideoAn + }); + + // Modify the element created with annotator to be an invisible span + var select = '
  • '; + var newfield = Annotator.$(select); + Annotator.$(this.field).replaceWith(newfield); + this.field = newfield[0]; + + // -- Listener for Open Video Annotator + this.initListeners(); + + return this.input = $(this.field).find(':input'); + }; + - // New JSON for the database - VideoJS.prototype.pluginSubmit = function(field, annotation) { - console.log("Plug-pluginSubmit"); - //Select the new JSON for the Object to save - if (this.EditVideoAn()){ - var annotator = this.annotator, - index = annotator.editor.VideoJS, - player = annotator.mplayer[index], - rs = player.rangeslider, - time = rs.getValues(), - isYoutube = (player && typeof player.techName!='undefined')?(player.techName == 'Youtube'):false, - isNew = typeof annotation.media=='undefined', - ext, - type = player.options_.sources[0].type.split("/") || ""; - if (typeof annotation.media == 'undefined') annotation.media = typeof type[0]!='undefined'?type[0]:"video"; // - media (by default: video) - annotation.target = annotation.target || {}; // - target - annotation.target.container = player.id_ || ""; // - target.container - annotation.target.src = player.options_.sources[0].src || ""; // - target.src (media source) - ext = (player.options_.sources[0].src.substring(player.options_.sources[0].src.lastIndexOf("."))).toLowerCase(); - ext = isYoutube?'Youtube':ext; //The extension for youtube - annotation.target.ext = ext || ""; // - target.ext (extension) - annotation.rangeTime = annotation.rangeTime || {}; // - rangeTime - annotation.rangeTime.start = time.start || 0; // - rangeTime.start - annotation.rangeTime.end = time.end || 0; // - rangeTime.end - annotation.updated = new Date().toISOString(); // - updated - if (typeof annotation.created == 'undefined') - annotation.created = annotation.updated; // - created - - //show the new annotation - var eventAn = isNew?"annotationCreated":"annotationUpdated"; - function afterFinish(){ - player.annotations.showAnnotation(annotation); - annotator.unsubscribe(eventAn, afterFinish); - }; - annotator.subscribe(eventAn, afterFinish);//show after the annotation is in the back-end - }else{ - if (typeof annotation.media == 'undefined') - annotation.media = "text"; // - media - annotation.updated = new Date().toISOString(); // - updated - if (typeof annotation.created == 'undefined') - annotation.created = annotation.updated; // - created - } - return annotation.media; - }; - - - //------ Methods ------// - //Detect if we are creating or editing a video-js annotation - VideoJS.prototype.EditVideoAn = function (){ - var wrapper = $('.annotator-wrapper').parent()[0], - annotator = window.annotator = $.data(wrapper, 'annotator'), - isOpenVideojs = (typeof annotator.mplayer != 'undefined'), - VideoJS = annotator.editor.VideoJS; - return (isOpenVideojs && typeof VideoJS!='undefined' && VideoJS!==-1); - }; - - - //Detect if the annotation is a video-js annotation - VideoJS.prototype.isVideoJS = function (an){ - var wrapper = $('.annotator-wrapper').parent()[0], - annotator = window.annotator = $.data(wrapper, 'annotator'), - rt = an.rangeTime, - isOpenVideojs = (typeof annotator.mplayer != 'undefined'), - isVideo = (typeof an.media!='undefined' && (an.media=='video' || an.media=='audio')), - isNumber = (typeof rt!='undefined' && !isNaN(parseFloat(rt.start)) && isFinite(rt.start) && !isNaN(parseFloat(rt.end)) && isFinite(rt.end)); - return (isOpenVideojs && isVideo && isNumber); - }; - - //Delete Video Annotation - VideoJS.prototype._deleteAnnotation = function(an){ - var target = an.target || {}, - container = target.container || {}, - player = this.annotator.mplayer[container]; - - var annotator = this.annotator, - annotations = annotator.plugins['Store'].annotations, - tot = typeof annotations !='undefined'?annotations.length:0, - attempts = 0; // max 100 + // New JSON for the database + VideoJS.prototype.pluginSubmit = function(field, annotation) { + console.log("Plug-pluginSubmit"); + // Select the new JSON for the Object to save + if (this.EditVideoAn()) { + var annotator = this.annotator; + var index = annotator.editor.VideoJS; + var player = annotator.mplayer[index]; + var rs = player.rangeslider; + var time = rs.getValues(); + var isYoutube = (player && typeof player.techName !== 'undefined') ? (player.techName === 'Youtube') : false; + var isNew = typeof annotation.media === 'undefined'; + var ext; + var type = player.options_.sources[0].type.split("/") || ""; - //This is to watch the annotations object, to see when is deleted the annotation - var ischanged = function(){ - var new_tot = annotator.plugins['Store'].annotations.length; - if (attempts<100) - setTimeout(function(){ - if (new_tot != tot){ - player.annotations.refreshDisplay(); //Reload the display of annotation - }else{ + if (isNew) + annotation.media = typeof type[0] !== 'undefined' ? type[0] : "video"; // - media (by default: video) + + annotation.target = annotation.target || {}; // - target + annotation.target.container = player.id_ || ""; // - target.container + annotation.target.src = player.options_.sources[0].src || ""; // - target.src (media source) + ext = (player.options_.sources[0].src.substring(player.options_.sources[0].src.lastIndexOf("."))).toLowerCase(); + ext = isYoutube ? 'Youtube' : ext; // The extension for youtube + annotation.target.ext = ext || ""; // - target.ext (extension) + annotation.rangeTime = annotation.rangeTime || {}; // - rangeTime + annotation.rangeTime.start = time.start || 0; // - rangeTime.start + annotation.rangeTime.end = time.end || 0; // - rangeTime.end + annotation.updated = new Date().toISOString(); // - updated + if (typeof annotation.created === 'undefined') + annotation.created = annotation.updated; // - created + + // show the new annotation + var eventAn = isNew ? "annotationCreated" : "annotationUpdated"; + function afterFinish(){ + player.annotations.showAnnotation(annotation); + annotator.unsubscribe(eventAn, afterFinish); + }; + annotator.subscribe(eventAn, afterFinish); // show after the annotation is in the back-end + } else { + if (typeof annotation.media === 'undefined') + annotation.media = "text"; // - media + + annotation.updated = new Date().toISOString(); // - updated + + if (typeof annotation.created === 'undefined') + annotation.created = annotation.updated; // - created + } + return annotation.media; + }; + + + // ------ Methods ------ // + // Detect if we are creating or editing a video-js annotation + VideoJS.prototype.EditVideoAn = function () { + var wrapper = $('.annotator-wrapper').parent()[0]; + var annotator = window.annotator = $.data(wrapper, 'annotator'); + var isOpenVideojs = (typeof annotator.mplayer !== 'undefined'); + var VideoJS = annotator.editor.VideoJS; + return (isOpenVideojs && typeof VideoJS !== 'undefined' && VideoJS !== -1); + }; + + + // Detect if the annotation is a video-js annotation + VideoJS.prototype.isVideoJS = function (an) { + var wrapper = $('.annotator-wrapper').parent()[0]; + var annotator = window.annotator = $.data(wrapper, 'annotator'); + var rt = an.rangeTime; + var isOpenVideojs = (typeof annotator.mplayer !== 'undefined'); + var isVideo = (typeof an.media !== 'undefined' && (an.media === 'video' || an.media === 'audio')); + var isNumber = (typeof rt !== 'undefined' && !isNaN(parseFloat(rt.start)) && isFinite(rt.start) && !isNaN(parseFloat(rt.end)) && isFinite(rt.end)); + return (isOpenVideojs && isVideo && isNumber); + }; + + // Delete Video Annotation + VideoJS.prototype._deleteAnnotation = function(an) { + var target = an.target || {}; + var container = target.container || {}; + var player = this.annotator.mplayer[container]; + + var annotator = this.annotator; + var annotations = annotator.plugins.Store.annotations; + var tot = typeof annotations !== 'undefined' ? annotations.length : 0; + var attempts = 0; // max 100 + + // This is to watch the annotations object, to see when is deleted the annotation + var ischanged = function() { + var new_tot = annotator.plugins.Store.annotations.length; + if (attempts < 100) + setTimeout(function() { + if (new_tot !== tot) { + player.annotations.refreshDisplay(); // Reload the display of annotation + } else { attempts++; ischanged(); } - },100); //wait for the change in the annotations + }, 100); // wait for the change in the annotations }; ischanged(); - - player.rangeslider.hide(); //Hide Range Slider - }; - - - //--Listeners - VideoJS.prototype.initListeners = function (){ - var wrapper = $('.annotator-wrapper').parent()[0], - annotator = $.data(wrapper, 'annotator'); - var EditVideoAn = this.EditVideoAn, - isVideoJS = this.isVideoJS, - self = this; - - //local functions - //-- Editor - function annotationEditorHidden(editor) { - console.log("annotationEditorHidden"); - if (EditVideoAn()){ - var index = annotator.editor.VideoJS; - annotator.mplayer[index].rangeslider.hide(); //Hide Range Slider - annotator.an[index].refreshDisplay(); //Reload the display of annotations - } - annotator.editor.VideoJS=-1; - annotator.unsubscribe("annotationEditorHidden", annotationEditorHidden); - }; - function annotationEditorShown(editor,annotation) { - console.log("annotationEditorShown"); - for (var index in annotator.an){ - annotator.an[index].editAnnotation(annotation,editor); - } - annotator.subscribe("annotationEditorHidden", annotationEditorHidden); - }; - //-- Annotations - function annotationDeleted(annotation) { - console.log("annotationDeleted"); - - if (isVideoJS(annotation)) - self._deleteAnnotation(annotation); - }; - //-- Viewer - function hideViewer(){ - for (var index in annotator.an){ - annotator.an[index].AnDisplay.onCloseViewer(); - } - annotator.viewer.unsubscribe("hide", hideViewer); - }; - function annotationViewerShown(viewer,annotations) { - console.log("annotationViewerShown"); - - var separation = viewer.element.hasClass(viewer.classes.invert.y)?5:-5, - newpos = { - top: parseFloat(viewer.element[0].style.top)+separation, - left: parseFloat(viewer.element[0].style.left) - }; - viewer.element.css(newpos); - - //Remove the time to wait until disapear, to be more faster that annotator by default - viewer.element.find('.annotator-controls').removeClass(viewer.classes.showControls); - - annotator.viewer.subscribe("hide", hideViewer); - }; - - //subscribe to Annotator - annotator.subscribe("annotationEditorShown", annotationEditorShown) - .subscribe("annotationDeleted", annotationDeleted) - .subscribe("annotationViewerShown", annotationViewerShown); - }; - return VideoJS; + + player.rangeslider.hide(); // Hide Range Slider + }; + + + // --Listeners + VideoJS.prototype.initListeners = function () { + var wrapper = $('.annotator-wrapper').parent()[0]; + var annotator = $.data(wrapper, 'annotator'); + var EditVideoAn = this.EditVideoAn; + var isVideoJS = this.isVideoJS; + var self = this; + + // local functions + // -- Editor + function annotationEditorHidden(editor) { + if (EditVideoAn()){ + var index = annotator.editor.VideoJS; + annotator.mplayer[index].rangeslider.hide(); // Hide Range Slider + annotator.an[index].refreshDisplay(); // Reload the display of annotations + } + annotator.editor.VideoJS=-1; + annotator.unsubscribe("annotationEditorHidden", annotationEditorHidden); + }; + function annotationEditorShown(editor, annotation) { + for (var index in annotator.an){ + annotator.an[index].editAnnotation(annotation, editor); + } + annotator.subscribe("annotationEditorHidden", annotationEditorHidden); + }; + // -- Annotations + function annotationDeleted(annotation) { + + if (isVideoJS(annotation)) + self._deleteAnnotation(annotation); + }; + // -- Viewer + function hideViewer(){ + for (var index in annotator.an) { + annotator.an[index].AnDisplay.onCloseViewer(); + } + annotator.viewer.unsubscribe("hide", hideViewer); + }; + function annotationViewerShown(viewer, annotations) { + + var separation = viewer.element.hasClass(viewer.classes.invert.y) ? 5 : -5; + var newpos = { + top: parseFloat(viewer.element[0].style.top)+separation, + left: parseFloat(viewer.element[0].style.left) + }; + viewer.element.css(newpos); + + // Remove the time to wait until disapear, to be more faster that annotator by default + viewer.element.find('.annotator-controls').removeClass(viewer.classes.showControls); + + annotator.viewer.subscribe("hide", hideViewer); + }; + + // subscribe to Annotator + annotator.subscribe("annotationEditorShown", annotationEditorShown) + .subscribe("annotationDeleted", annotationDeleted) + .subscribe("annotationViewerShown", annotationViewerShown); + }; + return VideoJS; })(Annotator.Plugin); -//----------------PUBLIC OBJECT TO CONTROL THE ANNOTATIONS----------------// +// ----------------PUBLIC OBJECT TO CONTROL THE ANNOTATIONS---------------- // -//The name of the plugin that the user will write in the html +// The name of the plugin that the user will write in the html OpenVideoAnnotation = ("OpenVideoAnnotation" in window) ? OpenVideoAnnotation : {}; OpenVideoAnnotation.Annotator = function (element, options) { - //local variables - var $ = jQuery, - options = options || {}; - options.optionsAnnotator = options.optionsAnnotator || {}; - options.optionsVideoJS = options.optionsVideoJS || {}; - options.optionsRS = options.optionsRS || {}; - options.optionsOVA = options.optionsOVA || {}; - - - //if there isn't store optinos it will create a uri and limit variables for the Back-end of Annotations - if (typeof options.optionsAnnotator.store=='undefined') - options.optionsAnnotator.store = {}; - var store = options.optionsAnnotator.store; - if (typeof store.annotationData=='undefined') - store.annotationData = {}; - if (typeof store.annotationData.uri=='undefined'){ - var uri = location.protocol + '//' + location.host + location.pathname; - store.annotationData.store = {uri:uri}; - } - if (typeof store.loadFromSearch=='undefined') - store.loadFromSearch={}; - if (typeof store.loadFromSearch.uri=='undefined') - store.loadFromSearch.uri = uri; - if (typeof store.loadFromSearch.limit=='undefined') - store.loadFromSearch.limit = 10000; - - //global variables - this.currentUser = null; + // local variables + var $ = jQuery; + var options = options || {}; + options.optionsAnnotator = options.optionsAnnotator || {}; + options.optionsVideoJS = options.optionsVideoJS || {}; + options.optionsRS = options.optionsRS || {}; + options.optionsOVA = options.optionsOVA || {}; + + + // if there isn't store optinos it will create a uri and limit variables for the Back-end of Annotations + if (typeof options.optionsAnnotator.store === 'undefined') + options.optionsAnnotator.store = {}; + var store = options.optionsAnnotator.store; + if (typeof store.annotationData === 'undefined') + store.annotationData = {}; + if (typeof store.annotationData.uri === 'undefined'){ + var uri = location.protocol + '//' + location.host + location.pathname; + store.annotationData.store = {uri: uri}; + } + if (typeof store.loadFromSearch === 'undefined') + store.loadFromSearch = {}; + if (typeof store.loadFromSearch.uri === 'undefined') + store.loadFromSearch.uri = uri; + if (typeof store.loadFromSearch.limit === 'undefined') + store.loadFromSearch.limit = 10000; + + // global variables + this.currentUser = null; - //-- Init all the classes --/ - //Annotator - this.annotator = $(element).annotator(options.optionsAnnotator.annotator).data('annotator'); - options.optionsOVA.optionsAnnotator = options.optionsAnnotator.annotator; //send the Annotator's options to OVA - - - //Video-JS - /* - mplayers -> Array with the html of all the video-js - mplayer -> Array with all the video-js that will be in the plugin - */ + // -- Init all the classes --/ + // Annotator + this.annotator = $(element).annotator(options.optionsAnnotator.annotator).data('annotator'); + options.optionsOVA.optionsAnnotator = options.optionsAnnotator.annotator; // send the Annotator's options to OVA + + + // Video-JS + /* + mplayers -> Array with the html of all the video-js + mplayer -> Array with all the video-js that will be in the plugin + */ var mplayers = $(element).find('div .video-js').toArray(); var mplayer = this.mplayer = {}; - for (var index in mplayers){ - var id = mplayers[index].id; - var mplayer_ = videojs(mplayers[index],options.optionsVideoJS); - //solve a problem with firefox. In Firefox the src() function is loaded before charge the optionsVideoJS, and the techOrder are not loaded - if (vjs.IS_FIREFOX && typeof options.optionsVideoJS.techOrder !='undefined'){ - mplayer_.options_.techOrder = options.optionsVideoJS.techOrder; - mplayer_.src(mplayer_.options_['sources']); - } - this.mplayer[id] = mplayer_; + for (var index in mplayers) { + var id = mplayers[index].id; + var mplayer_ = videojs(mplayers[index], options.optionsVideoJS); + // solve a problem with firefox. In Firefox the src() function is loaded before charge the optionsVideoJS, and the techOrder are not loaded + if (vjs.IS_FIREFOX && typeof options.optionsVideoJS.techOrder !== 'undefined'){ + mplayer_.options_.techOrder = options.optionsVideoJS.techOrder; + mplayer_.src(mplayer_.options_['sources']); + } + this.mplayer[id] = mplayer_; + } + + + // Video-JS + this.annotator.an = {}; // annotations video-js plugin to annotator + for (var index in this.mplayer) { + // to be their own options is necessary to extend deeply the options with all the childrens + this.mplayer[index].rangeslider($.extend(true, {}, options.optionsRS)); + this.mplayer[index].annotations($.extend(true, {}, options.optionsOVA)); + this.annotator.an[index]=this.mplayer[index].annotations; } - - - //Video-JS - this.annotator.an = {}; //annotations video-js plugin to annotator - for (var index in this.mplayer){ - //to be their own options is necessary to extend deeply the options with all the childrens - this.mplayer[index].rangeslider($.extend(true, {}, options.optionsRS)); - this.mplayer[index].annotations($.extend(true, {}, options.optionsOVA)); - this.annotator.an[index]=this.mplayer[index].annotations; - } - - //-- Experimental Global function for Open Video Annotator --// - this.setCurrentUser = function (user) { - this.currentUser = user; - this.annotator.plugins["Permissions"].setUser(user); - } - - //Local function to setup the keyboard listener - var focusedPlayer = this.focusedPlayer = '',//variable to know the focused player - lastfocusPlayer = this.lastfocusPlayer = ''; - - function onKeyUp(e){ - //skip the text areas - if (e.target.nodeName.toLowerCase()!='textarea') - mplayer[focusedPlayer].annotations.pressedKey(e.which); - }; - - ;(this._setupKeyboard = function(){ - $(document).mousedown(function(e) { - focusedPlayer = ''; - - //Detects if a player was click - for (var index in mplayer){ - if($(mplayer[index].el_).find(e.target).length) - focusedPlayer = mplayer[index].id_; - /* Could Fix keyboard Problem in full-screen mode - if ($(e.target).hasClass('vjs-fullscreen-control')) - mplayer[index].el_.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT); - }*/ - } - - //Enter if we change the focus between player or go out of the player - if(lastfocusPlayer != focusedPlayer){ - $(document).off("keyup", onKeyUp);//Remove the last listener - //set the key listener - if(focusedPlayer!='') - $(document).on("keyup", onKeyUp); - } - - lastfocusPlayer = focusedPlayer; - }); - - })(this); - - //-- Activate all the plugins --// - // Annotator - if (typeof options.optionsAnnotator.auth!='undefined') - this.annotator.addPlugin('Auth', options.optionsAnnotator.auth); - - if (typeof options.optionsAnnotator.permissions!='undefined') - this.annotator.addPlugin("Permissions", options.optionsAnnotator.permissions); - - if (typeof options.optionsAnnotator.store!='undefined') - this.annotator.addPlugin("Store", options.optionsAnnotator.store); + + // -- Experimental Global function for Open Video Annotator -- // + this.setCurrentUser = function (user) { + this.currentUser = user; + this.annotator.plugins["Permissions"].setUser(user); + } + + // Local function to setup the keyboard listener + var focusedPlayer = this.focusedPlayer = ''; // variable to know the focused player + var lastfocusPlayer = this.lastfocusPlayer = ''; + + function onKeyUp(e) { + // skip the text areas + if (e.target.nodeName.toLowerCase() !== 'textarea') + mplayer[focusedPlayer].annotations.pressedKey(e.which); + }; + + (this._setupKeyboard = function() { + $(document).mousedown(function(e) { + focusedPlayer = ''; + + // Detects if a player was click + for (var index in mplayer) { + if ($(mplayer[index].el_).find(e.target).length) + focusedPlayer = mplayer[index].id_; + } + + // Enter if we change the focus between player or go out of the player + if (lastfocusPlayer !== focusedPlayer) { + $(document).off("keyup", onKeyUp); // Remove the last listener + // set the key listener + if (focusedPlayer !== '') + $(document).on("keyup", onKeyUp); + } + + lastfocusPlayer = focusedPlayer; + }); + + }) (this); + + // -- Activate all the plugins -- // + // Annotator + if (typeof options.optionsAnnotator.auth !== 'undefined') + this.annotator.addPlugin('Auth', options.optionsAnnotator.auth); + + if (typeof options.optionsAnnotator.permissions !== 'undefined') + this.annotator.addPlugin("Permissions", options.optionsAnnotator.permissions); + + if (typeof options.optionsAnnotator.store !== 'undefined') + this.annotator.addPlugin("Store", options.optionsAnnotator.store); - if (typeof options.optionsAnnotator.diacriticMarks != 'undefined' && typeof Annotator.Plugin["Diacritics"] === 'function') - this.annotator.addPlugin("Diacritics", options.optionsAnnotator.diacriticMarks); - + if (typeof options.optionsAnnotator.diacriticMarks !== 'undefined' && typeof Annotator.Plugin["Diacritics"] === 'function') + this.annotator.addPlugin("Diacritics", options.optionsAnnotator.diacriticMarks); + if (typeof Annotator.Plugin["Geolocation"] === 'function') - this.annotator.addPlugin("Geolocation",options.optionsAnnotator.geolocation); - - if (typeof Annotator.Plugin["Share"] === 'function') - this.annotator.addPlugin("Share",options.optionsAnnotator.share); - - this.annotator.addPlugin("VideoJS"); //it is obligatory to have - - if (typeof Annotator.Plugin["RichText"] === 'function') - this.annotator.addPlugin("RichText",options.optionsAnnotator.richText); - - if (typeof Annotator.Plugin["Reply"] === 'function') - this.annotator.addPlugin("Reply"); + this.annotator.addPlugin("Geolocation", options.optionsAnnotator.geolocation); + + if (typeof Annotator.Plugin["Share"] === 'function') + this.annotator.addPlugin("Share", options.optionsAnnotator.share); + + this.annotator.addPlugin("VideoJS"); // it is obligatory to have + + if (typeof Annotator.Plugin["RichText"] === 'function') + this.annotator.addPlugin("RichText", options.optionsAnnotator.richText); + + if (typeof Annotator.Plugin["Reply"] === 'function') + this.annotator.addPlugin("Reply"); if (typeof Annotator.Plugin["Flagging"] === 'function') - this.annotator.addPlugin("Flagging"); + this.annotator.addPlugin("Flagging"); - if (typeof options.optionsAnnotator.highlightTags!='undefined') - this.annotator.addPlugin("HighlightTags", options.optionsAnnotator.highlightTags); - - //Will be add the player and the annotations plugin for video-js in the annotator - this.annotator.mplayer = this.mplayer; - this.annotator.editor.VideoJS=-1; - - this.options = options; - - return this; + if (typeof options.optionsAnnotator.highlightTags !== 'undefined') + this.annotator.addPlugin("HighlightTags", options.optionsAnnotator.highlightTags); + + // Will be add the player and the annotations plugin for video-js in the annotator + this.annotator.mplayer = this.mplayer; + this.annotator.editor.VideoJS = -1; + + this.options = options; + + return this; } -//----------------Local Functions for Open Video Annotator----------------// +// ----------------Local Functions for Open Video Annotator---------------- // -//--local functions -//if the annotation is a video return true -OpenVideoAnnotation.Annotator.prototype._isVideo = function(an){ - //Detect if the annotation is a Open Video Annotation - var an = an || {} - rt = an.rangeTime, - isVideo = (typeof an.media!='undefined' && (an.media=='video' || an.media=='audio')), - hasContainer = (typeof an.target!='undefined' && typeof an.target.container!='undefined' ), - isNumber = (typeof rt!='undefined' && !isNaN(parseFloat(rt.start)) && isFinite(rt.start) && !isNaN(parseFloat(rt.end)) && isFinite(rt.end)); - return (isVideo && hasContainer && isNumber); +// --local functions +// if the annotation is a video return true +OpenVideoAnnotation.Annotator.prototype._isVideo = function(an) { + // Detect if the annotation is a Open Video Annotation + var an = an || {}; + var rt = an.rangeTime; + var isVideo = (typeof an.media !== 'undefined' && (an.media === 'video' || an.media === 'audio')); + var hasContainer = (typeof an.target !== 'undefined' && typeof an.target.container !== 'undefined'); + var isNumber = (typeof rt !== 'undefined' && !isNaN(parseFloat(rt.start)) && isFinite(rt.start) && !isNaN(parseFloat(rt.end)) && isFinite(rt.end)); + return (isVideo && hasContainer && isNumber); } -//if the ova has been loaded and the video is opened return true -OpenVideoAnnotation.Annotator.prototype._isloaded = function(idElem){ - var loaded = typeof this.mplayer[idElem].annotations.loaded!='undefined'?true:false; - return loaded; +// if the ova has been loaded and the video is opened return true +OpenVideoAnnotation.Annotator.prototype._isloaded = function(idElem) { + return typeof this.mplayer[idElem].annotations.loaded !== 'undefined'; } -//----------------Public Functions for Open Video Annotator----------------// +// ----------------Public Functions for Open Video Annotator---------------- // -//Create a new video annotation -OpenVideoAnnotation.Annotator.prototype.newVideoAn = function(idElem){ - var player = this.mplayer[idElem]; - if (typeof player.play!='undefined'){ - player.play(); - player.one('playing',function(){ - player.annotations.newan(); - $('html,body').animate({ - scrollTop: $("#"+player.id_).offset().top}, - 'slow'); - player.pause(); - }); - } +// Create a new video annotation +OpenVideoAnnotation.Annotator.prototype.newVideoAn = function(idElem) { + var player = this.mplayer[idElem]; + if (typeof player.play !== 'undefined') { + player.play(); + player.one('playing', function() { + player.annotations.newan(); + $('html, body').animate({ + scrollTop: $("#" + player.id_).offset().top + }, 'slow'); + player.pause(); + }); + } }; -//Show the annotation display -OpenVideoAnnotation.Annotator.prototype.showDisplay = function(idElem){ - if(this._isloaded(idElem)) - return this.mplayer[idElem].annotations.showDisplay(); +// Show the annotation display +OpenVideoAnnotation.Annotator.prototype.showDisplay = function(idElem) { + if (this._isloaded(idElem)) + return this.mplayer[idElem].annotations.showDisplay(); }; -//Hide the annotation display -OpenVideoAnnotation.Annotator.prototype.hideDisplay = function(idElem){ - if(this._isloaded(idElem)) - return this.mplayer[idElem].annotations.hideDisplay(); +// Hide the annotation display +OpenVideoAnnotation.Annotator.prototype.hideDisplay = function(idElem) { + if (this._isloaded(idElem)) + return this.mplayer[idElem].annotations.hideDisplay(); }; -//Refresh the annotation display -OpenVideoAnnotation.Annotator.prototype.refreshDisplay = function(idElem){ - if(this._isloaded(idElem)) - return this.mplayer[idElem].annotations.hideDisplay(); +// Refresh the annotation display +OpenVideoAnnotation.Annotator.prototype.refreshDisplay = function(idElem) { + if (this._isloaded(idElem)) + return this.mplayer[idElem].annotations.hideDisplay(); }; -//Set the position of the big new annotation button -OpenVideoAnnotation.Annotator.prototype.setposBigNew = function(idElem,position){ - if(this._isloaded(idElem)) - return this.mplayer[idElem].annotations.setposBigNew(position); +// Set the position of the big new annotation button +OpenVideoAnnotation.Annotator.prototype.setposBigNew = function(idElem, position) { + if (this._isloaded(idElem)) + return this.mplayer[idElem].annotations.setposBigNew(position); }; -OpenVideoAnnotation.Annotator.prototype.playTarget = function (annotationId){ - var allannotations = this.annotator.plugins['Store'].annotations, - ovaId = annotationId, - mplayer = this.mplayer; - - for (var item in allannotations) { - var an = allannotations[item]; - if (typeof an.id!='undefined' && an.id == ovaId){//this is the annotation - if(this._isVideo(an)){//It is a video - for (var index in mplayer){ - var player = mplayer[index]; - if (player.id_ == an.target.container && player.tech.options_.source.src == an.target.src){ - var anFound = an; - - var playFunction = function(){ - //Fix problem with youtube videos in the first play. The plugin don't have this trigger - if (player.techName == 'Youtube'){ - var startAPI = function(){ - player.annotations.showAnnotation(anFound); - } - if (player.annotations.loaded) - startAPI(); - else - player.one('loadedRangeSlider', startAPI);//show Annotations once the RangeSlider is loaded - }else{ - player.annotations.showAnnotation(anFound); - } - - $('html,body').animate({ - scrollTop: $("#"+player.id_).offset().top}, - 'slow'); - }; - if (player.paused()) { - player.play(); - player.one('playing',playFunction); - }else{ - playFunction(); - } - - return false;//this will stop the code to not set a new player.one. - } - } - }else{//It is a text - var hasRanges = typeof an.ranges!='undefined' && typeof an.ranges[0] !='undefined', - startOffset = hasRanges?an.ranges[0].startOffset:'', - endOffset = hasRanges?an.ranges[0].endOffset:''; - - if(typeof startOffset!='undefined' && typeof endOffset!='undefined'){ - - $(an.highlights).parent().find('.annotator-hl').removeClass('api'); - //change the color - $(an.highlights).addClass('api'); - //animate to the annotation - $('html,body').animate({ - scrollTop: $(an.highlights[0]).offset().top}, - 'slow'); - } - } - } - } +OpenVideoAnnotation.Annotator.prototype.playTarget = function (annotationId) { + var allannotations = this.annotator.plugins.Store.annotations; + var ovaId = annotationId; + var mplayer = this.mplayer; + + for (var item in allannotations) { + var an = allannotations[item]; + if (typeof an.id != 'undefined' && an.id == ovaId) { // this is the annotation + if (this._isVideo(an)) { // It is a video + for (var index in mplayer) { + var player = mplayer[index]; + if (player.id_ == an.target.container && player.tech.options_.source.src === an.target.src){ + var anFound = an; + + var playFunction = function() { + // Fix problem with youtube videos in the first play. The plugin don't have this trigger + if (player.techName === 'Youtube') { + var startAPI = function() { + player.annotations.showAnnotation(anFound); + } + if (player.annotations.loaded) + startAPI(); + else + player.one('loadedRangeSlider', startAPI); // show Annotations once the RangeSlider is loaded + } else { + player.annotations.showAnnotation(anFound); + } + + $('html, body').animate({ + scrollTop: $("#"+player.id_).offset().top + }, 'slow'); + }; + if (player.paused()) { + player.play(); + player.one('playing', playFunction); + } else { + playFunction(); + } + + return false; // this will stop the code to not set a new player.one. + } + } + } else { // It is a text + var hasRanges = typeof an.ranges !== 'undefined' && typeof an.ranges[0] !== 'undefined'; + var startOffset = hasRanges ? an.ranges[0].startOffset : ''; + var endOffset = hasRanges ? an.ranges[0].endOffset : ''; + + if (typeof startOffset !== 'undefined' && typeof endOffset !== 'undefined') { + + $(an.highlights).parent().find('.annotator-hl').removeClass('api'); + // change the color + $(an.highlights).addClass('api'); + // animate to the annotation + $('html, body').animate({ + scrollTop: $(an.highlights[0]).offset().top + }, 'slow'); + } + } + } + } }