js/brivembed.js

// ========================================================================
// Brivembed JS
// ========================================================================
document.addEventListener('DOMContentLoaded', () => {
    const KEY = 'brivembed_allow';

    // Keep preferences in memory to avoid JSON.parse on every click.
    let prefs = (() => {
        try {
            return JSON.parse(localStorage.getItem(KEY)) || {};
        } catch {
            return {};
        }
    })();

    const savePrefs = () => localStorage.setItem(KEY, JSON.stringify(prefs));

    const PROVIDERS = {
        codepen: {
            label: 'CodePen',
            src: ({
                code,
                user = CODEPEN_USER,
                tab = 'result',
                editable = 'true'
            }) => `https://codepen.io/${encodeURIComponent(user)}/embed/${encodeURIComponent(code)}`
                + `?default-tab=${encodeURIComponent(tab)}`
                + `&editable=${encodeURIComponent(editable)}`
        },
        dailymotion: {
            label: 'Dailymotion',
            src: ({ code }) =>
                `https://geo.dailymotion.com/player.html?video=${encodeURIComponent(code)}`
        },
        githubpages: {
            label: 'GitHub Pages'
        },
        youtube: {
            label: 'YouTube',
            src: ({ code }) =>
                `https://www.youtube.com/embed/${encodeURIComponent(code)}`
        }
    };

    const getProvider = (box) => PROVIDERS[box.dataset.provider];

    const hasFullscreen = (box) => box.dataset.fullscreen === '1';

    const updateRememberUI = (box, active) => {
        const icon = box.querySelector('.brivembed-icon');

        if (!icon) return;

        icon.classList.toggle('fa-square', !active);
        icon.classList.toggle('fa-square-check', active);
    };

    const ensurePlaceholder = (box) => {
        if (box.querySelector('.brivembed-placeholder')) return;

        const p = getProvider(box);
        const label = p?.label || (box.dataset.provider || '');

        box.insertAdjacentHTML('afterbegin', `
            <div class="brivembed-placeholder">
                <h3>External content hosted by <span class="brivembed-provider-name-title">${label}</span></h3>
                <p>To respect your privacy, click “Show content” to load it.</p>

                <div class="brivembed-actions">
                    <button type="button" class="brivembed-load">Show content</button>

                    <div class="brivembed-remember" role="button" tabindex="0">
                        <span aria-hidden="true" class="brivembed-icon fa-regular fa-square fa-lg"></span>
                        <span class="brivembed-text">
                            Always allow the service
                            <span class="brivembed-provider-name-checkbox">${label}</span>
                        </span>
                    </div>
                </div>
            </div>
        `);
    };

    // The iframe is only created after explicit consent.
    const buildIframe = (src, providerLabel) => {
        const iframe = document.createElement('iframe');

        iframe.src = src;
        iframe.title = `Displaying external content hosted by ${providerLabel}`;
        iframe.loading = 'lazy';

        iframe.setAttribute(
            'allow',
            'accelerometer; encrypted-media; fullscreen; gyroscope; picture-in-picture'
        );

        return iframe;
    };

    const buildSrc = (box) => {
        if (box.dataset.src) return box.dataset.src;

        const p = getProvider(box);
        const code = box.dataset.code;

        if (!p || !code) return '';

        return p.src({
            code,
            user: box.dataset.user,
            tab: box.dataset.tab,
            editable: box.dataset.editable
        });
    };

    const updateFullscreenButtons = () => {
        document.querySelectorAll('.brivembed-fullscreen').forEach((btn) => {
            const box = btn.closest('.embed-container');
            const isFullscreen = document.fullscreenElement === box;

            btn.innerHTML = isFullscreen
                ? '<span class="fa-solid fa-2x fa-compress"></span>'
                : '<span class="fa-solid fa-2x fa-expand"></span>';

            const label = isFullscreen
                ? 'Exit fullscreen'
                : 'Show fullscreen';

            btn.setAttribute('aria-label', label);
            btn.setAttribute('title', label);
        });
    };

    const buildFullscreenButton = (box) => {
        const btn = document.createElement('button');

        btn.type = 'button';
        btn.className = 'brivembed-fullscreen';

        btn.addEventListener('click', () => {
            if (document.fullscreenElement === box) {
                document.exitFullscreen?.();
            } else {
                box.requestFullscreen?.();
            }
        });

        return btn;
    };

    const loadBox = (box) => {
        const p = getProvider(box);
        const src = buildSrc(box);

        if (!src) return;

        box.querySelector('.brivembed-placeholder')?.remove();

        box.classList.remove('brivembed');
        box.classList.add('embed-container');

        const iframe = buildIframe(
            src,
            p?.label || box.dataset.provider || ''
        );

        box.appendChild(iframe);

        if (hasFullscreen(box)) {
            box.appendChild(buildFullscreenButton(box));
        }

        updateFullscreenButtons();
    };

    const initBox = (box) => {
        const provider = box.dataset.provider;

        if (!provider) return;

        ensurePlaceholder(box);

        const active = prefs[provider] === true;

        updateRememberUI(box, active);

        if (active) loadBox(box);
    };

    const initAll = () => {
        document.querySelectorAll('.brivembed').forEach(initBox);
    };

    document.addEventListener(
        'fullscreenchange',
        updateFullscreenButtons
    );

    // Initialize placeholders once the DOM is ready.
    initAll();

    // Handle clicks.
    document.addEventListener('click', (e) => {
        const loadBtn = e.target.closest('.brivembed-load');
        const rememberBtn = e.target.closest('.brivembed-remember');

        if (!loadBtn && !rememberBtn) return;

        const box = e.target.closest('.brivembed');

        if (!box) return;

        const provider = box.dataset.provider;

        if (!provider) return;

        if (rememberBtn) {
            prefs[provider] = !prefs[provider];
            savePrefs();
            updateRememberUI(box, prefs[provider] === true);
            return;
        }

        if (loadBtn) {
            loadBox(box);
        }
    });

    // Keyboard support for the "always allow" control.
    document.addEventListener('keydown', (e) => {
        if (e.key !== 'Enter' && e.key !== ' ') return;

        const rememberBtn = e.target.closest?.('.brivembed-remember');

        if (!rememberBtn) return;

        const box = rememberBtn.closest('.brivembed');

        if (!box) return;

        e.preventDefault();

        const provider = box.dataset.provider;

        if (!provider) return;

        prefs[provider] = !prefs[provider];
        savePrefs();

        updateRememberUI(box, prefs[provider] === true);
    });
});

Contribute