From 94063235a6e50bea83563f29c9d54ab6cd64098d Mon Sep 17 00:00:00 2001 From: Robin Cornett Date: Thu, 22 Aug 2019 11:14:21 -0400 Subject: [PATCH] Update backstretch script to 2.1.17 --- includes/js/backstretch.js | 1660 +++++++++-------- includes/js/backstretch.min.js | 2 +- ...ss-displayfeaturedimagegenesis-enqueue.php | 2 +- 3 files changed, 845 insertions(+), 819 deletions(-) diff --git a/includes/js/backstretch.js b/includes/js/backstretch.js index df8e364..858f770 100644 --- a/includes/js/backstretch.js +++ b/includes/js/backstretch.js @@ -6,89 +6,90 @@ * Licensed under the MIT license. */ -;(function ($, window, undefined) { +; ( function ( $, window, undefined ) { 'use strict'; /** @const */ var YOUTUBE_REGEXP = /^.*(youtu\.be\/|youtube\.com\/v\/|youtube\.com\/embed\/|youtube\.com\/watch\?v=|youtube\.com\/watch\?.*\&v=)([^#\&\?]*).*/i; - + /* PLUGIN DEFINITION * ========================= */ - $.fn.backstretch = function (images, options) { + $.fn.backstretch = function ( images, options ) { var args = arguments; /* * Scroll the page one pixel to get the right window height on iOS * Pretty harmless for everyone else */ - if ($(window).scrollTop() === 0 ) { - window.scrollTo(0, 0); + if ( $( window ).scrollTop() === 0 ) { + window.scrollTo( 0, 0 ); } var returnValues; - - this.each(function (eachIndex) { - var $this = $(this) - , obj = $this.data('backstretch'); + + this.each( function ( eachIndex ) { + var $this = $( this ) + , obj = $this.data( 'backstretch' ); // Do we already have an instance attached to this element? - if (obj) { + if ( obj ) { // Is this a method they're trying to execute? - if (typeof args[0] === 'string' && - typeof obj[args[0]] === 'function') { - + if ( typeof args[ 0 ] === 'string' && + typeof obj[ args[ 0 ] ] === 'function' ) { + // Call the method - var returnValue = obj[args[0]].apply(obj, Array.prototype.slice.call(args, 1)); - if (returnValue === obj) { // If a method is chaining + var returnValue = obj[ args[ 0 ] ].apply( obj, Array.prototype.slice.call( args, 1 ) ); + if ( returnValue === obj ) { // If a method is chaining returnValue = undefined; } - if (returnValue !== undefined) { + if ( returnValue !== undefined ) { returnValues = returnValues || []; - returnValues[eachIndex] = returnValue; + returnValues[ eachIndex ] = returnValue; } - + return; // Nothing further to do } // Merge the old options with the new - options = $.extend(obj.options, options); + options = $.extend( obj.options, options ); // Remove the old instance - if ( obj.hasOwnProperty('destroy') ) { - obj.destroy(true); + if ( typeof obj === 'object' && 'destroy' in obj ) { + obj.destroy( true ); } } // We need at least one image - if (!images || (images && images.length === 0)) { - var cssBackgroundImage = $this.css('background-image'); - if (cssBackgroundImage && cssBackgroundImage !== 'none') { - images = [ { url: $this.css('backgroundImage').replace(/url\(|\)|"|'/g,"") } ]; - } else { - $.error('No images were supplied for Backstretch, or element must have a CSS-defined background image.'); + if ( !images || ( images && images.length === 0 ) ) { + var cssBackgroundImage = $this.css( 'background-image' ); + if ( cssBackgroundImage && cssBackgroundImage !== 'none' ) { + images = [ { url: $this.css( 'backgroundImage' ).replace( /url\(|\)|"|'/g, "" ) } ]; + } + else { + $.error( 'No images were supplied for Backstretch, or element must have a CSS-defined background image.' ); } } - obj = new Backstretch(this, images, options || {}); - $this.data('backstretch', obj); - }); - - return returnValues ? returnValues.length === 1 ? returnValues[0] : returnValues : this; + obj = new Backstretch( this, images, options || {} ); + $this.data( 'backstretch', obj ); + } ); + + return returnValues ? returnValues.length === 1 ? returnValues[ 0 ] : returnValues : this; }; // If no element is supplied, we'll attach to body - $.backstretch = function (images, options) { + $.backstretch = function ( images, options ) { // Return the instance - return $('body') - .backstretch(images, options) - .data('backstretch'); + return $( 'body' ) + .backstretch( images, options ) + .data( 'backstretch' ); }; // Custom selector - $.expr[':'].backstretch = function(elem) { - return $(elem).data('backstretch') !== undefined; + $.expr[ ':' ].backstretch = function ( elem ) { + return $( elem ).data( 'backstretch' ) !== undefined; }; /* DEFAULTS @@ -158,18 +159,18 @@ * Returns an array of urls optimized for the specified resolution. * */ - var optimalSizeImages = (function () { + var optimalSizeImages = ( function () { /* Sorts the array of image sizes based on width */ - var widthInsertSort = function (arr) { - for (var i = 1; i < arr.length; i++) { - var tmp = arr[i], - j = i; - while (arr[j - 1] && parseInt(arr[j - 1].width, 10) > parseInt(tmp.width, 10)) { - arr[j] = arr[j - 1]; + var widthInsertSort = function ( arr ) { + for ( var i = 1; i < arr.length; i++ ) { + var tmp = arr[ i ], + j = i; + while ( arr[ j - 1 ] && parseInt( arr[ j - 1 ].width, 10 ) > parseInt( tmp.width, 10 ) ) { + arr[ j ] = arr[ j - 1 ]; --j; } - arr[j] = tmp; + arr[ j ] = tmp; } return arr; @@ -178,279 +179,284 @@ /* Given an array of various sizes of the same image and a container width, * return the best image. */ - var selectBest = function (containerWidth, containerHeight, imageSizes) { + var selectBest = function ( containerWidth, containerHeight, imageSizes ) { var devicePixelRatio = window.devicePixelRatio || 1; var deviceOrientation = getDeviceOrientation(); var windowOrientation = getWindowOrientation(); - var wrapperOrientation = (containerHeight > containerWidth) ? + var wrapperOrientation = ( containerHeight > containerWidth ) ? 'portrait' : - (containerWidth > containerHeight ? 'landscape' : 'square'); + ( containerWidth > containerHeight ? 'landscape' : 'square' ); var lastAllowedImage = 0; var testWidth; - for (var j = 0, image; j < imageSizes.length; j++) { + for ( var j = 0, image; j < imageSizes.length; j++ ) { - image = imageSizes[j]; + image = imageSizes[ j ]; - // In case a new image was pushed in, process it: - if (typeof image === 'string') { - image = imageSizes[j] = { url: image }; - } + // In case a new image was pushed in, process it: + if ( typeof image === 'string' ) { + image = imageSizes[ j ] = { url: image }; + } - if (image.pixelRatio && image.pixelRatio !== 'auto' && parseFloat(image.pixelRatio) !== devicePixelRatio) { - // We disallowed choosing this image for current device pixel ratio, - // So skip this one. - continue; - } + if ( image.pixelRatio && image.pixelRatio !== 'auto' && parseFloat( image.pixelRatio ) !== devicePixelRatio ) { + // We disallowed choosing this image for current device pixel ratio, + // So skip this one. + continue; + } - if (image.deviceOrientation && image.deviceOrientation !== deviceOrientation) { - // We disallowed choosing this image for current device orientation, - // So skip this one. - continue; - } + if ( image.deviceOrientation && image.deviceOrientation !== deviceOrientation ) { + // We disallowed choosing this image for current device orientation, + // So skip this one. + continue; + } - if (image.windowOrientation && image.windowOrientation !== deviceOrientation) { - // We disallowed choosing this image for current window orientation, - // So skip this one. - continue; - } + if ( image.windowOrientation && image.windowOrientation !== deviceOrientation ) { + // We disallowed choosing this image for current window orientation, + // So skip this one. + continue; + } - if (image.orientation && image.orientation !== wrapperOrientation) { - // We disallowed choosing this image for current element's orientation, - // So skip this one. - continue; - } + if ( image.orientation && image.orientation !== wrapperOrientation ) { + // We disallowed choosing this image for current element's orientation, + // So skip this one. + continue; + } - // Mark this one as the last one we investigated - // which does not violate device pixel ratio rules. - // We may choose this one later if there's no match. - lastAllowedImage = j; + // Mark this one as the last one we investigated + // which does not violate device pixel ratio rules. + // We may choose this one later if there's no match. + lastAllowedImage = j; - // For most images, we match the specified width against element width, - // And enforcing a limit depending on the "pixelRatio" property if specified. - // But if a pixelRatio="auto", then we consider the width as the physical width of the image, - // And match it while considering the device's pixel ratio. - testWidth = containerWidth; - if (image.pixelRatio === 'auto') { - containerWidth *= devicePixelRatio; - } + // For most images, we match the specified width against element width, + // And enforcing a limit depending on the "pixelRatio" property if specified. + // But if a pixelRatio="auto", then we consider the width as the physical width of the image, + // And match it while considering the device's pixel ratio. + testWidth = containerWidth; + if ( image.pixelRatio === 'auto' ) { + containerWidth *= devicePixelRatio; + } - // Stop when the width of the image is larger or equal to the container width - if (image.width >= testWidth) { - break; - } + // Stop when the width of the image is larger or equal to the container width + if ( image.width >= testWidth ) { + break; + } } // Use the image located at where we stopped - return imageSizes[Math.min(j, lastAllowedImage)]; - }; - - var replaceTagsInUrl = function (url, templateReplacer) { - - if (typeof url === 'string') { - url = url.replace(/{{(width|height)}}/g, templateReplacer); - } else if (url instanceof Array) { - for (var i = 0; i < url.length; i++) { - if (url[i].src) { - url[i].src = replaceTagsInUrl(url[i].src, templateReplacer); - } else { - url[i] = replaceTagsInUrl(url[i], templateReplacer); - } - } - } - - return url; + return imageSizes[ Math.min( j, lastAllowedImage ) ]; }; - return function ($container, images) { + var replaceTagsInUrl = function ( url, templateReplacer ) { + + if ( typeof url === 'string' ) { + url = url.replace( /{{(width|height)}}/g, templateReplacer ); + } + else if ( url instanceof Array ) { + for ( var i = 0; i < url.length; i++ ) { + if ( url[ i ].src ) { + url[ i ].src = replaceTagsInUrl( url[ i ].src, templateReplacer ); + } + else { + url[ i ] = replaceTagsInUrl( url[ i ], templateReplacer ); + } + } + } + + return url; + }; + + return function ( $container, images ) { var containerWidth = $container.width(), - containerHeight = $container.height(); + containerHeight = $container.height(); var chosenImages = []; - var templateReplacer = function (match, key) { - if (key === 'width') { + var templateReplacer = function ( match, key ) { + if ( key === 'width' ) { return containerWidth; } - if (key === 'height') { + if ( key === 'height' ) { return containerHeight; } return match; }; - for (var i = 0; i < images.length; i++) { - if ($.isArray(images[i])) { - images[i] = widthInsertSort(images[i]); - var chosen = selectBest(containerWidth, containerHeight, images[i]); - chosenImages.push(chosen); - } else { + for ( var i = 0; i < images.length; i++ ) { + if ( $.isArray( images[ i ] ) ) { + images[ i ] = widthInsertSort( images[ i ] ); + var chosen = selectBest( containerWidth, containerHeight, images[ i ] ); + chosenImages.push( chosen ); + } + else { // In case a new image was pushed in, process it: - if (typeof images[i] === 'string') { - images[i] = { url: images[i] }; + if ( typeof images[ i ] === 'string' ) { + images[ i ] = { url: images[ i ] }; } - var item = $.extend({}, images[i]); - item.url = replaceTagsInUrl(item.url, templateReplacer); - chosenImages.push(item); + var item = $.extend( {}, images[ i ] ); + item.url = replaceTagsInUrl( item.url, templateReplacer ); + chosenImages.push( item ); } } return chosenImages; }; - })(); - - var isVideoSource = function (source) { - return YOUTUBE_REGEXP.test(source.url) || source.isVideo; + } )(); + + var isVideoSource = function ( source ) { + return YOUTUBE_REGEXP.test( source.url ) || source.isVideo; }; /* Preload images */ - var preload = (function (sources, startAt, count, batchSize, callback) { + var preload = ( function ( sources, startAt, count, batchSize, callback ) { // Plugin cache var cache = []; // Wrapper for cache - var caching = function(image){ - for (var i = 0; i < cache.length; i++) { - if (cache[i].src === image.src) { - return cache[i]; + var caching = function ( image ) { + for ( var i = 0; i < cache.length; i++ ) { + if ( cache[ i ].src === image.src ) { + return cache[ i ]; } } - cache.push(image); + cache.push( image ); return image; }; // Execute callback - var exec = function(sources, callback, last){ - if (typeof callback === 'function') { - callback.call(sources, last); + var exec = function ( sources, callback, last ) { + if ( typeof callback === 'function' ) { + callback.call( sources, last ); } }; // Closure to hide cache - return function preload (sources, startAt, count, batchSize, callback){ + return function preload ( sources, startAt, count, batchSize, callback ) { // Check input data - if (typeof sources === 'undefined') { + if ( typeof sources === 'undefined' ) { return; } - if (!$.isArray(sources)) { - sources = [sources]; + if ( !$.isArray( sources ) ) { + sources = [ sources ]; } - if (arguments.length < 5 && typeof arguments[arguments.length - 1] === 'function') { - callback = arguments[arguments.length - 1]; + if ( arguments.length < 5 && typeof arguments[ arguments.length - 1 ] === 'function' ) { + callback = arguments[ arguments.length - 1 ]; } - startAt = (typeof startAt === 'function' || !startAt) ? 0 : startAt; - count = (typeof count === 'function' || !count || count < 0) ? sources.length : Math.min(count, sources.length); - batchSize = (typeof batchSize === 'function' || !batchSize) ? 1 : batchSize; + startAt = ( typeof startAt === 'function' || !startAt ) ? 0 : startAt; + count = ( typeof count === 'function' || !count || count < 0 ) ? sources.length : Math.min( count, sources.length ); + batchSize = ( typeof batchSize === 'function' || !batchSize ) ? 1 : batchSize; - if (startAt >= sources.length) { - startAt = 0; - count = 0; + if ( startAt >= sources.length ) { + startAt = 0; + count = 0; } - if (batchSize < 0) { - batchSize = count; + if ( batchSize < 0 ) { + batchSize = count; } - batchSize = Math.min(batchSize, count); + batchSize = Math.min( batchSize, count ); - var next = sources.slice(startAt + batchSize, count - batchSize); - sources = sources.slice(startAt, batchSize); + var next = sources.slice( startAt + batchSize, count - batchSize ); + sources = sources.slice( startAt, batchSize ); count = sources.length; // If sources array is empty - if (!count) { - exec(sources, callback, true); + if ( !count ) { + exec( sources, callback, true ); return; } // Image loading callback var countLoaded = 0; - var loaded = function() { + var loaded = function () { countLoaded++; - if (countLoaded !== count) { + if ( countLoaded !== count ) { return; } - exec(sources, callback, !next); - preload(next, 0, 0, batchSize, callback); + exec( sources, callback, !next ); + preload( next, 0, 0, batchSize, callback ); }; // Loop sources to preload var image; - for (var i = 0; i < sources.length; i++) { - - if (isVideoSource(sources[i])) { - + for ( var i = 0; i < sources.length; i++ ) { + + if ( isVideoSource( sources[ i ] ) ) { + // Do not preload videos. There are issues with that. // First - we need to keep an instance of the preloaded and use that exactly, not a copy. // Second - there are memory issues. // If there will be a requirement from users - I'll try to implement this. continue; - - } else { - - image = new Image(); - image.src = sources[i].url; - image = caching(image); - - if (image.complete) { - loaded(); - } else { - $(image).on('load error', loaded); - } - } - + else { + + image = new Image(); + image.src = sources[ i ].url; + + image = caching( image ); + + if ( image.complete ) { + loaded(); + } + else { + $( image ).on( 'load error', loaded ); + } + + } + } }; - })(); + } )(); /* Process images array */ - var processImagesArray = function (images) { + var processImagesArray = function ( images ) { var processed = []; - for (var i = 0; i < images.length; i++) { - if (typeof images[i] === 'string') { - processed.push({ url: images[i] }); + for ( var i = 0; i < images.length; i++ ) { + if ( typeof images[ i ] === 'string' ) { + processed.push( { url: images[ i ] } ); } - else if ($.isArray(images[i])) { - processed.push(processImagesArray(images[i])); + else if ( $.isArray( images[ i ] ) ) { + processed.push( processImagesArray( images[ i ] ) ); } else { - processed.push(processOptions(images[i])); + processed.push( processOptions( images[ i ] ) ); } } return processed; }; /* Process options */ - var processOptions = function (options, required) { + var processOptions = function ( options, required ) { // Convert old options // centeredX/centeredY are deprecated - if (options.centeredX || options.centeredY) { - if (window.console && window.console.log) { - window.console.log('jquery.backstretch: `centeredX`/`centeredY` is deprecated, please use `alignX`/`alignY`'); + if ( options.centeredX || options.centeredY ) { + if ( window.console && window.console.log ) { + window.console.log( 'jquery.backstretch: `centeredX`/`centeredY` is deprecated, please use `alignX`/`alignY`' ); } - if (options.centeredX) { + if ( options.centeredX ) { options.alignX = 0.5; } - if (options.centeredY) { + if ( options.centeredY ) { options.alignY = 0.5; } } // Deprecated spec - if (options.speed !== undefined) { + if ( options.speed !== undefined ) { - if (window.console && window.console.log) { - window.console.log('jquery.backstretch: `speed` is deprecated, please use `transitionDuration`'); + if ( window.console && window.console.log ) { + window.console.log( 'jquery.backstretch: `speed` is deprecated, please use `transitionDuration`' ); } options.transitionDuration = options.speed; @@ -458,62 +464,62 @@ } // Typo - if (options.resolutionChangeRatioTreshold !== undefined) { - window.console.log('jquery.backstretch: `treshold` is a typo!'); + if ( options.resolutionChangeRatioTreshold !== undefined ) { + window.console.log( 'jquery.backstretch: `treshold` is a typo!' ); options.resolutionChangeRatioThreshold = options.resolutionChangeRatioTreshold; } // Current spec that needs processing - if (options.fadeFirst !== undefined) { + if ( options.fadeFirst !== undefined ) { options.animateFirst = options.fadeFirst; } - if (options.fade !== undefined) { + if ( options.fade !== undefined ) { options.transitionDuration = options.fade; options.transition = 'fade'; } - if (options.scale) { - options.scale = validScale(options.scale); + if ( options.scale ) { + options.scale = validScale( options.scale ); } - - return processAlignOptions(options); + + return processAlignOptions( options ); }; /* Process align options */ - var processAlignOptions = function (options, required) { - if (options.alignX === 'left') { + var processAlignOptions = function ( options, required ) { + if ( options.alignX === 'left' ) { options.alignX = 0.0; } - else if (options.alignX === 'center') { + else if ( options.alignX === 'center' ) { options.alignX = 0.5; } - else if (options.alignX === 'right') { + else if ( options.alignX === 'right' ) { options.alignX = 1.0; } else { - if (options.alignX !== undefined || required) { - options.alignX = parseFloat(options.alignX); - if (isNaN(options.alignX)) { + if ( options.alignX !== undefined || required ) { + options.alignX = parseFloat( options.alignX ); + if ( isNaN( options.alignX ) ) { options.alignX = 0.5; } } } - if (options.alignY === 'top') { + if ( options.alignY === 'top' ) { options.alignY = 0.0; } - else if (options.alignY === 'center') { + else if ( options.alignY === 'center' ) { options.alignY = 0.5; } - else if (options.alignY === 'bottom') { + else if ( options.alignY === 'bottom' ) { options.alignY = 1.0; } else { - if (options.alignX !== undefined || required) { - options.alignY = parseFloat(options.alignY); - if (isNaN(options.alignY)) { + if ( options.alignX !== undefined || required ) { + options.alignY = parseFloat( options.alignY ); + if ( isNaN( options.alignY ) ) { options.alignY = 0.5; } } @@ -523,52 +529,50 @@ }; var SUPPORTED_SCALE_OPTIONS = { - 'cover': 'cover', - 'fit': 'fit', - 'fit-smaller': 'fit-smaller', - 'fill': 'fill' + 'cover': 'cover', + 'fit': 'fit', + 'fit-smaller': 'fit-smaller', + 'fill': 'fill' }; - - function validScale(scale) { - if (!SUPPORTED_SCALE_OPTIONS.hasOwnProperty(scale)) { + + function validScale ( scale ) { + if ( !SUPPORTED_SCALE_OPTIONS.hasOwnProperty( scale ) ) { return 'cover'; } return scale; } - + /* CLASS DEFINITION * ========================= */ - var Backstretch = function (container, images, options) { - this.options = $.extend({}, $.fn.backstretch.defaults, options || {}); + var Backstretch = function ( container, images, options ) { + this.options = $.extend( {}, $.fn.backstretch.defaults, options || {} ); this.firstShow = true; // Process options - processOptions(this.options, true); + processOptions( this.options, true ); /* In its simplest form, we allow Backstretch to be called on an image path. * e.g. $.backstretch('/path/to/image.jpg') * So, we need to turn this back into an array. */ - this.images = processImagesArray($.isArray(images) ? images : [images]); + this.images = processImagesArray( $.isArray( images ) ? images : [ images ] ); /** * Paused-Option */ - if (this.options.paused) { - this.paused = true; + if ( this.options.paused ) { + this.paused = true; } /** * Start-Option (Index) */ - if (this.options.start >= this.images.length) - { - this.options.start = this.images.length - 1; + if ( this.options.start >= this.images.length ) { + this.options.start = this.images.length - 1; } - if (this.options.start < 0) - { - this.options.start = 0; + if ( this.options.start < 0 ) { + this.options.start = 0; } // Convenience reference to know if the container is body. @@ -580,116 +584,117 @@ * Wrap: a DIV that we place the image into, so we can hide the overflow. * Root: Convenience reference to help calculate the correct height. */ - var $window = $(window); - this.$container = $(container); - this.$root = this.isBody ? supportsFixedPosition ? $window : $(document) : this.$container; + var $window = $( window ); + this.$container = $( container ); + this.$root = this.isBody ? supportsFixedPosition ? $window : $( document ) : this.$container; this.originalImages = this.images; this.images = optimalSizeImages( - this.options.alwaysTestWindowResolution ? $window : this.$root, - this.originalImages); + this.options.alwaysTestWindowResolution ? $window : this.$root, + this.originalImages ); /** * Pre-Loading. * This is the first image, so we will preload a minimum of 1 images. */ - preload(this.images, this.options.start || 0, this.options.preload || 1); + preload( this.images, this.options.start || 0, this.options.preload || 1 ); // Don't create a new wrap if one already exists (from a previous instance of Backstretch) - var $existing = this.$container.children(".backstretch").first(); - this.$wrap = $existing.length ? $existing : - $('
') - .css(this.options.bypassCss ? {} : styles.wrap) - .appendTo(this.$container); + var $existing = this.$container.children( ".backstretch" ).first(); + this.$wrap = $existing.length ? $existing : + $( '
' ) + .css( this.options.bypassCss ? {} : styles.wrap ) + .appendTo( this.$container ); - if (!this.options.bypassCss) { - - // Non-body elements need some style adjustments - if (!this.isBody) { - // If the container is statically positioned, we need to make it relative, - // and if no zIndex is defined, we should set it to zero. - var position = this.$container.css('position') - , zIndex = this.$container.css('zIndex'); + if ( !this.options.bypassCss ) { - this.$container.css({ - position: position === 'static' ? 'relative' : position - , zIndex: zIndex === 'auto' ? 0 : zIndex - }); + // Non-body elements need some style adjustments + if ( !this.isBody ) { + // If the container is statically positioned, we need to make it relative, + // and if no zIndex is defined, we should set it to zero. + var position = this.$container.css( 'position' ) + , zIndex = this.$container.css( 'zIndex' ); - // Needs a higher z-index - this.$wrap.css({zIndex: -999998}); - } + this.$container.css( { + position: position === 'static' ? 'relative' : position + , zIndex: zIndex === 'auto' ? 0 : zIndex + } ); + + // Needs a higher z-index + this.$wrap.css( { zIndex: -999998 } ); + } + + // Fixed or absolute positioning? + this.$wrap.css( { + position: this.isBody && supportsFixedPosition ? 'fixed' : 'absolute' + } ); - // Fixed or absolute positioning? - this.$wrap.css({ - position: this.isBody && supportsFixedPosition ? 'fixed' : 'absolute' - }); - } // Set the first image this.index = this.options.start; - this.show(this.index); + this.show( this.index ); // Listen for resize - $window.on('resize.backstretch', $.proxy(this.resize, this)) - .on('orientationchange.backstretch', $.proxy(function () { - // Need to do this in order to get the right window height - if (this.isBody && window.pageYOffset === 0) { - window.scrollTo(0, 1); - this.resize(); - } - }, this)); + $window.on( 'resize.backstretch', $.proxy( this.resize, this ) ) + .on( 'orientationchange.backstretch', $.proxy( function () { + // Need to do this in order to get the right window height + if ( this.isBody && window.pageYOffset === 0 ) { + window.scrollTo( 0, 1 ); + this.resize(); + } + }, this ) ); }; - var performTransition = function (options) { + var performTransition = function ( options ) { var transition = options.transition || 'fade'; // Look for multiple options - if (typeof transition === 'string' && transition.indexOf('|') > -1) { - transition = transition.split('|'); + if ( typeof transition === 'string' && transition.indexOf( '|' ) > -1 ) { + transition = transition.split( '|' ); } - if (transition instanceof Array) { - transition = transition[Math.round(Math.random() * (transition.length - 1))]; + if ( transition instanceof Array ) { + transition = transition[ Math.round( Math.random() * ( transition.length - 1 ) ) ]; } - - var $new = options['new']; - var $old = options['old'] ? options['old'] : $([]); - switch (transition.toString().toLowerCase()) { + var $new = options[ 'new' ]; + var $old = options[ 'old' ] ? options[ 'old' ] : $( [] ); + + switch ( transition.toString().toLowerCase() ) { default: case 'fade': - $new.fadeIn({ + $new.fadeIn( { duration: options.duration, complete: options.complete, easing: options.easing || undefined - }); + } ); break; - + case 'fadeinout': case 'fade_in_out': - + var fadeInNew = function () { - $new.fadeIn({ - duration: options.duration / 2, - complete: options.complete, - easing: options.easing || undefined - }); + $new.fadeIn( { + duration: options.duration / 2, + complete: options.complete, + easing: options.easing || undefined + } ); }; - - if ($old.length) { - $old.fadeOut({ - duration: options.duration / 2, - complete: fadeInNew, - easing: options.easing || undefined - }); - } else { - fadeInNew(); + + if ( $old.length ) { + $old.fadeOut( { + duration: options.duration / 2, + complete: fadeInNew, + easing: options.easing || undefined + } ); } - + else { + fadeInNew(); + } + break; case 'pushleft': @@ -709,43 +714,43 @@ case 'coverdown': case 'cover_down': - var transitionParts = transition.match(/^(cover|push)_?(.*)$/); + var transitionParts = transition.match( /^(cover|push)_?(.*)$/ ); - var animProp = transitionParts[2] === 'left' ? 'right' : - transitionParts[2] === 'right' ? 'left' : - transitionParts[2] === 'down' ? 'top' : - transitionParts[2] === 'up' ? 'bottom' : - 'right'; + var animProp = transitionParts[ 2 ] === 'left' ? 'right' : + transitionParts[ 2 ] === 'right' ? 'left' : + transitionParts[ 2 ] === 'down' ? 'top' : + transitionParts[ 2 ] === 'up' ? 'bottom' : + 'right'; var newCssStart = { 'display': '' }, newCssAnim = {}; - newCssStart[animProp] = '-100%'; - newCssAnim[animProp] = 0; + newCssStart[ animProp ] = '-100%'; + newCssAnim[ animProp ] = 0; $new - .css(newCssStart) - .animate(newCssAnim, { + .css( newCssStart ) + .animate( newCssAnim, { + duration: options.duration, + complete: function () { + $new.css( animProp, '' ); + options.complete.apply( this, arguments ); + }, + easing: options.easing || undefined + } ); + + if ( transitionParts[ 1 ] === 'push' && $old.length ) { + var oldCssAnim = {}; + oldCssAnim[ animProp ] = '100%'; + + $old + .animate( oldCssAnim, { duration: options.duration, complete: function () { - $new.css(animProp, ''); - options.complete.apply(this, arguments); + $old.css( 'display', 'none' ); }, easing: options.easing || undefined - }); - - if (transitionParts[1] === 'push' && $old.length) { - var oldCssAnim = {}; - oldCssAnim[animProp] = '100%'; - - $old - .animate(oldCssAnim, { - duration: options.duration, - complete: function () { - $old.css('display', 'none'); - }, - easing: options.easing || undefined - }); + } ); } break; @@ -757,400 +762,411 @@ * ========================= */ Backstretch.prototype = { - resize: function () { - try { + resize: function () { + try { - // Check for a better suited image after the resize - var $resTest = this.options.alwaysTestWindowResolution ? $(window) : this.$root; - var newContainerWidth = $resTest.width(); - var newContainerHeight = $resTest.height(); - var changeRatioW = newContainerWidth / (this._lastResizeContainerWidth || 0); - var changeRatioH = newContainerHeight / (this._lastResizeContainerHeight || 0); - var resolutionChangeRatioThreshold = this.options.resolutionChangeRatioThreshold || 0.0; + // Check for a better suited image after the resize + var $resTest = this.options.alwaysTestWindowResolution ? $( window ) : this.$root; + var newContainerWidth = $resTest.width(); + var newContainerHeight = $resTest.height(); + var changeRatioW = newContainerWidth / ( this._lastResizeContainerWidth || 0 ); + var changeRatioH = newContainerHeight / ( this._lastResizeContainerHeight || 0 ); + var resolutionChangeRatioThreshold = this.options.resolutionChangeRatioThreshold || 0.0; - // check for big changes in container size - if ((newContainerWidth !== this._lastResizeContainerWidth || - newContainerHeight !== this._lastResizeContainerHeight) && - ((Math.abs(changeRatioW - 1) >= resolutionChangeRatioThreshold || isNaN(changeRatioW)) || - (Math.abs(changeRatioH - 1) >= resolutionChangeRatioThreshold || isNaN(changeRatioH)))) { + // check for big changes in container size + if ( ( newContainerWidth !== this._lastResizeContainerWidth || + newContainerHeight !== this._lastResizeContainerHeight ) && + ( ( Math.abs( changeRatioW - 1 ) >= resolutionChangeRatioThreshold || isNaN( changeRatioW ) ) || + ( Math.abs( changeRatioH - 1 ) >= resolutionChangeRatioThreshold || isNaN( changeRatioH ) ) ) ) { - this._lastResizeContainerWidth = newContainerWidth; - this._lastResizeContainerHeight = newContainerHeight; + this._lastResizeContainerWidth = newContainerWidth; + this._lastResizeContainerHeight = newContainerHeight; - // Big change: rebuild the entire images array - this.images = optimalSizeImages($resTest, this.originalImages); + // Big change: rebuild the entire images array + this.images = optimalSizeImages( $resTest, this.originalImages ); - // Preload them (they will be automatically inserted on the next cycle) - if (this.options.preload) { - preload(this.images, (this.index + 1) % this.images.length, this.options.preload); - } - - // In case there is no cycle and the new source is different than the current - if (this.images.length === 1 && - this._currentImage.url !== this.images[0].url) { - - // Wait a little an update the image being showed - var that = this; - clearTimeout(that._selectAnotherResolutionTimeout); - that._selectAnotherResolutionTimeout = setTimeout(function () { - that.show(0); - }, this.options.resolutionRefreshRate); - } + // Preload them (they will be automatically inserted on the next cycle) + if ( this.options.preload ) { + preload( this.images, ( this.index + 1 ) % this.images.length, this.options.preload ); } - var bgCSS = {left: 0, top: 0, right: 'auto', bottom: 'auto'} - - , boxWidth = this.isBody ? this.$root.width() : this.$root.innerWidth() - , boxHeight = this.isBody ? ( window.innerHeight ? window.innerHeight : this.$root.height() ) : this.$root.innerHeight() - - , naturalWidth = this.$itemWrapper.data('width') - , naturalHeight = this.$itemWrapper.data('height') - - , ratio = (naturalWidth / naturalHeight) || 1 - - , alignX = this._currentImage.alignX === undefined ? this.options.alignX : this._currentImage.alignX - , alignY = this._currentImage.alignY === undefined ? this.options.alignY : this._currentImage.alignY - , scale = validScale(this._currentImage.scale || this.options.scale); - - var width, height; - - if (scale === 'fit' || scale === 'fit-smaller') { - width = naturalWidth; - height = naturalHeight; - - if (width > boxWidth || - height > boxHeight || - scale === 'fit-smaller') { - var boxRatio = boxWidth / boxHeight; - if (boxRatio > ratio) { - width = Math.floor(boxHeight * ratio); - height = boxHeight; - } else if (boxRatio < ratio) { - width = boxWidth; - height = Math.floor(boxWidth / ratio); - } else { - width = boxWidth; - height = boxHeight; - } - } - } else if (scale === 'fill') { - width = boxWidth; - height = boxHeight; - } else { // 'cover' - width = Math.max(boxHeight * ratio, boxWidth); - height = Math.max(width / ratio, boxHeight); - } - - // Make adjustments based on image ratio - bgCSS.top = -(height - boxHeight) * alignY; - bgCSS.left = -(width - boxWidth) * alignX; - bgCSS.width = width; - bgCSS.height = height; - - if (!this.options.bypassCss) { + // In case there is no cycle and the new source is different than the current + if ( this.images.length === 1 && + this._currentImage.url !== this.images[ 0 ].url ) { - this.$wrap - .css({width: boxWidth, height: boxHeight}) - .find('>.backstretch-item').not('.deleteable') - .each(function () { - var $wrapper = $(this); - $wrapper.find('img,video,iframe') - .css(bgCSS); - }); + // Wait a little an update the image being showed + var that = this; + clearTimeout( that._selectAnotherResolutionTimeout ); + that._selectAnotherResolutionTimeout = setTimeout( function () { + that.show( 0 ); + }, this.options.resolutionRefreshRate ); } - - var evt = $.Event('backstretch.resize', { - relatedTarget: this.$container[0] - }); - this.$container.trigger(evt, this); - - } catch(err) { - // IE7 seems to trigger resize before the image is loaded. - // This try/catch block is a hack to let it fail gracefully. } - return this; + var bgCSS = { left: 0, top: 0, right: 'auto', bottom: 'auto' } + + , boxWidth = this.isBody ? this.$root.width() : this.$root.innerWidth() + , boxHeight = this.isBody + ? ( window.innerHeight ? window.innerHeight : this.$root.height() ) + : this.$root.innerHeight() + + , naturalWidth = this.$itemWrapper.data( 'width' ) + , naturalHeight = this.$itemWrapper.data( 'height' ) + + , ratio = ( naturalWidth / naturalHeight ) || 1 + + , alignX = this._currentImage.alignX === undefined ? this.options.alignX : this._currentImage.alignX + , alignY = this._currentImage.alignY === undefined ? this.options.alignY : this._currentImage.alignY + , scale = validScale( this._currentImage.scale || this.options.scale ); + + var width, height; + + if ( scale === 'fit' || scale === 'fit-smaller' ) { + width = naturalWidth; + height = naturalHeight; + + if ( width > boxWidth || + height > boxHeight || + scale === 'fit-smaller' ) { + var boxRatio = boxWidth / boxHeight; + if ( boxRatio > ratio ) { + width = Math.floor( boxHeight * ratio ); + height = boxHeight; + } + else if ( boxRatio < ratio ) { + width = boxWidth; + height = Math.floor( boxWidth / ratio ); + } + else { + width = boxWidth; + height = boxHeight; + } + } + } + else if ( scale === 'fill' ) { + width = boxWidth; + height = boxHeight; + } + else { // 'cover' + width = Math.max( boxHeight * ratio, boxWidth ); + height = Math.max( width / ratio, boxHeight ); + } + + // Make adjustments based on image ratio + bgCSS.top = -( height - boxHeight ) * alignY; + bgCSS.left = -( width - boxWidth ) * alignX; + bgCSS.width = width; + bgCSS.height = height; + + if ( !this.options.bypassCss ) { + + this.$wrap + .css( { width: boxWidth, height: boxHeight } ) + .find( '>.backstretch-item' ).not( '.deleteable' ) + .each( function () { + var $wrapper = $( this ); + $wrapper.find( 'img,video,iframe' ) + .css( bgCSS ); + } ); + } + + var evt = $.Event( 'backstretch.resize', { + relatedTarget: this.$container[ 0 ] + } ); + this.$container.trigger( evt, this ); + + } + catch ( err ) { + // IE7 seems to trigger resize before the image is loaded. + // This try/catch block is a hack to let it fail gracefully. } - // Show the slide at a certain position - , show: function (newIndex, overrideOptions) { + return this; + } - // Validate index - if (Math.abs(newIndex) > this.images.length - 1) { - return; - } + // Show the slide at a certain position + , show: function ( newIndex, overrideOptions ) { - // Vars - var that = this - , $oldItemWrapper = that.$wrap.find('>.backstretch-item').addClass('deleteable') - , oldVideoWrapper = that.videoWrapper - , evtOptions = { relatedTarget: that.$container[0] }; - - // Trigger the "before" event - that.$container.trigger($.Event('backstretch.before', evtOptions), [that, newIndex]); - - // Set the new frame index - this.index = newIndex; - var selectedImage = that.images[newIndex]; - - // Pause the slideshow - clearTimeout(that._cycleTimeout); - - // New image - - delete that.videoWrapper; // Current item may not be a video - - var isVideo = isVideoSource(selectedImage); - if (isVideo) { - that.videoWrapper = new VideoWrapper(selectedImage); - that.$item = that.videoWrapper.$video.css('pointer-events', 'none'); - } else { - that.$item = $(''); - } - - that.$itemWrapper = $('
') - .append(that.$item); - - if (this.options.bypassCss) { - that.$itemWrapper.css({ - 'display': 'none' - }); - } else { - that.$itemWrapper.css(styles.itemWrapper); - that.$item.css(styles.item); - } - - that.$item.bind(isVideo ? 'canplay' : 'load', function (e) { - var $this = $(this) - , $wrapper = $this.parent() - , options = $wrapper.data('options'); - - if (overrideOptions) { - options = $.extend({}, options, overrideOptions); - } - - var imgWidth = this.naturalWidth || this.videoWidth || this.width - , imgHeight = this.naturalHeight || this.videoHeight || this.height; - - // Save the natural dimensions - $wrapper - .data('width', imgWidth) - .data('height', imgHeight); - - var getOption = function (opt) { - return options[opt] !== undefined ? - options[opt] : - that.options[opt]; - }; - - var transition = getOption('transition'); - var transitionEasing = getOption('transitionEasing'); - var transitionDuration = getOption('transitionDuration'); - - // Show the image, then delete the old one - var bringInNextImage = function () { - - if (oldVideoWrapper) { - oldVideoWrapper.stop(); - oldVideoWrapper.destroy(); - } - - $oldItemWrapper.remove(); - - // Resume the slideshow - if (!that.paused && that.images.length > 1) { - that.cycle(); - } - - // Now we can clear the background on the element, to spare memory - if (!that.options.bypassCss && !that.isBody) { - that.$container.css('background-image', 'none'); - } - - // Trigger the "after" and "show" events - // "show" is being deprecated - $(['after', 'show']).each(function () { - that.$container.trigger($.Event('backstretch.' + this, evtOptions), [that, newIndex]); - }); - - if (isVideo) { - that.videoWrapper.play(); - } - }; - - if ((that.firstShow && !that.options.animateFirst) || !transitionDuration || !transition) { - // Avoid transition on first show or if there's no transitionDuration value - $wrapper.show(); - bringInNextImage(); - } else { - - performTransition({ - 'new': $wrapper, - old: $oldItemWrapper, - transition: transition, - duration: transitionDuration, - easing: transitionEasing, - complete: bringInNextImage - }); - - } - - that.firstShow = false; - - // Resize - that.resize(); - }); - - that.$itemWrapper.appendTo(that.$wrap); - - that.$item.attr('alt', selectedImage.alt || ''); - that.$itemWrapper.data('options', selectedImage); - - if (!isVideo) { - that.$item.attr('src', selectedImage.url); - } - - that._currentImage = selectedImage; - - return that; + // Validate index + if ( Math.abs( newIndex ) > this.images.length - 1 ) { + return; } + // Vars + var that = this + , $oldItemWrapper = that.$wrap.find( '>.backstretch-item' ).addClass( 'deleteable' ) + , oldVideoWrapper = that.videoWrapper + , evtOptions = { relatedTarget: that.$container[ 0 ] }; + + // Trigger the "before" event + that.$container.trigger( $.Event( 'backstretch.before', evtOptions ), [ that, newIndex ] ); + + // Set the new frame index + this.index = newIndex; + var selectedImage = that.images[ newIndex ]; + + // Pause the slideshow + clearTimeout( that._cycleTimeout ); + + // New image + + delete that.videoWrapper; // Current item may not be a video + + var isVideo = isVideoSource( selectedImage ); + if ( isVideo ) { + that.videoWrapper = new VideoWrapper( selectedImage ); + that.$item = that.videoWrapper.$video.css( 'pointer-events', 'none' ); + } + else { + that.$item = $( '' ); + } + + that.$itemWrapper = $( '
' ) + .append( that.$item ); + + if ( this.options.bypassCss ) { + that.$itemWrapper.css( { + 'display': 'none' + } ); + } + else { + that.$itemWrapper.css( styles.itemWrapper ); + that.$item.css( styles.item ); + } + + that.$item.bind( isVideo ? 'canplay' : 'load', function ( e ) { + var $this = $( this ) + , $wrapper = $this.parent() + , options = $wrapper.data( 'options' ); + + if ( overrideOptions ) { + options = $.extend( {}, options, overrideOptions ); + } + + var imgWidth = this.naturalWidth || this.videoWidth || this.width + , imgHeight = this.naturalHeight || this.videoHeight || this.height; + + // Save the natural dimensions + $wrapper + .data( 'width', imgWidth ) + .data( 'height', imgHeight ); + + var getOption = function ( opt ) { + return options[ opt ] !== undefined ? + options[ opt ] : + that.options[ opt ]; + }; + + var transition = getOption( 'transition' ); + var transitionEasing = getOption( 'transitionEasing' ); + var transitionDuration = getOption( 'transitionDuration' ); + + // Show the image, then delete the old one + var bringInNextImage = function () { + + if ( oldVideoWrapper ) { + oldVideoWrapper.stop(); + oldVideoWrapper.destroy(); + } + + $oldItemWrapper.remove(); + + // Resume the slideshow + if ( !that.paused && that.images.length > 1 ) { + that.cycle(); + } + + // Now we can clear the background on the element, to spare memory + if ( !that.options.bypassCss && !that.isBody ) { + that.$container.css( 'background-image', 'none' ); + } + + // Trigger the "after" and "show" events + // "show" is being deprecated + $( [ 'after', 'show' ] ).each( function () { + that.$container.trigger( $.Event( 'backstretch.' + this, evtOptions ), [ that, newIndex ] ); + } ); + + if ( isVideo ) { + that.videoWrapper.play(); + } + }; + + if ( ( that.firstShow && !that.options.animateFirst ) || !transitionDuration || !transition ) { + // Avoid transition on first show or if there's no transitionDuration value + $wrapper.show(); + bringInNextImage(); + } + else { + + performTransition( { + 'new': $wrapper, + old: $oldItemWrapper, + transition: transition, + duration: transitionDuration, + easing: transitionEasing, + complete: bringInNextImage + } ); + + } + + that.firstShow = false; + + // Resize + that.resize(); + } ); + + that.$itemWrapper.appendTo( that.$wrap ); + + that.$item.attr( 'alt', selectedImage.alt || '' ); + that.$itemWrapper.data( 'options', selectedImage ); + + if ( !isVideo ) { + that.$item.attr( 'src', selectedImage.url ); + } + + that._currentImage = selectedImage; + + return that; + } + , current: function () { - return this.index; - } + return this.index; + } , next: function () { - var args = Array.prototype.slice.call(arguments, 0); - args.unshift(this.index < this.images.length - 1 ? this.index + 1 : 0); - return this.show.apply(this, args); - } + var args = Array.prototype.slice.call( arguments, 0 ); + args.unshift( this.index < this.images.length - 1 ? this.index + 1 : 0 ); + return this.show.apply( this, args ); + } , prev: function () { - var args = Array.prototype.slice.call(arguments, 0); - args.unshift(this.index === 0 ? this.images.length - 1 : this.index - 1); - return this.show.apply(this, args); - } + var args = Array.prototype.slice.call( arguments, 0 ); + args.unshift( this.index === 0 ? this.images.length - 1 : this.index - 1 ); + return this.show.apply( this, args ); + } , pause: function () { - // Pause the slideshow - this.paused = true; - - if (this.videoWrapper) { - this.videoWrapper.pause(); - } - - return this; + // Pause the slideshow + this.paused = true; + + if ( this.videoWrapper ) { + this.videoWrapper.pause(); } + return this; + } + , resume: function () { - // Resume the slideshow - this.paused = false; - - if (this.videoWrapper) { - this.videoWrapper.play(); - } - - this.cycle(); - return this; + // Resume the slideshow + this.paused = false; + + if ( this.videoWrapper ) { + this.videoWrapper.play(); } + this.cycle(); + return this; + } + , cycle: function () { - // Start/resume the slideshow - if(this.images.length > 1) { - // Clear the timeout, just in case - clearTimeout(this._cycleTimeout); + // Start/resume the slideshow + if ( this.images.length > 1 ) { + // Clear the timeout, just in case + clearTimeout( this._cycleTimeout ); - var duration = (this._currentImage && this._currentImage.duration) || this.options.duration; - var isVideo = isVideoSource(this._currentImage); - - var callNext = function () { - this.$item.off('.cycle'); - - // Check for paused slideshow - if (!this.paused) { - this.next(); - } - }; + var duration = ( this._currentImage && this._currentImage.duration ) || this.options.duration; + var isVideo = isVideoSource( this._currentImage ); - // Special video handling - if (isVideo) { + var callNext = function () { + this.$item.off( '.cycle' ); - // Leave video at last frame - if (!this._currentImage.loop) { - var lastFrameTimeout = 0; + // Check for paused slideshow + if ( !this.paused ) { + this.next(); + } + }; - this.$item - .on('playing.cycle', function () { - var player = $(this).data('player'); + // Special video handling + if ( isVideo ) { - clearTimeout(lastFrameTimeout); - lastFrameTimeout = setTimeout(function () { - player.pause(); - player.$video.trigger('ended'); - }, (player.getDuration() - player.getCurrentTime()) * 1000); - }) - .on('ended.cycle', function () { - clearTimeout(lastFrameTimeout); - }); - } + // Leave video at last frame + if ( !this._currentImage.loop ) { + var lastFrameTimeout = 0; - // On error go to next - this.$item.on('error.cycle initerror.cycle', $.proxy(callNext, this)); + this.$item + .on( 'playing.cycle', function () { + var player = $( this ).data( 'player' ); + + clearTimeout( lastFrameTimeout ); + lastFrameTimeout = setTimeout( function () { + player.pause(); + player.$video.trigger( 'ended' ); + }, ( player.getDuration() - player.getCurrentTime() ) * 1000 ); + } ) + .on( 'ended.cycle', function () { + clearTimeout( lastFrameTimeout ); + } ); } - if (isVideo && !this._currentImage.duration) { - // It's a video - playing until end - this.$item.on('ended.cycle', $.proxy(callNext, this)); - - } else { - // Cycling according to specified duration - this._cycleTimeout = setTimeout($.proxy(callNext, this), duration); - } - + // On error go to next + this.$item.on( 'error.cycle initerror.cycle', $.proxy( callNext, this ) ); } - return this; + + if ( isVideo && !this._currentImage.duration ) { + // It's a video - playing until end + this.$item.on( 'ended.cycle', $.proxy( callNext, this ) ); + + } + else { + // Cycling according to specified duration + this._cycleTimeout = setTimeout( $.proxy( callNext, this ), duration ); + } + + } + return this; + } + + , destroy: function ( preserveBackground ) { + // Stop the resize events + $( window ).off( 'resize.backstretch orientationchange.backstretch' ); + + // Stop any videos + if ( this.videoWrapper ) { + this.videoWrapper.destroy(); } - , destroy: function (preserveBackground) { - // Stop the resize events - $(window).off('resize.backstretch orientationchange.backstretch'); + // Clear the timeout + clearTimeout( this._cycleTimeout ); - // Stop any videos - if (this.videoWrapper) { - this.videoWrapper.destroy(); - } - - // Clear the timeout - clearTimeout(this._cycleTimeout); - - // Remove Backstretch - if(!preserveBackground) { - this.$wrap.remove(); - } - this.$container.removeData('backstretch'); + // Remove Backstretch + if ( !preserveBackground ) { + this.$wrap.remove(); } + this.$container.removeData( 'backstretch' ); + } }; - - /** - * Video Abstraction Layer - * - * Static methods: - * > VideoWrapper.loadYoutubeAPI() -> Call in order to load the Youtube API. - * An 'youtube_api_load' event will be triggered on $(window) when the API is loaded. - * - * Generic: - * > player.type -> type of the video - * > player.video / player.$video -> contains the element holding the video - * > player.play() -> plays the video - * > player.pause() -> pauses the video - * > player.setCurrentTime(position) -> seeks to a position by seconds - * - * Youtube: - * > player.ytId will contain the youtube ID if the source is a youtube url - * > player.ytReady is a flag telling whether the youtube source is ready for playback - * */ - var VideoWrapper = function () { this.init.apply(this, arguments); }; + /** + * Video Abstraction Layer + * + * Static methods: + * > VideoWrapper.loadYoutubeAPI() -> Call in order to load the Youtube API. + * An 'youtube_api_load' event will be triggered on $(window) when the API is loaded. + * + * Generic: + * > player.type -> type of the video + * > player.video / player.$video -> contains the element holding the video + * > player.play() -> plays the video + * > player.pause() -> pauses the video + * > player.setCurrentTime(position) -> seeks to a position by seconds + * + * Youtube: + * > player.ytId will contain the youtube ID if the source is a youtube url + * > player.ytReady is a flag telling whether the youtube source is ready for playback + * */ + + var VideoWrapper = function () { this.init.apply( this, arguments ); }; /** * @param {Object} options @@ -1160,101 +1176,103 @@ * @param {String?} options.poster * loop, mute, poster */ - VideoWrapper.prototype.init = function (options) { + VideoWrapper.prototype.init = function ( options ) { var that = this; - + var $video; var setVideoElement = function () { that.$video = $video; - that.video = $video[0]; + that.video = $video[ 0 ]; }; - + // Determine video type - + var videoType = 'video'; - - if (!(options.url instanceof Array) && - YOUTUBE_REGEXP.test(options.url)) { + + if ( !( options.url instanceof Array ) && + YOUTUBE_REGEXP.test( options.url ) ) { videoType = 'youtube'; } - + that.type = videoType; - if (videoType === 'youtube') { + if ( videoType === 'youtube' ) { // Try to load the API in the meantime VideoWrapper.loadYoutubeAPI(); - that.ytId = options.url.match(YOUTUBE_REGEXP)[2]; + that.ytId = options.url.match( YOUTUBE_REGEXP )[ 2 ]; var src = 'https://www.youtube.com/embed/' + that.ytId + '?rel=0&autoplay=0&showinfo=0&controls=0&modestbranding=1' + '&cc_load_policy=0&disablekb=1&iv_load_policy=3&loop=0' + - '&enablejsapi=1&origin=' + encodeURIComponent(window.location.origin); + '&enablejsapi=1&origin=' + encodeURIComponent( window.location.origin ); that.__ytStartMuted = !!options.mute || options.mute === undefined; - $video = $('