1/*! 2 * parallax.js v1.5.0 (http://pixelcog.github.io/parallax.js/) 3 * @copyright 2016 PixelCog, Inc. 4 * @license MIT (https://github.com/pixelcog/parallax.js/blob/master/LICENSE) 5 */ 6 7;(function ( $, window, document, undefined ) { 8 9 // Polyfill for requestAnimationFrame 10 // via: https://gist.github.com/paulirish/1579671 11 12 (function() { 13 var lastTime = 0; 14 var vendors = ['ms', 'moz', 'webkit', 'o']; 15 for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 16 window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; 17 window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; 18 } 19 20 if (!window.requestAnimationFrame) 21 window.requestAnimationFrame = function(callback) { 22 var currTime = new Date().getTime(); 23 var timeToCall = Math.max(0, 16 - (currTime - lastTime)); 24 var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 25 timeToCall); 26 lastTime = currTime + timeToCall; 27 return id; 28 }; 29 30 if (!window.cancelAnimationFrame) 31 window.cancelAnimationFrame = function(id) { 32 clearTimeout(id); 33 }; 34 }()); 35 36 37 // Parallax Constructor 38 39 function Parallax(element, options) { 40 var self = this; 41 42 if (typeof options == 'object') { 43 delete options.refresh; 44 delete options.render; 45 $.extend(this, options); 46 } 47 48 this.$element = $(element); 49 50 if (!this.imageSrc && this.$element.is('img')) { 51 this.imageSrc = this.$element.attr('src'); 52 } 53 54 var positions = (this.position + '').toLowerCase().match(/\S+/g) || []; 55 56 if (positions.length < 1) { 57 positions.push('center'); 58 } 59 if (positions.length == 1) { 60 positions.push(positions[0]); 61 } 62 63 if (positions[0] == 'top' || positions[0] == 'bottom' || positions[1] == 'left' || positions[1] == 'right') { 64 positions = [positions[1], positions[0]]; 65 } 66 67 if (this.positionX !== undefined) positions[0] = this.positionX.toLowerCase(); 68 if (this.positionY !== undefined) positions[1] = this.positionY.toLowerCase(); 69 70 self.positionX = positions[0]; 71 self.positionY = positions[1]; 72 73 if (this.positionX != 'left' && this.positionX != 'right') { 74 if (isNaN(parseInt(this.positionX))) { 75 this.positionX = 'center'; 76 } else { 77 this.positionX = parseInt(this.positionX); 78 } 79 } 80 81 if (this.positionY != 'top' && this.positionY != 'bottom') { 82 if (isNaN(parseInt(this.positionY))) { 83 this.positionY = 'center'; 84 } else { 85 this.positionY = parseInt(this.positionY); 86 } 87 } 88 89 this.position = 90 this.positionX + (isNaN(this.positionX)? '' : 'px') + ' ' + 91 this.positionY + (isNaN(this.positionY)? '' : 'px'); 92 93 if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) { 94 if (this.imageSrc && this.iosFix && !this.$element.is('img')) { 95 this.$element.css({ 96 backgroundImage: 'url(' + this.imageSrc + ')', 97 backgroundSize: 'cover', 98 backgroundPosition: this.position 99 }); 100 } 101 return this; 102 } 103 104 if (navigator.userAgent.match(/(Android)/)) { 105 if (this.imageSrc && this.androidFix && !this.$element.is('img')) { 106 this.$element.css({ 107 backgroundImage: 'url(' + this.imageSrc + ')', 108 backgroundSize: 'cover', 109 backgroundPosition: this.position 110 }); 111 } 112 return this; 113 } 114 115 this.$mirror = $('<div />').prependTo(this.mirrorContainer); 116 117 var slider = this.$element.find('>.parallax-slider'); 118 var sliderExisted = false; 119 120 if (slider.length == 0) 121 this.$slider = $('<img />').prependTo(this.$mirror); 122 else { 123 this.$slider = slider.prependTo(this.$mirror) 124 sliderExisted = true; 125 } 126 127 this.$mirror.addClass('parallax-mirror').css({ 128 visibility: 'hidden', 129 zIndex: this.zIndex, 130 position: 'fixed', 131 top: 0, 132 left: 0, 133 overflow: 'hidden' 134 }); 135 136 this.$slider.addClass('parallax-slider').one('load', function() {
137 if (!self.naturalHeight || !self.naturalWidth) { 138 self.naturalHeight = this.naturalHeight || this.height || 1; 139 self.naturalWidth = this.naturalWidth || this.width || 1; 140 } 141 self.aspectRatio = self.naturalWidth / self.naturalHeight; 142 143 Parallax.isSetup || Parallax.setup(); 144 Parallax.sliders.push(self); 145 Parallax.isFresh = false; 146 Parallax.requestRender(); 147 }); 148 149 if (!sliderExisted) 150 this.$slider[0].src = this.imageSrc; 151 152 if (this.naturalHeight && this.naturalWidth || this.$slider[0].complete || slider.length > 0) { 153 this.$slider.trigger('load'); 154 } 155 156 } 157 158 159 // Parallax Instance Methods 160 161 $.extend(Parallax.prototype, { 162 speed: 0.2, 163 bleed: 0, 164 zIndex: -100, 165 iosFix: true, 166 androidFix: true, 167 position: 'center', 168 overScrollFix: false, 169 mirrorContainer: 'body', 170 171 refresh: function() { 172 this.boxWidth = this.$element.outerWidth(); 173 this.boxHeight = this.$element.outerHeight() + this.bleed * 2; 174 this.boxOffsetTop = this.$element.offset().top - this.bleed; 175 this.boxOffsetLeft = this.$element.offset().left; 176 this.boxOffsetBottom = this.boxOffsetTop + this.boxHeight; 177 178 var winHeight = Parallax.winHeight; 179 var docHeight = Parallax.docHeight; 180 var maxOffset = Math.min(this.boxOffsetTop, docHeight - winHeight); 181 var minOffset = Math.max(this.boxOffsetTop + this.boxHeight - winHeight, 0); 182 var imageHeightMin = this.boxHeight + (maxOffset - minOffset) * (1 - this.speed) | 0; 183 var imageOffsetMin = (this.boxOffsetTop - maxOffset) * (1 - this.speed) | 0; 184 var margin; 185 186 if (imageHeightMin * this.aspectRatio >= this.boxWidth) { 187 this.imageWidth = imageHeightMin * this.aspectRatio | 0; 188 this.imageHeight = imageHeightMin; 189 this.offsetBaseTop = imageOffsetMin; 190 191 margin = this.imageWidth - this.boxWidth; 192 193 if (this.positionX == 'left') { 194 this.offsetLeft = 0; 195 } else if (this.positionX == 'right') { 196 this.offsetLeft = - margin; 197 } else if (!isNaN(this.positionX)) { 198 this.offsetLeft = Math.max(this.positionX, - margin); 199 } else { 200 this.offsetLeft = - margin / 2 | 0; 201 } 202 } else { 203 this.imageWidth = this.boxWidth; 204 this.imageHeight = this.boxWidth / this.aspectRatio | 0; 205 this.offsetLeft = 0; 206 207 margin = this.imageHeight - imageHeightMin; 208 209 if (this.positionY == 'top') { 210 this.offsetBaseTop = imageOffsetMin; 211 } else if (this.positionY == 'bottom') { 212 this.offsetBaseTop = imageOffsetMin - margin; 213 } else if (!isNaN(this.positionY)) { 214 this.offsetBaseTop = imageOffsetMin + Math.max(this.positionY, - margin); 215 } else { 216 this.offsetBaseTop = imageOffsetMin - margin / 2 | 0; 217 } 218 } 219 }, 220 221 render: function() { 222 var scrollTop = Parallax.scrollTop; 223 var scrollLeft = Parallax.scrollLeft; 224 var overScroll = this.overScrollFix ? Parallax.overScroll : 0; 225 var scrollBottom = scrollTop + Parallax.winHeight; 226 227 if (this.boxOffsetBottom > scrollTop && this.boxOffsetTop <= scrollBottom) { 228 this.visibility = 'visible'; 229 this.mirrorTop = this.boxOffsetTop - scrollTop; 230 this.mirrorLeft = this.boxOffsetLeft - scrollLeft; 231 this.offsetTop = this.offsetBaseTop - this.mirrorTop * (1 - this.speed); 232 } else { 233 this.visibility = 'hidden'; 234 } 235 236 this.$mirror.css({ 237 transform: 'translate3d('+this.mirrorLeft+'px, '+(this.mirrorTop - overScroll)+'px, 0px)', 238 visibility: this.visibility, 239 height: this.boxHeight, 240 width: this.boxWidth 241 }); 242 243 this.$slider.css({ 244 transform: 'translate3d('+this.offsetLeft+'px, '+this.offsetTop+'px, 0px)', 245 position: 'absolute', 246 height: this.imageHeight, 247 width: this.imageWidth, 248 maxWidth: 'none' 249 }); 250 } 251 }); 252 253 254 // Parallax Static Methods 255 256 $.extend(Parallax, { 257 scrollTop: 0, 258 scrollLeft: 0, 259 winHeight: 0, 260 winWidth: 0, 261 docHeight: 1 << 30, 262 docWidth: 1 << 30, 263 sliders: [], 264 isReady: false, 265 isFresh: false, 266 isBusy: false, 267 268 setup: function() { 269 if (this.isReady) return; 270 271 var self = this; 272 273 var $doc = $(document), $win = $(window); 274 275 var loadDimensions = function() { 276 Parallax.winHeight = $win.height(); 277 Parallax.winWidth = $win.width(); 278 Parallax.docHeight = $doc.height(); 279 Parallax.docWidth = $doc.width(); 280 }; 281 282 var loadScrollPosition = function() { 283 var winScrollTop = $win.scrollTop(); 284 var scrollTopMax = Parallax.docHeight - Parallax.winHeight; 285 var scrollLeftMax = Parallax.docWidth - Parallax.winWidth; 286 Parallax.scrollTop = Math.max(0, Math.min(scrollTopMax, winScrollTop)); 287 Parallax.scrollLeft = Math.max(0, Math.min(scrollLeftMax, $win.scrollLeft())); 288 Parallax.overScroll = Math.max(winScrollTop - scrollTopMax, Math.min(winScrollTop, 0)); 289 }; 290 291 $win.on('resize.px.parallax load.px.parallax', function() { 292 loadDimensions(); 293 self.refresh(); 294 Parallax.isFresh = false;
295 Parallax.requestRender(); 296 }) 297 .on('scroll.px.parallax load.px.parallax', function() { 298 loadScrollPosition(); 299 Parallax.requestRender(); 300 }); 301 302 loadDimensions(); 303 loadScrollPosition(); 304 305 this.isReady = true; 306 307 var lastPosition = -1; 308 309 function frameLoop() { 310 if (lastPosition == window.pageYOffset) { // Avoid overcalculations 311 window.requestAnimationFrame(frameLoop); 312 return false; 313 } else lastPosition = window.pageYOffset; 314 315 self.render(); 316 window.requestAnimationFrame(frameLoop); 317 } 318 319 frameLoop(); 320 }, 321 322 configure: function(options) { 323 if (typeof options == 'object') { 324 delete options.refresh; 325 delete options.render; 326 $.extend(this.prototype, options); 327 } 328 }, 329 330 refresh: function() { 331 $.each(this.sliders, function(){ this.refresh(); }); 332 this.isFresh = true; 333 }, 334 335 render: function() { 336 this.isFresh || this.refresh(); 337 $.each(this.sliders, function(){ this.render(); }); 338 }, 339 340 requestRender: function() { 341 var self = this; 342 self.render(); 343 self.isBusy = false; 344 }, 345 destroy: function(el){ 346 var i, 347 parallaxElement = $(el).data('px.parallax'); 348 parallaxElement.$mirror.remove(); 349 for(i=0; i < this.sliders.length; i+=1){ 350 if(this.sliders[i] == parallaxElement){ 351 this.sliders.splice(i, 1); 352 } 353 } 354 $(el).data('px.parallax', false); 355 if(this.sliders.length === 0){ 356 $(window).off('scroll.px.parallax resize.px.parallax load.px.parallax'); 357 this.isReady = false; 358 Parallax.isSetup = false; 359 } 360 } 361 }); 362 363 364 // Parallax Plugin Definition 365 366 function Plugin(option) { 367 return this.each(function () { 368 var $this = $(this); 369 var options = typeof option == 'object' && option; 370 371 if (this == window || this == document || $this.is('section')) { 372 Parallax.configure(options); 373 } 374 else if (!$this.data('px.parallax')) { 375 options = $.extend({}, $this.data(), options); 376 $this.data('px.parallax', new Parallax(this, options)); 377 } 378 else if (typeof option == 'object') 379 { 380 $.extend($this.data('px.parallax'), options); 381 } 382 if (typeof option == 'string') { 383 if(option == 'destroy'){ 384 Parallax.destroy(this); 385 }else{ 386 Parallax[option](); 387 } 388 } 389 }); 390 } 391 392 var old = $.fn.parallax; 393 394 $.fn.parallax = Plugin; 395 $.fn.parallax.Constructor = Parallax; 396 397 398 // Parallax No Conflict 399 400 $.fn.parallax.noConflict = function () { 401 $.fn.parallax = old; 402 return this; 403 }; 404 405 406 // Parallax Data-API 407 408 $( function () { 409 $('[data-parallax="scroll"]').parallax(); 410 }); 411 412}(jQuery, window, document));
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.