1/*! 2 * Artlogic Parallax 3 * This file is heavily edited to work primarily with parallax on template and gallery sites 4 * This will only work with one parallax instance on each page, but is modified to accept slideshows and other elements in addition to just a single image within the parallax area 5 * To use the original functionality of parallax.js, please use parallax.original.js located in the same folder. 6 * 7 * parallax.js v1.3.1 (http://pixelcog.github.io/parallax.js/) 8 * @copyright 2015 PixelCog, Inc. 9 * @license MIT (https://github.com/pixelcog/parallax.js/blob/master/LICENSE) 10 */ 11 12parallax_init_callback = function() {}; 13parallax_resize_callback = function() {}; 14 15(function ( $, window, document, undefined ) { 16 17 // Polyfill for requestAnimationFrame 18 // via: https://gist.github.com/paulirish/1579671 19 20 (function() { 21 var lastTime = 0; 22 var vendors = ['ms', 'moz', 'webkit', 'o']; 23 for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 24 window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; 25 window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 26 || window[vendors[x]+'CancelRequestAnimationFrame']; 27 } 28 29 if (!window.requestAnimationFrame) 30 window.requestAnimationFrame = function(callback) { 31 var currTime = new Date().getTime(); 32 var timeToCall = Math.max(0, 16 - (currTime - lastTime)); 33 var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 34 timeToCall); 35 lastTime = currTime + timeToCall; 36 return id; 37 }; 38 39 if (!window.cancelAnimationFrame) 40 window.cancelAnimationFrame = function(id) { 41 clearTimeout(id); 42 }; 43 }()); 44 45 // Parallax Constructor 46 47 function Parallax(element, options) { 48 var self = this; 49 50 if (typeof options == 'object') { 51 delete options.refresh; 52 delete options.render; 53 $.extend(this, options); 54 } 55 56 this.$element = $(element); 57 58 this.id = ''; 59 if (this.$element.attr('id')) { 60 this.id = 'parallax-' + this.$element.attr('id'); 61 } 62 this.color = '#000000'; 63 if (this.$element.attr('data-color')) { 64 this.color = this.$element.attr('data-color'); 65 } 66 this.opacity = '1'; 67 if (this.$element.attr('data-opacity')) { 68 this.opacity = this.$element.attr('data-opacity'); 69 } 70 71 if (!this.imageSrc && this.$element.is('img')) { 72 this.imageSrc = this.$element.attr('src'); 73 } 74 75 var positions = (this.position + '').toLowerCase().match(/\S+/g) || []; 76 77 if (positions.length < 1) { 78 positions.push('center'); 79 } 80 if (positions.length == 1) { 81 positions.push(positions[0]); 82 } 83 84 if (positions[0] == 'top' || positions[0] == 'bottom' || positions[1] == 'left' || positions[1] == 'right') { 85 positions = [positions[1], positions[0]]; 86 } 87 88 if (this.positionX != undefined) positions[0] = this.positionX.toLowerCase(); 89 if (this.positionY != undefined) positions[1] = this.positionY.toLowerCase(); 90 91 self.positionX = positions[0]; 92 self.positionY = positions[1]; 93 94 if (this.positionX != 'left' && this.positionX != 'right') { 95 if (isNaN(parseInt(this.positionX))) { 96 this.positionX = 'center'; 97 } else { 98 this.positionX = parseInt(this.positionX); 99 } 100 } 101 102 if (this.positionY != 'top' && this.positionY != 'bottom') { 103 if (isNaN(parseInt(this.positionY))) { 104 this.positionY = 'center'; 105 } else { 106 this.positionY = parseInt(this.positionY); 107 } 108 } 109 110 this.position = 111 this.positionX + (isNaN(this.positionX)? '' : 'px') + ' ' + 112 this.positionY + (isNaN(this.positionY)? '' : 'px'); 113 114 if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) { 115 if (false && this.iosFix && !this.$element.is('img')) { 116 this.$element.css({ 117 backgroundImage: 'url(' + this.imageSrc + ')', 118 backgroundSize: 'cover', 119 backgroundPosition: this.position 120 }); 121 return this; 122 } 123 } 124 125 if (navigator.userAgent.match(/(Android)/)) { 126 if (false && this.androidFix && !this.$element.is('img')) { 127 this.$element.css({ 128 backgroundImage: 'url(' + this.imageSrc + ')', 129 backgroundSize: 'cover', 130 backgroundPosition: this.position 131 }); 132 return this; 133 } 134 } 135 136 this.$mirror = $('<div />').prependTo('body'); 137 this.$slider = $('<img />').prependTo(this.$mirror); 138 139 this.$mirror.addClass('parallax-mirror').attr({id: this.id, role: "complementary"}).css({ 140 visibility: 'hidden', 141 zIndex: this.zIndex, 142 position: 'fixed', 143 top: 0, 144 left: 0, 145 overflow: 'hidden', 146 background: this.color 147 }); 148 149 this.$slider.fadeTo(0, this.opacity).addClass('parallax-slider').attr('alt', 'Placeholder image').one('load', function() {
150 if (!self.naturalHeight || !self.naturalWidth) { 151 self.naturalHeight = this.naturalHeight || this.height || 1; 152 self.naturalWidth = this.naturalWidth || this.width || 1; 153 } 154 self.aspectRatio = self.naturalWidth / self.naturalHeight; 155 156 Parallax.isSetup || Parallax.setup(); 157 Parallax.sliders.push(self); 158 Parallax.isFresh = false; 159 Parallax.requestRender(); 160 }); 161 162 this.$slider[0].src = this.imageSrc; 163 164 if (this.naturalHeight && this.naturalWidth || this.$slider[0].complete) { 165 this.$slider.trigger('load'); 166 } 167 168 }; 169 170 171 // Parallax Instance Methods 172 173 $.extend(Parallax.prototype, { 174 speed: 0.2, 175 bleed: 0, 176 zIndex: 0, 177 iosFix: true, 178 androidFix: true, 179 position: 'center', 180 overScrollFix: false, 181 182 refresh: function() { 183 if (this.$element.hasClass('parallax-loaded')) { 184 var element_display_status = this.$element.css('display'); 185 this.$element.css('display', 'block'); 186 } 187 188 this.cmsToolbarHeight = $('#cms-frontend-toolbar-container').height(); 189 this.originalElementOffsetTop = this.$element.offset().top; 190 this.boxWidth = this.$element.outerWidth(); 191 this.boxHeight = this.$element.outerHeight() + this.bleed * 2; // previously this.$element.outerHeight() + this.bleed * 2 + this.$element.offset().top - this.bleed 192 this.boxOffsetTop = this.$element.offset().top - this.bleed; // previously 0 193 this.boxOffsetLeft = this.$element.offset().left; 194 this.boxOffsetBottom = this.boxOffsetTop + this.boxHeight; 195 196 var winHeight = Parallax.winHeight; 197 var docHeight = Parallax.docHeight; 198 var maxOffset = Math.min(this.boxOffsetTop, docHeight - winHeight); 199 var minOffset = Math.max(this.boxOffsetTop + this.boxHeight - winHeight, 0); 200 var imageHeightMin = this.boxHeight + (maxOffset - minOffset) * (1 - this.speed) | 0; 201 var imageOffsetMin = (this.boxOffsetTop - maxOffset) * (1 - this.speed) | 0; 202 203 if (imageHeightMin * this.aspectRatio >= this.boxWidth) { 204 this.imageWidth = imageHeightMin * this.aspectRatio | 0; 205 this.imageHeight = imageHeightMin; 206 this.offsetBaseTop = imageOffsetMin; 207 208 var margin = this.imageWidth - this.boxWidth; 209 210 if (this.positionX == 'left') { 211 this.offsetLeft = 0; 212 } else if (this.positionX == 'right') { 213 this.offsetLeft = - margin; 214 } else if (!isNaN(this.positionX)) { 215 this.offsetLeft = Math.max(this.positionX, - margin); 216 } else { 217 this.offsetLeft = - margin / 2 | 0; 218 } 219 } else { 220 this.imageWidth = this.boxWidth; 221 this.imageHeight = this.boxWidth / this.aspectRatio | 0; 222 this.offsetLeft = 0; 223 224 var margin = this.imageHeight - imageHeightMin; 225 226 if (this.positionY == 'top') { 227 this.offsetBaseTop = imageOffsetMin; 228 } else if (this.positionY == 'bottom') { 229 this.offsetBaseTop = imageOffsetMin - margin; 230 } else if (!isNaN(this.positionY)) { 231 this.offsetBaseTop = imageOffsetMin + Math.max(this.positionY, - margin); 232 } else { 233 this.offsetBaseTop = imageOffsetMin - margin / 2 | 0; 234 } 235 } 236 237 if (this.$element.hasClass('parallax-loaded')) { 238 this.$element.css('display', ''); 239 } 240 241 var scrollTop = Parallax.scrollTop; 242 var mirrorTop = this.boxOffsetTop; 243 this.originalOffsetTop = this.offsetBaseTop - mirrorTop * (1 - this.speed); 244 }, 245 246 render: function() { 247 var scrollTop = Parallax.scrollTop; 248 var scrollLeft = Parallax.scrollLeft; 249 var overScroll = this.overScrollFix ? Parallax.overScroll : 0; 250 var scrollBottom = scrollTop + Parallax.winHeight; 251 252 //console.log('2222#########################'); 253 //console.log('boxOffsetBottom ' + this.boxOffsetBottom); 254 //console.log('scrollTop ' + this.scrollTop); 255 //console.log('boxOffsetTop ' + this.boxOffsetTop); 256 //console.log('scrollBottom ' + this.scrollBottom); 257 258 //console.log(this.boxOffsetBottom > scrollTop && this.boxOffsetTop < scrollBottom); 259 260 if (this.boxOffsetBottom > scrollTop && this.boxOffsetTop < scrollBottom) { 261 //console.log('visible'); 262 this.visibility = 'visible'; 263 this.mirrorTop = this.boxOffsetTop - scrollTop; 264 this.mirrorLeft = this.boxOffsetLeft - scrollLeft; 265 this.offsetTop = this.offsetBaseTop - this.mirrorTop * (1 - this.speed); 266 267 this.slideshowOffsetTop = 0 - this.mirrorTop * (1 - this.speed); 268 this.$mirror.css({ 269 transform: 'translate3d(0px, 0px, 0px)', 270 visibility: this.visibility, 271 top: this.mirrorTop - overScroll, 272 left: this.mirrorLeft, 273 height: this.boxHeight, 274 width: this.boxWidth 275 }); 276 } else { 277 //console.log('hidden'); 278 this.visibility = 'hidden'; 279 this.$mirror.css({ 280 visibility: this.visibility 281 }); 282 } 283 284 var parallax_before_load = this.visibility == 'visible' && !$(this.$element).hasClass('parallax-loaded'); 285
286 if (parallax_before_load) { 287 $(this.$element).addClass('parallax-loaded'); 288 if ($(this.$element).find('.hero-parallax-element').length) { 289 var element_id = $(this.$element).find('.hero-parallax-element').parent().attr('id'); 290 var original_element_class = (typeof $(this.$element).find('.hero-parallax-element').parent().attr('class') != 'undefined' ? $(this.$element).find('.hero-parallax-element').parent().attr('class') : ''); 291 if (element_id == 'slideshow' || element_id == 'hero_parallax_content') { 292 this.$slider.css({ 293 opacity: 0 294 }); 295 this.$mirror.append('<div id="mirror-' + element_id + '" class="hero-parallax-element-mirror ' + original_element_class + '" style="opacity:' + this.opacity + ';">' + $(this.$element).find('.hero-parallax-element').parent().html() + '</div>'); 296 this.$mirror.find('.hero-parallax-element').removeClass('hero-parallax-element'); 297 this.$mirror.find('.fullscreen_slideshow_video').remove(); 298 if (element_id == 'slideshow') { 299 window.galleries.slideshow.init(); 300 } 301 } 302 } 303 } 304 305 if (this.$mirror.find('.hero-parallax-element-mirror').length) { 306 var mirror_element_height = this.imageHeight; 307 308 var mirror_container_height = this.$mirror.height(); 309 var mirror_element_height = mirror_container_height + this.$mirror.offset().top; 310 if (mirror_element_height > $(window).height()) { 311 var mirror_element_height = $(window).height() 312 } 313 314 //if (this.boxHeight > this.imageHeight) { 315 // var mirror_element_height = this.boxHeight; 316 //} 317 this.$mirror.find('.hero-parallax-element-mirror').css({ 318 transform: 'translate3d(0px, 0px, 0px)', 319 top: this.slideshowOffsetTop, 320 height: mirror_element_height 321 //height: this.boxHeight - this.originalOffsetTop 322 }); 323 this.$slider.css({ 324 opacity: 0 325 }); 326 } else { 327 this.$slider.css({ 328 transform: 'translate3d(0px, 0px, 0px)', 329 position: 'absolute', 330 top: this.offsetTop, 331 left: this.offsetLeft, 332 height: this.imageHeight, 333 width: this.imageWidth, 334 maxWidth: 'none' 335 }); 336 } 337 338 if (parallax_before_load) { 339 parallax_init_callback(); 340 } 341 342 } 343 }); 344 345 346 // Parallax Static Methods 347 348 $.extend(Parallax, { 349 scrollTop: 0, 350 scrollLeft: 0, 351 winHeight: 0, 352 winWidth: 0, 353 docHeight: 1 << 30, 354 docWidth: 1 << 30, 355 sliders: [], 356 isReady: false, 357 isFresh: false, 358 isBusy: false, 359 360 setup: function() { 361 if (this.isReady) return; 362 363 var $doc = $(document), $win = $(window); 364 365 $win.on('scroll.px.parallax load.px.parallax', function() { 366 var scrollTopMax = Parallax.docHeight - Parallax.winHeight; 367 var scrollLeftMax = Parallax.docWidth - Parallax.winWidth; 368 Parallax.scrollTop = $win.scrollTop(); 369 // Removed the 'maximum' rule for scrolltop, this would cause problems if the height increased on a very short page: 370 // Parallax.scrollTop = Math.max(0, Math.min(scrollTopMax, $win.scrollTop())); 371 Parallax.scrollLeft = Math.max(0, Math.min(scrollLeftMax, $win.scrollLeft())); 372 Parallax.overScroll = Math.max($win.scrollTop() - scrollTopMax, Math.min($win.scrollTop(), 0)); 373 Parallax.requestRender(); 374 }) 375 .on('resize.px.parallax load.px.parallax', function() { 376 Parallax.winHeight = $win.height(); 377 Parallax.winWidth = $win.width(); 378 Parallax.docHeight = $doc.height(); 379 Parallax.docWidth = $doc.width(); 380 Parallax.isFresh = false; 381 Parallax.requestRender(); 382 parallax_resize_callback(); 383 }); 384 385 this.isReady = true; 386 387 $(window).trigger('resize.px.parallax'); 388 }, 389 390 configure: function(options) { 391 if (typeof options == 'object') { 392 delete options.refresh; 393 delete options.render; 394 $.extend(this.prototype, options); 395 } 396 }, 397 398 refresh: function() { 399 $.each(this.sliders, function(){this.refresh()}); 400 this.isFresh = true; 401 }, 402 403 render: function() { 404 this.isFresh || this.refresh(); 405 $.each(this.sliders, function(){this.render()}); 406 }, 407 408 requestRender: function() { 409 var self = this; 410 411 if (!this.isBusy) { 412 this.isBusy = true; 413 window.requestAnimationFrame(function() { 414 415 self.render(); 416 self.isBusy = false;
417 }); 418 } 419 }, 420 421 destroy: function(){ 422 Parallax.sliders = [] 423 this.isReady = false; 424 // delete Parallax 425 $('body').addClass('parallax-destroyed'); 426 $('.parallax-mirror').each(function() { 427 $(this).remove(); 428 }); 429 } 430 }); 431 432 433 434 function ParallaxDestroy(element, options) {} 435 436 437 // Parallax Plugin Definition 438 function Plugin(option) { 439 return this.each(function () { 440 var $this = $(this); 441 var options = typeof option == 'object' && option; 442 443 if (this == window || this == document || $this.is('body')) { 444 Parallax.configure(options); 445 } 446 else if (!$this.data('px.parallax')) { 447 options = $.extend({}, $this.data(), options); 448 $this.data('px.parallax', new Parallax(this, options)); 449 }else if($('body').hasClass('parallax-destroyed')){ 450 options = $.extend({}, $this.data(), options); 451 $this.data('px.parallax', new Parallax(this, options)); 452 $('body').removeClass('parallax-destroyed') 453 } 454 if (typeof option == 'string') { 455 Parallax[option](); 456 } 457 }) 458 }; 459 460 var old = $.fn.parallax; 461 462 $.fn.parallax = Plugin; 463 $.fn.parallax.Constructor = Parallax; 464 $.fn.parallax.destroy = Parallax.destroy; 465 $.fn.parallax.setup = Parallax.setup; 466 //$.fn.parallax_destroy = ParallaxDestroy; 467 468 469 // Parallax No Conflict 470 471 $.fn.parallax.noConflict = function () { 472 $.fn.parallax = old; 473 return this; 474 }; 475 476 477 // Parallax Data-API 478 479 $(document).on('ready.px.parallax.data-api', function () { 480 $('[data-parallax="scroll"]').parallax(); 481 }); 482 483 window.onbeforeunload = function() { 484 if (!$('body').hasClass('cms-frontend-toolbar-fallback-mode')) { 485 // Stop mousewheel when navigating away from the page 486 // mousewheel on OSX allows users to scroll on Chrome even when jquery events do not fire 487 $('body').bind("mousewheel.parallax", function() { 488 return false; 489 }); 490 // Remove mousewheel event after set amount of time 491 window.setTimeout(function() { 492 $('body').unbind("mousewheel.parallax"); 493 }, 5000); 494 } 495 //$('.parallax-mirror').fadeOut(150); 496 //$('body').addClass('device-handheld'); 497 //$('.parallax-loaded').removeClass('.parallax-loaded'); 498 //$('.hero-parallax-element').removeClass('hero-parallax-element'); 499 //$('body').css('overflow', 'hidden'); 500 } 501 502}(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.