PageSourceSearch

https://pattaylorinc.com/js/scrollReveal.js

js pattaylorinc.com collected 2026-10-08 23:15:20 UTC 12,028 bytes, 412 lines download raw bytes

1/*
2                       _ _ _____                      _   _
3                      | | |  __ \                    | | (_)
4    ___  ___ _ __ ___ | | | |__) |_____   _____  __ _| |  _ ___
5   / __|/ __| '__/ _ \| | |  _  // _ \ \ / / _ \/ _` | | | / __|
6   \__ \ (__| | | (_) | | | | \ \  __/\ V /  __/ (_| | |_| \__ \
7   |___/\___|_|  \___/|_|_|_|  \_\___| \_/ \___|\__,_|_(_) |___/ v.0.1.3
8                                                        _/ |
9                                                       |__/
10
11    "Declarative on-scroll reveal animations."
12
13/*=============================================================================
14
15    scrollReveal.js was inspired by cbpScroller.js (c) 2014 Codrops.
16
17    Licensed under the MIT license.
18    http://www.opensource.org/licenses/mit-license.php
19
20=============================================================================*/
21
22/*! scrollReveal.js v0.1.3 (c) 2014 Julian Lloyd | MIT license */
23
24/*===========================================================================*/
25
26
27window.scrollReveal = (function (window) {
28
29  'use strict';
30
31  // generator (increments) for the next scroll-reveal-id
32  var nextId = 1;
33
34  /**
35   * RequestAnimationFrame polyfill
36   * @function
37   * @private
38   */
39  var requestAnimFrame = (function () {
40    return window.requestAnimationFrame ||
41      window.webkitRequestAnimationFrame ||
42      window.mozRequestAnimationFrame ||
43      function (callback) {
44        window.setTimeout(callback, 1000 / 60);
45    };
46  }());
47
48  function scrollReveal(options) {
49
50      this.options = this.extend(this.defaults, options);
51      this.docElem = this.options.elem;
52      this.styleBank = {};
53
54      if (this.options.init == true) this.init();
55  }
56
57  scrollReveal.prototype = {
58
59    defaults: {
60      after:   '0s',
61      enter:   'bottom',
62      move:    '24px',
63      over:    '0.66s',
64      easing:  'ease-in-out',
65      opacity: 0,
66      complete: function() {},
67
68  //  if 0, the element is considered in the viewport as soon as it enters
69  //  if 1, the element is considered in the viewport when it's fully visible
70      viewportFactor: 0.33,
71
72  // if false, animations occur only once
73  // if true, animations occur each time an element enters the viewport
74      reset: false,
75
76  // if true, scrollReveal.init() is automaticaly called upon instantiation
77      init: true,
78	  elem: window.document.documentElement
79    },
80
81    /*=============================================================================*/
82
83    init: function () {
84
85      this.scrolled = false;
86
87      var self = this;
88
89  //  Check DOM for the data-scrollReveal attribute
90  //  and initialize all found elements.
91      this.elems = Array.prototype.slice.call(this.docElem.querySelectorAll('[data-scroll-reveal]'));
92      this.elems.forEach(function (el, i) {
93
94    //  Capture original style attribute
95        var id = el.getAttribute("data-scroll-reveal-id");
96        if (!id) {
97            id = nextId++;
98            el.setAttribute("data-scroll-reveal-id", id);
99        }
100        if (!self.styleBank[id]) {
101          self.styleBank[id] = el.getAttribute('style');
102        }
103
104        self.update(el);
105      });
106
107      var scrollHandler = function (e) {
108        // No changing, exit
109        if (!self.scrolled) {
110          self.scrolled = true;
111          requestAnimFrame(function () {
112            self._scrollPage();
113          });
114        }
115      };
116
117      var resizeHandler = function () {
118
119    //  If we’re still waiting for settimeout, reset the timer.
120        if (self.resizeTimeout) {
121          clearTimeout(self.resizeTimeout);
122        }
123        function delayed() {
124          self._scrollPage();
125          self.resizeTimeout = null;
126        }
127        self.resizeTimeout = setTimeout(delayed, 200);
128      };
129
130      // captureScroll
131      if (this.docElem == window.document.documentElement) {
132			window.addEventListener('scroll', scrollHandler, false);
133			window.addEventListener('resize', resizeHandler, false);
134		}
135		else {
136			this.docElem.addEventListener('scroll', scrollHandler, false);
137		}
138    },
139
140    /*=============================================================================*/
141
142    _scrollPage: function () {
143        var self = this;
144
145        this.elems.forEach(function (el, i) {
146          self.update(el);
147        });
148        this.scrolled = false;
149    },
150
151    /*=============================================================================*/
152
153    parseLanguage: function (el) {
154
155  //  Splits on a sequence of one or more commas or spaces.
156      var words = el.getAttribute('data-scroll-reveal').split(/[, ]+/),
157          parsed = {};
158
159      function filter (words) {
160        var ret = [],
161
162            blacklist = [
163              "from",
164              "the",
165              "and",
166              "then",
167              "but",
168              "with"
169            ];
170
171        words.forEach(function (word, i) {
172          if (blacklist.indexOf(word) > -1) {
173            return;
174          }
175          ret.push(word);
176        });
177
178        return ret;
179      }
180
181      words = filter(words);
182
183      words.forEach(function (word, i) {
184
185        switch (word) {
186          case "enter":
187            parsed.enter = words[i + 1];
188            return;
189
190          case "after":
191            parsed.after = words[i + 1];
192            return;
193
194          case "wait":
195            parsed.after = words[i + 1];
196            return;
197
198          case "move":
199            parsed.move = words[i + 1];
200            return;
201
202          case "ease":
203            parsed.move = words[i + 1];
204            parsed.ease = "ease";
205            return;
206
207          case "ease-in":
208            parsed.move = words[i + 1];
209            parsed.easing = "ease-in";
210            return;
211
212          case "ease-in-out":
213            parsed.move = words[i + 1];
214            parsed.easing = "ease-in-out";
215            return;
216
217          case "ease-out":
218            parsed.move = words[i + 1];
219            parsed.easing = "ease-out";
220            return;
221
222          case "over":
223            parsed.over = words[i + 1];
224            return;
225
226          default:
227            return;
228        }
229      });
230
231      return parsed;
232    },
233
234
235    /*=============================================================================*/
236
237    update: function (el) {
238
239      var that = this;
240      var css   = this.genCSS(el);
241      var style = this.styleBank[el.getAttribute("data-scroll-reveal-id")];
242
243      if (style != null) style += ";"; else style = "";
244
245      if (!el.getAttribute('data-scroll-reveal-initialized')) {
246        el.setAttribute('style', style + css.initial);
247        el.setAttribute('data-scroll-reveal-initialized', true);
248      }
249
250      if (!this.isElementInViewport(el, this.options.viewportFactor)) {
251        if (this.options.reset) {
252          el.setAttribute('style', style + css.initial + css.reset);
253        }
254        return;
255      }
256
257      if (el.getAttribute('data-scroll-reveal-complete')) return;
258
259      if (this.isElementInViewport(el, this.options.viewportFactor)) {
260        el.setAttribute('style', style + css.target + css.transition);
261    //  Without reset enabled, we can safely remove the style tag
262    //  to prevent CSS specificy wars with authored CSS.
263        if (!this.options.reset) {
264          setTimeout(function () {
265            if (style != "") {
266              el.setAttribute('style', style);
267            } else {
268              el.removeAttribute('style');
269            }
270            el.setAttribute('data-scroll-reveal-complete',true);
271            that.options.complete(el);
272          }, css.totalDuration);
273        }
274      return;
275      }
276    },
277
278    /*=============================================================================*/
279
280    genCSS: function (el) {
281      var parsed = this.parseLanguage(el),
282          enter,
283          axis;
284
285      if (parsed.enter) {
286
287        if (parsed.enter == "top" || parsed.enter == "bottom") {
288          enter = parsed.enter;
289          axis = "y";
290        }
291
292        if (parsed.enter == "left" || parsed.enter == "right") {
293          enter = parsed.enter;
294          axis = "x";
295        }
296
297      } else {
298
299        if (this.options.enter == "top" || this.options.enter == "bottom") {
300          enter = this.options.enter
301          axis = "y";
302        }
303
304        if (this.options.enter == "left" || this.options.enter == "right") {
305          enter = this.options.enter
306          axis = "x";
307        }
308      }
309
310  //  After all values are parsed, let’s make sure our our
311  //  pixel distance is negative for top and left entrances.
312  //
313  //  ie. "move 25px from top" starts at 'top: -25px' in CSS.
314
315      if (enter == "top" || enter == "left") {
316        if (parsed.move) {
317          parsed.move = "-" + parsed.move;
318        }
319        else {
320          parsed.move = "-" + this.options.move;
321        }
322      }
323
324      var dist    = parsed.move    || this.options.move,
325          dur     = parsed.over    || this.options.over,
326          delay   = parsed.after   || this.options.after,
327          easing  = parsed.easing  || this.options.easing,
328          opacity = parsed.opacity || this.options.opacity;
329
330      var transition = "-webkit-transition: -webkit-transform " + dur + " " + easing + " " + delay + ",  opacity " + dur + " " + easing + " " + delay + ";" +
331                               "transition: transform " + dur + " " + easing + " " + delay + ", opacity " + dur + " " + easing + " " + delay + ";" +
332                      "-webkit-perspective: 1000;" +
333              "-webkit-backface-visibility: hidden;";
334
335  //  The same as transition, but removing the delay for elements fading out.
336      var reset = "-webkit-transition: -webkit-transform " + dur + " " + easing + " 0s,  opacity " + dur + " " + easing + " " + delay + ";" +
337                          "transition: transform " + dur + " " + easing + " 0s,  opacity " + dur + " " + easing + " " + delay + ";" +
338                 "-webkit-perspective: 1000;" +
339         "-webkit-backface-visibility: hidden;";
340
341      var initial = "-webkit-transform: translate" + axis + "(" + dist + ");" +
342                            "transform: translate" + axis + "(" + dist + ");" +
343                              "opacity: " + opacity + ";";
344
345      var target = "-webkit-transform: translate" + axis + "(0);" +
346                           "transform: translate" + axis + "(0);" +
347                             "opacity: 1;";
348      return {
349        transition: transition,
350        initial: initial,
351        target: target,
352        reset: reset,
353        totalDuration: ((parseFloat(dur) + parseFloat(delay)) * 1000)
354      };
355    },
356
357    getViewportH : function () {
358      var client = this.docElem['clientHeight'],
359        inner = window['innerHeight'];
360
361      if (this.docElem == window.document.documentElement)
362                return (client < inner) ? inner : client;
363            else
364                return client;
365    },
366
367    getOffset : function(el) {
368      var offsetTop = 0,
369          offsetLeft = 0;
370
371      do {
372        if (!isNaN(el.offsetTop)) {
373          offsetTop += el.offsetTop;
374        }
375        if (!isNaN(el.offsetLeft)) {
376          offsetLeft += el.offsetLeft;
377        }
378      } while (el = el.offsetParent)
379
380      return {
381        top: offsetTop,
382        left: offsetLeft
383      }
384    },
385
386    isElementInViewport : function(el, h) {
387      var scrolled = this.docElem.scrollTop + this.docElem.offsetTop;
388		if (this.docElem == window.document.documentElement)scrolled = window.pageYOffset;
389		var
390			viewed = scrolled + this.getViewportH(),
391          elH = el.offsetHeight,
392          elTop = this.getOffset(el).top,
393          elBottom = elTop + elH,
394          h = h || 0;
395
396      return (elTop + elH * h) <= viewed
397          && (elBottom) >= scrolled
398          || (el.currentStyle? el.currentStyle : window.getComputedStyle(el, null)).position == 'fixed';
399    },
400
401    extend: function (a, b){
402      for (var key in b) {
403        if (b.hasOwnProperty(key)) {
404          a[key] = b[key];
405        }
406      }
407      return a;
408    }
409  }; // end scrollReveal.prototype
410
411  return scrollReveal;
412})(window);

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.