PluginProbe ʕ •ᴥ•ʔ
FrontBlocks for Gutenberg/GeneratePress / trunk
FrontBlocks for Gutenberg/GeneratePress vtrunk
trunk 0.2.0 0.2.1 0.2.2 0.2.3 0.2.4 0.2.5 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.1.0 1.2.0 1.2.1 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 ci-artifacts
frontblocks / assets / counter / frontblocks-counter-runtime.js
frontblocks / assets / counter Last commit date
frontblocks-counter-option.jsx 1 month ago frontblocks-counter-runtime.js 4 months ago frontblocks-counter.css 8 months ago frontblocks-counter.js 1 month ago
frontblocks-counter-runtime.js
87 lines
1 const COUNTER_CLASS = 'frontblocks-counter-active';
2
3 document.addEventListener('DOMContentLoaded', function() {
4 const counterElements = document.querySelectorAll(`.${COUNTER_CLASS}`);
5
6 if (counterElements.length === 0) return;
7
8 const runCounterAnimation = (element) => {
9 if (element.classList.contains('count-up-animated')) {
10 return;
11 }
12
13 const originalText = element.getAttribute('data-counter-target');
14 if (!originalText) return;
15
16 const animationDuration = parseInt(element.getAttribute('data-counter-duration'), 10) || 2000;
17 const customPrefix = element.getAttribute('data-counter-prefix') || '';
18 const customSuffix = element.getAttribute('data-counter-suffix') || '';
19 const startNumberAttr = element.getAttribute('data-counter-start') || '0';
20
21 element.setAttribute('data-original-text', originalText);
22
23 const prefix = customPrefix || '';
24
25 let numberString = originalText;
26
27 const numberMatch = numberString.match(/[\d\.,]+/);
28 if (!numberMatch) return;
29
30 let targetString = numberMatch[0].replace(/[^0-9]/g, '');
31 const target = parseInt(targetString, 10);
32
33 if (isNaN(target)) return;
34
35 const startValue = parseInt(startNumberAttr.replace(/[^0-9]/g, ''), 10) || 0;
36 let current = startValue;
37 const interval = 10;
38 const steps = animationDuration / interval;
39 const stepValue = (target - startValue) / steps;
40
41 const timer = setInterval(() => {
42 current += stepValue;
43
44 if (current >= target) {
45 current = target;
46 clearInterval(timer);
47 element.classList.add('count-up-animated');
48 }
49
50 element.textContent = prefix + Math.floor(current).toLocaleString('en-US') + customSuffix;
51 }, interval);
52 };
53
54 const observerOptions = {
55 root: null,
56 rootMargin: '0px',
57 threshold: 0.5
58 };
59
60 const observer = new IntersectionObserver((entries, observer) => {
61 entries.forEach(entry => {
62 if (entry.isIntersecting) {
63 const element = entry.target;
64
65 if (!element.classList.contains('count-up-animated')) {
66 runCounterAnimation(element);
67 }
68
69 observer.unobserve(element);
70 }
71 });
72 }, observerOptions);
73
74 counterElements.forEach(counter => {
75 const fullTargetText = counter.getAttribute('data-counter-target');
76 if (!fullTargetText) return;
77
78 const customPrefix = counter.getAttribute('data-counter-prefix') || '';
79 const customSuffix = counter.getAttribute('data-counter-suffix') || '';
80 const startNumberAttr = counter.getAttribute('data-counter-start') || '0';
81 const startValue = parseInt(startNumberAttr.replace(/[^0-9]/g, ''), 10) || 0;
82
83 counter.textContent = customPrefix + startValue.toLocaleString('en-US') + customSuffix;
84
85 observer.observe(counter);
86 });
87 });