User:Jono Bean/common.js: Difference between revisions

From DQWiki
Jump to navigationJump to search
No edit summary
m (update to more robust script)
 
Line 1: Line 1:
/* Lorekeeper Widget Loader - v1.1.3 (Hardened Responsive Iframe) */
/* Lorekeeper Widget Loader - v1.1.4 (MediaWiki Hardened Loader) */
(function() {
(function () {
     var username = mw.config.get('wgUserName');
     if (window.__lorekeeperWidgetLoaded) return;
     var isMobileParent = window.innerWidth < 768; // Measure the true Wiki window size
     window.__lorekeeperWidgetLoaded = true;
   
 
    // Uses the correct Firebase Hosted App URL
     var APP_ORIGIN = 'https://npc-forge--npc-forge-qh4gc.asia-southeast1.hosted.app';
     var iframeUrl = 'https://npc-forge--npc-forge-qh4gc.asia-southeast1.hosted.app/widget';
    var APP_WIDGET_URL = APP_ORIGIN + '/widget';
      
     var MOBILE_BREAKPOINT = 768;
     var params = [];
    var CONTAINER_ID = 'lorekeeper-widget-container';
    if (username) {
     var IFRAME_ID = 'lorekeeper-widget-frame';
        params.push('user=' + encodeURIComponent(username));
 
    } else {
    function isMobileViewport() {
        params.push('guest=Traveler');
        return window.innerWidth < MOBILE_BREAKPOINT;
    }
 
    function getUsername() {
        try {
            return (mw && mw.config && mw.config.get('wgUserName')) || '';
        } catch (err) {
            return '';
        }
    }
 
    function buildIframeUrl() {
        var params = [];
        var username = getUsername();
 
        if (username) {
            params.push('user=' + encodeURIComponent(username));
        } else {
            params.push('guest=' + encodeURIComponent('Traveler'));
        }
 
        if (isMobileViewport()) {
            params.push('isMobile=true');
        }
 
        params.push('parentOrigin=' + encodeURIComponent(window.location.origin));
 
        return APP_WIDGET_URL + '?' + params.join('&');
    }
 
    function setCollapsedSize(container) {
        if (isMobileViewport()) {
            container.style.width = '80px';
            container.style.height = '80px';
        } else {
            container.style.width = '300px';
            container.style.height = '120px';
        }
    }
 
    function ensureContainer() {
        var existing = document.getElementById(CONTAINER_ID);
        if (existing) return existing;
 
        var container = document.createElement('div');
        container.id = CONTAINER_ID;
        container.style.position = 'fixed';
        container.style.bottom = '0';
        container.style.right = '0';
        container.style.zIndex = '99999';
        container.style.pointerEvents = 'none';
        container.style.overflow = 'hidden';
        container.style.background = 'transparent';
        container.style.transition = 'width 0.3s ease, height 0.3s ease';
        setCollapsedSize(container);
 
        return container;
    }
 
    function ensureIframe() {
        var existing = document.getElementById(IFRAME_ID);
        if (existing) return existing;
 
        var iframe = document.createElement('iframe');
        iframe.id = IFRAME_ID;
        iframe.src = buildIframeUrl();
        iframe.style.width = '100%';
        iframe.style.height = '100%';
        iframe.style.border = 'none';
        iframe.style.background = 'transparent';
        iframe.style.pointerEvents = 'auto';
        iframe.setAttribute('allow', 'clipboard-write');
        iframe.setAttribute('loading', 'lazy');
        iframe.setAttribute('referrerpolicy', 'strict-origin-when-cross-origin');
 
        return iframe;
    }
 
    function mountWidget() {
        if (!document.body) return false;
 
        var container = ensureContainer();
        var iframe = ensureIframe();
 
        if (!container.parentNode) {
            container.appendChild(iframe);
            document.body.appendChild(container);
        } else if (!iframe.parentNode) {
            container.appendChild(iframe);
        }
 
        return true;
     }
     }
      
 
    // Tell the iframe if the user is ACTUALLY on mobile
     function applyResize(container, width, height) {
    if (isMobileParent) {
        if (!container) return;
         params.push('isMobile=true');
 
        if (typeof width === 'number') {
            container.style.width = width + 'px';
         } else if (typeof width === 'string' && width) {
            container.style.width = width;
        }
 
        if (typeof height === 'number') {
            container.style.height = height + 'px';
        } else if (typeof height === 'string' && height) {
            container.style.height = height;
        }
     }
     }
      
 
    if (params.length > 0) {
     function handleMessage(event) {
         iframeUrl += '?' + params.join('&');
        if (event.origin !== APP_ORIGIN) return;
         if (!event.data || event.data.type !== 'lorekeeper-resize') return;
 
        var container = document.getElementById(CONTAINER_ID);
        if (!container) return;
 
        applyResize(container, event.data.width, event.data.height);
     }
     }


     // Create a container that doesn't block the Wiki
     function handleWindowResize() {
    var widgetContainer = document.createElement('div');
        var container = document.getElementById(CONTAINER_ID);
    widgetContainer.id = 'lorekeeper-widget-container';
        var iframe = document.getElementById(IFRAME_ID);
    widgetContainer.style.cssText = 'position:fixed; bottom:0; right:0; z-index:99999; pointer-events:none; transition: width 0.3s ease, height 0.3s ease;';
        if (!container || !iframe) return;
    widgetContainer.style.width = isMobileParent ? '80px' : '300px';  
 
    widgetContainer.style.height = isMobileParent ? '80px' : '120px';
        var wasMobile = iframe.getAttribute('data-is-mobile') === 'true';
        var nowMobile = isMobileViewport();


    var iframe = document.createElement('iframe');
        if (wasMobile !== nowMobile) {
    iframe.src = iframeUrl;
            iframe.setAttribute('data-is-mobile', nowMobile ? 'true' : 'false');
    iframe.style.cssText = 'width:100%; height:100%; border:none; background:transparent; pointer-events:auto;';
            iframe.src = buildIframeUrl();
    iframe.setAttribute('allow', 'clipboard-write'); // For links/sharing later
            setCollapsedSize(container);
            return;
        }


    widgetContainer.appendChild(iframe);
        if (
    document.body.appendChild(widgetContainer);
            container.style.width === '80px' ||
            container.style.width === '300px' ||
            container.style.width === '100vw'
        ) {
            setCollapsedSize(container);
        }
    }


     // Listen for the widget telling the Wiki to "Grow" and "Shrink"
     function init() {
    window.addEventListener('message', function(event) {
         if (!mountWidget()) {
        // Enforce secure origin check for the correct App Hosting domain
             window.setTimeout(init, 50);
         if (event.origin !== 'https://npc-forge--npc-forge-qh4gc.asia-southeast1.hosted.app') return;
             return;
       
        if (event.data.type === 'lorekeeper-resize') {
             var w = event.data.width;
            var h = event.data.height;
            // Handle both pixel numbers (desktop) and string values like "100vw" (mobile)
            widgetContainer.style.width = (typeof w === 'number') ? w + 'px' : w;
             widgetContainer.style.height = (typeof h === 'number') ? h + 'px' : h;
         }
         }
    });


    // Optional: Resync if they resize the window wildly (desktop to mobile mode live)
         var iframe = document.getElementById(IFRAME_ID);
    window.addEventListener('resize', function() {
         if (iframe) {
         var newIsMobile = window.innerWidth < 768;
             iframe.setAttribute('data-is-mobile', isMobileViewport() ? 'true' : 'false');
         if (newIsMobile !== isMobileParent) {
             isMobileParent = newIsMobile;
            // You could reload the iframe here, but keeping it simple is usually safest.
         }
         }
     });
 
        window.addEventListener('message', handleMessage, false);
        window.addEventListener('resize', handleWindowResize, false);
     }
 
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init, { once: true });
    } else {
        init();
    }
})();
})();

Latest revision as of 04:59, 3 April 2026

/* Lorekeeper Widget Loader - v1.1.4 (MediaWiki Hardened Loader) */
(function () {
    if (window.__lorekeeperWidgetLoaded) return;
    window.__lorekeeperWidgetLoaded = true;

    var APP_ORIGIN = 'https://npc-forge--npc-forge-qh4gc.asia-southeast1.hosted.app';
    var APP_WIDGET_URL = APP_ORIGIN + '/widget';
    var MOBILE_BREAKPOINT = 768;
    var CONTAINER_ID = 'lorekeeper-widget-container';
    var IFRAME_ID = 'lorekeeper-widget-frame';

    function isMobileViewport() {
        return window.innerWidth < MOBILE_BREAKPOINT;
    }

    function getUsername() {
        try {
            return (mw && mw.config && mw.config.get('wgUserName')) || '';
        } catch (err) {
            return '';
        }
    }

    function buildIframeUrl() {
        var params = [];
        var username = getUsername();

        if (username) {
            params.push('user=' + encodeURIComponent(username));
        } else {
            params.push('guest=' + encodeURIComponent('Traveler'));
        }

        if (isMobileViewport()) {
            params.push('isMobile=true');
        }

        params.push('parentOrigin=' + encodeURIComponent(window.location.origin));

        return APP_WIDGET_URL + '?' + params.join('&');
    }

    function setCollapsedSize(container) {
        if (isMobileViewport()) {
            container.style.width = '80px';
            container.style.height = '80px';
        } else {
            container.style.width = '300px';
            container.style.height = '120px';
        }
    }

    function ensureContainer() {
        var existing = document.getElementById(CONTAINER_ID);
        if (existing) return existing;

        var container = document.createElement('div');
        container.id = CONTAINER_ID;
        container.style.position = 'fixed';
        container.style.bottom = '0';
        container.style.right = '0';
        container.style.zIndex = '99999';
        container.style.pointerEvents = 'none';
        container.style.overflow = 'hidden';
        container.style.background = 'transparent';
        container.style.transition = 'width 0.3s ease, height 0.3s ease';
        setCollapsedSize(container);

        return container;
    }

    function ensureIframe() {
        var existing = document.getElementById(IFRAME_ID);
        if (existing) return existing;

        var iframe = document.createElement('iframe');
        iframe.id = IFRAME_ID;
        iframe.src = buildIframeUrl();
        iframe.style.width = '100%';
        iframe.style.height = '100%';
        iframe.style.border = 'none';
        iframe.style.background = 'transparent';
        iframe.style.pointerEvents = 'auto';
        iframe.setAttribute('allow', 'clipboard-write');
        iframe.setAttribute('loading', 'lazy');
        iframe.setAttribute('referrerpolicy', 'strict-origin-when-cross-origin');

        return iframe;
    }

    function mountWidget() {
        if (!document.body) return false;

        var container = ensureContainer();
        var iframe = ensureIframe();

        if (!container.parentNode) {
            container.appendChild(iframe);
            document.body.appendChild(container);
        } else if (!iframe.parentNode) {
            container.appendChild(iframe);
        }

        return true;
    }

    function applyResize(container, width, height) {
        if (!container) return;

        if (typeof width === 'number') {
            container.style.width = width + 'px';
        } else if (typeof width === 'string' && width) {
            container.style.width = width;
        }

        if (typeof height === 'number') {
            container.style.height = height + 'px';
        } else if (typeof height === 'string' && height) {
            container.style.height = height;
        }
    }

    function handleMessage(event) {
        if (event.origin !== APP_ORIGIN) return;
        if (!event.data || event.data.type !== 'lorekeeper-resize') return;

        var container = document.getElementById(CONTAINER_ID);
        if (!container) return;

        applyResize(container, event.data.width, event.data.height);
    }

    function handleWindowResize() {
        var container = document.getElementById(CONTAINER_ID);
        var iframe = document.getElementById(IFRAME_ID);
        if (!container || !iframe) return;

        var wasMobile = iframe.getAttribute('data-is-mobile') === 'true';
        var nowMobile = isMobileViewport();

        if (wasMobile !== nowMobile) {
            iframe.setAttribute('data-is-mobile', nowMobile ? 'true' : 'false');
            iframe.src = buildIframeUrl();
            setCollapsedSize(container);
            return;
        }

        if (
            container.style.width === '80px' ||
            container.style.width === '300px' ||
            container.style.width === '100vw'
        ) {
            setCollapsedSize(container);
        }
    }

    function init() {
        if (!mountWidget()) {
            window.setTimeout(init, 50);
            return;
        }

        var iframe = document.getElementById(IFRAME_ID);
        if (iframe) {
            iframe.setAttribute('data-is-mobile', isMobileViewport() ? 'true' : 'false');
        }

        window.addEventListener('message', handleMessage, false);
        window.addEventListener('resize', handleWindowResize, false);
    }

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