PageSourceSearch

https://bluehill.org/wp-content/themes/bho-theme-3/assets/js/bho-counter.js?ver=2.0.0

js bluehill.org collected 2026-09-24 09:40:33 UTC 1,977 bytes, 71 lines download raw bytes

1/**
2 * BHO Count-Up Animation
3 * Animates any element with class .bho-count-up and data-count="NNNNN"
4 * counting from 0 up to the final number with an ease-out effect.
5 */
6(function () {
7  'use strict';
8
9  function formatNumber(n) {
10    return Math.floor(n).toLocaleString('en-US');
11  }
12
13  function animateCounter(el) {
14    var target   = parseInt(el.getAttribute('data-count'), 10);
15    var duration = 2200; // ms — feel free to adjust
16    var start    = null;
17
18    // Ease-out cubic: fast at start, decelerates to final value
19    function easeOutCubic(t) {
20      return 1 - Math.pow(1 - t, 3);
21    }
22
23    function step(timestamp) {
24      if (!start) start = timestamp;
25      var elapsed  = timestamp - start;
26      var progress = Math.min(elapsed / duration, 1);
27      var eased    = easeOutCubic(progress);
28      var current  = target * eased;
29
30      el.textContent = formatNumber(current);
31
32      if (progress < 1) {
33        requestAnimationFrame(step);
34      } else {
35        // Ensure exact final value with correct formatting
36        el.textContent = formatNumber(target);
37      }
38    }
39
40    requestAnimationFrame(step);
41  }
42
43  // Use IntersectionObserver so counter only fires when visible
44  function initCounters() {
45    var els = document.querySelectorAll('.bho-count-up[data-count]');
46    if (!els.length) return;
47
48    if ('IntersectionObserver' in window) {
49      var observer = new IntersectionObserver(function (entries) {
50        entries.forEach(function (entry) {
51          if (entry.isIntersecting) {
52            animateCounter(entry.target);
53            observer.unobserve(entry.target);
54          }
55        });
56      }, { threshold: 0.3 });
57
58      els.forEach(function (el) { observer.observe(el); });
59    } else {
60      // Fallback: just animate immediately
61      els.forEach(animateCounter);
62    }
63  }
64
65  if (document.readyState === 'loading') {
66    document.addEventListener('DOMContentLoaded', initCounters);
67  } else {
68    initCounters();
69  }
70
71})();

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.