1/*! 2 * Name : Just Another Parallax [Jarallax] 3 * Version : 1.1.0 4 * Author : _nK http://nkdev.info 5 * GitHub : https://github.com/nk-o/jarallax 6 */ 7(function(factory) { 8 'use strict'; 9 if (typeof define === 'function' && define.amd) { 10 define(['jquery'], factory); 11 } else if (typeof exports !== 'undefined') { 12 module.exports = factory(require('jquery')); 13 } else { 14 factory(jQuery); 15 } 16}(function($) { 17 // Adapted from https://gist.github.com/paulirish/1579671 18 if (!Date.now) 19 Date.now = function() { return new Date().getTime(); }; 20 if(!window.requestAnimationFrame) 21 (function() { 22 'use strict'; 23 24 var vendors = ['webkit', 'moz']; 25 for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) { 26 var vp = vendors[i]; 27 window.requestAnimationFrame = window[vp+'RequestAnimationFrame']; 28 window.cancelAnimationFrame = (window[vp+'CancelAnimationFrame'] 29 || window[vp+'CancelRequestAnimationFrame']); 30 } 31 if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy 32 || !window.requestAnimationFrame || !window.cancelAnimationFrame) { 33 var lastTime = 0; 34 window.requestAnimationFrame = function(callback) { 35 var now = Date.now(); 36 var nextTime = Math.max(lastTime + 16, now); 37 return setTimeout(function() { callback(lastTime = nextTime); }, 38 nextTime - now); 39 }; 40 window.cancelAnimationFrame = clearTimeout; 41 } 42 }()); 43 44 var supportTransform = (function() { 45 var prefixes = 'transform WebkitTransform MozTransform OTransform msTransform'.split(' '); 46 var div = document.createElement('div'); 47 for(var i = 0; i < prefixes.length; i++) { 48 if(div && div.style[prefixes[i]] !== undefined) { 49 return prefixes[i]; 50 } 51 } 52 return false; 53 }()); 54 55 var support3dtransform = (function() { 56 if (!window.getComputedStyle) { 57 return false; 58 } 59 60 var el = document.createElement('p'), 61 has3d, 62 transforms = { 63 'webkitTransform':'-webkit-transform', 64 'OTransform':'-o-transform', 65 'msTransform':'-ms-transform', 66 'MozTransform':'-moz-transform', 67 'transform':'transform' 68 }; 69 70 // Add it to the body to get the computed style. 71 (document.body || document.documentElement).insertBefore(el, null); 72 73 for (var t in transforms) { 74 if (el.style[t] !== undefined) { 75 el.style[t] = "translate3d(1px,1px,1px)"; 76 has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); 77 } 78 } 79 80 (document.body || document.documentElement).removeChild(el); 81 82 return (has3d !== undefined && has3d.length > 0 && has3d !== "none"); 83 }()); 84 85 var isAndroid = navigator.userAgent.toLowerCase().indexOf('android') > -1; 86 var isOperaOld = !!window.opera; 87 88 // list with all jarallax instances 89 // need to render all in one scroll/resize event 90 var jarallaxList = []; 91 92 // Jarallax instance 93 var Jarallax = (function() { 94 var instanceID = 0; 95 96 function Jarallax(item, userOptions) { 97 var _this = this, 98 dataOptions; 99 100 _this.$item = $(item); 101 102 _this.defaults = { 103 speed : 0.5, 104 imgSrc : null, 105 imgWidth : null, 106 imgHeight : null, 107 enableTransform : true, 108 zIndex : -100 109 }; 110 dataOptions = _this.$item.data('jarallax') || {}; 111 _this.options = $.extend({}, _this.defaults, dataOptions, userOptions); 112 113 // fix speed option [0.0, 1.0] 114 _this.options.speed = Math.min(1, Math.max(0, parseFloat(_this.options.speed))); 115 116 _this.instanceID = instanceID++; 117 118 _this.image = { 119 src : _this.options.imgSrc || null, 120 $container : null, 121 $item : null, 122 width : _this.options.imgWidth || null, 123 height : _this.options.imgHeight || null, 124 // fix for Android devices 125 // use <img> instead background image - more smoothly 126 useImgTag : isAndroid || isOperaOld 127 } 128 129 if(_this.initImg()) { 130 _this.init(); 131 132 jarallaxList.push(_this); 133 } 134 } 135 136 return Jarallax; 137 }()); 138 139 Jarallax.prototype.initImg = function() { 140 var _this = this; 141 142 // get image src 143 if(_this.image.src === null) { 144 _this.image.src = _this.$item.css('background-image').replace(/^url\(['"]?/g,'').replace(/['"]?\)$/g,''); 145 } 146 if(!_this.image.src || _this.image.src === 'none') { 147 return false;
148 } 149 return true; 150 } 151 152 Jarallax.prototype.init = function() { 153 var _this = this, 154 containerStyles = { 155 position : 'absolute', 156 top : 0, 157 left : 0, 158 width : '100%', 159 height : '100%', 160 overflow : 'hidden', 161 'pointer-events' : 'none', 162 'transition' : 'transform linear -1ms, -webkit-transform linear -1ms' 163 }, 164 imageStyles = { 165 position : 'fixed' 166 }; 167 168 // container for parallax image 169 _this.image.$container = $('<div>') 170 .css(containerStyles) 171 .css({ 172 visibility : 'hidden', 173 'z-index' : _this.options.zIndex 174 }) 175 .attr('id', 'jarallax-container-' + _this.instanceID) 176 .prependTo(_this.$item); 177 178 // use img tag 179 if(_this.image.useImgTag && supportTransform) { 180 _this.image.$item = $('<img>').attr('src', _this.image.src); 181 imageStyles = $.extend({ 182 'max-width' : 'none' 183 }, containerStyles, imageStyles) 184 } 185 186 // use div with background image 187 else { 188 _this.image.$item = $('<div>'); 189 imageStyles = $.extend({ 190 'background-position' : '50% 50%', 191 'background-repeat' : 'no-repeat no-repeat', 192 'background-image' : 'url("' + _this.image.src + '")' 193 }, containerStyles, imageStyles) 194 } 195 196 // parallax image 197 _this.image.$item.css(imageStyles) 198 .prependTo(_this.image.$container); 199 200 // cover image if width and height is ready 201 function initAfterReady() { 202 _this.coverImage(); 203 _this.clipContainer(); 204 _this.onScroll(true); 205 206 // save default user styles 207 _this.$item.data('jarallax-original-styles', _this.$item.attr('style')); 208 209 // timeout to fix IE blinking 210 setTimeout(function() { 211 // remove default user background 212 _this.$item.css({ 213 'background-image' : 'none', 214 'background-attachment' : 'scroll', 215 'background-size' : 'auto' 216 }); 217 }, 0); 218 } 219 220 if(_this.image.width && _this.image.height) { 221 // init if width and height already exists 222 initAfterReady(); 223 } else { 224 // load image and get width and height 225 _this.getImageSize(_this.image.src, function(width, height) { 226 _this.image.width = width; 227 _this.image.height = height; 228 initAfterReady(); 229 }); 230 } 231 }; 232 233 Jarallax.prototype.destroy = function() { 234 var _this = this; 235 236 // remove from instances list 237 for(var k = 0, len = jarallaxList.length; k < len; k++) { 238 if(jarallaxList[k].instanceID === _this.instanceID) { 239 jarallaxList.splice(k, 1); 240 break; 241 } 242 } 243 244 // remove additional styles for clip 245 $('head #jarallax-clip-' + _this.instanceID).remove(); 246 247 _this.$item.attr('style', _this.$item.data('jarallax-original-styles')); 248 _this.$item.removeData('jarallax-original-styles'); 249 250 _this.image.$container.remove(); 251 252 delete _this.$item[0].jarallax; 253 } 254 255 // round to 2 decimals 256 Jarallax.prototype.round = function(num) { 257 return Math.floor(num * 100) / 100; 258 } 259 260 Jarallax.prototype.getImageSize = function(src, callback) { 261 if(!src || !callback) { 262 return false; 263 } 264 265 var tempImg = new Image(); 266 tempImg.onload = function() { 267 callback(tempImg.width, tempImg.height) 268 } 269 tempImg.src = src; 270 } 271 272 // it will remove some image overlapping 273 // overlapping occur due to an image position fixed inside absolute possition element (webkit based browsers works without any fix) 274 Jarallax.prototype.clipContainer = function() { 275 var _this = this, 276 width = _this.image.$container.outerWidth(true), 277 height = _this.image.$container.outerHeight(true); 278 279 var $styles = $('head #jarallax-clip-' + _this.instanceID); 280 if(!$styles.length) { 281 $('head').append('<style type="text/css" id="jarallax-clip-' + _this.instanceID + '"></style>'); 282 $styles = $('head #jarallax-clip-' + _this.instanceID); 283 } 284 285 var css = [ 286 '#jarallax-container-' + _this.instanceID + ' {', 287 ' clip: rect(0px ' + width + 'px ' + height + 'px 0);', 288 ' clip: rect(0px, ' + width + 'px, ' + height + 'px, 0);', 289 '}' 290 ].join('\n'); 291 292 // add clip styles inline (this method need for support IE8 and less browsers) 293 if ($styles[0].styleSheet) { 294 $styles[0].styleSheet.cssText = css; 295 } else { 296 $styles.html(css); 297 } 298 } 299 300 Jarallax.prototype.coverImage = function() { 301 var _this = this; 302 303 if(!_this.image.width || !_this.image.height) { 304 return; 305 } 306 307 var contW = _this.image.$container.outerWidth(true), 308 contH = _this.image.$container.outerHeight(true), 309 wndW = $(window).outerWidth(true), 310 whdH = $(window).outerHeight(true), 311 imgW = _this.image.width, 312 imgH = _this.image.height, 313 resultWidth, resultHeight; 314 315 var css = { 316 width : Math.max(wndW, contW) * Math.max(_this.options.speed, 1), 317 height : Math.max(whdH, contH) * Math.max(_this.options.speed, 1) 318 }; 319 320 // cover by width 321 if(css.width / css.height > imgW / imgH) { 322 resultWidth = css.width; 323 resultHeight = css.width * imgH / imgW; 324 } 325 326 // cover by height 327 else { 328 resultWidth = css.height * imgW / imgH; 329 resultHeight = css.height; 330 } 331 332 // for img tag 333 if(_this.image.useImgTag && supportTransform) { 334 css.width = _this.round(resultWidth); 335 css.height = _this.round(resultHeight); 336 css.marginLeft = _this.round(- (resultWidth - contW) / 2); 337 css.marginTop = _this.round(- (resultHeight - contH) / 2); 338 } 339 340 // for div with background image 341 else { 342 css.backgroundSize = _this.round(resultWidth) + 'px ' + _this.round(resultHeight) + 'px'; 343 } 344 345 // apply to item 346 _this.image.$item.css(css); 347 }; 348 349 Jarallax.prototype.onScroll = function(force) { 350 var _this = this; 351 352 if(!_this.image.width || !_this.image.height) { 353 return; 354 } 355 356 var scrollTop = $(window).scrollTop(), 357 scrollLeft = $(window).scrollLeft(), 358 wndWidth = $(window).width(), 359 wndHeight = $(window).height(), 360 // starting position of each element to have parallax applied to it 361 sectionTop = _this.$item.offset().top, 362 sectionLeft = _this.$item.offset().left, 363 sectionHeight = _this.$item.outerHeight(true), 364 css = { 365 visibility : 'visible', 366 backgroundPosition : '50% 50%' 367 }; 368 369 // Check if totally above or totally below viewport 370 var check = force ? false 371 : sectionTop + sectionHeight < scrollTop || sectionTop > scrollTop + wndHeight; 372 if (check) { 373 return; 374 } 375 376 // calculate parallax 377 var positionY = - (scrollTop - sectionTop) * _this.options.speed; 378 var positionX = - (scrollLeft - sectionLeft) * _this.options.speed; 379 positionY = _this.round(positionY); 380 positionX = _this.round(positionX); 381 382 if(supportTransform && _this.options.enableTransform) { 383 css.transform = 'translateY(' + positionY + 'px) translateX(' + positionX + 'px)'; 384 if(support3dtransform) { 385 css.transform = 'translate3d(' + positionX + 'px, ' + positionY + 'px, 0)'; 386 } 387 } else { 388 css.backgroundPosition = positionX + 'px ' + positionY + 'px'; 389 } 390 391 _this.image.$item.css(css); 392 }; 393 394 // init events 395 (function() { 396 $(window).on('scroll.jarallax', function() { 397 window.requestAnimationFrame(function() { 398 for(var k = 0, len = jarallaxList.length; k < len; k++) { 399 jarallaxList[k].onScroll(); 400 } 401 }); 402 }); 403 404 var timeout; 405 $(window).on('resize.jarallax orientationchange.jarallax load.jarallax', function() { 406 clearTimeout(timeout); 407 timeout = setTimeout(function() { 408 window.requestAnimationFrame(function() { 409 for(var k = 0, len = jarallaxList.length; k < len; k++) { 410 var _this = jarallaxList[k]; 411 _this.coverImage(); 412 _this.clipContainer(); 413 _this.onScroll(); 414 } 415 }); 416 }, 100); 417 }); 418 }()); 419 420 var oldJarallax = $.fn.jarallax; 421 422 $.fn.jarallax = function() { 423 var items = this, 424 options = arguments[0], 425 args = Array.prototype.slice.call(arguments, 1), 426 len = items.length, 427 k = 0, 428 ret; 429 430 for (k; k < len; k++) { 431 if (typeof options === 'object' || typeof options === 'undefined') { 432 if(!items[k].jarallax) { 433 items[k].jarallax = new Jarallax(items[k], options); 434 } 435 } 436 else { 437 ret = items[k].jarallax ? items[k].jarallax[options].apply(items[k].jarallax, args) : undefined; 438 } 439 if (typeof ret !== 'undefined') { 440 return ret; 441 } 442 } 443 444 return this; 445 }; 446 447 // no conflict 448 $.fn.jarallax.noConflict = function () { 449 $.fn.jarallax = oldJarallax; 450 return this; 451 }; 452 453 // data-jarallax initialization 454 $(document).on('ready.data-jarallax', function () { 455 $('[data-jarallax]').jarallax(); 456 }); 457}));
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.