PageSourceSearch

https://phodu.club/fixes/elementor-counters.js?v=2026080401

js phodu.club collected 2026-09-25 11:56:16 UTC 3,575 bytes, 114 lines download raw bytes

1/**
2 * Elementor counter widget fallback.
3 *
4 * Elementor ships the counter handler in a lazily imported webpack chunk
5 * (l.<hash>.bundle.min.js) that is not part of the mirrored plugin assets, so
6 * the import 404s and `.elementor-counter-number` spans stay empty. This fills
7 * them from data-to-value and counts up the first time they scroll into view.
8 */
9(function () {
10  var SELECTOR = "span.elementor-counter-number[data-to-value]";
11  var DONE_ATTR = "data-pc-counter";
12
13  var prefersReducedMotion =
14    window.matchMedia &&
15    window.matchMedia("(prefers-reduced-motion: reduce)").matches;
16
17  function decimalsOf(value) {
18    var dot = value.indexOf(".");
19    return dot === -1 ? 0 : value.length - dot - 1;
20  }
21
22  function format(value, decimals, delimiter) {
23    var text = value.toFixed(decimals);
24    if (!delimiter) return text;
25    var parts = text.split(".");
26    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, delimiter);
27    return parts.join(".");
28  }
29
30  function animate(el, from, to, decimals, delimiter, duration) {
31    var start = 0;
32
33    function frame(now) {
34      if (!start) start = now;
35      var progress = Math.min((now - start) / duration, 1);
36      // jQuery "swing" easing, matching Elementor's numerator default.
37      var eased = 0.5 - Math.cos(progress * Math.PI) / 2;
38      el.textContent = format(from + (to - from) * eased, decimals, delimiter);
39      if (progress < 1) requestAnimationFrame(frame);
40    }
41
42    requestAnimationFrame(frame);
43  }
44
45  function prepare(el) {
46    if (el.hasAttribute(DONE_ATTR)) return null;
47    var raw = (el.getAttribute("data-to-value") || "").trim();
48    var to = parseFloat(raw);
49    if (!raw || isNaN(to)) return null;
50
51    el.setAttribute(DONE_ATTR, "1");
52
53    var from = parseFloat(el.getAttribute("data-from-value"));
54    var duration = parseInt(el.getAttribute("data-duration"), 10);
55    var config = {
56      el: el,
57      from: isNaN(from) ? 0 : from,
58      to: to,
59      decimals: decimalsOf(raw),
60      delimiter: el.getAttribute("data-delimiter") || "",
61      duration: isNaN(duration) || duration <= 0 ? 2000 : duration,
62    };
63
64    // Show the final value straight away; the count-up (below) only replaces it
65    // once we know the element is on screen, so a stalled observer or a hidden
66    // ancestor can never leave the number blank.
67    el.textContent = format(to, config.decimals, config.delimiter);
68    return config;
69  }
70
71  function init() {
72    var counters = [];
73    var nodes = document.querySelectorAll(SELECTOR);
74    for (var i = 0; i < nodes.length; i++) {
75      var config = prepare(nodes[i]);
76      if (config) counters.push(config);
77    }
78
79    if (!counters.length || prefersReducedMotion) return;
80    if (!("IntersectionObserver" in window) || !window.requestAnimationFrame) {
81      return;
82    }
83
84    var observer = new IntersectionObserver(
85      function (entries) {
86        entries.forEach(function (entry) {
87          if (!entry.isIntersecting) return;
88          observer.unobserve(entry.target);
89          var config = entry.target.pcCounterConfig;
90          animate(
91            config.el,
92            config.from,
93            config.to,
94            config.decimals,
95            config.delimiter,
96            config.duration,
97          );
98        });
99      },
100      { threshold: 0.25 },
101    );
102
103    counters.forEach(function (config) {
104      config.el.pcCounterConfig = config;
105      observer.observe(config.el);
106    });
107  }
108
109  if (document.readyState === "loading") {
110    document.addEventListener("DOMContentLoaded", init);
111  } else {
112    init();
113  }
114})();

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.