LAN_Portal/chat/chat-live.js
2026-10-16 16:22:59 -04:00

58 lines
2.2 KiB
JavaScript
Executable file

// Live chat: sends forms without reloading the page and refreshes the message list every 3 seconds.
(function () {
var box = document.getElementById('chat');
var log = document.getElementById('chat-log');
var notice = document.getElementById('chat-notice');
if (!box || !log || !notice || !window.fetch || !window.DOMParser) return;
var busy = false;
log.scrollTop = log.scrollHeight;
// Copy the chat log (and optionally the notice) out of a fresh copy of the page.
// Returns false if the server reported an error.
function show(html, withNotice) {
var doc = new DOMParser().parseFromString(html, 'text/html');
var newLog = doc.getElementById('chat-log');
var newNotice = doc.getElementById('chat-notice');
if (!newLog) return false;
if (log.innerHTML !== newLog.innerHTML) {
var stick = log.scrollHeight - log.scrollTop - log.clientHeight < 40; // only follow if already at the bottom
var top = log.scrollTop;
log.innerHTML = newLog.innerHTML;
log.scrollTop = stick ? log.scrollHeight : top;
box.dispatchEvent(new CustomEvent('chat:updated')); // lets features react
}
if (withNotice) notice.innerHTML = newNotice ? newNotice.innerHTML : '';
return !(newNotice && newNotice.querySelector('.alert-danger'));
}
box.addEventListener('submit', function (e) {
var form = e.target;
e.preventDefault();
if (busy) return;
busy = true;
fetch('', { method: 'POST', body: new FormData(form) })
.then(function (r) { return r.text(); })
.then(function (html) {
var ok = show(html, true);
if (form.chat_text) {
if (ok) form.chat_text.value = '';
form.chat_text.focus();
log.scrollTop = log.scrollHeight;
}
})
.catch(function () {
notice.innerHTML = '<div class="alert alert-danger">Could not reach the server.</div>';
})
.then(function () { busy = false; });
});
var ticks = 0;
setInterval(function () {
if (busy || (document.hidden && ++ticks % 5)) return; // hidden tabs poll every 15 seconds
fetch('', { cache: 'no-store' })
.then(function (r) { return r.text(); })
.then(function (html) { show(html, false); })
.catch(function () {});
}, 3000);
})();