PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.11
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.11
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 / case-study / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.11, at blocks/case-study/frontend.js

78 lines 3.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 /* ── Utilities ─────────────────────────────────────────────────── */
3 function extractNumber(str) {
4 var m = (str || '').match(/[\d,]+\.?\d*/);
5 return m ? parseFloat(m[0].replace(/,/g,'')) : null;
6 }
7
8 function formatNumber(n, original) {
9 /* Preserve suffix/prefix from original string */
10 var hasDecimal = original.indexOf('.') !== -1;
11 var prefix = original.replace(/[\d,. ]+.*/, '');
12 var suffix = original.replace(/.*[\d.]+/, '');
13 if (hasDecimal) {
14 var decimals = (original.split('.')[1] || '').replace(/\D+/,'').length;
15 return prefix + n.toFixed(decimals) + suffix;
16 }
17 return prefix + Math.round(n).toLocaleString() + suffix;
18 }
19
20 function animateCount(el, originalText, duration) {
21 duration = duration || 1200;
22 var targetNum = extractNumber(originalText);
23 if (targetNum === null) return;
24 var start = null;
25 function step(ts) {
26 if (!start) start = ts;
27 var progress = Math.min((ts - start) / duration, 1);
28 var eased = 1 - Math.pow(1 - progress, 3); /* ease-out cubic */
29 el.textContent = formatNumber(eased * targetNum, originalText);
30 if (progress < 1) requestAnimationFrame(step);
31 else el.textContent = originalText;
32 }
33 requestAnimationFrame(step);
34 }
35
36 /* ── Init entrance + count-up ──────────────────────────────────── */
37 function initCaseStudy(wrapper) {
38 /* Staggered entrance for main sections */
39 var animEls = wrapper.querySelectorAll('.bkbg-cs-client-bar, .bkbg-cs-card, .bkbg-cs-metric, .bkbg-cs-quote, .bkbg-cs-cta-row');
40 animEls.forEach(function (el, i) {
41 el.style.opacity = '0';
42 el.style.transform = 'translateY(20px)';
43 el.style.transition = 'opacity 0.55s ease, transform 0.55s ease';
44 el.style.transitionDelay = (i * 80) + 'ms';
45 });
46
47 var io = new IntersectionObserver(function (entries, obs) {
48 entries.forEach(function (entry) {
49 if (!entry.isIntersecting) return;
50 obs.unobserve(entry.target);
51
52 var el = entry.target;
53 el.style.opacity = '1';
54 el.style.transform = 'none';
55
56 /* Count-up for metric values */
57 if (el.classList.contains('bkbg-cs-metric')) {
58 var valueEl = el.querySelector('.bkbg-cs-metric-value');
59 if (valueEl) {
60 var original = valueEl.textContent;
61 animateCount(valueEl, original, 1400);
62 }
63 }
64 });
65 }, { threshold: 0.25 });
66
67 animEls.forEach(function (el) { io.observe(el); });
68 }
69
70 function init() {
71 var wrappers = document.querySelectorAll('.bkbg-cs-wrapper');
72 wrappers.forEach(initCaseStudy);
73 }
74
75 if (document.readyState !== 'loading') { init(); }
76 else { document.addEventListener('DOMContentLoaded', init); }
77 })();
78