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

From DQWiki
Jump to navigationJump to search
mNo edit summary
mNo edit summary
Line 1: Line 1:
/* Lorekeeper Standalone Terminal v2 */
/* Lorekeeper Standalone Terminal v3 - Failsafe ES5 */
(function() {
(function() {
     function initLorekeeper() {
     var checkCount = 0;
    var initTimer = setInterval(function() {
        checkCount++;
        if (document.body) {
            clearInterval(initTimer);
            setupLore();
        }
        if (checkCount > 100) clearInterval(initTimer); // Stop trying after 10s
    }, 100);
 
    function setupLore() {
         if (document.getElementById('lore-terminal-btn')) return;
         if (document.getElementById('lore-terminal-btn')) return;


Line 7: Line 17:
         var btn = document.createElement('div');
         var btn = document.createElement('div');
         btn.id = 'lore-terminal-btn';
         btn.id = 'lore-terminal-btn';
         btn.innerHTML = '?';
         btn.innerHTML = '✨'; // Sparkles icon
         btn.style.cssText = 'position:fixed !important; bottom:30px !important; right:30px !important; width:60px; height:60px; background:#8b5cf6; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:30px; cursor:pointer; box-shadow:0 10px 25px rgba(139,92,246,0.6); z-index:9999999 !important; border:2px solid rgba(255,255,255,0.3); transition: transform 0.2s ease;';
         btn.setAttribute('style', 'position:fixed !important; bottom:20px !important; right:20px !important; width:60px !important; height:60px !important; background:#8b5cf6 !important; border-radius:50% !important; display:flex !important; align-items:center !important; justify-content:center !important; font-size:30px !important; cursor:pointer !important; box-shadow:0 10px 25px rgba(0,0,0,0.5) !important; z-index:999999 !important; border:2px solid #fff !important;');
       
 
         // 2. Create Chat Box
         // 2. Create Box
         var box = document.createElement('div');
         var box = document.createElement('div');
         box.id = 'lore-terminal-box';
         box.id = 'lore-terminal-box';
         box.style.cssText = 'position:fixed !important; bottom:100px !important; right:30px !important; width:400px; height:600px; background:rgb(15,15,20); border:1px solid rgba(139,92,246,0.5); border-radius:24px; display:none; flex-direction:column; box-shadow:0 25px 60px rgba(0,0,0,0.8); overflow:hidden; z-index:9999999 !important; color:#ffffff; font-family: sans-serif;';
         box.setAttribute('style', 'position:fixed !important; bottom:90px !important; right:20px !important; width:380px !important; height:550px !important; background:#0f0f14 !important; border:2px solid #8b5cf6 !important; border-radius:15px !important; display:none; flex-direction:column !important; box-shadow:0 20px 50px rgba(0,0,0,0.8) !important; z-index:999999 !important; color:#fff !important; font-family:sans-serif !important;');
          
          
         box.innerHTML =  
         box.innerHTML =  
             '<div style="padding:15px 20px; background:rgba(139,92,246,0.15); border-bottom:1px solid rgba(139,92,246,0.3); display:flex; justify-content:space-between; align-items:center;">' +
             '<div style="padding:15px; border-bottom:1px solid #333; display:flex; justify-content:space-between; align-items:center;">' +
                 '<div style="font-weight:bold; color:#a78bfa; font-size:16px;">Archives of the Western Kingdom</div>' +
                 '<b style="color:#a78bfa">Lorekeeper Terminal</b>' +
                 '<div id="lore-close" style="cursor:pointer; font-size:20px; color:#fff; padding:5px;">?</div>' +
                 '<span id="lore-close" style="cursor:pointer; padding:5px;">&times;</span>' +
             '</div>' +
             '</div>' +
             '<div id="lore-chat" style="flex:1; overflow-y:auto; padding:20px; display:flex; flex-direction:column; gap:12px; font-size:14px; line-height:1.5;">' +
             '<div id="lore-chat" style="flex:1; overflow-y:auto; padding:15px; font-size:13px; line-height:1.4;">' +
                 '<div style="background:rgba(255,255,255,0.08); padding:12px 16px; border-radius:12px; border-left:4px solid #8b5cf6;">Greetings, Scribe. What knowledge do you seek from the archives?</div>' +
                 '<div style="background:#1a1a24; padding:10px; border-radius:8px; margin-bottom:10px;">The archives are ready. What is your inquiry?</div>' +
             '</div>' +
             '</div>' +
             '<div style="padding:15px; background:rgba(0,0,0,0.3); border-top:1px solid rgba(255,255,255,0.1); display:flex; gap:10px;">' +
             '<div style="padding:15px; border-top:1px solid #333; display:flex;">' +
                 '<input id="lore-input" placeholder="Ask about the Iron Guild..." style="flex:1; background:rgba(255,255,255,0.05); border:1px solid rgba(139,92,246,0.3); padding:10px 14px; border-radius:10px; color:#fff; outline:none; font-size:14px;">' +
                 '<input id="lore-input" type="text" style="flex:1; background:#000; color:#fff; border:1px solid #444; padding:8px; border-radius:5px; outline:none;">' +
                 '<button id="lore-send" style="background:#8b5cf6; border:none; color:#fff; padding:0 18px; border-radius:10px; cursor:pointer; font-weight:bold; font-size:14px;">Ask</button>' +
                 '<button id="lore-send" style="margin-left:5px; background:#8b5cf6; color:#fff; border:none; padding:8px 15px; border-radius:5px; cursor:pointer;">Ask</button>' +
             '</div>';
             '</div>';


Line 31: Line 41:
         document.body.appendChild(box);
         document.body.appendChild(box);


         // Events
         // Logic
        var chat = document.getElementById('lore-chat');
        var input = document.getElementById('lore-input');
        var send = document.getElementById('lore-send');
        var convId = 'anon-' + Math.random().toString(36).substring(7);
 
         btn.onclick = function() {
         btn.onclick = function() {
             box.style.display = (box.style.display === 'none' || box.style.display === '') ? 'flex' : 'none';
             box.style.display = (box.style.display == 'none') ? 'flex' : 'none';
         };
         };
         document.getElementById('lore-close').onclick = function() { box.style.display = 'none'; };
         document.getElementById('lore-close').onclick = function() { box.style.display = 'none'; };


         async function handleAsk() {
         var input = document.getElementById('lore-input');
             var text = input.value.trim();
        var chat = document.getElementById('lore-chat');
             if (!text) return;
 
        document.getElementById('lore-send').onclick = function() {
             var val = input.value.trim();
             if (!val) return;
             input.value = '';
             input.value = '';


            // User UI
             var uMsg = document.createElement('div');
             var uDiv = document.createElement('div');
             uMsg.style.cssText = 'margin-bottom:10px; background:#8b5cf6; padding:8px; border-radius:8px; align-self:flex-end;';
             uDiv.style.cssText = 'align-self:flex-end; background:#8b5cf6; padding:10px 14px; border-radius:12px; max-width:85%; font-weight:500;';
             uMsg.innerText = val;
            uDiv.textContent = text;
             chat.appendChild(uMsg);
            chat.appendChild(uDiv);
            chat.scrollTop = chat.scrollHeight;
 
            // AI UI Placeholder
            var aDiv = document.createElement('div');
            aDiv.style.cssText = 'background:rgba(255,255,255,0.05); padding:12px 16px; border-radius:12px; max-width:92%; border-left:4px solid #8b5cf6; white-space: pre-wrap;';
             aDiv.innerHTML = '<i>Searching the archives...</i>';
             chat.appendChild(aDiv);
 
            try {
                const response = await fetch('https://npc-forge--npc-forge-qh4gc.asia-southeast1.hosted.app/api/lore/stream', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ question: text, conversationId: convId })
                });


                const reader = response.body.getReader();
            var aMsg = document.createElement('div');
                const decoder = new TextDecoder();
            aMsg.style.cssText = 'margin-bottom:10px; background:#222; padding:10px; border-radius:8px; border-left:3px solid #8b5cf6;';
                aDiv.textContent = '';
            aMsg.innerText = 'Consulting the records...';
                var content = '';
            chat.appendChild(aMsg);


                while (true) {
            // Using simple AJAX for compatibility
                    const { done, value } = await reader.read();
            var xhr = new XMLHttpRequest();
                     if (done) break;
            xhr.open("POST", "https://npc-forge--npc-forge-qh4gc.asia-southeast1.hosted.app/api/askLore", true);
                    content += decoder.decode(value);
            xhr.setRequestHeader("Content-Type", "application/json");
                    aDiv.textContent = content; // Typewriter
            xhr.onreadystatechange = function() {
                     chat.scrollTop = chat.scrollHeight;
                if (xhr.readyState === 4) {
                     if (xhr.status === 200) {
                        try {
                            var response = JSON.parse(xhr.responseText);
                            aMsg.innerText = response.text || response.data.text;
                        } catch(e) { aMsg.innerText = "Error parsing response."; }
                     } else {
                        aMsg.innerText = "API Error: " + xhr.status;
                    }
                 }
                 }
             } catch (e) {
             };
                aDiv.innerHTML = '<span style="color:#f87171;">Connection to archives lost.</span>';
             xhr.send(JSON.stringify({ prompt: val }));
             }
         };
        }
 
        send.onclick = handleAsk;
        input.onkeydown = function(e) { if (e.key === 'Enter') handleAsk(); };
    }
 
    // Wait for the document to be ready
    if (document.readyState === "complete" || document.readyState === "interactive") {
         initLorekeeper();
    } else {
        window.addEventListener("DOMContentLoaded", initLorekeeper);
     }
     }
})();
})();

Revision as of 07:58, 25 February 2026

/* Lorekeeper Standalone Terminal v3 - Failsafe ES5 */
(function() {
    var checkCount = 0;
    var initTimer = setInterval(function() {
        checkCount++;
        if (document.body) {
            clearInterval(initTimer);
            setupLore();
        }
        if (checkCount > 100) clearInterval(initTimer); // Stop trying after 10s
    }, 100);

    function setupLore() {
        if (document.getElementById('lore-terminal-btn')) return;

        // 1. Create Floating Button
        var btn = document.createElement('div');
        btn.id = 'lore-terminal-btn';
        btn.innerHTML = '&#10024;'; // Sparkles icon
        btn.setAttribute('style', 'position:fixed !important; bottom:20px !important; right:20px !important; width:60px !important; height:60px !important; background:#8b5cf6 !important; border-radius:50% !important; display:flex !important; align-items:center !important; justify-content:center !important; font-size:30px !important; cursor:pointer !important; box-shadow:0 10px 25px rgba(0,0,0,0.5) !important; z-index:999999 !important; border:2px solid #fff !important;');

        // 2. Create Box
        var box = document.createElement('div');
        box.id = 'lore-terminal-box';
        box.setAttribute('style', 'position:fixed !important; bottom:90px !important; right:20px !important; width:380px !important; height:550px !important; background:#0f0f14 !important; border:2px solid #8b5cf6 !important; border-radius:15px !important; display:none; flex-direction:column !important; box-shadow:0 20px 50px rgba(0,0,0,0.8) !important; z-index:999999 !important; color:#fff !important; font-family:sans-serif !important;');
        
        box.innerHTML = 
            '<div style="padding:15px; border-bottom:1px solid #333; display:flex; justify-content:space-between; align-items:center;">' +
                '<b style="color:#a78bfa">Lorekeeper Terminal</b>' +
                '<span id="lore-close" style="cursor:pointer; padding:5px;">&times;</span>' +
            '</div>' +
            '<div id="lore-chat" style="flex:1; overflow-y:auto; padding:15px; font-size:13px; line-height:1.4;">' +
                '<div style="background:#1a1a24; padding:10px; border-radius:8px; margin-bottom:10px;">The archives are ready. What is your inquiry?</div>' +
            '</div>' +
            '<div style="padding:15px; border-top:1px solid #333; display:flex;">' +
                '<input id="lore-input" type="text" style="flex:1; background:#000; color:#fff; border:1px solid #444; padding:8px; border-radius:5px; outline:none;">' +
                '<button id="lore-send" style="margin-left:5px; background:#8b5cf6; color:#fff; border:none; padding:8px 15px; border-radius:5px; cursor:pointer;">Ask</button>' +
            '</div>';

        document.body.appendChild(btn);
        document.body.appendChild(box);

        // Logic
        btn.onclick = function() {
            box.style.display = (box.style.display == 'none') ? 'flex' : 'none';
        };
        document.getElementById('lore-close').onclick = function() { box.style.display = 'none'; };

        var input = document.getElementById('lore-input');
        var chat = document.getElementById('lore-chat');

        document.getElementById('lore-send').onclick = function() {
            var val = input.value.trim();
            if (!val) return;
            input.value = '';

            var uMsg = document.createElement('div');
            uMsg.style.cssText = 'margin-bottom:10px; background:#8b5cf6; padding:8px; border-radius:8px; align-self:flex-end;';
            uMsg.innerText = val;
            chat.appendChild(uMsg);

            var aMsg = document.createElement('div');
            aMsg.style.cssText = 'margin-bottom:10px; background:#222; padding:10px; border-radius:8px; border-left:3px solid #8b5cf6;';
            aMsg.innerText = 'Consulting the records...';
            chat.appendChild(aMsg);

            // Using simple AJAX for compatibility
            var xhr = new XMLHttpRequest();
            xhr.open("POST", "https://npc-forge--npc-forge-qh4gc.asia-southeast1.hosted.app/api/askLore", true);
            xhr.setRequestHeader("Content-Type", "application/json");
            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;
                        } catch(e) { aMsg.innerText = "Error parsing response."; }
                    } else {
                        aMsg.innerText = "API Error: " + xhr.status;
                    }
                }
            };
            xhr.send(JSON.stringify({ prompt: val }));
        };
    }
})();