; (function () { 'use strict'; /** * Play videos based on scroll position * @namespace */ db.libs.videoDefer = (function ($) { var name = 'videoDefer'; /** * The threshold for when videos in view should be played * @private * @memberof db.libs.videoDefer * @constant {number} */ var threshold = 200; /** * The array for all the videos to be played * @private * @memberof db.libs.videoDefer * @type {array} */ var videos = []; /** * Check to see if scroll-listener has been added * @private * @memberof db.libs.videoDefer * @type {bool} */ var scrollListenerAdded = false; /** * Plays a video with <code>data-video-defer="view"</code> attribute if it's within the viewport threshold * @private * @memberof db.libs.videoDefer */ function playVideosInView() { var offset = $(document).scrollTop() + $(window).height() + threshold; videos.each(function (i, video) { if (video !== null) { if ($(video).offset().top < offset) { video.play(); // Take it away! videos[i] = null; $(video).attr('data-is-played', 'true'); } } }); } /** * Find videos in document that haven't been played yet * @private * @memberof db.libs.videoDefer */ function findVideos() { videos = $('[data-video-defer="view"]:not([data-is-played="true"])'); // If video has no <source> children, we check for the attributes data-sources-small and data-sources-mediumup to create them. // This makes it possible to have different sources for different screensizes, for example different cropped videos for small screens. videos.each(function(i, video) { if(!$(video).children().length) { var sources = []; var types = []; // Get the attributes based on screensize if(window.innerWidth <= 640 && $(video).attr('data-sources-small')) { sources = $(video).attr('data-sources-small').split(","); if($(video).attr('data-types-small')) { types = $(video).attr('data-types-small').split(","); } if($(video).attr('data-poster-small')) { $(video).attr('poster', $(video).attr('data-poster-small')); } } else if (window.innerWidth >= 641 && $(video).attr('data-sources-mediumup')) { sources = $(video).attr('data-sources-mediumup').split(","); if($(video).attr('data-types-mediumup')) { types = $(video).attr('data-types-mediumup').split(","); } if($(video).attr('data-poster-mediumup')) { $(video).attr('poster', $(video).attr('data-poster-mediumup')); } } // Create the <source> elements if(sources.length) { sources.forEach(function(source, i) { var sourceElem = document.createElement('source'); sourceElem.src = source.trim(); if(types[i]) { sourceElem.type = "video/" + types[i].trim(); } $(video).append(sourceElem); }); } } }); } /** * Bind scroll-listener * @private * @memberof db.libs.videoDefer */ function bindScroll() { scrollListenerAdded = true; $(window).on('scroll', function () { window.requestAnimationFrame(playVideosInView); }); } /** * Initialize the component * @public * @memberof db.libs.videoDefer */ function init() { if (!db.utils.isInitialized($('body'), name)) { if (document.readyState === 'complete') { playVideosInView(); } else { window.addEventListener('load', function () { setTimeout(function () { playVideosInView(); }, 0); }); } // Find videos in document findVideos(); // Bind scroll if(videos.length && !scrollListenerAdded) { bindScroll(); } // Set component as initialized db.utils.initialized($('body'), name); } } /** * Reflow the component * @public * @memberof db.libs.videoDefer */ function reflow() { if (!scrollListenerAdded) { bindScroll(); } findVideos(); playVideosInView(); } return { init: init, reflow: reflow }; })(jQuery); })();