Merge pull request #4796 from lduarte1991/lduarte-harvardx-pr18
Annotation Tools: Fixing implicit typecasting and reordering plugins
This commit is contained in:
18
common/static/js/vendor/ova/catch/js/catch.js
vendored
18
common/static/js/vendor/ova/catch/js/catch.js
vendored
@@ -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;
|
||||
|
||||
4839
common/static/js/vendor/ova/ova.js
vendored
4839
common/static/js/vendor/ova/ova.js
vendored
@@ -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('<span class="annotator-hl"></div>');
|
||||
$(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: '<div class="vjs-big-menu-button vjs-control">A</div>',
|
||||
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('<span class="annotator-hl"></div>');
|
||||
$(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 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: '<div class="vjs-big-menu-button vjs-control">A</div>',
|
||||
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: '<div class="vjs-selector-arrow" title="Left Annotation Selector"></div><div class="vjs-leftselector-back"></div>'
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
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: '<div class="vjs-selector-arrow" title="Right Annotation Selector"></div><div class="vjs-rightselector-back"></div>'
|
||||
});
|
||||
};
|
||||
|
||||
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: '<span class="vjs-time-text">00:00</span>',
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-- 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: '<span class="vjs-time-text">00:00</span>'
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-- 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: '<canvas class="vjs-char-anstat-annotation">Your browser does not support the HTML5 canvas tag.</canvas>',
|
||||
});
|
||||
};
|
||||
|
||||
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('<div class="vjs-totan-anstat-annotation">');
|
||||
$(this.canvas).parent().append('<div class="vjs-maxcon-anstat-annotation">');
|
||||
}
|
||||
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: '<div class="vjs-up-scroll-annotation"></div><div class="vjs-down-scroll-annotation"></div>',
|
||||
});
|
||||
};
|
||||
|
||||
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: '<div class="vjs-up-scrolltime-annotation"><span class="vjs-time-text"></span></div><div class="vjs-down-scrolltime-annotation"><span class="vjs-time-text"></span></div>',
|
||||
});
|
||||
};
|
||||
|
||||
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: '<div class="vjs-selector-arrow" title="Left Annotation Selector"></div><div class="vjs-leftselector-back"></div>'
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
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: '<div class="vjs-selector-arrow" title="Right Annotation Selector"></div><div class="vjs-rightselector-back"></div>'
|
||||
});
|
||||
};
|
||||
|
||||
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: '<span class="vjs-time-text">00:00</span>',
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
// -- 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: '<span class="vjs-time-text">00:00</span>'
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
// -- 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: '<canvas class="vjs-char-anstat-annotation">Your browser does not support the HTML5 canvas tag.</canvas>',
|
||||
});
|
||||
};
|
||||
|
||||
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('<div class="vjs-totan-anstat-annotation">');
|
||||
$(this.canvas).parent().append('<div class="vjs-maxcon-anstat-annotation">');
|
||||
}
|
||||
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: '<div class="vjs-up-scroll-annotation"></div><div class="vjs-down-scroll-annotation"></div>',
|
||||
});
|
||||
};
|
||||
|
||||
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: '<div class="vjs-up-scrolltime-annotation"><span class="vjs-time-text"></span></div><div class="vjs-down-scrolltime-annotation"><span class="vjs-time-text"></span></div>',
|
||||
});
|
||||
};
|
||||
|
||||
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 = '<li><span id="vjs-input-rangeTime-annotations"></span></li>',
|
||||
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 = '<li><span id="vjs-input-rangeTime-annotations"></span></li>';
|
||||
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);
|
||||
|
||||
if (typeof options.optionsAnnotator.highlightTags!='undefined')
|
||||
this.annotator.addPlugin("HighlightTags", options.optionsAnnotator.highlightTags);
|
||||
|
||||
// -- 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");
|
||||
|
||||
//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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------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');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user