// 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 = '
Could not reach the server.
'; }) .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); })();