const areaId = "doctext"; const validEvents = [ "insertText", "insertFromPaste", "insertLineBreak", "deleteContentBackward", "deleteContentForward", ]; let selectionStart = 0; let selectionEnd = 0; let area; let ws; const uuid = self.crypto.randomUUID(); const wsUrl = "ws://localhost:3000/ws"; function setup() { area = document.querySelector(`#${areaId}`); ws = new WebSocket(wsUrl); setupUi(); setupWs(); } function setupUi() { document.addEventListener("selectionchange", onSelectionChange, false); area.addEventListener("input", onInput, false); } function setupWs() { ws.onclose = function (e) { console.log(e); setTimeout(() => { ws = new WebSocket(wsUrl); }, 2000); }; ws.onmessage = function (e) { let payload = JSON.parse(e.data); if (payload.client !== uuid) { area.value = payload.doc; } }; } function onSelectionChange() { const activeElement = document.activeElement; if (activeElement && activeElement.id === areaId) { selectionStart = area.selectionStart; selectionEnd = area.selectionEnd; } } function onInput(event) { if (!validEvents.includes(event.inputType)) return; const payload = { client: uuid, time: performance.now(), action: event.inputType, data: event.data, start: selectionStart, end: selectionEnd, }; ws.send(JSON.stringify(payload)); console.log(event.inputType); console.log(selectionStart); console.log(selectionEnd); console.log(event.data); }