/* * Vide - v0.5.1 * Easy as hell jQuery plugin for video backgrounds. * http://vodkabears.github.io/vide/ * * Made by Ilya Makarov * Under MIT License */ !(function(root, factory) { if (typeof define === 'function' && define.amd) { define(['jquery'], factory); } else if (typeof exports === 'object') { factory(require('jquery')); } else { factory(root.jQuery); } })(this, function($) { 'use strict'; /** * Name of the plugin * @private * @const * @type {String} */ var PLUGIN_NAME = 'vide'; /** * Default settings * @private * @const * @type {Object} */ var DEFAULTS = { volume: 1, playbackRate: 1, muted: true, loop: true, autoplay: true, position: '50% 50%', posterType: 'detect', resizing: true, bgColor: 'transparent', className: '' }; /** * Not implemented error message * @private * @const * @type {String} */ var NOT_IMPLEMENTED_MSG = 'Not implemented'; /** * Parse a string with options * @private * @param {String} str * @returns {Object|String} */ function parseOptions(str) { var obj = {}; var delimiterIndex; var option; var prop; var val; var arr; var len; var i; // Remove spaces around delimiters and split arr = str.replace(/\s*:\s*/g, ':').replace(/\s*,\s*/g, ',').split(','); // Parse a string for (i = 0, len = arr.length; i < len; i++) { option = arr[i]; // Ignore urls and a string without colon delimiters if ( option.search(/^(http|https|ftp):\/\//) !== -1 || option.search(':') === -1 ) { break; } delimiterIndex = option.indexOf(':'); prop = option.substring(0, delimiterIndex); val = option.substring(delimiterIndex + 1); // If val is an empty string, make it undefined if (!val) { val = undefined; } // Convert a string value if it is like a boolean if (typeof val === 'string') { val = val === 'true' || (val === 'false' ? false : val); } // Convert a string value if it is like a number if (typeof val === 'string') { val = !isNaN(val) ? +val : val; } obj[prop] = val; } // If nothing is parsed if (prop == null && val == null) { return str; } return obj; } /** * Parse a position option * @private * @param {String} str * @returns {Object} */ function parsePosition(str) { str = '' + str; // Default value is a center var args = str.split(/\s+/); var x = '50%'; var y = '50%'; var len; var arg; var i; for (i = 0, len = args.length; i < len; i++) { arg = args[i]; // Convert values if (arg === 'left') { x = '0%'; } else if (arg === 'right') { x = '100%'; } else if (arg === 'top') { y = '0%'; } else if (arg === 'bottom') { y = '100%'; } else if (arg === 'center') { if (i === 0) { x = '50%'; } else { y = '50%'; } } else { if (i === 0) { x = arg; } else { y = arg; } } } return { x: x, y: y }; } /** * Search a poster * @private * @param {String} path * @param {Function} callback */ function findPoster(path, callback) { var onLoad = function() { callback(this.src); }; $('').on('load', onLoad); $('').on('load', onLoad); $('').on('load', onLoad); $('').on('load', onLoad); } /** * Vide constructor * @param {HTMLElement} element * @param {Object|String} path * @param {Object|String} options * @constructor */ function Vide(element, path, options) { this.$element = $(element); // Parse path if (typeof path === 'string') { path = parseOptions(path); } // Parse options if (!options) { options = {}; } else if (typeof options === 'string') { options = parseOptions(options); } // Remove an extension if (typeof path === 'string') { path = path.replace(/\.\w*$/, ''); } else if (typeof path === 'object') { for (var i in path) { if (path.hasOwnProperty(i)) { path[i] = path[i].replace(/\.\w*$/, ''); } } } this.settings = $.extend({}, DEFAULTS, options); this.path = path; // https://github.com/VodkaBears/Vide/issues/110 try { this.init(); } catch (e) { if (e.message !== NOT_IMPLEMENTED_MSG) { throw e; } } } /** * Initialization * @public */ Vide.prototype.init = function() { var vide = this; var path = vide.path; var poster = path; var sources = ''; var $element = vide.$element; var settings = vide.settings; var position = parsePosition(settings.position); var posterType = settings.posterType; var $video; var $wrapper; // Set styles of a video wrapper $wrapper = vide.$wrapper = $('
') .addClass(settings.className) .css({ position: 'absolute', 'z-index': -1, top: 0, left: 0, bottom: 0, right: 0, overflow: 'hidden', '-webkit-background-size': 'cover', '-moz-background-size': 'cover', '-o-background-size': 'cover', 'background-size': 'cover', 'background-color': settings.bgColor, 'background-repeat': 'no-repeat', 'background-position': position.x + ' ' + position.y }); // Get a poster path if (typeof path === 'object') { if (path.poster) { poster = path.poster; } else { if (path.mp4) { poster = path.mp4; } else if (path.webm) { poster = path.webm; } else if (path.ogv) { poster = path.ogv; } } } // Set a video poster if (posterType === 'detect') { findPoster(poster, function(url) { $wrapper.css('background-image', 'url(' + url + ')'); }); } else if (posterType !== 'none') { $wrapper.css('background-image', 'url(' + poster + '.' + posterType + ')'); } // If a parent element has a static position, make it relative if ($element.css('position') === 'static') { $element.css('position', 'relative'); } $element.prepend($wrapper); if (typeof path === 'object') { if (path.mp4) { sources += ''; } if (path.webm) { sources += ''; } if (path.ogv) { sources += ''; } $video = vide.$video = $(''); } else { $video = vide.$video = $(''); } // https://github.com/VodkaBears/Vide/issues/110 try { $video // Set video properties .prop({ autoplay: settings.autoplay, loop: settings.loop, volume: settings.volume, muted: settings.muted, defaultMuted: settings.muted, playbackRate: settings.playbackRate, defaultPlaybackRate: settings.playbackRate }); } catch (e) { throw new Error(NOT_IMPLEMENTED_MSG); } // Video alignment $video.css({ margin: 'auto', position: 'absolute', 'z-index': -1, top: position.y, left: position.x, '-webkit-transform': 'translate(-' + position.x + ', -' + position.y + ')', '-ms-transform': 'translate(-' + position.x + ', -' + position.y + ')', '-moz-transform': 'translate(-' + position.x + ', -' + position.y + ')', transform: 'translate(-' + position.x + ', -' + position.y + ')', // Disable visibility, while loading visibility: 'hidden', opacity: 0 }) // Resize a video, when it's loaded .one('canplaythrough.' + PLUGIN_NAME, function() { vide.resize(); }) // Make it visible, when it's already playing .one('playing.' + PLUGIN_NAME, function() { $video.css({ visibility: 'visible', opacity: 1 }); $wrapper.css('background-image', 'none'); }); // Resize event is available only for 'window' // Use another code solutions to detect DOM elements resizing $element.on('resize.' + PLUGIN_NAME, function() { if (settings.resizing) { vide.resize(); } }); // Append a video $wrapper.append($video); }; /** * Get a video element * @public * @returns {HTMLVideoElement} */ Vide.prototype.getVideoObject = function() { return this.$video[0]; }; /** * Resize a video background * @public */ Vide.prototype.resize = function() { if (!this.$video) { return; } var $wrapper = this.$wrapper; var $video = this.$video; var video = $video[0]; // Get a native video size var videoHeight = video.videoHeight; var videoWidth = video.videoWidth; // Get a wrapper size var wrapperHeight = $wrapper.height(); var wrapperWidth = $wrapper.width(); if (wrapperWidth / videoWidth > wrapperHeight / videoHeight) { $video.css({ // +2 pixels to prevent an empty space after transformation width: wrapperWidth + 2, height: 'auto' }); } else { $video.css({ width: 'auto', // +2 pixels to prevent an empty space after transformation height: wrapperHeight + 2 }); } }; /** * Destroy a video background * @public */ Vide.prototype.destroy = function() { delete $[PLUGIN_NAME].lookup[this.index]; this.$video && this.$video.off(PLUGIN_NAME); this.$element.off(PLUGIN_NAME).removeData(PLUGIN_NAME); this.$wrapper.remove(); }; /** * Special plugin object for instances. * @public * @type {Object} */ $[PLUGIN_NAME] = { lookup: [] }; /** * Plugin constructor * @param {Object|String} path * @param {Object|String} options * @returns {JQuery} * @constructor */ $.fn[PLUGIN_NAME] = function(path, options) { var instance; this.each(function() { instance = $.data(this, PLUGIN_NAME); // Destroy the plugin instance if exists instance && instance.destroy(); // Create the plugin instance instance = new Vide(this, path, options); instance.index = $[PLUGIN_NAME].lookup.push(instance) - 1; $.data(this, PLUGIN_NAME, instance); }); return this; }; $(document).ready(function() { var $window = $(window); // Window resize event listener $window.on('resize.' + PLUGIN_NAME, function() { for (var len = $[PLUGIN_NAME].lookup.length, i = 0, instance; i < len; i++) { instance = $[PLUGIN_NAME].lookup[i]; if (instance && instance.settings.resizing) { instance.resize(); } } }); // https://github.com/VodkaBears/Vide/issues/68 $window.on('unload.' + PLUGIN_NAME, function() { return false; }); // Auto initialization // Add 'data-vide-bg' attribute with a path to the video without extension // Also you can pass options throw the 'data-vide-options' attribute // 'data-vide-options' must be like 'muted: false, volume: 0.5' $(document).find('[data-' + PLUGIN_NAME + '-bg]').each(function(i, element) { var $element = $(element); var options = $element.data(PLUGIN_NAME + '-options'); var path = $element.data(PLUGIN_NAME + '-bg'); $element[PLUGIN_NAME](path, options); }); }); }); {"version":"1.0","provider_name":"Vias del Sur","provider_url":"https:\/\/citvviasdelsur.com","author_name":"admin-citvviasdelsur","author_url":"https:\/\/citvviasdelsur.com\/author\/admin-citvviasdelsur\/","title":"\u00a1Hola mundo!","type":"rich","width":600,"height":338,"html":"
\u00a1Hola mundo!<\/a><\/blockquote>