import init, { State } from "/dist_text_js.js"; await init(); const areaId = "doctext"; const validEvents = [ "insertText", "insertFromPaste", "insertLineBreak", "insertCompositionText", "deleteContentBackward", "deleteContentForward", ]; let selectionStart = 0; let selectionEnd = 0; let area; let ws; const uuid = self.crypto.randomUUID(); const wsUrl = "ws://localhost:3000/ws"; const state = State.default(); function setup() { area = document.querySelector(`#${areaId}`); ws = new WebSocket(wsUrl); setupUi(); setupWs(); } function setupUi() { document.addEventListener("selectionchange", onSelectionChange, false); area.addEventListener("beforeinput", 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) { const newText = state.apply(payload.ops); state.text = payload.ops.length > 0 ? newText : payload.doc; area.value = state.text; } }; } function onSelectionChange() { const activeElement = document.activeElement; if (activeElement && activeElement.id === areaId) { selectionStart = area.selectionStart; selectionEnd = area.selectionEnd; } } function onInput(event) { const data = event.data ? event.data : ""; let ops = state.execute(event.inputType, selectionStart, selectionEnd, data, uuid); if (!validEvents.includes(event.inputType)) return; const payload = { client: uuid, ops }; ws.send(JSON.stringify(payload)); console.log(selectionStart, selectionEnd); // workaround for differences between firefox and chrome // chrome does not fire selectionchange events on backspace/delete events, // while firefox does if (event.inputType === "deleteContentBackward") { selectionStart = area.selectionStart - 1; selectionEnd = area.selectionEnd - 1; } } setup();