vendor: 12,046 bytes, lines 1-501
1/* 2 * Vide - v0.5.1 3 * Easy as hell jQuery plugin for video backgrounds. 4 * http://vodkabears.github.io/vide/ 5 * 6 * Made by Ilya Makarov 7 * Under MIT License 8 */ 9!(function(root, factory) { 10 if (typeof define === 'function' && define.amd) { 11 define(['jquery'], factory); 12 } else if (typeof exports === 'object') { 13 factory(require('jquery')); 14 } else { 15 factory(root.jQuery); 16 } 17})(this, function($) { 18 19 'use strict'; 20 21 /** 22 * Name of the plugin 23 * @private 24 * @const 25 * @type {String} 26 */ 27 var PLUGIN_NAME = 'vide'; 28 29 /** 30 * Default settings 31 * @private 32 * @const 33 * @type {Object} 34 */ 35 var DEFAULTS = { 36 volume: 1, 37 playbackRate: 1, 38 muted: true, 39 loop: true, 40 autoplay: true, 41 position: '50% 50%', 42 posterType: 'detect', 43 resizing: true, 44 bgColor: 'transparent', 45 className: '' 46 }; 47 48 /** 49 * Not implemented error message 50 * @private 51 * @const 52 * @type {String} 53 */ 54 var NOT_IMPLEMENTED_MSG = 'Not implemented'; 55 56 /** 57 * Parse a string with options 58 * @private 59 * @param {String} str 60 * @returns {Object|String} 61 */ 62 function parseOptions(str) { 63 var obj = {}; 64 var delimiterIndex; 65 var option; 66 var prop; 67 var val; 68 var arr; 69 var len; 70 var i; 71 72 // Remove spaces around delimiters and split 73 arr = str.replace(/\s*:\s*/g, ':').replace(/\s*,\s*/g, ',').split(','); 74 75 // Parse a string 76 for (i = 0, len = arr.length; i < len; i++) { 77 option = arr[i]; 78 79 // Ignore urls and a string without colon delimiters 80 if ( 81 option.search(/^(http|https|ftp):\/\//) !== -1 || 82 option.search(':') === -1 83 ) { 84 break; 85 } 86 87 delimiterIndex = option.indexOf(':'); 88 prop = option.substring(0, delimiterIndex); 89 val = option.substring(delimiterIndex + 1); 90 91 // If val is an empty string, make it undefined 92 if (!val) { 93 val = undefined; 94 } 95 96 // Convert a string value if it is like a boolean 97 if (typeof val === 'string') { 98 val = val === 'true' || (val === 'false' ? false : val); 99 } 100 101 // Convert a string value if it is like a number 102 if (typeof val === 'string') { 103 val = !isNaN(val) ? +val : val; 104 } 105 106 obj[prop] = val; 107 } 108 109 // If nothing is parsed 110 if (prop == null && val == null) { 111 return str; 112 } 113 114 return obj; 115 } 116 117 /** 118 * Parse a position option 119 * @private 120 * @param {String} str 121 * @returns {Object} 122 */ 123 function parsePosition(str) { 124 str = '' + str; 125 126 // Default value is a center 127 var args = str.split(/\s+/); 128 var x = '50%'; 129 var y = '50%'; 130 var len; 131 var arg; 132 var i; 133 134 for (i = 0, len = args.length; i < len; i++) { 135 arg = args[i]; 136 137 // Convert values 138 if (arg === 'left') { 139 x = '0%'; 140 } else if (arg === 'right') { 141 x = '100%'; 142 } else if (arg === 'top') { 143 y = '0%'; 144 } else if (arg === 'bottom') { 145 y = '100%'; 146 } else if (arg === 'center') { 147 if (i === 0) { 148 x = '50%'; 149 } else { 150 y = '50%'; 151 } 152 } else { 153 if (i === 0) { 154 x = arg; 155 } else { 156 y = arg; 157 } 158 } 159 } 160 161 return { x: x, y: y }; 162 } 163 164 /** 165 * Search a poster 166 * @private 167 * @param {String} path 168 * @param {Function} callback 169 */ 170 function findPoster(path, callback) { 171 var onLoad = function() { 172 callback(this.src); 173 }; 174 175 $('<img src="' + path + '.gif">').on('load', onLoad); 176 $('<img src="' + path + '.jpg">').on('load', onLoad); 177 $('<img src="' + path + '.jpeg">').on('load', onLoad); 178 $('<img src="' + path + '.png">').on('load', onLoad); 179 } 180 181 /** 182 * Vide constructor 183 * @param {HTMLElement} element 184 * @param {Object|String} path 185 * @param {Object|String} options 186 * @constructor 187 */ 188 function Vide(element, path, options) { 189 this.$element = $(element); 190 191 // Parse path 192 if (typeof path === 'string') { 193 path = parseOptions(path); 194 } 195 196 // Parse options 197 if (!options) { 198 options = {}; 199 } else if (typeof options === 'string') { 200 options = parseOptions(options); 201 } 202 203 // Remove an extension 204 if (typeof path === 'string') { 205 path = path.replace(/\.\w*$/, ''); 206 } else if (typeof path === 'object') { 207 for (var i in path) { 208 if (path.hasOwnProperty(i)) { 209 path[i] = path[i].replace(/\.\w*$/, ''); 210 } 211 } 212 } 213 214 this.settings = $.extend({}, DEFAULTS, options); 215 this.path = path; 216 217 // https://github.com/VodkaBears/Vide/issues/110 218 try { 219 this.init(); 220 } catch (e) { 221 if (e.message !== NOT_IMPLEMENTED_MSG) { 222 throw e; 223 } 224 } 225 } 226 227 /** 228 * Initialization 229 * @public 230 */ 231 Vide.prototype.init = function() { 232 var vide = this; 233 var path = vide.path; 234 var poster = path; 235 var sources = ''; 236 var $element = vide.$element; 237 var settings = vide.settings; 238 var position = parsePosition(settings.position); 239 var posterType = settings.posterType; 240 var $video; 241 var $wrapper; 242 243 // Set styles of a video wrapper 244 $wrapper = vide.$wrapper = $('<div>') 245 .addClass(settings.className) 246 .css({ 247 position: 'absolute', 248 'z-index': -1, 249 top: 0, 250 left: 0, 251 bottom: 0, 252 right: 0, 253 overflow: 'hidden', 254 '-webkit-background-size': 'cover', 255 '-moz-background-size': 'cover', 256 '-o-background-size': 'cover', 257 'background-size': 'cover', 258 'background-color': settings.bgColor, 259 'background-repeat': 'no-repeat', 260 'background-position': position.x + ' ' + position.y 261 }); 262 263 // Get a poster path 264 if (typeof path === 'object') { 265 if (path.poster) { 266 poster = path.poster; 267 } else { 268 if (path.mp4) { 269 poster = path.mp4; 270 } else if (path.webm) { 271 poster = path.webm; 272 } else if (path.ogv) { 273 poster = path.ogv; 274 } 275 } 276 } 277 278 // Set a video poster 279 if (posterType === 'detect') { 280 findPoster(poster, function(url) { 281 $wrapper.css('background-image', 'url(' + url + ')'); 282 }); 283 } else if (posterType !== 'none') { 284 $wrapper.css('background-image', 'url(' + poster + '.' + posterType + ')'); 285 } 286 287 // If a parent element has a static position, make it relative 288 if ($element.css('position') === 'static') { 289 $element.css('position', 'relative'); 290 } 291 292 $element.prepend($wrapper); 293 294 if (typeof path === 'object') { 295 if (path.mp4) { 296 sources += '<source src="' + path.mp4 + '.mp4" type="video/mp4">'; 297 } 298 299 if (path.webm) { 300 sources += '<source src="' + path.webm + '.webm" type="video/webm">'; 301 } 302 303 if (path.ogv) { 304 sources += '<source src="' + path.ogv + '.ogv" type="video/ogg">'; 305 } 306 307 $video = vide.$video = $('<video>' + sources + '</video>'); 308 } else { 309 $video = vide.$video = $('<video>' + 310 '<source src="' + path + '.mp4" type="video/mp4">' + 311 '<source src="' + path + '.webm" type="video/webm">' + 312 '<source src="' + path + '.ogv" type="video/ogg">' + 313 '</video>'); 314 } 315 316 // https://github.com/VodkaBears/Vide/issues/110 317 try { 318 $video 319 320 // Set video properties 321 .prop({ 322 autoplay: settings.autoplay, 323 loop: settings.loop, 324 volume: settings.volume, 325 muted: settings.muted, 326 defaultMuted: settings.muted, 327 playbackRate: settings.playbackRate, 328 defaultPlaybackRate: settings.playbackRate 329 }); 330 } catch (e) { 331 throw new Error(NOT_IMPLEMENTED_MSG); 332 } 333 334 // Video alignment 335 $video.css({ 336 margin: 'auto', 337 position: 'absolute', 338 'z-index': -1, 339 top: position.y, 340 left: position.x, 341 '-webkit-transform': 'translate(-' + position.x + ', -' + position.y + ')', 342 '-ms-transform': 'translate(-' + position.x + ', -' + position.y + ')', 343 '-moz-transform': 'translate(-' + position.x + ', -' + position.y + ')', 344 transform: 'translate(-' + position.x + ', -' + position.y + ')', 345 346 // Disable visibility, while loading 347 visibility: 'hidden', 348 opacity: 0 349 }) 350 351 // Resize a video, when it's loaded 352 .one('canplaythrough.' + PLUGIN_NAME, function() { 353 vide.resize(); 354 }) 355 356 // Make it visible, when it's already playing 357 .one('playing.' + PLUGIN_NAME, function() { 358 $video.css({ 359 visibility: 'visible', 360 opacity: 1 361 }); 362 $wrapper.css('background-image', 'none'); 363 }); 364 365 // Resize event is available only for 'window' 366 // Use another code solutions to detect DOM elements resizing 367 $element.on('resize.' + PLUGIN_NAME, function() { 368 if (settings.resizing) { 369 vide.resize(); 370 } 371 }); 372 373 // Append a video 374 $wrapper.append($video); 375 }; 376 377 /** 378 * Get a video element 379 * @public 380 * @returns {HTMLVideoElement} 381 */ 382 Vide.prototype.getVideoObject = function() { 383 return this.$video[0]; 384 }; 385 386 /** 387 * Resize a video background 388 * @public 389 */ 390 Vide.prototype.resize = function() { 391 if (!this.$video) { 392 return; 393 } 394 395 var $wrapper = this.$wrapper; 396 var $video = this.$video; 397 var video = $video[0]; 398 399 // Get a native video size 400 var videoHeight = video.videoHeight; 401 var videoWidth = video.videoWidth; 402 403 // Get a wrapper size 404 var wrapperHeight = $wrapper.height(); 405 var wrapperWidth = $wrapper.width(); 406 407 if (wrapperWidth / videoWidth > wrapperHeight / videoHeight) { 408 $video.css({ 409 410 // +2 pixels to prevent an empty space after transformation 411 width: wrapperWidth + 2, 412 height: 'auto' 413 }); 414 } else { 415 $video.css({ 416 width: 'auto', 417 418 // +2 pixels to prevent an empty space after transformation 419 height: wrapperHeight + 2 420 }); 421 } 422 }; 423 424 /** 425 * Destroy a video background 426 * @public 427 */ 428 Vide.prototype.destroy = function() { 429 delete $[PLUGIN_NAME].lookup[this.index]; 430 this.$video && this.$video.off(PLUGIN_NAME); 431 this.$element.off(PLUGIN_NAME).removeData(PLUGIN_NAME); 432 this.$wrapper.remove(); 433 }; 434 435 /** 436 * Special plugin object for instances. 437 * @public 438 * @type {Object} 439 */ 440 $[PLUGIN_NAME] = { 441 lookup: [] 442 }; 443 444 /** 445 * Plugin constructor 446 * @param {Object|String} path 447 * @param {Object|String} options 448 * @returns {JQuery} 449 * @constructor 450 */ 451 $.fn[PLUGIN_NAME] = function(path, options) { 452 var instance; 453 454 this.each(function() { 455 instance = $.data(this, PLUGIN_NAME); 456 457 // Destroy the plugin instance if exists 458 instance && instance.destroy(); 459 460 // Create the plugin instance 461 instance = new Vide(this, path, options); 462 instance.index = $[PLUGIN_NAME].lookup.push(instance) - 1; 463 $.data(this, PLUGIN_NAME, instance); 464 }); 465 466 return this; 467 }; 468 469 $(document).ready(function() { 470 var $window = $(window); 471 472 // Window resize event listener 473 $window.on('resize.' + PLUGIN_NAME, function() { 474 for (var len = $[PLUGIN_NAME].lookup.length, i = 0, instance; i < len; i++) { 475 instance = $[PLUGIN_NAME].lookup[i]; 476 477 if (instance && instance.settings.resizing) { 478 instance.resize(); 479 } 480 } 481 }); 482 483 // https://github.com/VodkaBears/Vide/issues/68 484 $window.on('unload.' + PLUGIN_NAME, function() { 485 return false; 486 }); 487 488 // Auto initialization 489 // Add 'data-vide-bg' attribute with a path to the video without extension 490 // Also you can pass options throw the 'data-vide-options' attribute 491 // 'data-vide-options' must be like 'muted: false, volume: 0.5' 492 $(document).find('[data-' + PLUGIN_NAME + '-bg]').each(function(i, element) { 493 var $element = $(element); 494 var options = $element.data(PLUGIN_NAME + '-options'); 495 var path = $element.data(PLUGIN_NAME + '-bg'); 496 497 $element[PLUGIN_NAME](path, options); 498 }); 499 }); 500 501});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.