User:Jono Bean/common.js: Difference between revisions
From DQWiki
Jump to navigationJump to search
(Replaced content with "alert("The Lorekeeper is awake!");") Tag: Replaced |
mNo edit summary |
||
| Line 1: | Line 1: | ||
/* Lorekeeper Standalone Terminal v2 */ | |||
(function() { | |||
function initLorekeeper() { | |||
if (document.getElementById('lore-terminal-btn')) return; | |||
// 1. Create Floating Button | |||
var btn = document.createElement('div'); | |||
btn.id = 'lore-terminal-btn'; | |||
btn.innerHTML = '?'; | |||
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;'; | |||
// 2. Create Chat Box | |||
var box = document.createElement('div'); | |||
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.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="font-weight:bold; color:#a78bfa; font-size:16px;">Archives of the Western Kingdom</div>' + | |||
'<div id="lore-close" style="cursor:pointer; font-size:20px; color:#fff; padding:5px;">?</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 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>' + | |||
'<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;">' + | |||
'<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;">' + | |||
'<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>' + | |||
'</div>'; | |||
document.body.appendChild(btn); | |||
document.body.appendChild(box); | |||
// Events | |||
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() { | |||
box.style.display = (box.style.display === 'none' || box.style.display === '') ? 'flex' : 'none'; | |||
}; | |||
document.getElementById('lore-close').onclick = function() { box.style.display = 'none'; }; | |||
async function handleAsk() { | |||
var text = input.value.trim(); | |||
if (!text) return; | |||
input.value = ''; | |||
// User UI | |||
var uDiv = document.createElement('div'); | |||
uDiv.style.cssText = 'align-self:flex-end; background:#8b5cf6; padding:10px 14px; border-radius:12px; max-width:85%; font-weight:500;'; | |||
uDiv.textContent = text; | |||
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(); | |||
const decoder = new TextDecoder(); | |||
aDiv.textContent = ''; | |||
var content = ''; | |||
while (true) { | |||
const { done, value } = await reader.read(); | |||
if (done) break; | |||
content += decoder.decode(value); | |||
aDiv.textContent = content; // Typewriter | |||
chat.scrollTop = chat.scrollHeight; | |||
} | |||
} catch (e) { | |||
aDiv.innerHTML = '<span style="color:#f87171;">Connection to archives lost.</span>'; | |||
} | |||
} | |||
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:57, 25 February 2026
/* Lorekeeper Standalone Terminal v2 */
(function() {
function initLorekeeper() {
if (document.getElementById('lore-terminal-btn')) return;
// 1. Create Floating Button
var btn = document.createElement('div');
btn.id = 'lore-terminal-btn';
btn.innerHTML = '?';
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;';
// 2. Create Chat Box
var box = document.createElement('div');
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.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="font-weight:bold; color:#a78bfa; font-size:16px;">Archives of the Western Kingdom</div>' +
'<div id="lore-close" style="cursor:pointer; font-size:20px; color:#fff; padding:5px;">?</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 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>' +
'<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;">' +
'<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;">' +
'<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>' +
'</div>';
document.body.appendChild(btn);
document.body.appendChild(box);
// Events
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() {
box.style.display = (box.style.display === 'none' || box.style.display === '') ? 'flex' : 'none';
};
document.getElementById('lore-close').onclick = function() { box.style.display = 'none'; };
async function handleAsk() {
var text = input.value.trim();
if (!text) return;
input.value = '';
// User UI
var uDiv = document.createElement('div');
uDiv.style.cssText = 'align-self:flex-end; background:#8b5cf6; padding:10px 14px; border-radius:12px; max-width:85%; font-weight:500;';
uDiv.textContent = text;
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();
const decoder = new TextDecoder();
aDiv.textContent = '';
var content = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
content += decoder.decode(value);
aDiv.textContent = content; // Typewriter
chat.scrollTop = chat.scrollHeight;
}
} catch (e) {
aDiv.innerHTML = '<span style="color:#f87171;">Connection to archives lost.</span>';
}
}
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);
}
})();