PageSourceSearch

https://petersdrivein.com/cloud/global/js/parallax.js

js petersdrivein.com collected 2026-10-04 07:49:14 UTC 14,556 bytes, 411 lines download raw bytes

vendor: 14,516 bytes, lines 1-408
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(/(Android123)/)) {
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('body')) {
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                $.extend($this.data('px.parallax'), options);
380            }
381            if (typeof option == 'string') {
382                if (option == 'destroy') {
383                    Parallax.destroy(this);
384                } else {
385                    Parallax[option]();
386                }
387            }
388        });
389    }
390
391    var old = $.fn.parallax;
392
393    $.fn.parallax = Plugin;
394    $.fn.parallax.Constructor = Parallax;
395
396
397    // Parallax No Conflict
398
399    $.fn.parallax.noConflict = function () {
400        $.fn.parallax = old;
401        return this;
402    };
403
404
405    // Parallax Data-API
406
407    $(function () {
408        $('[data-parallax="scroll"]').parallax();
409    });
410
411}(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.