;(() => { // expectingMessage is set to true // if the user has just submitted a message // and so we should scroll the next message into view when received. let expectingMessage = false function dial() { const conn = new WebSocket(`ws://${location.host}/subscribe`) conn.addEventListener("close", ev => { appendLog(`WebSocket Disconnected code: ${ev.code}, reason: ${ev.reason}`, true) if (ev.code !== 1001) { appendLog("Reconnecting in 1s", true) setTimeout(dial, 1000) } }) conn.addEventListener("open", ev => { console.info("websocket connected") }) // This is where we handle messages received. conn.addEventListener("message", ev => { if (typeof ev.data !== "string") { console.error("unexpected message type", typeof ev.data) return } const p = appendLog(ev.data) if (expectingMessage) { p.scrollIntoView() expectingMessage = false } }) } dial() const messageLog = document.getElementById("message-log") const publishForm = document.getElementById("publish-form") const messageInput = document.getElementById("message-input") // appendLog appends the passed text to messageLog. function appendLog(text, error) { const p = document.createElement("p") // Adding a timestamp to each message makes the log easier to read. p.innerText = `${new Date().toLocaleTimeString()}: ${text}` if (error) { p.style.color = "red" p.style.fontStyle = "bold" } messageLog.append(p) return p } appendLog("Submit a message to get started!") // onsubmit publishes the message from the user when the form is submitted. publishForm.onsubmit = async ev => { ev.preventDefault() const msg = messageInput.value if (msg === "") { return } messageInput.value = "" expectingMessage = true try { const resp = await fetch("/publish", { method: "POST", body: msg, }) if (resp.status !== 202) { throw new Error(`Unexpected HTTP Status ${resp.status} ${resp.statusText}`) } } catch (err) { appendLog(`Publish failed: ${err.message}`, true) } } })()