PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / metric-cards / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/metric-cards/frontend.js

84 lines 2.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 'use strict';
3
4 /* ── Numeric count-up ── */
5 function parseValue(str) {
6 /* Extract leading/trailing non-numeric parts and the numeric core */
7 var match = str.match(/^([^0-9-]*)(-?[\d,\.]+)([^0-9]*)$/);
8 if (!match) return null;
9 return {
10 prefix: match[1],
11 number: parseFloat(match[2].replace(/,/g, '')),
12 suffix: match[3],
13 raw: match[2],
14 hasComma: match[2].indexOf(',') !== -1,
15 decimals: (match[2].split('.')[1] || '').length,
16 };
17 }
18
19 function formatNumber(n, info) {
20 var fixed = n.toFixed(info.decimals);
21 if (info.hasComma) {
22 var parts = fixed.split('.');
23 parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
24 fixed = parts.join('.');
25 }
26 return info.prefix + fixed + info.suffix;
27 }
28
29 function countUp(el, info, duration) {
30 var start = 0;
31 var end = info.number;
32 var startTime = null;
33 el.classList.add('bkbg-counting');
34
35 function step(ts) {
36 if (!startTime) startTime = ts;
37 var progress = Math.min((ts - startTime) / duration, 1);
38 /* Ease out */
39 var eased = 1 - Math.pow(1 - progress, 3);
40 el.textContent = formatNumber(start + (end - start) * eased, info);
41 if (progress < 1) {
42 requestAnimationFrame(step);
43 } else {
44 el.textContent = formatNumber(end, info);
45 el.classList.remove('bkbg-counting');
46 }
47 }
48 requestAnimationFrame(step);
49 }
50
51 function initCard(card) {
52 var valueEl = card.querySelector('.bkbg-metric-value');
53 if (!valueEl) return;
54 var info = parseValue(valueEl.textContent.trim());
55 if (!info || isNaN(info.number)) return;
56 countUp(valueEl, info, 1200);
57 }
58
59 function observeCards() {
60 var cards = document.querySelectorAll('.bkbg-metric-card');
61 if (!cards.length) return;
62
63 if ('IntersectionObserver' in window) {
64 var io = new IntersectionObserver(function (entries) {
65 entries.forEach(function (entry) {
66 if (entry.isIntersecting) {
67 io.unobserve(entry.target);
68 initCard(entry.target);
69 }
70 });
71 }, { threshold: 0.25 });
72 cards.forEach(function (card) { io.observe(card); });
73 } else {
74 cards.forEach(initCard);
75 }
76 }
77
78 if (document.readyState === 'loading') {
79 document.addEventListener('DOMContentLoaded', observeCards);
80 } else {
81 observeCards();
82 }
83 }());
84