# blockenberg/2.0.7/blocks/floating-stats/frontend.js

Blockenberg — 600+ Advanced Gutenberg Blocks &amp; AI Agent for WordPress Block Editor, version 2.0.7. 103 lines.

- Page: https://pluginprobe.com/plugins/blockenberg/2.0.7/code/blocks/floating-stats/frontend.js
- Raw: https://pluginprobe.com/plugins/blockenberg/2.0.7/raw/blocks/floating-stats/frontend.js
- Modified: 2026-03-06T12:32:40+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/blockenberg/2.0.7/code/blocks/floating-stats/frontend.js#L10-L20`.

```javascript
(function () {
    'use strict';

    // Floating Stats — card reveal + numeric count-up animation

    function parseNumber(str) {
        // Extract leading number from strings like "10,000+" or "99.9%" or "4.9"
        var clean = str.replace(/,/g, '').match(/[\d.]+/);
        return clean ? parseFloat(clean[0]) : null;
    }

    function formatNumber(num, original) {
        // Restore formatting similar to original
        var hasComma = original.indexOf(',') !== -1;
        var suffix = original.replace(/[\d,. ]/g, '');
        var prefix = '';
        // detect prefix like $ £ €
        var prefixMatch = original.match(/^[^0-9]*/);
        if (prefixMatch && prefixMatch[0]) prefix = prefixMatch[0];
        var formatted = hasComma ? num.toLocaleString('en-US', { maximumFractionDigits: 1 }) : (Number.isInteger(num) ? num.toString() : num.toFixed(1));
        return prefix + formatted + suffix;
    }

    function animateCountUp(el, duration) {
        var original = el.textContent.trim();
        var target = parseNumber(original);
        if (target === null || target === 0) return;

        var start = null;
        var startVal = 0;

        function step(timestamp) {
            if (!start) start = timestamp;
            var progress = Math.min((timestamp - start) / duration, 1);
            // Ease out cubic
            var eased = 1 - Math.pow(1 - progress, 3);
            var current = startVal + (target - startVal) * eased;

            // Format matches original (integer vs decimal)
            var isInt = Number.isInteger(target);
            var displayVal = isInt ? Math.round(current) : parseFloat(current.toFixed(1));
            el.textContent = formatNumber(displayVal, original);

            if (progress < 1) {
                requestAnimationFrame(step);
            } else {
                el.textContent = original; // restore exact original
            }
        }

        requestAnimationFrame(step);
    }

    function initFloatingStats() {
        var wraps = document.querySelectorAll('.bkbg-floating-stats');
        if (!wraps.length) return;

        if (!('IntersectionObserver' in window)) {
            wraps.forEach(function (wrap) {
                wrap.querySelectorAll('.bkbg-floating-card').forEach(function (card) {
                    card.classList.add('is-visible');
                });
            });
            return;
        }

        var cardObs = new IntersectionObserver(function (entries) {
            entries.forEach(function (entry) {
                if (!entry.isIntersecting) return;
                entry.target.classList.add('is-visible');
                cardObs.unobserve(entry.target);
            });
        }, { threshold: 0.2, rootMargin: '0px 0px -30px 0px' });

        var wrapObs = new IntersectionObserver(function (entries) {
            entries.forEach(function (entry) {
                if (!entry.isIntersecting) return;
                var wrap = entry.target;
                var doCountUp = wrap.getAttribute('data-count-up') === '1';
                if (doCountUp) {
                    wrap.querySelectorAll('.bkbg-floating-card__value').forEach(function (el) {
                        animateCountUp(el, 1600);
                    });
                }
                wrapObs.unobserve(wrap);
            });
        }, { threshold: 0.25 });

        wraps.forEach(function (wrap) {
            wrap.querySelectorAll('.bkbg-floating-card').forEach(function (card) {
                cardObs.observe(card);
            });
            wrapObs.observe(wrap);
        });
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initFloatingStats);
    } else {
        initFloatingStats();
    }
}());

```
