feat: Add comprehensive documentation suite and reorganize project structure
- Created complete documentation in docs/ directory - Added PROJECT_OVERVIEW.md with feature highlights and getting started guide - Added ARCHITECTURE.md with system design and technical details - Added SECURITY.md with comprehensive security implementation guide - Added DEVELOPMENT.md with development workflows and best practices - Added DEPLOYMENT.md with production deployment instructions - Added API.md with complete REST API documentation - Added CONTRIBUTING.md with contribution guidelines - Added CHANGELOG.md with version history and migration notes - Reorganized all documentation files into docs/ directory for better organization - Updated README.md with proper documentation links and quick navigation - Enhanced project structure with professional documentation standards
This commit is contained in:
46
f_scripts/shared/videojs/min/ads.vast.js
Normal file
46
f_scripts/shared/videojs/min/ads.vast.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
$(document).ready(function() {
|
||||
|
||||
if (adTagUrl == '' || ad_client != 'vast') {
|
||||
return;
|
||||
}
|
||||
|
||||
pb = "view-player-";
|
||||
var player = videojs(pb+fk);
|
||||
var options = {
|
||||
adTagUrl: adTagUrl,
|
||||
adCancelTimeout: 5000,
|
||||
playAdAlways: true,
|
||||
adsEnabled: true,
|
||||
vpaidFlashLoaderPath: current_url + 'f_scripts/shared/videojs/VPAIDFlash.swf'
|
||||
};
|
||||
player.vastClient(options);
|
||||
player.on('vast.adStart', function () {
|
||||
count=(typeof ad_skip != "undefined" ? parseInt(ad_skip) : 0);
|
||||
if (count > 0) {
|
||||
counter=setInterval(timer, 1000);
|
||||
html = '<div class="vast-skip-button">Skip <span id="skipspan">in <span id="skiptime">'+count+'</span>...</span></div>';
|
||||
$(".video-js").append(html);
|
||||
}
|
||||
$('.vjs-ad-playing .vjs-resolution-button').css({'display':'none'});
|
||||
});
|
||||
player.on('vast.adEnd', function () {
|
||||
$('.vjs-resolution-button').css({'display':'block'});
|
||||
$('.vast-skip-button').detach();
|
||||
});
|
||||
});
|
||||
function timer() { count=count-1; if (count <= 0) { clearInterval(counter); $('#skipspan').detach(); $('.vast-skip-button').addClass('enabled'); $('.vjs-ad-playing .vjs-progress-control').css({'pointer-events':'auto'}); $(".vast-skip-button.enabled").click(function() { player.trigger('vast.adEnd'); $(this).detach(); $('.vjs-resolution-button').css({'display':'block'}); }); return; } document.getElementById("skiptime").innerHTML= count; }
|
||||
1
f_scripts/shared/videojs/min/ads.vast.min.js
vendored
Normal file
1
f_scripts/shared/videojs/min/ads.vast.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
$(document).ready(function(){if(adTagUrl==""||ad_client!="vast"){return}pb="view-player-";var player=videojs(pb+fk);var options={adTagUrl:adTagUrl,adCancelTimeout:5e3,playAdAlways:true,adsEnabled:true,vpaidFlashLoaderPath:current_url+"f_scripts/shared/videojs/VPAIDFlash.swf"};player.vastClient(options);player.on("vast.adStart",function(){count=typeof ad_skip!="undefined"?parseInt(ad_skip):0;if(count>0){counter=setInterval(timer,1e3);html='<div class="vast-skip-button">Skip <span id="skipspan">in <span id="skiptime">'+count+"</span>...</span></div>";$(".video-js").append(html)}$(".vjs-ad-playing .vjs-resolution-button").css({display:"none"})});player.on("vast.adEnd",function(){$(".vjs-resolution-button").css({display:"block"});$(".vast-skip-button").detach()})});function timer(){count=count-1;if(count<=0){clearInterval(counter);$("#skipspan").detach();$(".vast-skip-button").addClass("enabled");$(".vjs-ad-playing .vjs-progress-control").css({"pointer-events":"auto"});$(".vast-skip-button.enabled").click(function(){player.trigger("vast.adEnd");$(this).detach();$(".vjs-resolution-button").css({display:"block"})});return}document.getElementById("skiptime").innerHTML=count}
|
||||
2
f_scripts/shared/videojs/min/ima.min.js
vendored
Normal file
2
f_scripts/shared/videojs/min/ima.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
482
f_scripts/shared/videojs/min/jquery.marquee.js
Normal file
482
f_scripts/shared/videojs/min/jquery.marquee.js
Normal file
@@ -0,0 +1,482 @@
|
||||
/**
|
||||
* jQuery.marquee - scrolling text like old marquee element
|
||||
* @author Aamir Afridi - aamirafridi(at)gmail(dot)com / http://aamirafridi.com/jquery/jquery-marquee-plugin
|
||||
*/;
|
||||
(function($) {
|
||||
$.fn.marquee = function(options) {
|
||||
return this.each(function() {
|
||||
// Extend the options if any provided
|
||||
var o = $.extend({}, $.fn.marquee.defaults, options),
|
||||
$this = $(this),
|
||||
$marqueeWrapper, containerWidth, animationCss, verticalDir, elWidth,
|
||||
loopCount = 3,
|
||||
playState = 'animation-play-state',
|
||||
css3AnimationIsSupported = false,
|
||||
|
||||
// Private methods
|
||||
_prefixedEvent = function(element, type, callback) {
|
||||
var pfx = ["webkit", "moz", "MS", "o", ""];
|
||||
for (var p = 0; p < pfx.length; p++) {
|
||||
if (!pfx[p]) type = type.toLowerCase();
|
||||
element.addEventListener(pfx[p] + type, callback, false);
|
||||
}
|
||||
},
|
||||
|
||||
_objToString = function(obj) {
|
||||
var tabjson = [];
|
||||
for (var p in obj) {
|
||||
if (obj.hasOwnProperty(p)) {
|
||||
tabjson.push(p + ':' + obj[p]);
|
||||
}
|
||||
}
|
||||
tabjson.push();
|
||||
return '{' + tabjson.join(',') + '}';
|
||||
},
|
||||
|
||||
_startAnimationWithDelay = function() {
|
||||
$this.timer = setTimeout(animate, o.delayBeforeStart);
|
||||
},
|
||||
|
||||
// Public methods
|
||||
methods = {
|
||||
pause: function() {
|
||||
if (css3AnimationIsSupported && o.allowCss3Support) {
|
||||
$marqueeWrapper.css(playState, 'paused');
|
||||
} else {
|
||||
// pause using pause plugin
|
||||
if ($.fn.pause) {
|
||||
$marqueeWrapper.pause();
|
||||
}
|
||||
}
|
||||
// save the status
|
||||
$this.data('runningStatus', 'paused');
|
||||
// fire event
|
||||
$this.trigger('paused');
|
||||
},
|
||||
|
||||
resume: function() {
|
||||
// resume using css3
|
||||
if (css3AnimationIsSupported && o.allowCss3Support) {
|
||||
$marqueeWrapper.css(playState, 'running');
|
||||
} else {
|
||||
// resume using pause plugin
|
||||
if ($.fn.resume) {
|
||||
$marqueeWrapper.resume();
|
||||
}
|
||||
}
|
||||
// save the status
|
||||
$this.data('runningStatus', 'resumed');
|
||||
// fire event
|
||||
$this.trigger('resumed');
|
||||
},
|
||||
|
||||
toggle: function() {
|
||||
methods[$this.data('runningStatus') == 'resumed' ? 'pause' : 'resume']();
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
// Clear timer
|
||||
clearTimeout($this.timer);
|
||||
// Unbind all events
|
||||
$this.find("*").addBack().unbind();
|
||||
// Just unwrap the elements that has been added using this plugin
|
||||
$this.html($this.find('.js-marquee:first').html());
|
||||
}
|
||||
};
|
||||
|
||||
// Check for methods
|
||||
if (typeof options === 'string') {
|
||||
if ($.isFunction(methods[options])) {
|
||||
// Following two IF statements to support public methods
|
||||
if (!$marqueeWrapper) {
|
||||
$marqueeWrapper = $this.find('.js-marquee-wrapper');
|
||||
}
|
||||
if ($this.data('css3AnimationIsSupported') === true) {
|
||||
css3AnimationIsSupported = true;
|
||||
}
|
||||
methods[options]();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if element has data attributes. They have top priority
|
||||
For details https://twitter.com/aamirafridi/status/403848044069679104 - Can't find a better solution :/
|
||||
jQuery 1.3.2 doesn't support $.data().KEY hence writting the following */
|
||||
var dataAttributes = {},
|
||||
attr;
|
||||
$.each(o, function(key, value) {
|
||||
// Check if element has this data attribute
|
||||
attr = $this.attr('data-' + key);
|
||||
if (typeof attr !== 'undefined') {
|
||||
// Now check if value is boolean or not
|
||||
switch (attr) {
|
||||
case 'true':
|
||||
attr = true;
|
||||
break;
|
||||
case 'false':
|
||||
attr = false;
|
||||
break;
|
||||
}
|
||||
o[key] = attr;
|
||||
}
|
||||
});
|
||||
|
||||
// since speed option is changed to duration, to support speed for those who are already using it
|
||||
o.duration = o.speed || o.duration;
|
||||
|
||||
// Shortcut to see if direction is upward or downward
|
||||
verticalDir = o.direction == 'up' || o.direction == 'down';
|
||||
|
||||
// no gap if not duplicated
|
||||
o.gap = o.duplicated ? parseInt(o.gap) : 0;
|
||||
|
||||
// wrap inner content into a div
|
||||
$this.wrapInner('<div class="js-marquee"></div>');
|
||||
|
||||
// Make copy of the element
|
||||
var $el = $this.find('.js-marquee').css({
|
||||
'margin-right': o.gap,
|
||||
'float': 'left'
|
||||
});
|
||||
|
||||
if (o.duplicated) {
|
||||
$el.clone(true).appendTo($this);
|
||||
}
|
||||
|
||||
// wrap both inner elements into one div
|
||||
$this.wrapInner('<div style="width:100000px" class="js-marquee-wrapper"></div>');
|
||||
|
||||
// Save the reference of the wrapper
|
||||
$marqueeWrapper = $this.find('.js-marquee-wrapper');
|
||||
|
||||
// If direction is up or down, get the height of main element
|
||||
if (verticalDir) {
|
||||
var containerHeight = $this.height();
|
||||
$marqueeWrapper.removeAttr('style');
|
||||
$this.height(containerHeight);
|
||||
|
||||
// Change the CSS for js-marquee element
|
||||
$this.find('.js-marquee').css({
|
||||
'float': 'none',
|
||||
'margin-bottom': o.gap,
|
||||
'margin-right': 0
|
||||
});
|
||||
|
||||
// Remove bottom margin from 2nd element if duplicated
|
||||
if (o.duplicated) $this.find('.js-marquee:last').css({
|
||||
'margin-bottom': 0
|
||||
});
|
||||
|
||||
var elHeight = $this.find('.js-marquee:first').height() + o.gap;
|
||||
|
||||
// adjust the animation speed according to the text length
|
||||
if (o.startVisible && !o.duplicated) {
|
||||
// Compute the complete animation duration and save it for later reference
|
||||
// formula is to: (Height of the text node + height of the main container / Height of the main container) * speed;
|
||||
o._completeDuration = ((parseInt(elHeight, 10) + parseInt(containerHeight, 10)) / parseInt(containerHeight, 10)) * o.duration;
|
||||
|
||||
// formula is to: (Height of the text node / height of the main container) * speed
|
||||
o.duration = (parseInt(elHeight, 10) / parseInt(containerHeight, 10)) * o.duration;
|
||||
} else {
|
||||
// formula is to: (Height of the text node + height of the main container / Height of the main container) * speed;
|
||||
o.duration = ((parseInt(elHeight, 10) + parseInt(containerHeight, 10)) / parseInt(containerHeight, 10)) * o.duration;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Save the width of the each element so we can use it in animation
|
||||
elWidth = $this.find('.js-marquee:first').width() + o.gap;
|
||||
|
||||
// container width
|
||||
containerWidth = $this.width();
|
||||
|
||||
// adjust the animation speed according to the text length
|
||||
if (o.startVisible && !o.duplicated) {
|
||||
// Compute the complete animation duration and save it for later reference
|
||||
// formula is to: (Width of the text node + width of the main container / Width of the main container) * speed;
|
||||
o._completeDuration = ((parseInt(elWidth, 10) + parseInt(containerWidth, 10)) / parseInt(containerWidth, 10)) * o.duration;
|
||||
|
||||
// (Width of the text node / width of the main container) * speed
|
||||
o.duration = (parseInt(elWidth, 10) / parseInt(containerWidth, 10)) * o.duration;
|
||||
} else {
|
||||
// formula is to: (Width of the text node + width of the main container / Width of the main container) * speed;
|
||||
o.duration = ((parseInt(elWidth, 10) + parseInt(containerWidth, 10)) / parseInt(containerWidth, 10)) * o.duration;
|
||||
}
|
||||
}
|
||||
|
||||
// if duplicated then reduce the speed
|
||||
if (o.duplicated) {
|
||||
o.duration = o.duration / 2;
|
||||
}
|
||||
|
||||
if (o.allowCss3Support) {
|
||||
var
|
||||
elm = document.body || document.createElement('div'),
|
||||
animationName = 'marqueeAnimation-' + Math.floor(Math.random() * 10000000),
|
||||
domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
|
||||
animationString = 'animation',
|
||||
animationCss3Str = '',
|
||||
keyframeString = '';
|
||||
|
||||
// Check css3 support
|
||||
if (elm.style.animation) {
|
||||
keyframeString = '@keyframes ' + animationName + ' ';
|
||||
css3AnimationIsSupported = true;
|
||||
}
|
||||
|
||||
if (css3AnimationIsSupported === false) {
|
||||
for (var i = 0; i < domPrefixes.length; i++) {
|
||||
if (elm.style[domPrefixes[i] + 'AnimationName'] !== undefined) {
|
||||
var prefix = '-' + domPrefixes[i].toLowerCase() + '-';
|
||||
animationString = prefix + animationString;
|
||||
playState = prefix + playState;
|
||||
keyframeString = '@' + prefix + 'keyframes ' + animationName + ' ';
|
||||
css3AnimationIsSupported = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (css3AnimationIsSupported) {
|
||||
animationCss3Str = animationName + ' ' + o.duration / 1000 + 's ' + o.delayBeforeStart / 1000 + 's infinite ' + o.css3easing;
|
||||
$this.data('css3AnimationIsSupported', true);
|
||||
}
|
||||
}
|
||||
|
||||
var _rePositionVertically = function() {
|
||||
$marqueeWrapper.css('margin-top', o.direction == 'up' ? containerHeight + 'px' : '-' + elHeight + 'px');
|
||||
},
|
||||
_rePositionHorizontally = function() {
|
||||
$marqueeWrapper.css('margin-left', o.direction == 'left' ? containerWidth + 'px' : '-' + elWidth + 'px');
|
||||
};
|
||||
|
||||
// if duplicated option is set to true than position the wrapper
|
||||
if (o.duplicated) {
|
||||
if (verticalDir) {
|
||||
if (o.startVisible) {
|
||||
$marqueeWrapper.css('margin-top', 0);
|
||||
} else {
|
||||
$marqueeWrapper.css('margin-top', o.direction == 'up' ? containerHeight + 'px' : '-' + ((elHeight * 2) - o.gap) + 'px');
|
||||
}
|
||||
} else {
|
||||
if (o.startVisible) {
|
||||
$marqueeWrapper.css('margin-left', 0);
|
||||
} else {
|
||||
$marqueeWrapper.css('margin-left', o.direction == 'left' ? containerWidth + 'px' : '-' + ((elWidth * 2) - o.gap) + 'px');
|
||||
}
|
||||
}
|
||||
|
||||
// If the text starts out visible we can skip the two initial loops
|
||||
if (!o.startVisible) {
|
||||
loopCount = 1;
|
||||
}
|
||||
} else if (o.startVisible) {
|
||||
// We only have two different loops if marquee is duplicated and starts visible
|
||||
loopCount = 2;
|
||||
} else {
|
||||
if (verticalDir) {
|
||||
_rePositionVertically();
|
||||
} else {
|
||||
_rePositionHorizontally();
|
||||
}
|
||||
}
|
||||
|
||||
// Animate recursive method
|
||||
var animate = function() {
|
||||
if (o.duplicated) {
|
||||
// When duplicated, the first loop will be scroll longer so double the duration
|
||||
if (loopCount === 1) {
|
||||
o._originalDuration = o.duration;
|
||||
if (verticalDir) {
|
||||
o.duration = o.direction == 'up' ? o.duration + (containerHeight / ((elHeight) / o.duration)) : o.duration * 2;
|
||||
} else {
|
||||
o.duration = o.direction == 'left' ? o.duration + (containerWidth / ((elWidth) / o.duration)) : o.duration * 2;
|
||||
}
|
||||
// Adjust the css3 animation as well
|
||||
if (animationCss3Str) {
|
||||
animationCss3Str = animationName + ' ' + o.duration / 1000 + 's ' + o.delayBeforeStart / 1000 + 's ' + o.css3easing;
|
||||
}
|
||||
loopCount++;
|
||||
}
|
||||
// On 2nd loop things back to normal, normal duration for the rest of animations
|
||||
else if (loopCount === 2) {
|
||||
o.duration = o._originalDuration;
|
||||
// Adjust the css3 animation as well
|
||||
if (animationCss3Str) {
|
||||
animationName = animationName + '0';
|
||||
keyframeString = $.trim(keyframeString) + '0 ';
|
||||
animationCss3Str = animationName + ' ' + o.duration / 1000 + 's 0s infinite ' + o.css3easing;
|
||||
}
|
||||
loopCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (verticalDir) {
|
||||
if (o.duplicated) {
|
||||
|
||||
// Adjust the starting point of animation only when first loops finishes
|
||||
if (loopCount > 2) {
|
||||
$marqueeWrapper.css('margin-top', o.direction == 'up' ? 0 : '-' + elHeight + 'px');
|
||||
}
|
||||
|
||||
animationCss = {
|
||||
'margin-top': o.direction == 'up' ? '-' + elHeight + 'px' : 0
|
||||
};
|
||||
} else if (o.startVisible) {
|
||||
// This loop moves the marquee out of the container
|
||||
if (loopCount === 2) {
|
||||
// Adjust the css3 animation as well
|
||||
if (animationCss3Str) {
|
||||
animationCss3Str = animationName + ' ' + o.duration / 1000 + 's ' + o.delayBeforeStart / 1000 + 's ' + o.css3easing;
|
||||
}
|
||||
animationCss = {
|
||||
'margin-top': o.direction == 'up' ? '-' + elHeight + 'px' : containerHeight + 'px'
|
||||
};
|
||||
loopCount++;
|
||||
} else if (loopCount === 3) {
|
||||
// Set the duration for the animation that will run forever
|
||||
o.duration = o._completeDuration;
|
||||
// Adjust the css3 animation as well
|
||||
if (animationCss3Str) {
|
||||
animationName = animationName + '0';
|
||||
keyframeString = $.trim(keyframeString) + '0 ';
|
||||
animationCss3Str = animationName + ' ' + o.duration / 1000 + 's 0s infinite ' + o.css3easing;
|
||||
}
|
||||
_rePositionVertically();
|
||||
}
|
||||
} else {
|
||||
_rePositionVertically();
|
||||
animationCss = {
|
||||
'margin-top': o.direction == 'up' ? '-' + ($marqueeWrapper.height()) + 'px' : containerHeight + 'px'
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if (o.duplicated) {
|
||||
|
||||
// Adjust the starting point of animation only when first loops finishes
|
||||
if (loopCount > 2) {
|
||||
$marqueeWrapper.css('margin-left', o.direction == 'left' ? 0 : '-' + elWidth + 'px');
|
||||
}
|
||||
|
||||
animationCss = {
|
||||
'margin-left': o.direction == 'left' ? '-' + elWidth + 'px' : 0
|
||||
};
|
||||
|
||||
} else if (o.startVisible) {
|
||||
// This loop moves the marquee out of the container
|
||||
if (loopCount === 2) {
|
||||
// Adjust the css3 animation as well
|
||||
if (animationCss3Str) {
|
||||
animationCss3Str = animationName + ' ' + o.duration / 1000 + 's ' + o.delayBeforeStart / 1000 + 's ' + o.css3easing;
|
||||
}
|
||||
animationCss = {
|
||||
'margin-left': o.direction == 'left' ? '-' + elWidth + 'px' : containerWidth + 'px'
|
||||
};
|
||||
loopCount++;
|
||||
} else if (loopCount === 3) {
|
||||
// Set the duration for the animation that will run forever
|
||||
o.duration = o._completeDuration;
|
||||
// Adjust the css3 animation as well
|
||||
if (animationCss3Str) {
|
||||
animationName = animationName + '0';
|
||||
keyframeString = $.trim(keyframeString) + '0 ';
|
||||
animationCss3Str = animationName + ' ' + o.duration / 1000 + 's 0s infinite ' + o.css3easing;
|
||||
}
|
||||
_rePositionHorizontally();
|
||||
}
|
||||
} else {
|
||||
_rePositionHorizontally();
|
||||
animationCss = {
|
||||
'margin-left': o.direction == 'left' ? '-' + elWidth + 'px' : containerWidth + 'px'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// fire event
|
||||
$this.trigger('beforeStarting');
|
||||
|
||||
// If css3 support is available than do it with css3, otherwise use jQuery as fallback
|
||||
if (css3AnimationIsSupported) {
|
||||
// Add css3 animation to the element
|
||||
$marqueeWrapper.css(animationString, animationCss3Str);
|
||||
var keyframeCss = keyframeString + ' { 100% ' + _objToString(animationCss) + '}',
|
||||
$styles = $marqueeWrapper.find('style');
|
||||
|
||||
// Now add the keyframe animation to the marquee element
|
||||
if ($styles.length !== 0) {
|
||||
// Bug fixed for jQuery 1.3.x - Instead of using .last(), use following
|
||||
$styles.filter(":last").html(keyframeCss);
|
||||
} else {
|
||||
$('head').append('<style>' + keyframeCss + '</style>');
|
||||
}
|
||||
|
||||
// Animation iteration event
|
||||
_prefixedEvent($marqueeWrapper[0], "AnimationIteration", function() {
|
||||
$this.trigger('finished');
|
||||
});
|
||||
// Animation stopped
|
||||
_prefixedEvent($marqueeWrapper[0], "AnimationEnd", function() {
|
||||
animate();
|
||||
$this.trigger('finished');
|
||||
});
|
||||
|
||||
} else {
|
||||
// Start animating
|
||||
$marqueeWrapper.animate(animationCss, o.duration, o.easing, function() {
|
||||
// fire event
|
||||
$this.trigger('finished');
|
||||
// animate again
|
||||
if (o.pauseOnCycle) {
|
||||
_startAnimationWithDelay();
|
||||
} else {
|
||||
animate();
|
||||
}
|
||||
});
|
||||
}
|
||||
// save the status
|
||||
$this.data('runningStatus', 'resumed');
|
||||
};
|
||||
|
||||
// bind pause and resume events
|
||||
$this.bind('pause', methods.pause);
|
||||
$this.bind('resume', methods.resume);
|
||||
|
||||
if (o.pauseOnHover) {
|
||||
$this.bind('mouseenter mouseleave', methods.toggle);
|
||||
}
|
||||
|
||||
// If css3 animation is supported than call animate method at once
|
||||
if (css3AnimationIsSupported && o.allowCss3Support) {
|
||||
animate();
|
||||
} else {
|
||||
// Starts the recursive method
|
||||
_startAnimationWithDelay();
|
||||
}
|
||||
|
||||
});
|
||||
}; // End of Plugin
|
||||
// Public: plugin defaults options
|
||||
$.fn.marquee.defaults = {
|
||||
// If you wish to always animate using jQuery
|
||||
allowCss3Support: true,
|
||||
// works when allowCss3Support is set to true - for full list see http://www.w3.org/TR/2013/WD-css3-transitions-20131119/#transition-timing-function
|
||||
css3easing: 'linear',
|
||||
// requires jQuery easing plugin. Default is 'linear'
|
||||
easing: 'linear',
|
||||
// pause time before the next animation turn in milliseconds
|
||||
delayBeforeStart: 1000,
|
||||
// 'left', 'right', 'up' or 'down'
|
||||
direction: 'left',
|
||||
// true or false - should the marquee be duplicated to show an effect of continues flow
|
||||
duplicated: false,
|
||||
// speed in milliseconds of the marquee in milliseconds
|
||||
duration: 5000,
|
||||
// gap in pixels between the tickers
|
||||
gap: 20,
|
||||
// on cycle pause the marquee
|
||||
pauseOnCycle: false,
|
||||
// on hover pause the marquee - using jQuery plugin https://github.com/tobia/Pause
|
||||
pauseOnHover: false,
|
||||
// the marquee is visible initially positioned next to the border towards it will be moving
|
||||
startVisible: false
|
||||
};
|
||||
})(jQuery);
|
||||
1
f_scripts/shared/videojs/min/jquery.marquee.min.js
vendored
Normal file
1
f_scripts/shared/videojs/min/jquery.marquee.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
f_scripts/shared/videojs/min/marquee.min.js
vendored
Normal file
2
f_scripts/shared/videojs/min/marquee.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
109
f_scripts/shared/videojs/min/videojs-marquee-overlay.js
Normal file
109
f_scripts/shared/videojs/min/videojs-marquee-overlay.js
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* @videojs-marquee-overlay/videojs-marquee-overlay
|
||||
* @version 1.0.4
|
||||
* @copyright 2017 Emre Karatasoglu (emre.karatasoglu@hotmail.com)
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('video.js')) :
|
||||
typeof define === 'function' && define.amd ? define(['video.js'], factory) :
|
||||
(global.videojsMarqueeOverlay = factory(global.videojs));
|
||||
}(this, (function (videojs) { 'use strict';
|
||||
|
||||
videojs = 'default' in videojs ? videojs['default'] : videojs;
|
||||
|
||||
var version = "1.0.4";
|
||||
|
||||
// Default options for the plugin.
|
||||
var defaults = {
|
||||
contentOfMarquee: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
position: "bottom",
|
||||
direction: "left",
|
||||
duration: 15000,
|
||||
backgroundcolor: "#dedede",
|
||||
color: "#fefefe"
|
||||
};
|
||||
|
||||
// Cross-compatibility for Video.js 5 and 6.
|
||||
var registerPlugin = videojs.registerPlugin || videojs.plugin;
|
||||
var dom = videojs.dom || videojs;
|
||||
|
||||
/**
|
||||
* Function to invoke when the player is ready.
|
||||
*
|
||||
* This is a great place for your plugin to initialize itself. When this
|
||||
* function is called, the player will have its DOM and child components
|
||||
* in place.
|
||||
*
|
||||
* @function onPlayerReady
|
||||
* @param {Player} player
|
||||
* A Video.js player object.
|
||||
*
|
||||
* @param {Object} [options={}]
|
||||
* A plain object containing options for the plugin.
|
||||
*/
|
||||
var onPlayerReady = function onPlayerReady(player, options) {
|
||||
player.addClass('vjs-marquee-overlay');
|
||||
var el = dom.createEl('div', {
|
||||
className: 'vjs-emre-marquee'
|
||||
});
|
||||
el.innerHTML = options.contentOfMarquee;
|
||||
player.el().appendChild(el);
|
||||
if (options.position == "bottom") {
|
||||
el.style.bottom = 0;
|
||||
} else {
|
||||
el.style.top = 0;
|
||||
}
|
||||
el.style.backgroundColor = options.backgroundcolor;
|
||||
el.style.color = options.color;
|
||||
player.on('timeupdate', function () {
|
||||
if (player.userActive()) {
|
||||
if (options.position == "bottom") {
|
||||
el.style.bottom = "30px";
|
||||
}
|
||||
} else {
|
||||
if (options.position == "bottom") {
|
||||
el.style.bottom = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
$(function () {
|
||||
$('.vjs-emre-marquee').marquee({
|
||||
duration: options.duration,
|
||||
gap: 50,
|
||||
delayBeforeStart: 0,
|
||||
direction: options.direction,
|
||||
duplicated: true
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* A video.js plugin.
|
||||
*
|
||||
* In the plugin function, the value of `this` is a video.js `Player`
|
||||
* instance. You cannot rely on the player being in a "ready" state here,
|
||||
* depending on how the plugin is invoked. This may or may not be important
|
||||
* to you; if not, remove the wait for "ready"!
|
||||
*
|
||||
* @function marqueeOverlay
|
||||
* @param {Object} [options={}]
|
||||
* An object of options left to the plugin author to define.
|
||||
*/
|
||||
var marqueeOverlay = function marqueeOverlay(options) {
|
||||
var _this = this;
|
||||
|
||||
this.ready(function () {
|
||||
onPlayerReady(_this, videojs.mergeOptions(defaults, options));
|
||||
});
|
||||
};
|
||||
|
||||
// Register the plugin with video.js.
|
||||
registerPlugin('marqueeOverlay', marqueeOverlay);
|
||||
|
||||
// Include the version number.
|
||||
marqueeOverlay.VERSION = version;
|
||||
|
||||
return marqueeOverlay;
|
||||
|
||||
})));
|
||||
1
f_scripts/shared/videojs/min/videojs-marquee-overlay.min.js
vendored
Normal file
1
f_scripts/shared/videojs/min/videojs-marquee-overlay.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory(require("video.js")):typeof define==="function"&&define.amd?define(["video.js"],factory):global.videojsMarqueeOverlay=factory(global.videojs)})(this,function(videojs){"use strict";videojs="default"in videojs?videojs["default"]:videojs;var version="1.0.4";var defaults={contentOfMarquee:"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",position:"bottom",direction:"left",duration:15e3,backgroundcolor:"#dedede",color:"#fefefe"};var registerPlugin=videojs.registerPlugin||videojs.plugin;var dom=videojs.dom||videojs;var onPlayerReady=function onPlayerReady(player,options){player.addClass("vjs-marquee-overlay");var el=dom.createEl("div",{className:"vjs-emre-marquee"});el.innerHTML=options.contentOfMarquee;player.el().appendChild(el);if(options.position=="bottom"){el.style.bottom=0}else{el.style.top=0}el.style.backgroundColor=options.backgroundcolor;el.style.color=options.color;player.on("timeupdate",function(){if(player.userActive()){if(options.position=="bottom"){el.style.bottom="30px"}}else{if(options.position=="bottom"){el.style.bottom=0}}});$(function(){$(".vjs-emre-marquee").marquee({duration:options.duration,gap:50,delayBeforeStart:0,direction:options.direction,duplicated:true})})};var marqueeOverlay=function marqueeOverlay(options){var _this=this;this.ready(function(){onPlayerReady(_this,videojs.mergeOptions(defaults,options))})};registerPlugin("marqueeOverlay",marqueeOverlay);marqueeOverlay.VERSION=version;return marqueeOverlay});
|
||||
794
f_scripts/shared/videojs/min/videojs.ads.js
Normal file
794
f_scripts/shared/videojs/min/videojs.ads.js
Normal file
@@ -0,0 +1,794 @@
|
||||
/**
|
||||
* Basic Ad support plugin for video.js.
|
||||
*
|
||||
* Common code to support ad integrations.
|
||||
*/
|
||||
(function(window, videojs, undefined) {
|
||||
'use strict';
|
||||
|
||||
var
|
||||
|
||||
VIDEO_EVENTS = videojs.getComponent('Html5').Events,
|
||||
|
||||
/**
|
||||
* If ads are not playing, pauses the player at the next available
|
||||
* opportunity. Has no effect if ads have started. This function is necessary
|
||||
* because pausing a video element while processing a `play` event on iOS can
|
||||
* cause the video element to continuously toggle between playing and paused
|
||||
* states.
|
||||
*
|
||||
* @param {object} player The video player
|
||||
*/
|
||||
cancelContentPlay = function(player) {
|
||||
if (player.ads.cancelPlayTimeout) {
|
||||
// another cancellation is already in flight, so do nothing
|
||||
return;
|
||||
}
|
||||
player.ads.cancelPlayTimeout = window.setTimeout(function() {
|
||||
// deregister the cancel timeout so subsequent cancels are scheduled
|
||||
player.ads.cancelPlayTimeout = null;
|
||||
|
||||
// pause playback so ads can be handled.
|
||||
if (!player.paused()) {
|
||||
player.pause();
|
||||
}
|
||||
|
||||
// add a contentplayback handler to resume playback when ads finish.
|
||||
player.one('contentplayback', function() {
|
||||
if (player.paused()) {
|
||||
player.play();
|
||||
}
|
||||
});
|
||||
}, 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a boolean indicating if given player is in live mode.
|
||||
* Can be replaced when this is fixed: https://github.com/videojs/video.js/issues/3262
|
||||
*/
|
||||
isLive = function(player) {
|
||||
if (player.duration() === Infinity) {
|
||||
return true;
|
||||
} else if (videojs.browser.IOS_VERSION === "8" && player.duration() === 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns an object that captures the portions of player state relevant to
|
||||
* video playback. The result of this function can be passed to
|
||||
* restorePlayerSnapshot with a player to return the player to the state it
|
||||
* was in when this function was invoked.
|
||||
* @param {object} player The videojs player object
|
||||
*/
|
||||
getPlayerSnapshot = function(player) {
|
||||
|
||||
var currentTime;
|
||||
|
||||
if (videojs.browser.IS_IOS && isLive(player)) {
|
||||
// Record how far behind live we are
|
||||
currentTime = player.currentTime() - player.seekable().end(0);
|
||||
} else {
|
||||
currentTime = player.currentTime();
|
||||
}
|
||||
|
||||
var
|
||||
tech = player.$('.vjs-tech'),
|
||||
tracks = player.remoteTextTracks ? player.remoteTextTracks() : [],
|
||||
track,
|
||||
i,
|
||||
suppressedTracks = [],
|
||||
snapshot = {
|
||||
ended: player.ended(),
|
||||
currentSrc: player.currentSrc(),
|
||||
src: player.src(),
|
||||
currentTime: currentTime,
|
||||
type: player.currentType()
|
||||
};
|
||||
|
||||
if (tech) {
|
||||
snapshot.nativePoster = tech.poster;
|
||||
snapshot.style = tech.getAttribute('style');
|
||||
}
|
||||
|
||||
i = tracks.length;
|
||||
while (i--) {
|
||||
track = tracks[i];
|
||||
suppressedTracks.push({
|
||||
track: track,
|
||||
mode: track.mode
|
||||
});
|
||||
track.mode = 'disabled';
|
||||
}
|
||||
snapshot.suppressedTracks = suppressedTracks;
|
||||
|
||||
return snapshot;
|
||||
},
|
||||
|
||||
/**
|
||||
* Attempts to modify the specified player so that its state is equivalent to
|
||||
* the state of the snapshot.
|
||||
* @param {object} snapshot - the player state to apply
|
||||
*/
|
||||
restorePlayerSnapshot = function(player, snapshot) {
|
||||
var
|
||||
// the playback tech
|
||||
tech = player.$('.vjs-tech'),
|
||||
|
||||
// the number of remaining attempts to restore the snapshot
|
||||
attempts = 20,
|
||||
|
||||
suppressedTracks = snapshot.suppressedTracks,
|
||||
trackSnapshot,
|
||||
restoreTracks = function() {
|
||||
var i = suppressedTracks.length;
|
||||
while (i--) {
|
||||
trackSnapshot = suppressedTracks[i];
|
||||
trackSnapshot.track.mode = trackSnapshot.mode;
|
||||
}
|
||||
},
|
||||
|
||||
// finish restoring the playback state
|
||||
resume = function() {
|
||||
var ended = false;
|
||||
var updateEnded = function() {
|
||||
ended = true;
|
||||
};
|
||||
var currentTime;
|
||||
|
||||
if (videojs.browser.IS_IOS && isLive(player)) {
|
||||
if (snapshot.currentTime < 0) {
|
||||
// Playback was behind real time, so seek backwards to match
|
||||
currentTime = player.seekable().end(0) + snapshot.currentTime;
|
||||
player.currentTime(currentTime);
|
||||
}
|
||||
} else {
|
||||
player.currentTime(snapshot.currentTime);
|
||||
}
|
||||
|
||||
// Resume playback if this wasn't a postroll
|
||||
if (!snapshot.ended) {
|
||||
player.play();
|
||||
} else {
|
||||
// On iOS 8.1, the "ended" event will not fire if you seek
|
||||
// directly to the end of a video. To make that behavior
|
||||
// consistent with the standard, fire a synthetic event if
|
||||
// "ended" does not fire within 250ms. Note that the ended
|
||||
// event should occur whether the browser actually has data
|
||||
// available for that position
|
||||
// (https://html.spec.whatwg.org/multipage/embedded-content.html#seeking),
|
||||
// so it should not be necessary to wait for the seek to
|
||||
// indicate completion.
|
||||
player.ads.resumeEndedTimeout = window.setTimeout(function() {
|
||||
if (!ended) {
|
||||
player.play();
|
||||
}
|
||||
player.off('ended', updateEnded);
|
||||
player.ads.resumeEndedTimeout = null;
|
||||
}, 250);
|
||||
player.on('ended', updateEnded);
|
||||
|
||||
// Need to clear the resume/ended timeout on dispose. If it fires
|
||||
// after a player is disposed, an error will be thrown!
|
||||
player.on('dispose', function() {
|
||||
window.clearTimeout(player.ads.resumeEndedTimeout);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// determine if the video element has loaded enough of the snapshot source
|
||||
// to be ready to apply the rest of the state
|
||||
tryToResume = function() {
|
||||
|
||||
// tryToResume can either have been called through the `contentcanplay`
|
||||
// event or fired through setTimeout.
|
||||
// When tryToResume is called, we should make sure to clear out the other
|
||||
// way it could've been called by removing the listener and clearing out
|
||||
// the timeout.
|
||||
player.off('contentcanplay', tryToResume);
|
||||
if (player.ads.tryToResumeTimeout_) {
|
||||
player.clearTimeout(player.ads.tryToResumeTimeout_);
|
||||
player.ads.tryToResumeTimeout_ = null;
|
||||
}
|
||||
|
||||
// Tech may have changed depending on the differences in sources of the
|
||||
// original video and that of the ad
|
||||
tech = player.el().querySelector('.vjs-tech');
|
||||
|
||||
if (tech.readyState > 1) {
|
||||
// some browsers and media aren't "seekable".
|
||||
// readyState greater than 1 allows for seeking without exceptions
|
||||
return resume();
|
||||
}
|
||||
|
||||
if (tech.seekable === undefined) {
|
||||
// if the tech doesn't expose the seekable time ranges, try to
|
||||
// resume playback immediately
|
||||
return resume();
|
||||
}
|
||||
|
||||
if (tech.seekable.length > 0) {
|
||||
// if some period of the video is seekable, resume playback
|
||||
return resume();
|
||||
}
|
||||
|
||||
// delay a bit and then check again unless we're out of attempts
|
||||
if (attempts--) {
|
||||
window.setTimeout(tryToResume, 50);
|
||||
} else {
|
||||
(function() {
|
||||
try {
|
||||
resume();
|
||||
} catch(e) {
|
||||
videojs.log.warn('Failed to resume the content after an advertisement', e);
|
||||
}
|
||||
})();
|
||||
}
|
||||
},
|
||||
|
||||
// whether the video element has been modified since the
|
||||
// snapshot was taken
|
||||
srcChanged;
|
||||
|
||||
if (snapshot.nativePoster) {
|
||||
tech.poster = snapshot.nativePoster;
|
||||
}
|
||||
|
||||
if ('style' in snapshot) {
|
||||
// overwrite all css style properties to restore state precisely
|
||||
tech.setAttribute('style', snapshot.style || '');
|
||||
}
|
||||
|
||||
// Determine whether the player needs to be restored to its state
|
||||
// before ad playback began. With a custom ad display or burned-in
|
||||
// ads, the content player state hasn't been modified and so no
|
||||
// restoration is required
|
||||
|
||||
srcChanged = player.src() !== snapshot.src || player.currentSrc() !== snapshot.currentSrc;
|
||||
|
||||
if (srcChanged) {
|
||||
// on ios7, fiddling with textTracks too early will cause safari to crash
|
||||
player.one('contentloadedmetadata', restoreTracks);
|
||||
|
||||
// if the src changed for ad playback, reset it
|
||||
player.src({ src: snapshot.currentSrc, type: snapshot.type });
|
||||
// safari requires a call to `load` to pick up a changed source
|
||||
player.load();
|
||||
// and then resume from the snapshots time once the original src has loaded
|
||||
// in some browsers (firefox) `canplay` may not fire correctly.
|
||||
// Reace the `canplay` event with a timeout.
|
||||
player.one('contentcanplay', tryToResume);
|
||||
player.ads.tryToResumeTimeout_ = player.setTimeout(tryToResume, 2000);
|
||||
} else if (!player.ended() || !snapshot.ended) {
|
||||
// if we didn't change the src, just restore the tracks
|
||||
restoreTracks();
|
||||
// the src didn't change and this wasn't a postroll
|
||||
// just resume playback at the current time.
|
||||
player.play();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove the poster attribute from the video element tech, if present. When
|
||||
* reusing a video element for multiple videos, the poster image will briefly
|
||||
* reappear while the new source loads. Removing the attribute ahead of time
|
||||
* prevents the poster from showing up between videos.
|
||||
* @param {object} player The videojs player object
|
||||
*/
|
||||
removeNativePoster = function(player) {
|
||||
var tech = player.$('.vjs-tech');
|
||||
if (tech) {
|
||||
tech.removeAttribute('poster');
|
||||
}
|
||||
},
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Ad Framework
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// default framework settings
|
||||
defaults = {
|
||||
// maximum amount of time in ms to wait to receive `adsready` from the ad
|
||||
// implementation after play has been requested. Ad implementations are
|
||||
// expected to load any dynamic libraries and make any requests to determine
|
||||
// ad policies for a video during this time.
|
||||
timeout: 5000,
|
||||
|
||||
// maximum amount of time in ms to wait for the ad implementation to start
|
||||
// linear ad mode after `readyforpreroll` has fired. This is in addition to
|
||||
// the standard timeout.
|
||||
prerollTimeout: 100,
|
||||
|
||||
// maximum amount of time in ms to wait for the ad implementation to start
|
||||
// linear ad mode after `contentended` has fired.
|
||||
postrollTimeout: 100,
|
||||
|
||||
// when truthy, instructs the plugin to output additional information about
|
||||
// plugin state to the video.js log. On most devices, the video.js log is
|
||||
// the same as the developer console.
|
||||
debug: false
|
||||
},
|
||||
|
||||
adFramework = function(options) {
|
||||
var player = this;
|
||||
var settings = videojs.mergeOptions(defaults, options);
|
||||
var fsmHandler;
|
||||
|
||||
// prefix all video element events during ad playback
|
||||
// if the video element emits ad-related events directly,
|
||||
// plugins that aren't ad-aware will break. prefixing allows
|
||||
// plugins that wish to handle ad events to do so while
|
||||
// avoiding the complexity for common usage
|
||||
(function() {
|
||||
var videoEvents = VIDEO_EVENTS.concat([
|
||||
'firstplay',
|
||||
'loadedalldata'
|
||||
]);
|
||||
|
||||
var returnTrue = function() { return true; };
|
||||
|
||||
var triggerEvent = function(type, event) {
|
||||
// pretend we called stopImmediatePropagation because we want the native
|
||||
// element events to continue propagating
|
||||
event.isImmediatePropagationStopped = returnTrue;
|
||||
event.cancelBubble = true;
|
||||
event.isPropagationStopped = returnTrue;
|
||||
player.trigger({
|
||||
type: type + event.type,
|
||||
state: player.ads.state,
|
||||
originalEvent: event
|
||||
});
|
||||
};
|
||||
|
||||
player.on(videoEvents, function redispatch(event) {
|
||||
if (player.ads.state === 'ad-playback') {
|
||||
triggerEvent('ad', event);
|
||||
} else if (player.ads.state === 'content-playback' && event.type === 'ended') {
|
||||
triggerEvent('content', event);
|
||||
} else if (player.ads.state === 'content-resuming') {
|
||||
if (player.ads.snapshot) {
|
||||
// the video element was recycled for ad playback
|
||||
if (player.currentSrc() !== player.ads.snapshot.currentSrc) {
|
||||
if (event.type === 'loadstart') {
|
||||
return;
|
||||
}
|
||||
return triggerEvent('content', event);
|
||||
|
||||
// we ended playing postrolls and the video itself
|
||||
// the content src is back in place
|
||||
} else if (player.ads.snapshot.ended) {
|
||||
if ((event.type === 'pause' ||
|
||||
event.type === 'ended')) {
|
||||
// after loading a video, the natural state is to not be started
|
||||
// in this case, it actually has, so, we do it manually
|
||||
player.addClass('vjs-has-started');
|
||||
// let `pause` and `ended` events through, naturally
|
||||
return;
|
||||
}
|
||||
// prefix all other events in content-resuming with `content`
|
||||
return triggerEvent('content', event);
|
||||
}
|
||||
}
|
||||
if (event.type !== 'playing') {
|
||||
triggerEvent('content', event);
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
// We now auto-play when an ad gets loaded if we're playing ads in the same video element as the content.
|
||||
// The problem is that in IE11, we cannot play in addurationchange but in iOS8, we cannot play from adcanplay.
|
||||
// This will allow ad-integrations from needing to do this themselves.
|
||||
player.on(['addurationchange', 'adcanplay'], function() {
|
||||
if (typeof player.ads.snapshot !== "undefined" && player.currentSrc() === player.ads.snapshot.currentSrc) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.play();
|
||||
});
|
||||
|
||||
player.on('nopreroll', function() {
|
||||
player.ads.nopreroll_ = true;
|
||||
});
|
||||
|
||||
player.on('nopostroll', function() {
|
||||
player.ads.nopostroll_ = true;
|
||||
});
|
||||
|
||||
// replace the ad initializer with the ad namespace
|
||||
player.ads = {
|
||||
state: 'content-set',
|
||||
|
||||
// Call this when an ad response has been received and there are
|
||||
// linear ads ready to be played.
|
||||
startLinearAdMode: function() {
|
||||
if (player.ads.state === 'preroll?' ||
|
||||
player.ads.state === 'content-playback' ||
|
||||
player.ads.state === 'postroll?') {
|
||||
player.trigger('adstart');
|
||||
}
|
||||
},
|
||||
|
||||
// Call this when a linear ad pod has finished playing.
|
||||
endLinearAdMode: function() {
|
||||
if (player.ads.state === 'ad-playback') {
|
||||
player.trigger('adend');
|
||||
}
|
||||
},
|
||||
|
||||
// Call this when an ad response has been received but there are no
|
||||
// linear ads to be played (i.e. no ads available, or overlays).
|
||||
// This has no effect if we are already in a linear ad mode. Always
|
||||
// use endLinearAdMode() to exit from linear ad-playback state.
|
||||
skipLinearAdMode: function() {
|
||||
if (player.ads.state !== 'ad-playback') {
|
||||
player.trigger('adskip');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fsmHandler = function(event) {
|
||||
// Ad Playback State Machine
|
||||
var fsm = {
|
||||
'content-set': {
|
||||
events: {
|
||||
'adscanceled': function() {
|
||||
this.state = 'content-playback';
|
||||
},
|
||||
'adsready': function() {
|
||||
this.state = 'ads-ready';
|
||||
},
|
||||
'play': function() {
|
||||
this.state = 'ads-ready?';
|
||||
cancelContentPlay(player);
|
||||
// remove the poster so it doesn't flash between videos
|
||||
removeNativePoster(player);
|
||||
},
|
||||
'adserror': function() {
|
||||
this.state = 'content-playback';
|
||||
},
|
||||
'adskip': function() {
|
||||
this.state = 'content-playback';
|
||||
}
|
||||
}
|
||||
},
|
||||
'ads-ready': {
|
||||
events: {
|
||||
'play': function() {
|
||||
this.state = 'preroll?';
|
||||
cancelContentPlay(player);
|
||||
},
|
||||
'adskip': function() {
|
||||
this.state = 'content-playback';
|
||||
},
|
||||
'adserror': function() {
|
||||
this.state = 'content-playback';
|
||||
}
|
||||
}
|
||||
},
|
||||
'preroll?': {
|
||||
enter: function() {
|
||||
if (player.ads.nopreroll_) {
|
||||
// This will start the ads manager in case there are later ads
|
||||
player.trigger('readyforpreroll');
|
||||
// Don't wait for a preroll
|
||||
player.trigger('nopreroll');
|
||||
} else {
|
||||
// change class to show that we're waiting on ads
|
||||
player.addClass('vjs-ad-loading');
|
||||
// schedule an adtimeout event to fire if we waited too long
|
||||
player.ads.adTimeoutTimeout = window.setTimeout(function() {
|
||||
player.trigger('adtimeout');
|
||||
}, settings.prerollTimeout);
|
||||
// signal to ad plugin that it's their opportunity to play a preroll
|
||||
player.trigger('readyforpreroll');
|
||||
}
|
||||
},
|
||||
leave: function() {
|
||||
window.clearTimeout(player.ads.adTimeoutTimeout);
|
||||
player.removeClass('vjs-ad-loading');
|
||||
},
|
||||
events: {
|
||||
'play': function() {
|
||||
cancelContentPlay(player);
|
||||
},
|
||||
'adstart': function() {
|
||||
this.state = 'ad-playback';
|
||||
},
|
||||
'adskip': function() {
|
||||
this.state = 'content-playback';
|
||||
},
|
||||
'adtimeout': function() {
|
||||
this.state = 'content-playback';
|
||||
},
|
||||
'adserror': function() {
|
||||
this.state = 'content-playback';
|
||||
},
|
||||
'nopreroll': function() {
|
||||
this.state = 'content-playback';
|
||||
}
|
||||
}
|
||||
},
|
||||
'ads-ready?': {
|
||||
enter: function() {
|
||||
player.addClass('vjs-ad-loading');
|
||||
player.ads.adTimeoutTimeout = window.setTimeout(function() {
|
||||
player.trigger('adtimeout');
|
||||
}, settings.timeout);
|
||||
},
|
||||
leave: function() {
|
||||
window.clearTimeout(player.ads.adTimeoutTimeout);
|
||||
player.removeClass('vjs-ad-loading');
|
||||
},
|
||||
events: {
|
||||
'play': function() {
|
||||
cancelContentPlay(player);
|
||||
},
|
||||
'adscanceled': function() {
|
||||
this.state = 'content-playback';
|
||||
},
|
||||
'adsready': function() {
|
||||
this.state = 'preroll?';
|
||||
},
|
||||
'adskip': function() {
|
||||
this.state = 'content-playback';
|
||||
},
|
||||
'adtimeout': function() {
|
||||
this.state = 'content-playback';
|
||||
},
|
||||
'adserror': function() {
|
||||
this.state = 'content-playback';
|
||||
}
|
||||
}
|
||||
},
|
||||
'ad-playback': {
|
||||
enter: function() {
|
||||
// capture current player state snapshot (playing, currentTime, src)
|
||||
if (videojs.browser.IS_IOS || player.duration() !== Infinity) {
|
||||
this.snapshot = getPlayerSnapshot(player);
|
||||
}
|
||||
|
||||
// Mute the player behind the ad
|
||||
if (!videojs.browser.IS_IOS && player.duration() === Infinity) {
|
||||
this.preAdVolume_ = player.volume();
|
||||
player.volume(0);
|
||||
}
|
||||
|
||||
// add css to the element to indicate and ad is playing.
|
||||
player.addClass('vjs-ad-playing');
|
||||
|
||||
// remove the poster so it doesn't flash between ads
|
||||
removeNativePoster(player);
|
||||
|
||||
// We no longer need to supress play events once an ad is playing.
|
||||
// Clear it if we were.
|
||||
if (player.ads.cancelPlayTimeout) {
|
||||
window.clearTimeout(player.ads.cancelPlayTimeout);
|
||||
player.ads.cancelPlayTimeout = null;
|
||||
}
|
||||
},
|
||||
leave: function() {
|
||||
player.removeClass('vjs-ad-playing');
|
||||
if (videojs.browser.IS_IOS || player.duration() !== Infinity) {
|
||||
restorePlayerSnapshot(player, this.snapshot);
|
||||
}
|
||||
|
||||
// Reset the volume to pre-ad levels
|
||||
if (!videojs.browser.IS_IOS && player.duration() === Infinity) {
|
||||
player.volume(this.preAdVolume_);
|
||||
}
|
||||
|
||||
// trigger 'adend' as a consistent notification
|
||||
// event that we're exiting ad-playback.
|
||||
if (player.ads.triggerevent !== 'adend') {
|
||||
player.trigger('adend');
|
||||
}
|
||||
},
|
||||
events: {
|
||||
'adend': function() {
|
||||
this.state = 'content-resuming';
|
||||
},
|
||||
'adserror': function() {
|
||||
this.state = 'content-resuming';
|
||||
}
|
||||
}
|
||||
},
|
||||
'content-resuming': {
|
||||
enter: function() {
|
||||
if (this.snapshot && this.snapshot.ended) {
|
||||
window.clearTimeout(player.ads._fireEndedTimeout);
|
||||
// in some cases, ads are played in a swf or another video element
|
||||
// so we do not get an ended event in this state automatically.
|
||||
// If we don't get an ended event we can use, we need to trigger
|
||||
// one ourselves or else we won't actually ever end the current video.
|
||||
player.ads._fireEndedTimeout = window.setTimeout(function() {
|
||||
player.trigger('ended');
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
leave: function() {
|
||||
window.clearTimeout(player.ads._fireEndedTimeout);
|
||||
},
|
||||
events: {
|
||||
'contentupdate': function() {
|
||||
this.state = 'content-set';
|
||||
},
|
||||
contentresumed: function() {
|
||||
this.state = 'content-playback';
|
||||
},
|
||||
'playing': function() {
|
||||
this.state = 'content-playback';
|
||||
},
|
||||
'ended': function() {
|
||||
this.state = 'content-playback';
|
||||
}
|
||||
}
|
||||
},
|
||||
'postroll?': {
|
||||
enter: function() {
|
||||
this.snapshot = getPlayerSnapshot(player);
|
||||
if (player.ads.nopostroll_) {
|
||||
player.ads.state = 'content-resuming';
|
||||
window.setTimeout(function() {
|
||||
player.trigger('ended');
|
||||
}, 1);
|
||||
} else {
|
||||
player.addClass('vjs-ad-loading');
|
||||
|
||||
player.ads.adTimeoutTimeout = window.setTimeout(function() {
|
||||
player.trigger('adtimeout');
|
||||
}, settings.postrollTimeout);
|
||||
}
|
||||
},
|
||||
leave: function() {
|
||||
window.clearTimeout(player.ads.adTimeoutTimeout);
|
||||
player.removeClass('vjs-ad-loading');
|
||||
},
|
||||
events: {
|
||||
'adstart': function() {
|
||||
this.state = 'ad-playback';
|
||||
},
|
||||
'adskip': function() {
|
||||
this.state = 'content-resuming';
|
||||
window.setTimeout(function() {
|
||||
player.trigger('ended');
|
||||
}, 1);
|
||||
},
|
||||
'adtimeout': function() {
|
||||
this.state = 'content-resuming';
|
||||
window.setTimeout(function() {
|
||||
player.trigger('ended');
|
||||
}, 1);
|
||||
},
|
||||
'adserror': function() {
|
||||
this.state = 'content-resuming';
|
||||
window.setTimeout(function() {
|
||||
player.trigger('ended');
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
'content-playback': {
|
||||
enter: function() {
|
||||
// make sure that any cancelPlayTimeout is cleared
|
||||
if (player.ads.cancelPlayTimeout) {
|
||||
window.clearTimeout(player.ads.cancelPlayTimeout);
|
||||
player.ads.cancelPlayTimeout = null;
|
||||
}
|
||||
// this will cause content to start if a user initiated
|
||||
// 'play' event was canceled earlier.
|
||||
player.trigger({
|
||||
type: 'contentplayback',
|
||||
triggerevent: player.ads.triggerevent
|
||||
});
|
||||
},
|
||||
events: {
|
||||
// in the case of a timeout, adsready might come in late.
|
||||
'adsready': function() {
|
||||
player.trigger('readyforpreroll');
|
||||
},
|
||||
'adstart': function() {
|
||||
this.state = 'ad-playback';
|
||||
},
|
||||
'contentupdate': function() {
|
||||
if (player.paused()) {
|
||||
this.state = 'content-set';
|
||||
} else {
|
||||
this.state = 'ads-ready?';
|
||||
}
|
||||
},
|
||||
'contentended': function() {
|
||||
this.state = 'postroll?';
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
(function(state) {
|
||||
var noop = function() {};
|
||||
|
||||
// process the current event with a noop default handler
|
||||
((fsm[state].events || {})[event.type] || noop).apply(player.ads);
|
||||
|
||||
// check whether the state has changed
|
||||
if (state !== player.ads.state) {
|
||||
|
||||
// record the event that caused the state transition
|
||||
player.ads.triggerevent = event.type;
|
||||
|
||||
// execute leave/enter callbacks if present
|
||||
(fsm[state].leave || noop).apply(player.ads);
|
||||
(fsm[player.ads.state].enter || noop).apply(player.ads);
|
||||
|
||||
// output debug logging
|
||||
if (settings.debug) {
|
||||
videojs.log('ads', player.ads.triggerevent + ' triggered: ' + state + ' -> ' + player.ads.state);
|
||||
}
|
||||
}
|
||||
|
||||
})(player.ads.state);
|
||||
|
||||
};
|
||||
|
||||
// register for the events we're interested in
|
||||
player.on(VIDEO_EVENTS.concat([
|
||||
// events emitted by ad plugin
|
||||
'adtimeout',
|
||||
'contentupdate',
|
||||
'contentplaying',
|
||||
'contentended',
|
||||
'contentresumed',
|
||||
|
||||
// events emitted by third party ad implementors
|
||||
'adsready',
|
||||
'adserror',
|
||||
'adscanceled',
|
||||
'adstart', // startLinearAdMode()
|
||||
'adend', // endLinearAdMode()
|
||||
'adskip', // skipLinearAdMode()
|
||||
'nopreroll'
|
||||
]), fsmHandler);
|
||||
|
||||
// keep track of the current content source
|
||||
// if you want to change the src of the video without triggering
|
||||
// the ad workflow to restart, you can update this variable before
|
||||
// modifying the player's source
|
||||
player.ads.contentSrc = player.currentSrc();
|
||||
|
||||
// implement 'contentupdate' event.
|
||||
(function(){
|
||||
var
|
||||
// check if a new src has been set, if so, trigger contentupdate
|
||||
checkSrc = function() {
|
||||
var src;
|
||||
if (player.ads.state !== 'ad-playback') {
|
||||
src = player.currentSrc();
|
||||
if (src !== player.ads.contentSrc) {
|
||||
player.trigger({
|
||||
type: 'contentupdate',
|
||||
oldValue: player.ads.contentSrc,
|
||||
newValue: src
|
||||
});
|
||||
player.ads.contentSrc = src;
|
||||
}
|
||||
}
|
||||
};
|
||||
// loadstart reliably indicates a new src has been set
|
||||
player.on('loadstart', checkSrc);
|
||||
// check immediately in case we missed the loadstart
|
||||
window.setTimeout(checkSrc, 1);
|
||||
})();
|
||||
|
||||
// kick off the fsm
|
||||
if (!player.paused()) {
|
||||
// simulate a play event if we're autoplaying
|
||||
fsmHandler({type:'play'});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// register the ad plugin framework
|
||||
videojs.plugin('ads', adFramework);
|
||||
|
||||
})(window, videojs);
|
||||
1
f_scripts/shared/videojs/min/videojs.ads.min.js
vendored
Normal file
1
f_scripts/shared/videojs/min/videojs.ads.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1443
f_scripts/shared/videojs/min/videojs.ima.js
Normal file
1443
f_scripts/shared/videojs/min/videojs.ima.js
Normal file
File diff suppressed because it is too large
Load Diff
1
f_scripts/shared/videojs/min/videojs.ima.min.js
vendored
Normal file
1
f_scripts/shared/videojs/min/videojs.ima.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
f_scripts/shared/videojs/min/videojs_5.vast.vpaid.min.js
vendored
Normal file
6
f_scripts/shared/videojs/min/videojs_5.vast.vpaid.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user