PageSourceSearch

https://www.ehs.com/wp-content/themes/velocity_ehs/blocks/stats/js/stats-script.js?ver=1776784786

js ehs.com collected 2026-10-09 21:39:10 UTC 3,248 bytes, 94 lines download raw bytes

1(function() {
2    'use strict';
3
4    function parseStatText(text) {
5        var match = text.match(/^(\D*)([\d,.]+)(.*)$/);
6        if (!match) return null;
7        var prefix = match[1];
8        var numStr = match[2];
9        var suffix = match[3];
10        var cleanNum = numStr.replace(/,/g, '');
11        var target = parseFloat(cleanNum);
12        if (isNaN(target)) return null;
13        var hasComma = numStr.indexOf(',') !== -1;
14        var decimalMatch = cleanNum.match(/\.(\d+)$/);
15        var decimals = decimalMatch ? decimalMatch[1].length : 0;
16        return {
17            prefix: prefix,
18            target: target,
19            suffix: suffix,
20            decimals: decimals,
21            hasComma: hasComma,
22            original: text
23        };
24    }
25
26    function formatNumber(value, decimals, hasComma) {
27        if (decimals > 0) {
28            var fixed = value.toFixed(decimals);
29            if (hasComma) {
30                var parts = fixed.split('.');
31                return Number(parts[0]).toLocaleString() + '.' + parts[1];
32            }
33            return fixed;
34        }
35        var intVal = Math.floor(value);
36        return hasComma ? intVal.toLocaleString() : intVal.toString();
37    }
38
39    function animateStat(el, parsed, duration) {
40        var startTime = performance.now();
41        function tick(now) {
42            var elapsed = now - startTime;
43            var progress = Math.min(elapsed / duration, 1);
44            var eased = 1 - Math.pow(1 - progress, 3);
45            if (progress >= 1) {
46                el.textContent = parsed.original;
47                return;
48            }
49            var current = parsed.target * eased;
50            el.textContent = parsed.prefix + formatNumber(current, parsed.decimals, parsed.hasComma) + parsed.suffix;
51            requestAnimationFrame(tick);
52        }
53        requestAnimationFrame(tick);
54    }
55
56    function startCountup(el) {
57        if (el.dataset.countupDone === 'true') return;
58        var text = el.textContent.trim();
59        var parsed = parseStatText(text);
60        if (!parsed) return;
61        el.dataset.countupDone = 'true';
62        el.textContent = parsed.prefix + formatNumber(0, parsed.decimals, parsed.hasComma) + parsed.suffix;
63        animateStat(el, parsed, 1500);
64    }
65
66    function init() {
67        var stats = document.querySelectorAll('.stats .stat-item .display');
68        if (!stats.length) return;
69
70        if ('IntersectionObserver' in window) {
71            var observer = new IntersectionObserver(function(entries) {
72                entries.forEach(function(entry) {
73                    if (entry.isIntersecting) {
74                        startCountup(entry.target);
75                        observer.unobserve(entry.target);
76                    }
77                });
78            }, { threshold: 0.3 });
79            stats.forEach(function(el) {
80                if (el.dataset.countupObserved === 'true') return;
81                el.dataset.countupObserved = 'true';
82                observer.observe(el);
83            });
84        } else {
85            stats.forEach(startCountup);
86        }
87    }
88
89    if (document.readyState === 'loading') {
90        document.addEventListener('DOMContentLoaded', init);
91    } else {
92        init();
93    }
94})();

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.