# blockenberg/2.0.7/blocks/cron-builder/frontend.js

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

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

```javascript
function typoCssVarsForEl(typo, prefix, el) {
    if (!typo || typeof typo !== 'object') return;
    var map = {
        family: 'font-family', weight: 'font-weight', style: 'font-style',
        transform: 'text-transform', decoration: 'text-decoration',
        sizeDesktop: 'font-size-d', sizeTablet: 'font-size-t', sizeMobile: 'font-size-m',
        sizeUnit: null,
        lineHeightDesktop: 'line-height-d', lineHeightTablet: 'line-height-t', lineHeightMobile: 'line-height-m',
        lineHeightUnit: null,
        letterSpacingDesktop: 'letter-spacing-d', letterSpacingTablet: 'letter-spacing-t', letterSpacingMobile: 'letter-spacing-m',
        letterSpacingUnit: null,
        wordSpacingDesktop: 'word-spacing-d', wordSpacingTablet: 'word-spacing-t', wordSpacingMobile: 'word-spacing-m',
        wordSpacingUnit: null
    };
    var sizeU = typo.sizeUnit || 'px';
    var lhU   = typo.lineHeightUnit || '';
    var lsU   = typo.letterSpacingUnit || 'px';
    var wsU   = typo.wordSpacingUnit || 'px';
    Object.keys(map).forEach(function (k) {
        var css = map[k]; if (!css) return;
        var v = typo[k]; if (v === undefined || v === '' || v === null) return;
        if (/size|spacing/i.test(k)) {
            var u = /letterSpacing/.test(k) ? lsU : /wordSpacing/.test(k) ? wsU : /lineHeight/.test(k) ? lhU : sizeU;
            v = v + u;
        }
        el.style.setProperty(prefix + css, v);
    });
}

(function () {
    'use strict';

    var PRESETS = [
        { label: 'Every minute',   expr: '* * * * *'   },
        { label: 'Every hour',     expr: '0 * * * *'   },
        { label: 'Daily 9 AM',     expr: '0 9 * * *'   },
        { label: 'Weekdays 9 AM',  expr: '0 9 * * 1-5' },
        { label: 'Weekly Monday',  expr: '0 9 * * 1'   },
        { label: 'Monthly 1st',    expr: '0 9 1 * *'   },
        { label: 'Yearly Jan 1st', expr: '0 0 1 1 *'   }
    ];

    var MONTHS   = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
    var WEEKDAYS = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];

    /* ---- Describe a cron expression in English ---- */
    function describe(expr) {
        var parts = (expr || '').trim().split(/\s+/);
        if (parts.length !== 5) return 'Invalid expression';

        var min = parts[0], hr = parts[1], dom = parts[2], mon = parts[3], dow = parts[4];

        function fmtTime(h, m) {
            var H = parseInt(h, 10), M = parseInt(m, 10);
            if (isNaN(H) || isNaN(M)) return 'at ' + m + ':' + h;
            var ampm = H >= 12 ? 'PM' : 'AM';
            var h12 = H % 12 || 12;
            return 'at ' + h12 + ':' + String(M).padStart(2, '0') + ' ' + ampm;
        }

        var timeStr = '';
        if (min === '*' && hr === '*') {
            timeStr = 'every minute';
        } else if (min === '*') {
            timeStr = 'every minute of hour ' + hr;
        } else if (hr === '*') {
            timeStr = 'at minute ' + min + ' of every hour';
        } else {
            timeStr = fmtTime(hr, min);
        }

        var domStr = '';
        if (dom !== '*') {
            if (/^\d+$/.test(dom)) domStr = 'on day ' + dom + ' of the month';
            else domStr = 'on day ' + dom + ' of the month';
        }

        var monStr = '';
        if (mon !== '*') {
            if (/^\d+$/.test(mon) && parseInt(mon) >= 1 && parseInt(mon) <= 12) monStr = 'in ' + MONTHS[parseInt(mon) - 1];
            else monStr = 'in month ' + mon;
        }

        var dowStr = '';
        if (dow !== '*') {
            var days = dow.split(',').map(function (d) {
                if (/^\d+$/.test(d)) return WEEKDAYS[parseInt(d) % 7] || d;
                if (/^\d+-\d+$/.test(d)) {
                    var range = d.split('-');
                    return (WEEKDAYS[parseInt(range[0])] || range[0]) + '–' + (WEEKDAYS[parseInt(range[1])] || range[1]);
                }
                return d;
            });
            dowStr = 'on ' + days.join(', ');
        }

        var parts2 = [timeStr];
        if (domStr) parts2.push(domStr);
        if (monStr) parts2.push(monStr);
        if (dowStr) parts2.push(dowStr);
        if (dom === '*' && mon === '*' && dow === '*' && timeStr !== 'every minute') parts2.push('every day');

        return parts2.join(', ');
    }

    /* ---- Validate a cron field ---- */
    function validateField(val, min, max) {
        if (val === '*') return true;
        if (/^\*\/\d+$/.test(val)) return true;
        if (/^\d+$/.test(val)) { var n = parseInt(val); return n >= min && n <= max; }
        if (/^\d+-\d+$/.test(val)) {
            var parts = val.split('-');
            return parseInt(parts[0]) >= min && parseInt(parts[1]) <= max && parseInt(parts[0]) <= parseInt(parts[1]);
        }
        if (/^\d+(,\d+)+$/.test(val)) {
            return val.split(',').every(function (n) { var x = parseInt(n); return x >= min && x <= max; });
        }
        return false;
    }

    /* ---- Compute next N run times ---- */
    function nextRuns(expr, count) {
        var parts = (expr || '').trim().split(/\s+/);
        if (parts.length !== 5) return [];

        function matchField(val, n, min, max) {
            if (val === '*') return true;
            if (/^\*\/(\d+)$/.test(val)) { var step = parseInt(val.slice(2)); return n % step === 0; }
            if (/^\d+$/.test(val)) return parseInt(val) === n;
            if (/^\d+-\d+$/.test(val)) { var r = val.split('-'); return n >= parseInt(r[0]) && n <= parseInt(r[1]); }
            if (/^\d+(,\d+)+$/.test(val)) return val.split(',').map(Number).indexOf(n) !== -1;
            return false;
        }

        var results = [];
        var d = new Date();
        d.setSeconds(0, 0);
        d.setMinutes(d.getMinutes() + 1);

        var limit = 0;
        while (results.length < count && limit < 525600) {
            limit++;
            if (
                matchField(parts[3], d.getMonth() + 1, 1, 12) &&
                matchField(parts[2], d.getDate(), 1, 31) &&
                matchField(parts[4], d.getDay(), 0, 7) &&
                matchField(parts[1], d.getHours(), 0, 23) &&
                matchField(parts[0], d.getMinutes(), 0, 59)
            ) {
                results.push(new Date(d));
            }
            d.setMinutes(d.getMinutes() + 1);
        }
        return results;
    }

    function relativeTime(date) {
        var diff = date - Date.now();
        var mins = Math.round(diff / 60000);
        if (mins < 60) return 'in ' + mins + ' min';
        var hrs = Math.round(mins / 60);
        if (hrs < 24) return 'in ' + hrs + ' hr';
        return 'in ' + Math.round(hrs / 24) + ' day' + (Math.round(hrs/24) > 1 ? 's' : '');
    }

    function initBlock(root) {
        var opts;
        try { opts = JSON.parse(root.getAttribute('data-opts')); } catch (e) { return; }

        var a = opts;
        var expr = a.defaultExpression || '0 9 * * *';
        var exprParts = expr.split(/\s+/);
        while (exprParts.length < 5) exprParts.push('*');

        root.innerHTML = '';

        var wrap = document.createElement('div');
        wrap.className = 'bkbg-cb-wrap';
        wrap.style.cssText = 'background:' + a.sectionBg + ';max-width:' + a.contentMaxWidth + 'px;margin:0 auto;';
        root.appendChild(wrap);

        typoCssVarsForEl(a.typoTitle, '--bkbg-cb-ttl-', wrap);
        typoCssVarsForEl(a.typoSubtitle, '--bkbg-cb-sub-', wrap);

        if (a.showTitle) {
            var h = document.createElement('div');
            h.className = 'bkbg-cb-title';
            h.style.color = a.titleColor;
            h.textContent = a.title;
            wrap.appendChild(h);
        }

        if (a.showSubtitle) {
            var s = document.createElement('div');
            s.className = 'bkbg-cb-subtitle';
            s.style.color = a.subtitleColor;
            s.textContent = a.subtitle;
            wrap.appendChild(s);
        }

        // Presets
        if (a.showPresets) {
            var presetsEl = document.createElement('div');
            presetsEl.className = 'bkbg-cb-presets';
            presetsEl.style.background = a.cardBg;
            PRESETS.forEach(function (p) {
                var btn = document.createElement('button');
                btn.className = 'bkbg-cb-preset-btn';
                btn.textContent = p.label;
                btn.title = p.expr;
                updatePresetStyle(btn, p.expr === expr);
                btn.addEventListener('click', function () {
                    expr = p.expr;
                    exprParts = expr.split(/\s+/);
                    updateInputs();
                    renderAll();
                    presetsEl.querySelectorAll('.bkbg-cb-preset-btn').forEach(function (b) {
                        updatePresetStyle(b, b.title === expr);
                    });
                });
                presetsEl.appendChild(btn);
            });
            wrap.appendChild(presetsEl);
        }

        function updatePresetStyle(btn, active) {
            btn.style.cssText = 'background:' + (active ? a.accentColor : '#e5e7eb') + ';color:' + (active ? '#fff' : '#374151') + ';';
        }

        // Fields card
        var fieldsCard = document.createElement('div');
        fieldsCard.className = 'bkbg-cb-card';
        fieldsCard.style.background = a.cardBg;
        wrap.appendChild(fieldsCard);

        var FIELD_DEFS = [
            { label: 'Minute',  min: 0, max: 59 },
            { label: 'Hour',    min: 0, max: 23 },
            { label: 'Day',     min: 1, max: 31 },
            { label: 'Month',   min: 1, max: 12 },
            { label: 'Weekday', min: 0, max: 7  }
        ];

        var fieldsRow = document.createElement('div');
        fieldsRow.className = 'bkbg-cb-fields';
        fieldsCard.appendChild(fieldsRow);

        var inputs = [];

        FIELD_DEFS.forEach(function (def, idx) {
            var col = document.createElement('div');
            col.className = 'bkbg-cb-field-col';

            var inp = document.createElement('input');
            inp.type = 'text';
            inp.className = 'bkbg-cb-field-input';
            inp.value = exprParts[idx] || '*';
            inp.style.cssText = 'background:' + a.fieldBg + ';color:' + a.accentColor + ';';
            inp.setAttribute('aria-label', def.label);
            inp.title = def.label + ' (' + def.min + '-' + def.max + ')';

            inp.addEventListener('input', function () {
                exprParts[idx] = inp.value || '*';
                expr = exprParts.join(' ');
                renderAll();
            });

            inputs.push(inp);

            var lbl = document.createElement('div');
            lbl.className = 'bkbg-cb-field-label';
            lbl.style.color = a.subtitleColor;
            lbl.textContent = def.label;

            col.appendChild(inp);
            col.appendChild(lbl);
            fieldsRow.appendChild(col);
        });

        function updateInputs() {
            inputs.forEach(function (inp, idx) {
                inp.value = exprParts[idx] || '*';
            });
        }

        // Expression display
        var exprDisplay = document.createElement('div');
        exprDisplay.className = 'bkbg-cb-expr-display';
        exprDisplay.style.cssText = 'background:' + a.fieldBg + ';color:' + a.accentColor + ';';
        fieldsCard.appendChild(exprDisplay);

        // Error display
        var errorEl = document.createElement('div');
        errorEl.className = 'bkbg-cb-error';
        errorEl.style.display = 'none';
        fieldsCard.appendChild(errorEl);

        // Actions
        var actionsRow = document.createElement('div');
        actionsRow.className = 'bkbg-cb-actions';
        var copyBtn = document.createElement('button');
        copyBtn.className = 'bkbg-cb-btn';
        copyBtn.style.background = a.accentColor;
        copyBtn.textContent = 'Copy Expression';
        var copyMsg = document.createElement('div');
        copyMsg.className = 'bkbg-cb-copy-msg';
        copyMsg.style.color = a.accentColor;
        copyMsg.textContent = '✓ Copied to clipboard!';

        copyBtn.addEventListener('click', function () {
            navigator.clipboard && navigator.clipboard.writeText(expr).catch(function () {
                var t = document.createElement('textarea');
                t.value = expr; document.body.appendChild(t); t.select();
                document.execCommand('copy'); document.body.removeChild(t);
            });
            copyMsg.classList.add('bkbg-cb-show');
            setTimeout(function () { copyMsg.classList.remove('bkbg-cb-show'); }, 2000);
        });

        actionsRow.appendChild(copyBtn);
        fieldsCard.appendChild(actionsRow);
        fieldsCard.appendChild(copyMsg);

        // Description card
        var descCard = null, descText = null;
        if (a.showDescription) {
            descCard = document.createElement('div');
            descCard.className = 'bkbg-cb-desc-card';
            descCard.style.cssText = 'background:' + a.cardBg + ';border-left-color:' + a.accentColor + ';';

            var descLabel = document.createElement('div');
            descLabel.className = 'bkbg-cb-desc-label';
            descLabel.style.color = a.subtitleColor;
            descLabel.textContent = 'DESCRIPTION';
            descCard.appendChild(descLabel);

            descText = document.createElement('div');
            descText.className = 'bkbg-cb-desc-text';
            descText.style.color = a.labelColor;
            descCard.appendChild(descText);
            wrap.appendChild(descCard);
        }

        // Next runs card
        var nextCard = null, nextList = null;
        if (a.showNextRuns) {
            nextCard = document.createElement('div');
            nextCard.className = 'bkbg-cb-card';
            nextCard.style.background = a.cardBg;

            var nextTitle = document.createElement('div');
            nextTitle.className = 'bkbg-cb-next-title';
            nextTitle.style.color = a.labelColor;
            nextTitle.textContent = 'Next Run Times';
            nextCard.appendChild(nextTitle);

            nextList = document.createElement('div');
            nextCard.appendChild(nextList);
            wrap.appendChild(nextCard);
        }

        function renderAll() {
            // Update expression display
            exprDisplay.textContent = exprParts.join(' ');

            // Validate
            var valid = [
                validateField(exprParts[0], 0, 59),
                validateField(exprParts[1], 0, 23),
                validateField(exprParts[2], 1, 31),
                validateField(exprParts[3], 1, 12),
                validateField(exprParts[4], 0, 7)
            ];

            var allValid = valid.every(Boolean);
            inputs.forEach(function (inp, idx) {
                inp.style.borderColor = valid[idx] ? 'transparent' : '#ef4444';
            });

            if (!allValid) {
                errorEl.style.display = 'block';
                errorEl.textContent = 'Invalid expression — check highlighted fields';
            } else {
                errorEl.style.display = 'none';
            }

            // Description
            if (descText) {
                descText.textContent = describe(exprParts.join(' '));
            }

            // Next runs
            if (nextList) {
                nextList.innerHTML = '';
                if (allValid) {
                    var runs = nextRuns(exprParts.join(' '), parseInt(a.nextRunsCount) || 5);
                    runs.forEach(function (d) {
                        var item = document.createElement('div');
                        item.className = 'bkbg-cb-next-item';
                        item.style.color = a.labelColor;

                        var arrow = document.createElement('span');
                        arrow.className = 'bkbg-cb-next-arrow';
                        arrow.style.color = a.accentColor;
                        arrow.textContent = '→';

                        var dateText = document.createElement('span');
                        dateText.textContent = d.toLocaleString(undefined, { dateStyle: 'medium', timeStyle: 'short' });

                        var rel = document.createElement('span');
                        rel.className = 'bkbg-cb-next-relative';
                        rel.textContent = relativeTime(d);

                        [arrow, dateText, rel].forEach(function (el) { item.appendChild(el); });
                        nextList.appendChild(item);
                    });
                    if (runs.length === 0) {
                        var noRun = document.createElement('div');
                        noRun.style.cssText = 'color:' + a.subtitleColor + ';font-size:13px;padding:8px 0;';
                        noRun.textContent = 'No upcoming runs found in the next year.';
                        nextList.appendChild(noRun);
                    }
                } else {
                    var errNote = document.createElement('div');
                    errNote.style.cssText = 'color:#ef4444;font-size:13px;padding:8px 0;';
                    errNote.textContent = 'Fix the expression to see next run times.';
                    nextList.appendChild(errNote);
                }
            }
        }

        renderAll();
    }

    function init() {
        document.querySelectorAll('.bkbg-cb-app').forEach(initBlock);
    }

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

```
