PageSourceSearch

https://www.izbori.hr/site/js/scrollreveal.js

js izbori.hr collected 2026-09-24 18:31:35 UTC 34,472 bytes, 947 lines download raw bytes

1
2(function(root, factory) {
3  if (typeof define === 'function' && define.amd) {
4    define(factory);
5  } else if (typeof exports === 'object') {
6    module.exports = factory(require, exports, module);
7  } else {
8    root.ScrollReveal = factory();
9  }
10}(this, function(require, exports, module) {
11
12
13/////    /////    /////    /////
14/////    /////    /////    /////
15/////    /////    /////    /////
16/////    /////    /////    /////
17/////             /////    /////
18/////             /////    /////
19/////    /////    /////    /////
20/////    /////    /////    /////
21         /////    /////
22         /////    /////
23/////    /////    /////    /////
24/////    /////    /////    /////
25/////    /////    /////    /////
26/////    /////    /////    /////
27
28/**
29 * ScrollReveal
30 * ------------
31 * Version : 3.1.4
32 * Website : scrollrevealjs.org
33 * Repo    : github.com/jlmakes/scrollreveal.js
34 * Author  : Julian Lloyd (@jlmakes)
35 */
36
37;(function() {
38    'use strict';
39
40    var
41        sr,
42        Tools,
43        _requestAnimationFrame;
44
45    this.ScrollReveal = (function() {
46
47        /**
48         * Configuration
49         * -------------
50         * This object signature can be passed directly to the ScrollReveal constructor,
51         * or as the second argument of the `reveal()` method.
52         */
53
54        ScrollReveal.prototype.defaults = {
55
56            //            'bottom', 'left', 'top', 'right'
57            origin      : 'bottom',
58
59            //            Can be any valid CSS distance, e.g. '5rem', '10%', '20vw', etc.
60            distance    : '20px',
61
62            //            Time in milliseconds.
63            duration    : 500,
64            delay       : 0,
65
66            //            Starting angles in degrees, will transition from these values to 0 in all axes.
67            rotate      : { x: 0, y: 0, z: 0 },
68
69            //            Starting opacity value, before transitioning to the computed opacity.
70            opacity     : 0,
71
72            //            Starting scale value, will transition from this value to 1
73            scale       : 0.9,
74
75            //            Accepts any valid CSS easing, e.g. 'ease', 'ease-in-out', 'linear', etc.
76            easing      : 'cubic-bezier(0.6, 0.2, 0.1, 1)',
77
78            //            When null, `<html>` is assumed to be the reveal container. You can pass a
79            //            DOM node as a custom container, e.g. document.querySelector('.fooContainer')
80            //            or a selector, e.g. '.fooContainer'
81            container   : null,
82
83            //            true/false to control reveal animations on mobile.
84            mobile      : true,
85
86            //            true:  reveals occur every time elements become visible
87            //            false: reveals occur once as elements become visible
88            reset       : false,
89
90            //            'always' — delay for all reveal animations
91            //            'once'   — delay only the first time reveals occur
92            //            'onload' - delay only for animations triggered by first load
93            useDelay    : 'always',
94
95            //            Change when an element is considered in the viewport. The default value
96            //            of 0.20 means 20% of an element must be visible for its reveal to occur.
97            viewFactor  : 0.2,
98
99            //            Pixel values that alter the container boundaries.
100            //            e.g. Set `{ top: 48 }`, if you have a 48px tall fixed toolbar.
101            //            --
102            //            Visual Aid: https://scrollrevealjs.org/assets/view
102offset.png
103            viewOffset  : { top: 0, right: 0, bottom: 0, left: 0 },
104
105            //            Callbacks that fire for each completed element reveal, and if
106            //            `config.reset = true`, for each completed element reset. When creating your
107            //            callbacks, remember they are passed the element’s DOM node that triggered
108            //            it as the first argument.
109            afterReveal : function(domEl) {},
110            afterReset  : function(domEl) {}
111        };
112
113
114
115        function ScrollReveal(config) {
116
117            // Support instantiation without the `new` keyword.
118            if (typeof this == 'undefined' || Object.getPrototypeOf(this) !== ScrollReveal.prototype) {
119                return new ScrollReveal(config)
120            }
121
122            sr = this; // Save reference to instance.
123            sr.tools = new Tools(); // *required utilities
124
125            if (sr.isSupported()) {
126
127                sr.tools.extend(sr.defaults, config || {});
128
129                _resolveContainer(sr.defaults);
130
131                sr.store = {
132                    elements   : {},
133                    containers : []
134                };
135
136                sr.sequences   = {};
137                sr.history     = [];
138                sr.uid         = 0;
139                sr.initialized = false;
140            }
141
142            // Note: IE9 only supports console if devtools are open.
143            else if (typeof console !== 'undefined' && console !== null) {
144                console.log('ScrollReveal is not supported in this browser.');
145            }
146
147            return sr
148        }
149
150
151
152        /**
153         * Check if client supports CSS Transform and CSS Transition.
154         * @return {boolean}
155         */
156        ScrollReveal.prototype.isSupported = function() {
157            var style = document.documentElement.style;
158            return 'WebkitTransition' in style && 'WebkitTransform' in style
159                || 'transition' in style && 'transform' in style
160        };
161
162
163
164        /**
165         * Creates a reveal set, a group of elements that will animate when they
166         * become visible. If [interval] is provided, a new sequence is created
167         * that will ensure elements reveal in the order they appear in the DOM.
168         *
169         * @param {string|Node} [selector] The element (node) or elements (selector) to animate.
170         * @param {Object}      [config]   Override the defaults for this reveal set.
171         * @param {number}      [interval] Time between sequenced element animations (milliseconds).
172         * @param {boolean}     [sync]     Used internally when updating reveals for async content.
173         *
174         * @return {Object} The current ScrollReveal instance.
175         */
176        ScrollReveal.prototype.reveal = function(selector, config, interval, sync) {
177
178            var
179                container,
180                elements,
181                elem,
182                elemId,
183                sequence,
184                sequenceId;
185
186            // Resolve container.
187            if (config && config.container) {
188                container = _resolveContainer(config);
189            } else {
190                container = sr.defaults.container;
191            }
192
193            // Let’s check to see if a DOM node was passed in as the first argument,
194            // otherwise query the container for all elements matching the selector.
195            if (sr.tools.isNode(selector)) {
196                elements = [selector];
197            } else {
198                elements = Array.prototype.slice.call(container.querySelectorAll(selector));
199            }
200
201            if (!elements.length) {
202                console.log('ScrollReveal: reveal on "'+ selector + '" failed, no elements found.');
203                return sr
204            }
205
206            // No custom configuration was passed, but a sequence interval instead.
207            // let’s shuffle things around to make sure everything works.
208            if (config && typeof config == 'number') {
209                interval = config;
210                config = {};
211            }
212
213            // Prepare a new sequence if an interval is passed.
214            if (interval && typeof interval == 'number') {
215                sequenceId = _nextUid();
216
217                sequence = sr.sequences[sequenceId] = {
218                    id       : sequenceId,
219                    interval : interval,
220                    elemIds  : [],
221                    active   : false
222                }
223            }
224
225            // Begin main loop to configure ScrollReveal elements.
226            for (var i = 0; i < elements.length; i++) {
227
228                // Check if the element has already been configured and grab it from the store.
229                elemId = elements[i].getAttribute('data-sr-id');
230                if (elemId) {
231                    elem = sr.store.elements[elemId];
232                }
233
234                // Otherwise, let’s do some basic setup.
235                else {
236                    elem = {
237                        id        : _nextUid(),
238                        domEl     : elements[i],
239                        seen      : false,
240                        revealing : false
241                    };
242                    elem.domEl.setAttribute('data-sr-id', elem.id);
243                }
244
245                // Sequence only setup
246                if (sequence) {
247
248                    elem.sequence = {
249                        id    : sequence.id,
250                        index : sequence.elemIds.length
251                    };
252
253                    sequence.elemIds.push(elem.id);
254                }
255
256                // New or existing element, it’s time to update its configuration, styles,
257                // and send the updates to our store.
258                _configure(elem, config || {});
259                _style(elem);
260                _updateStore(elem);
261
262                // We need to make sure elements are set to visibility: visible, even when
263                // on mobile and `config.mobile == false`, or if unsupported.
264                if (sr.tools.isMobile() && !elem.config.mobile || !sr.isSupported()) {
265                    elem.domEl.setAttribute('style', elem.styles.inline);
266                    elem.disabled = true;
267                }
268
269                // Otherwise, proceed normally.
270                else if (!elem.revealing) {
271                    elem.domEl.setAttribute('style',
272                        elem.styles.inline
273                      + elem.styles.transform.initial
274                    );
275                }
276            }
277
278            // Each `reveal()` is recorded so that when calling `sync()` while working
279            // with asynchronously loaded content, it can re-trace your steps but with
280            // all your new elements now in the DOM.
281
282            // Since `reveal()` is called internally by `sync()`, we don’t want to
283            // record or intiialize each reveal during syncing.
284            if (!sync && sr.isSupported()) {
285                _record(selector, config);
286
287                // We push initialization to the event queue using setTimeout, so that we can
288                // give ScrollReveal room to process all reveal calls before putting things into motion.
289                // --
290                // Philip Roberts - What the heck is the event loop anyway? (JSConf EU 2014)
291                // https://www.youtube.com/watch?v=8aGhZQkoFbQ
292                if (sr.initTimeout) {
293                    window.clearTimeout(sr.initTimeout);
294                }
295                sr.initTimeout = window.setTimeout(_init, 0);
296            }
297
298            return sr
299        };
300
301
302
303        /**
304         * Re-runs `reveal()` for each record stored in history, effectively capturing
305         * any content loaded asynchronously that matches existing reveal set selectors.
306         *
307         * @return {Object} The current ScrollReveal instance.
308         */
309        ScrollReveal.prototype.sync = function() {
310            if (sr.history.length && sr.isSupported()) {
311                for (var i = 0; i < sr.history.length; i++) {
312                    var record = sr.history[i];
313                    sr.reveal(record.selector, record.config, record.interval, true);
314                };
315                _init();
316            } else {
317                console.log('ScrollReveal: sync failed, no reveals found.');
318            }
319            return sr
320        };
321
322
323
324        /**
325         * Private Methods
326         * ---------------
327         * These methods remain accessible only to the ScrollReveal instance, even
328         * though they only "exist" during instantiation outside of the constructors scope.
329         * --
330         * http://stackoverflow.com/questions/111102/how-do-javascript-closures-work
331         */
332
333        function _resolveContainer(config) {
334            var container = config.container;
335
336            // Check if our container is defined by a selector.
337            if (container && typeof container == 'string') {
338                return config.container = window.document.querySelector(container);
339            }
340
341            // Check if our container is defined by a node.
342            else if (container && !sr.tools.isNode(container)) {
343                console.log('ScrollReveal: Invalid container provided, using <html> instead.');
344                config.container = null;
345            }
346
347            // Otherwise use <html> by default.
348            if (container == null) {
349                config.container = window.document.documentElement;
350            }
351
352            return config.container
353        }
354
355
356
357        /**
358         * A consistent way of creating unique IDs.
359         * @returns {number}
360         */
361        function _nextUid() {
362            return ++sr.uid;
363        }
364
365
366
367        function _configure(elem, config) {
368
369            // If the element hasn’t already been configured, let’s use a clone of the
370            // defaults extended by the configuration passed as the second argument.
371            if (!elem.config) {
372                elem.config = sr.tools.extendClone(sr.defaults, config);
373            }
374
375            // Otherwise, let’s use a clone of the existing element configuration extended
376            // by the configuration passed as the second argument.
377            else {
378                elem.config = sr.tools.extendClone(elem.config, config);
379            }
380
381            // Infer CSS Transform axis from origin string.
382            if (elem.config.origin === 'top' || elem.config.origin === 'bottom') {
383                elem.config.axis = 'Y';
384            } else {
385                elem.config.axis = 'X';
386            }
387
388            // Let’s make sure our our pixel distances are negative for top and left.
389            // e.g. config.origin = 'top' and config.distance = '25px' starts at `top: -25px` in CSS.
390            if (elem.config.origin === 'top' || elem.config.origin === 'left') {
391                elem.config.distance = '-' + elem.config.distance;
392            }
393        }
394
395
396
397        function _style(elem) {
398            var computed = window.getComputedStyle(elem.domEl);
399
400            if (!elem.styles) {
401                elem.styles = {
402                    transition : {},
403                    transform  : {},
404                    computed   : {}
405                };
406
407                // Capture any existing inline styles, and add our visibility override.
408                // --
409                // See section 4.2. in the Documentation:
410                // https://github.com/jlmakes/scrollreveal.js#42-improve-user-experience
411                elem.styles.inline  = elem.domEl.getAttribute('style') || '';
412                elem.styles.inline += '; visibility: visible; ';
413
414                // grab the elements existing opacity.
415                elem.styles.computed.opacity = computed.opacity;
416
417                // grab the elements existing transitions.
418                if (!computed.transition || computed.transition == 'all 0s ease 0s') {
419                    elem.styles.computed.transition = '';
420                } else {
421                    elem.styles.computed.transition = computed.transition + ', ';
422                }
423            }
424
425            // Create transition styles
426            elem.styles.transition.instant = _generateTransition(elem, 0);
427            elem.styles.transition.delayed = _generateTransition(elem, elem.config.delay);
428
429            // Generate transform styles, first with the webkit prefix.
430            elem.styles.transform.initial = ' -webkit-transform:';
431            elem.styles.transform.target  = ' -webkit-transform:';
432            _generateTransform(elem);
433
434            // And again without any prefix.
435            elem.styles.transform.initial += 'transform:';
436            elem.styles.transform.target  += 'transform:';
437            _generateTransform(elem);
438
439        }
440
441
442
443        function _generateTransition(elem, delay) {
444            var config = elem.config;
445
446            return '-webkit-transition: ' + elem.styles.computed.transition +
447                     '-webkit-transform ' + config.duration / 1000 + 's '
448                                          + config.easing + ' '
449                                          + delay / 1000 + 's, opacity '
450                                          + config.duration / 1000 + 's '
451                                          + config.easing + ' '
452                                          + delay / 1000 + 's; ' +
453
454                           'transition: ' + elem.styles.computed.transition +
455                             'transform ' + config.duration / 1000 + 's '
456                                          + config.easing + ' '
457                                          + delay / 1000 + 's, opacity '
458                                          + config.duration / 1000 + 's '
459                                          + config.easing + ' '
460                                          + delay / 1000 + 's; '
461        }
462
463
464
465        function _generateTransform(elem) {
466            var config    = elem.config;
467            var transform = elem.styles.transform;
468
469            if (parseInt(config.distance)) {
470                transform.initial += ' translate' + config.axis + '(' + config.distance + ')';
471                transform.target  += ' translate' + config.axis + '(0)';
472            }
473            if (config.scale) {
474                transform.initial += ' scale(' + config.scale + ')';
475                transform.target  += ' scale(1)';
476            }
477            if (config.rotate.x) {
478                transform.initial += ' rotateX(' + config.rotate.x + 'deg)';
479                transform.target  += ' rotateX(0)';
480            }
481            if (config.rotate.y) {
482                transform.initial += ' rotateY(' + config.rotate.y + 'deg)';
483                transform.target  += ' rotateY(0)';
484            }
485            if (config.rotate.z) {
486                transform.initial += ' rotateZ(' + config.rotate.z + 'deg)';
487                transform.target  += ' rotateZ(0)';
488            }
489            transform.initial += '; opacity: ' + config.opacity + ';';
490            transform.target  += '; opacity: ' + elem.styles.computed.opacity + ';';
491        }
492
493
494
495        function _updateStore(elem) {
496            var container = elem.config.container;
497
498            // If this element’s container isn’t already in the store, let’s add it.
499            if (container && sr.store.containers.indexOf(container) == -1) {
500                sr.store.containers.push(elem.config.container);
501            }
502
503            // Update the element stored with our new element.
504            sr.store.elements[elem.id] = elem;
505        };
506
507
508
509        function _record(selector, config, interval) {
510
511            // Save the `reveal()` arguments that triggered this `_record()` call, so we
512            // can re-trace our steps when calling the `sync()` method.
513            var record = {
514                selector : selector,
515                config   : config,
516                interval : interval
517            };
518            sr.history.push(record);
519        }
520
521
522
523        function _init() {
524            if (sr.isSupported()) {
525
526                // Initial animate call triggers valid reveal animations on first load.
527                // Subsequent animate calls are made inside the event handler.
528                _animate();
529
530                // Then we loop through all container nodes in the store and bind event
531                // listeners to each.
532                for (var i = 0; i < sr.store.containers.length; i++) {
533                    sr.store.containers[i].addEventListener('scroll', _handler);
534                    sr.store.containers[i].addEventListener('resize', _handler);
535                }
536
537                // Let’s also do a one-time binding of window event listeners.
538                if (!sr.initialized) {
539                    window.addEventListener('scroll', _handler);
540                    window.addEventListener('resize', _handler);
541                    sr.initialized = true;
542                }
543            }
544            return sr
545        }
546
547
548
549        function _handler() {
550            _requestAnimationFrame(_animate);
551        }
552
553
554
555        function _setActiveSequences() {
556
557            var
558                active,
559                elem,
560                elemId,
561                sequence;
562
563            // Loop through all sequences
564            sr.tools.forOwn(sr.sequences, function(sequenceId) {
565                sequence = sr.sequences[sequenceId];
566                active   = false;
567
568                // For each sequenced elemenet, let’s check visibility and if
569                // any are visible, set it’s sequence to active.
570                for (var i = 0; i < sequence.elemIds.length; i++) {
571                    elemId = sequence.elemIds[i]
572                    elem   = sr.store.elements[elemId];
573                    if (_isElemVisible(elem) && !active) {
574                        active = true;
575                    }
576                }
577
578                sequence.active = active;
579            });
580        }
581
582
583
584        function _animate() {
585
586            var
587                delayed,
588                elem;
589
590            _setActiveSequences();
591
592            // Loop through all elements in the store
593            sr.tools.forOwn(sr.store.elements, function(elemId) {
594
595                elem = sr.store.elements[elemId];
596                delayed = _shouldUseDelay(elem);
597
598                // Let’s see if we should reveal, and if so, whether to use delay.
599                if (_shouldReveal(elem)) {
600                    if (delayed) {
601                        elem.domEl.setAttribute('style',
602                            elem.styles.inline
603                          + elem.styles.transform.target
604                          + elem.styles.transition.delayed
605                        );
606                    } else {
607                        elem.domEl.setAttribute('style',
608                            elem.styles.inline
609                          + elem.styles.transform.target
610                          + elem.styles.transition.instant
611                        );
612                    }
613
614                    // Let’s queue the `afterReveal` callback and tag the element.
615                    _queueCallback('reveal', elem, delayed);
616                    elem.revealing = true;
617                    elem.seen = true;
618
619                    if (elem.sequence) {
620                        _queueNextInSequence(elem, delayed);
621                    }
622                }
623
624                // If we got this far our element shouldn’t reveal, but should it reset?
625                else if (_shouldReset(elem)) {
626                    elem.domEl.setAttribute('style',
627                        elem.styles.inline
628                      + elem.styles.transform.initial
629                      + elem.styles.transition.instant
630                    );
631                    _queueCallback('reset', elem);
632                    elem.revealing = false;
633                }
634            });
635        }
636
637
638
639        /**
640         * Sequence callback that triggers the next element.
641         */
642        function _queueNextInSequence(elem, delayed) {
643
644            var
645                elapsed  = 0,
646                delay    = 0,
647                sequence = sr.sequences[elem.sequence.id];
648
649            // We’re processing a sequenced element, so let's block other elements in this sequence.
650            sequence.blocked = true;
651
652            // Since we’re triggering animations a part of a sequence after animations on first load,
653            // we need to check for that condition and explicitly add the delay to our timer.
654            if (delayed && elem.config.useDelay == 'onload') {
655                delay = elem.config.delay;
656            }
657
658            // If a sequence timer is already running, capture the elapsed time and clear it.
659            if (elem.sequence.timer) {
660                elapsed = Math.abs(elem.sequence.timer.started - new Date());
661                window.clearTimeout(elem.sequence.timer);
662            }
663
664            // Start a new timer.
665            elem.sequence.timer = { started: new Date() };
666            elem.sequence.timer.clock = window.setTimeout(function() {
667
668                // Sequence interval has passed, so unblock the sequence and re-run the handler.
669                sequence.blocked = false;
670                elem.sequence.timer = null;
671                _handler();
672
673            }, Math.abs(sequence.interval) + delay - elapsed);
674        }
675
676
677
678        function _queueCallback(type, elem, delayed) {
679
680            var
681                elapsed  = 0,
682                duration = 0,
683                callback = 'after';
684
685            // Check which callback we’re working with.
686            switch (type) {
687
688                case 'reveal':
689                    duration = elem.config.duration;
690                    if (delayed) {
691                        duration += elem.config.delay;
692                    }
693                    callback += 'Reveal';
694                    break
695
696                case 'reset':
697                    duration = elem.config.duration;
698                    callback += 'Reset';
699                    break
700            }
701
702            // If a timer is already running, capture the elapsed time and clear it.
703            if (elem.timer) {
704                elapsed = Math.abs(elem.timer.started - new Date());
705                window.clearTimeout(elem.timer.clock);
706            }
707
708            // Start a new timer.
709            elem.timer = { started: new Date() };
710            elem.timer.clock = window.setTimeout(function() {
711
712                // The timer completed, so let’s fire the callback and null the timer.
713                elem.config[callback](elem.domEl);
714                elem.timer = null;
715
716            }, duration - elapsed);
717        }
718
719
720
721        function _shouldReveal(elem) {
722            if (elem.sequence) {
723                var sequence = sr.sequences[elem.sequence.id];
724                return sequence.active
725                    && !sequence.blocked
726                    && !elem.revealing
727                    && !elem.disabled
728            }
729            return _isElemVisible(elem)
730                && !elem.revealing
731                && !elem.disabled
732        }
733
734
735
736        function _shouldUseDelay(elem) {
737            var config = elem.config.useDelay;
738            return config === 'always'
739                || (config === 'onload' && !sr.initialized)
740                || (config === 'once' && !elem.seen)
741        }
742
743
744
745        function _shouldReset(elem) {
746            if (elem.sequence) {
747                var sequence = sr.sequences[elem.sequence.id];
748                return !sequence.active
749                    && elem.config.reset
750                    && elem.revealing
751                    && !elem.disabled
752            }
753            return !_isElemVisible(elem)
754                && elem.config.reset
755                && elem.revealing
756                && !elem.disabled
757        }
758
759
760
761        function _getContainer(container) {
762            return {
763                width  : container.clientWidth,
764                height : container.clientHeight
765            }
766        }
767
768
769
770        function _getScrolled(container) {
771
772            // Return the container scroll values, plus the its offset.
773            if (container && container !== window.document.documentElement) {
774                var offset = _getOffset(container);
775                return {
776                    x : container.scrollLeft + offset.left,
777                    y : container.scrollTop  + offset.top
778                }
779            }
780
781            // Otherwise, default to the window object’s scroll values.
782            else {
783                return {
784                    x : window.pageXOffset,
785                    y : window.pageYOffset
786                }
787            }
788        }
789
790
791
792        function _getOffset(domEl) {
793
794            var
795                offsetTop    = 0,
796                offsetLeft   = 0,
797
798                // Grab the element’s dimensions.
799                offsetHeight = domEl.offsetHeight,
800                offsetWidth  = domEl.offsetWidth;
801
802            // Now calculate the distance between the element and its parent, then
803            // again for the parent to its parent, and again etc... until we have the
804            // total distance of the element to the document’s top and left origin.
805            do {
806                if (!isNaN(domEl.offsetTop)) {
807                    offsetTop += domEl.offsetTop;
808                }
809                if (!isNaN(domEl.offsetLeft)) {
810                    offsetLeft += domEl.offsetLeft;
811                }
812            } while (domEl = domEl.offsetParent);
813
814            return {
815                top    : offsetTop,
816                left   : offsetLeft,
817                height : offsetHeight,
818                width  : offsetWidth
819            }
820        }
821
822
823
824        function _isElemVisible(elem) {
825
826            var
827                offset     = _getOffset(elem.domEl),
828                container  = _getContainer(elem.config.container),
829                scrolled   = _getScrolled(elem.config.container),
830                vF         = elem.config.viewFactor,
831
832                // Define the element geometry.
833                elemHeight = offset.height,
834                elemWidth  = offset.width,
835                elemTop    = offset.top,
836                elemLeft   = offset.left,
837                elemBottom = elemTop  + elemHeight,
838                elemRight  = elemLeft + elemWidth;
839
840            return confirmBounds() || isPositionFixed()
841
842            function confirmBounds() {
843
844                var
845                    // Define the element’s functional boundaries using its view factor.
846                    top        = elemTop    + elemHeight * vF,
847                    left       = elemLeft   + elemWidth  * vF,
848                    bottom     = elemBottom - elemHeight * vF,
849                    right      = elemRight  - elemWidth  * vF,
850
851                    // Define the container functional boundaries using its view offset.
852                    viewTop    = scrolled.y + elem.config.viewOffset.top,
853                    viewLeft   = scrolled.x + elem.config.viewOffset.left,
854                    viewBottom = scrolled.y - elem.config.viewOffset.bottom + container.height,
855                    viewRight  = scrolled.x - elem.config.viewOffset.right  + container.width;
856
857                return top    < viewBottom
858                    && bottom > viewTop
859                    && left   > viewLeft
860                    && right  < viewRight
861            }
862
863            function isPositionFixed() {
864                return (window.getComputedStyle(elem.domEl).position === 'fixed')
865            }
866        }
867
868
869
870        return ScrollReveal
871
872    })();
873
874
875    /**
876     * helper.tools.js
877     * ---------------
878     * Simple deep object extend, and a few other agnostic helper methods.
879     * gist: https://gist.github.com/jlmakes/9f104e3f1b4d86334987
880     */
881
882    Tools = (function() {
883
884        Tools.prototype.isObject = function(object) {
885            return object !== null && typeof object === 'object' && object.constructor == Object
886        };
887
888        Tools.prototype.isNode = function(object) {
889            return typeof Node === 'object'
890                ? object instanceof Node
891                : object && typeof object === 'object'
892                         && typeof object.nodeType === 'number'
893                         && typeof object.nodeName === 'string'
894        };
895
896        Tools.prototype.forOwn = function(object, callback) {
897            if (!this.isObject(object)) {
898                throw new TypeError('Expected "object", but received "' + typeof object + '".');
899            } else {
900                for (var property in object) {
901                    if (object.hasOwnProperty(property)) {
902                        callback(property);
903                    }
904                }
905            }
906        };
907
908        Tools.prototype.extend = function(target, source) {
909            this.forOwn(source, function(property) {
910                if (this.isObject(source[property])) {
911                    if (!target[property] || !this.isObject(target[property])) {
912                        target[property] = {};
913                    }
914                    this.extend(target[property], source[property]);
915                } else {
916                    target[property] = source[property];
917                }
918            }.bind(this));
919            return target
920        };
921
922        Tools.prototype.extendClone = function(target, source) {
923            return this.extend(this.extend({}, target), source)
924        };
925
926        Tools.prototype.isMobile = function() {
927            return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
928        };
929
930        function Tools() {};
931        return Tools
932
933    })();
934
935
936
937    _requestAnimationFrame = window.requestAnimationFrame       ||
938                             window.webkitRequestAnimationFrame ||
939                             window.mozRequestAnimationFrame;
940
941
942
943}).call(this);
944
945return this.ScrollReveal;
946
947}));

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.