# blockenberg/2.0.7/blocks/countdown/frontend.js

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

- Page: https://pluginprobe.com/plugins/blockenberg/2.0.7/code/blocks/countdown/frontend.js
- Raw: https://pluginprobe.com/plugins/blockenberg/2.0.7/raw/blocks/countdown/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/countdown/frontend.js#L10-L20`.

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

    function isSafeRedirectUrl(url) {
        if (!url) return false;
        var u = String(url).trim();
        if (!u) return false;
        if (/^\s*(javascript|data|vbscript):/i.test(u)) return false;
        // allow absolute http(s) or relative URLs/fragments
        return /^(https?:\/\/|\/|\.|\?|#)/i.test(u);
    }

    function clearEl(el) {
        while (el && el.firstChild) {
            el.removeChild(el.firstChild);
        }
    }

    function pad(num) {
        return num < 10 ? '0' + num : String(num);
    }

    function getTimeRemaining(targetDate) {
        var now = new Date();
        var target = new Date(targetDate);
        var total = target - now;

        if (total <= 0) {
            return { days: 0, hours: 0, minutes: 0, seconds: 0, total: 0, expired: true };
        }

        return {
            days: Math.floor(total / (1000 * 60 * 60 * 24)),
            hours: Math.floor((total / (1000 * 60 * 60)) % 24),
            minutes: Math.floor((total / (1000 * 60)) % 60),
            seconds: Math.floor((total / 1000) % 60),
            total: total,
            expired: false
        };
    }

    // Get evergreen target date from localStorage or create new one
    function getEvergreenTarget(wrap, duration) {
        var storageKey = 'bkbg_cd_evergreen_' + (wrap.id || wrap.getAttribute('data-evergreen-id') || 'default');
        var stored = localStorage.getItem(storageKey);
        
        if (stored) {
            var storedDate = new Date(stored);
            // If stored date is still in future, use it
            if (storedDate > new Date()) {
                return stored;
            }
        }
        
        // Create new target date based on duration
        var now = new Date();
        var target = new Date(now.getTime() + duration);
        var isoString = target.toISOString();
        localStorage.setItem(storageKey, isoString);
        return isoString;
    }

    function initCountdown(wrap) {
        var target = wrap.getAttribute('data-target');
        var unitsConfig = wrap.getAttribute('data-units') || '';
        var showLabels = wrap.getAttribute('data-show-labels') === '1';
        var showSeparators = wrap.getAttribute('data-show-separators') === '1';
        var expiredAction = wrap.getAttribute('data-expired-action') || 'message';
        var expiredMessage = wrap.getAttribute('data-expired-message') || "Time's up!";
        var expiredRedirect = wrap.getAttribute('data-expired-redirect') || '';
        // Evergreen mode
        var evergreenMode = wrap.getAttribute('data-evergreen') === '1';
        var evergreenDuration = parseInt(wrap.getAttribute('data-evergreen-duration') || '86400000', 10); // default 24h in ms

        if (evergreenMode) {
            target = getEvergreenTarget(wrap, evergreenDuration);
        }

        if (!target) return;

        // Parse units config
        var units = [];
        unitsConfig.split('|').forEach(function (item) {
            if (!item) return;
            var parts = item.split(':');
            if (parts.length >= 2) {
                units.push({ key: parts[0], label: parts.slice(1).join(':') });
            }
        });

        var countdownEl = wrap.querySelector('.bkbg-cd-countdown');
        if (!countdownEl) return;

        var hasExpired = false;

        function render() {
            var time = getTimeRemaining(target);

            if (time.expired && !hasExpired) {
                hasExpired = true;
                
                // For evergreen mode, restart the countdown
                if (evergreenMode) {
                    var storageKey = 'bkbg_cd_evergreen_' + (wrap.id || wrap.getAttribute('data-evergreen-id') || 'default');
                    localStorage.removeItem(storageKey);
                    target = getEvergreenTarget(wrap, evergreenDuration);
                    hasExpired = false;
                    render();
                    return;
                }
                
                handleExpiration();
                return;
            }

            if (hasExpired) return;

            // Build DOM safely (avoid innerHTML)
            clearEl(countdownEl);
            units.forEach(function (unit, index) {
                var value = time[unit.key] !== undefined ? time[unit.key] : 0;
                var isLast = index === units.length - 1;
                var valueStr = pad(value);

                var unitEl = document.createElement('div');
                unitEl.className = 'bkbg-cd-unit';

                var digitEl = document.createElement('div');
                digitEl.className = 'bkbg-cd-digit';

                var numberEl = document.createElement('span');
                numberEl.className = 'bkbg-cd-number';
                numberEl.textContent = valueStr;
                digitEl.appendChild(numberEl);
                unitEl.appendChild(digitEl);

                if (showLabels) {
                    var labelEl = document.createElement('span');
                    labelEl.className = 'bkbg-cd-label';
                    labelEl.textContent = unit.label || '';
                    unitEl.appendChild(labelEl);
                }

                countdownEl.appendChild(unitEl);

                if (showSeparators && !isLast) {
                    var sep = document.createElement('span');
                    sep.className = 'bkbg-cd-separator';
                    sep.textContent = ':';
                    countdownEl.appendChild(sep);
                }
            });
        }

        function handleExpiration() {
            switch (expiredAction) {
                case 'message':
                    clearEl(wrap);
                    var msg = document.createElement('div');
                    msg.className = 'bkbg-cd-expired';
                    msg.textContent = expiredMessage || "Time's up!";
                    wrap.appendChild(msg);
                    break;
                case 'hide':
                    wrap.style.display = 'none';
                    break;
                case 'redirect':
                    if (isSafeRedirectUrl(expiredRedirect)) {
                        window.location.href = expiredRedirect;
                    }
                    break;
                case 'keep':
                    // Do nothing, keep showing 00:00:00
                    break;
            }
        }

        // Initial render
        render();

        // Update every second
        var interval = setInterval(function () {
            if (hasExpired && expiredAction !== 'keep') {
                clearInterval(interval);
                return;
            }
            render();
        }, 1000);
    }

    function init() {
        var countdowns = document.querySelectorAll('.bkbg-cd-wrap[data-target], .bkbg-cd-wrap[data-evergreen="1"]');
        countdowns.forEach(initCountdown);
    }

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



```
