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