PageSourceSearch

https://www.ironwifi.com/js/scroll-reveal.js

js ironwifi.com collected 2026-10-03 19:48:54 UTC 4,673 bytes, 105 lines download raw bytes

1/**
2 * IronWiFi Scroll Reveal — lightweight IntersectionObserver animations
3 * ~3KB, no dependencies, progressive enhancement
4 * Usage: add data-reveal="up|fade|stagger|steps" to elements
5 *        add data-counter to number elements for count-up animation
6 */
7(function() {
8  'use strict';
9
10  // Respect reduced motion preference
11  if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
12
13  // Add base hidden styles via JS (progressive enhancement: no JS = everything visible)
14  var style = document.createElement('style');
15  style.textContent = [
16    '[data-reveal]{opacity:0;transition:opacity 0.7s ease-out,transform 0.7s ease-out}',
17    '[data-reveal="up"]{transform:translateY(30px)}',
18    '[data-reveal="fade"]{transform:none}',
19    '[data-reveal].revealed{opacity:1!important;transform:translateY(0)!important}',
20    '[data-reveal="stagger"]>*{opacity:0;transform:translateY(20px);transition:opacity 0.5s ease-out,transform 0.5s ease-out}',
21    '[data-reveal="stagger"].revealed>*{opacity:1;transform:translateY(0)}',
22    '[data-reveal="stagger"].revealed>*:nth-child(1){transition-delay:0ms}',
23    '[data-reveal="stagger"].revealed>*:nth-child(2){transition-delay:100ms}',
24    '[data-reveal="stagger"].revealed>*:nth-child(3){transition-delay:200ms}',
25    '[data-reveal="stagger"].revealed>*:nth-child(4){transition-delay:300ms}',
26    '[data-reveal="stagger"].revealed>*:nth-child(5){transition-delay:400ms}',
27    '[data-reveal="stagger"].revealed>*:nth-child(6){transition-delay:500ms}',
28    '[data-reveal="stagger"].revealed>*:nth-child(7){transition-delay:600ms}',
29    '[data-reveal="stagger"].revealed>*:nth-child(8){transition-delay:700ms}',
30    '[data-reveal="steps"] .pp-step-number,[data-reveal="steps"] .pp-journey-icon{opacity:0;transform:scale(0.5);transition:opacity 0.4s ease-out,transform 0.4s ease-out}',
31    '[data-reveal="steps"].revealed .pp-step-number,[data-reveal="steps"].revealed .pp-journey-icon{opacity:1;transform:scale(1)}',
32    '[data-reveal="steps"].revealed *:nth-child(1) .pp-step-number,[data-reveal="steps"].revealed *:nth-child(1) .pp-journey-icon{transition-delay:0s}',
33    '[data-reveal="steps"].revealed *:nth-child(2) .pp-step-number,[data-reveal="steps"].revealed *:nth-child(2) .pp-journey-icon{transition-delay:0.3s}',
34    '[data-reveal="steps"].revealed *:nth-child(3) .pp-step-number,[data-reveal="steps"].revealed *:nth-child(3) .pp-journey-icon{transition-delay:0.6s}',
35    '[data-reveal="steps"].revealed *:nth-child(4) .pp-step-number,[data-reveal="steps"].revealed *:nth-child(4) .pp-journey-icon{transition-delay:0.9s}'
36  ].join('\n');
37  document.head.appendChild(style);
38
39  // Scroll reveal observer
40  var revealObserver = new IntersectionObserver(function(entries) {
41    entries.forEach(function(entry) {
42      if (entry.isIntersecting) {
43        entry.target.classList.add('revealed');
44        revealObserver.unobserve(entry.target);
45      }
46    });
47  }, { threshold: 0.15, rootMargin: '0px 0px -40px 0px' });
48
49  document.querySelectorAll('[data-reveal]').forEach(function(el) {
50    // Immediately reveal elements already in viewport (no animation for above-fold)
51    var rect = el.getBoundingClientRect();
52    if (rect.top < window.innerHeight && rect.bottom > 0) {
53      el.classList.add('revealed');
54    } else {
55      revealObserver.observe(el);
56    }
57  });
58
59  // Counter animation
60  function animateCounter(el) {
61    var text = el.textContent.trim();
62    var match = text.match(/^([<>]?)(\d+(?:\.\d+)?)(.*)/);
63    if (!match) return;
64
65    var prefix = match[1];
66    var target = parseFloat(match[2]);
67    var suffix = match[3];
68    var isFloat = match[2].indexOf('.') !== -1;
69    var decimals = isFloat ? match[2].split('.')[1].length : 0;
70    var duration = 1500;
71    var start = performance.now();
72
73    function easeOutExpo(t) {
74      return t === 1 ? 1 : 1 - Math.pow(2, -10 * t);
75    }
76
77    function tick(now) {
78      var elapsed = now - start;
79      var progress = Math.min(elapsed / duration, 1);
80      var eased = easeOutExpo(progress);
81      var current = eased * target;
82
83      el.textContent = prefix + (isFloat ? current.toFixed(decimals) : Math.round(current)) + suffix;
84
85      if (progress < 1) {
86        requestAnimationFrame(tick);
87      }
88    }
89
90    requestAnimationFrame(tick);
91  }
92
93  var counterObserver = new IntersectionObserver(function(entries) {
94    entries.forEach(function(entry) {
95      if (entry.isIntersecting) {
96        animateCounter(entry.target);
97        counterObserver.unobserve(entry.target);
98      }
99    });
100  }, { threshold: 0.5 });
101
102  document.querySelectorAll('[data-counter]').forEach(function(el) {
103    counterObserver.observe(el);
104  });
105})();

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.