58 lines
2.2 KiB
JavaScript
Executable file
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);
|
|
})();
|