PageSourceSearch

https://proofed.co.uk/wp-content/themes/proofed-v2/static/js/figures.js

js proofed.co.uk collected 2026-10-01 15:58:33 UTC 2,442 bytes, 64 lines download raw bytes

1/**
2 * Figures block — count each number up from 0 when it scrolls into view.
3 *
4 * SEO / progressive enhancement: the real, final number is always in the HTML.
5 * We only touch it here — and only when the element enters the viewport, so bots,
6 * no-JS users and reduced-motion users always read the correct value, never "0".
7 */
8(function () {
9    'use strict';
10
11    var counters = document.querySelectorAll('.js-figure-count');
12    if (!counters.length) return;
13
14    var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
15    if (reduceMotion || !('IntersectionObserver' in window) || !window.requestAnimationFrame) {
16        return; // leave the final numbers untouched
17    }
18
19    var DURATION = 1600;
20
21    function animate(el) {
22        var raw = el.getAttribute('data-value') || el.textContent;
23        var parts = raw.match(/^(\D*)(\d+(?:[.,]\d+)*)(.*)$/);
24        if (!parts) return; // no number to animate — leave as is
25
26        var prefix = parts[1];
27        var numStr = parts[2];
28        var suffix = parts[3];
29        var grouped = numStr.indexOf(',') > -1;
30        var dotIndex = numStr.lastIndexOf('.');
31        var decimals = (!grouped && dotIndex > -1) ? numStr.length - dotIndex - 1 : 0;
32        var target = parseFloat(numStr.replace(/,/g, ''));
33        if (isNaN(target)) return;
34
35        function format(n) {
36            var body = grouped ? Math.round(n).toLocaleString('en-US') : n.toFixed(decimals);
37            return prefix + body + suffix;
38        }
39
40        var startTime = null;
41        function tick(now) {
42            if (startTime === null) startTime = now;
43            var progress = Math.min((now - startTime) / DURATION, 1);
44            var eased = 1 - Math.pow(1 - progress, 3); // easeOutCubic
45            if (progress < 1) {
46                el.textContent = format(target * eased);
47                window.requestAnimationFrame(tick);
48            } else {
49                el.textContent = raw; // guarantee the exact final value
50            }
51        }
52        window.requestAnimationFrame(tick);
53    }
54
55    var observer = new IntersectionObserver(function (entries) {
56        entries.forEach(function (entry) {
57            if (!entry.isIntersecting) return;
58            observer.unobserve(entry.target);
59            animate(entry.target);
60        });
61    }, { threshold: 0.35 });
62
63    counters.forEach(function (el) { observer.observe(el); });
64})();

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.