MediaWiki:Common.js
Appearance
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/**
* Retina Chip Wiki chat widget (wiki3.rohmega.com).
* Floating chat bubble in the bottom-right. Grounded Q&A over the wiki.
* Public wiki -> the backend enforces a daily token budget.
*
* ES5-safe only: ResourceLoader minifier rejects trailing commas in call args,
* arrow functions, template literals.
*/
(function () {
'use strict';
// Don't double-inject
if (document.getElementById('rmg-chat-root')) {
return;
}
var CHAT_ENDPOINT = '/chat/chat'; // same-origin via Caddy /chat/* -> :8111
function buildUI() {
var root = document.createElement('div');
root.id = 'rmg-chat-root';
// --- floating toggle button ---
var btn = document.createElement('button');
btn.id = 'rmg-chat-toggle';
btn.setAttribute('aria-label', 'Ask the wiki');
btn.textContent = '💬';
root.appendChild(btn);
// --- panel ---
var panel = document.createElement('div');
panel.id = 'rmg-chat-panel';
panel.style.display = 'none';
var head = document.createElement('div');
head.id = 'rmg-chat-head';
var title = document.createElement('span');
title.textContent = 'Ask the Retina Chip Wiki';
var close = document.createElement('button');
close.textContent = '×';
close.setAttribute('aria-label', 'Close');
head.appendChild(title);
head.appendChild(close);
panel.appendChild(head);
var msgs = document.createElement('div');
msgs.id = 'rmg-chat-msgs';
panel.appendChild(msgs);
var foot = document.createElement('div');
foot.id = 'rmg-chat-foot';
var input = document.createElement('input');
input.id = 'rmg-chat-input';
input.setAttribute('placeholder', 'Ask about blocks, ADRs, methods…');
var send = document.createElement('button');
send.id = 'rmg-chat-send';
send.textContent = 'Send';
foot.appendChild(input);
foot.appendChild(send);
panel.appendChild(foot);
root.appendChild(panel);
document.body.appendChild(root);
// wire events
btn.addEventListener('click', function () {
var open = panel.style.display !== 'none';
panel.style.display = open ? 'none' : 'block';
});
close.addEventListener('click', function () {
panel.style.display = 'none';
});
send.addEventListener('click', ask);
input.addEventListener('keydown', function (e) {
if (e.key === 'Enter') {
ask();
}
});
}
function addBubble(text, who) {
var msgs = document.getElementById('rmg-chat-msgs');
var b = document.createElement('div');
b.className = 'rmg-bubble ' + who;
b.textContent = text;
msgs.appendChild(b);
msgs.scrollTop = msgs.scrollHeight;
return b;
}
function ask() {
var input = document.getElementById('rmg-chat-input');
var send = document.getElementById('rmg-chat-send');
var q = input.value.trim();
if (!q) {
return;
}
input.value = '';
addBubble(q, 'user');
send.disabled = true;
var typing = addBubble('…', 'bot');
var xhr = new XMLHttpRequest();
xhr.open('POST', CHAT_ENDPOINT, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) {
return;
}
send.disabled = false;
if (xhr.status === 200) {
try {
var d = JSON.parse(xhr.responseText);
typing.textContent = d.answer || '(no answer)';
} catch (err) {
typing.textContent = 'Error reading response.';
}
} else {
try {
var e = JSON.parse(xhr.responseText);
typing.textContent = e.answer || ('Error ' + xhr.status);
} catch (err) {
typing.textContent = 'Error ' + xhr.status;
}
}
};
xhr.send(JSON.stringify({ message: q }));
}
// Run after DOM ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', buildUI);
} else {
buildUI();
}
})();