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

From DQWiki
Jump to navigationJump to search
mNo edit summary
m (update to more robust script)
 
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
/* Lorekeeper Standalone Terminal v5 - Compatible & Premium */
/* Lorekeeper Widget Loader - v1.1.4 (MediaWiki Hardened Loader) */
(function() {
(function () {
     var checkCount = 0;
    if (window.__lorekeeperWidgetLoaded) return;
     var initTimer = setInterval(function() {
    window.__lorekeeperWidgetLoaded = true;
         if (document.body) {
 
             clearInterval(initTimer);
    var APP_ORIGIN = 'https://npc-forge--npc-forge-qh4gc.asia-southeast1.hosted.app';
             setupLore();
    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;
         }
         }
        if (checkCount++ > 100) clearInterval(initTimer);
     }
     }, 100);


     function setupLore() {
     function handleMessage(event) {
         if (document.getElementById('lore-terminal-btn')) return;
         if (event.origin !== APP_ORIGIN) return;
        if (!event.data || event.data.type !== 'lorekeeper-resize') return;


        // 1. Set up Styles manually
         var container = document.getElementById(CONTAINER_ID);
         var css =
         if (!container) return;
            '#lore-chat::-webkit-scrollbar { width: 4px; }' +
            '#lore-chat::-webkit-scrollbar-thumb { background: #8b5cf6; border-radius: 10px; }' +
            '.lore-msg { margin-bottom: 15px; padding: 12px 16px; border-radius: 15px; font-size: 14px; position: relative; }' +
            '.lore-user { background: #8b5cf6; color: #fff; align-self: flex-end; margin-left: 40px; border-bottom-right-radius: 4px; text-align: right; }' +
            '.lore-ai { background: #1a1a24; color: #e2e8f0; align-self: flex-start; margin-right: 40px; border-left: 4px solid #8b5cf6; border-bottom-left-radius: 4px; }';
       
        var style = document.createElement('style');
        style.type = 'text/css';
         if (style.styleSheet) style.styleSheet.cssText = css;
        else style.appendChild(document.createTextNode(css));
        document.getElementsByTagName('head')[0].appendChild(style);


         // 2. Create Floating Button
         applyResize(container, event.data.width, event.data.height);
        var btn = document.createElement('div');
    }
        btn.id = 'lore-terminal-btn';
        btn.innerHTML = '&#10024;'; // Sparkles
        btn.setAttribute('style', 'position:fixed !important; bottom:25px !important; right:25px !important; width:65px !important; height:65px !important; background:linear-gradient(135deg, #8b5cf6, #6d28d9) !important; border-radius:50% !important; display:flex !important; align-items:center !important; justify-content:center !important; font-size:32px !important; cursor:pointer !important; box-shadow:0 10px 30px rgba(139,92,246,0.5) !important; z-index:999999 !important; border:2px solid rgba(255,255,255,0.4) !important;');


        // 3. Create Chat Box
    function handleWindowResize() {
         var box = document.createElement('div');
         var container = document.getElementById(CONTAINER_ID);
         box.id = 'lore-terminal-box';
         var iframe = document.getElementById(IFRAME_ID);
        box.setAttribute('style', 'position:fixed !important; bottom:105px !important; right:25px !important; width:400px !important; height:600px !important; background:#0a0a0f !important; border:1px solid #8b5cf6 !important; border-radius:30px !important; display:none; flex-direction:column !important; box-shadow:0 30px 60px rgba(0,0,0,0.8) !important; z-index:999999 !important; color:#fff !important; font-family:sans-serif !important; overflow:hidden;');
         if (!container || !iframe) return;
          
        box.innerHTML =
            '<div style="padding:20px; border-bottom:1px solid rgba(139,92,246,0.2); background:rgba(139,92,246,0.1); display:flex; justify-content:space-between; align-items:center;">' +
                '<div><b style="color:#a78bfa; font-size:16px;">The Lorekeeper</b><br><small style="opacity:0.6; font-size:10px; text-transform:uppercase;">Royal Archives</small></div>' +
                '<span id="lore-close" style="cursor:pointer; font-size:24px; opacity:0.5;">&times;</span>' +
            '</div>' +
            '<div id="lore-chat" style="flex:1; overflow-y:auto; padding:20px; display:flex; flex-direction:column; gap:5px; background:#0a0a0f;">' +
                '<div class="lore-msg lore-ai">Greetings, Traveler. I am the Scribe of the Western Kingdom. What knowledge do you seek from the archives?</div>' +
            '</div>' +
            '<div style="padding:15px; background:rgba(0,0,0,0.4); border-top:1px solid #333; display:flex; gap:10px;">' +
                '<input id="lore-input" placeholder="Inquire about the world..." style="flex:1; background:#111; border:1px solid #444; padding:12px; border-radius:15px; color:#fff; outline:none; font-size:14px;">' +
                '<button id="lore-send" style="background:#8b5cf6; color:#fff; border:none; padding:10px 15px; border-radius:12px; cursor:pointer; font-weight:bold;">Ask</button>' +
            '</div>';


         document.body.appendChild(btn);
         var wasMobile = iframe.getAttribute('data-is-mobile') === 'true';
         document.body.appendChild(box);
         var nowMobile = isMobileViewport();


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


         btn.onclick = function() { box.style.display = (box.style.display == 'none') ? 'flex' : 'none'; };
         if (
         document.getElementById('lore-close').onclick = function() { box.style.display = 'none'; };
            container.style.width === '80px' ||
            container.style.width === '300px' ||
            container.style.width === '100vw'
         ) {
            setCollapsedSize(container);
        }
    }


         document.getElementById('lore-send').onclick = function() {
    function init() {
             var val = input.value.trim();
         if (!mountWidget()) {
             if (!val) return;
             window.setTimeout(init, 50);
            input.value = '';
             return;
        }


            // User Message
        var iframe = document.getElementById(IFRAME_ID);
            var uMsg = document.createElement('div');
        if (iframe) {
             uMsg.className = 'lore-msg lore-user';
             iframe.setAttribute('data-is-mobile', isMobileViewport() ? 'true' : 'false');
            uMsg.innerText = val;
        }
            chat.appendChild(uMsg);
            chat.scrollTop = chat.scrollHeight;


            // AI Message Container
        window.addEventListener('message', handleMessage, false);
            var aMsg = document.createElement('div');
        window.addEventListener('resize', handleWindowResize, false);
            aMsg.className = 'lore-msg lore-ai';
    }
            aMsg.innerText = "Consulting the records...";
            chat.appendChild(aMsg);


            // API Call (ES5 Compatible)
    if (document.readyState === 'loading') {
            var xhr = new XMLHttpRequest();
        document.addEventListener('DOMContentLoaded', init, { once: true });
            xhr.open("POST", "https://npc-forge--npc-forge-qh4gc.asia-southeast1.hosted.app/api/askLore", true);
    } else {
            xhr.setRequestHeader("Content-Type", "application/json");
         init();
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        try {
                            var response = JSON.parse(xhr.responseText);
                            aMsg.innerText = response.text || response.data.text;
                            chat.scrollTop = chat.scrollHeight;
                        } catch(e) { aMsg.innerText = "Error parsing archives."; }
                    } else { aMsg.innerText = "Connection lost."; }
                }
            };
            xhr.send(JSON.stringify({ prompt: val }));
        };
       
         input.onkeydown = function(e) { if (e.keyCode === 13) document.getElementById('lore-send').click(); };
     }
     }
})();
})();

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();
    }
})();