From 96476044387e98ee1ee7a6eb992b521bd447813c Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Fri, 3 Mar 2023 16:55:33 +0100 Subject: Renamed whiteboard to webchat --- html/index.html | 17 +-- html/pdf-icon-100.png | Bin 4526 -> 0 bytes html/pdf-icon-30.png | Bin 1356 -> 0 bytes html/pdf-icon-50.png | Bin 2317 -> 0 bytes html/pdf-icon.svg | 56 -------- html/stats.html | 2 +- html/stats.js | 6 +- html/webchat.css | 150 +++++++++++++++++++++ html/webchat.js | 351 ++++++++++++++++++++++++++++++++++++++++++++++++++ html/whiteboard.css | 150 --------------------- html/whiteboard.js | 351 -------------------------------------------------- 11 files changed, 512 insertions(+), 571 deletions(-) delete mode 100644 html/pdf-icon-100.png delete mode 100644 html/pdf-icon-30.png delete mode 100644 html/pdf-icon-50.png delete mode 100644 html/pdf-icon.svg create mode 100644 html/webchat.css create mode 100644 html/webchat.js delete mode 100644 html/whiteboard.css delete mode 100644 html/whiteboard.js (limited to 'html') diff --git a/html/index.html b/html/index.html index b72e23b..260b1a9 100644 --- a/html/index.html +++ b/html/index.html @@ -3,30 +3,27 @@ - - Reichwein Whiteboard + + Reichwein.IT Webchat - - - + + +
-

Whiteboard

+

Webchat



- - Starting up... -

- Reichwein.IT Whiteboard by https://www.reichwein.it
+ Reichwein.IT Webchat by https://www.reichwein.it
diff --git a/html/pdf-icon-100.png b/html/pdf-icon-100.png deleted file mode 100644 index 9a20387..0000000 Binary files a/html/pdf-icon-100.png and /dev/null differ diff --git a/html/pdf-icon-30.png b/html/pdf-icon-30.png deleted file mode 100644 index 5f60d2f..0000000 Binary files a/html/pdf-icon-30.png and /dev/null differ diff --git a/html/pdf-icon-50.png b/html/pdf-icon-50.png deleted file mode 100644 index 62873ea..0000000 Binary files a/html/pdf-icon-50.png and /dev/null differ diff --git a/html/pdf-icon.svg b/html/pdf-icon.svg deleted file mode 100644 index 8b30bbb..0000000 --- a/html/pdf-icon.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - PDF file icon - - - - - - - - - - image/svg+xml - - PDF file icon - 08/10/2018 - - - Adobe Systems - - - - - CMetalCore - - - Fuente del texto "PDF": -Franklin Gothic Medium Cond - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/html/stats.html b/html/stats.html index 3f7e141..9501c18 100644 --- a/html/stats.html +++ b/html/stats.html @@ -18,7 +18,7 @@

Statistics

- +
Active Connections:
Number of Documents:
Number of Users:
Database Size (gross):Bytes
Database Size (net):Bytes
diff --git a/html/stats.js b/html/stats.js index 89c674a..4174877 100644 --- a/html/stats.js +++ b/html/stats.js @@ -20,9 +20,9 @@ var websocket; // Callbacks for websocket data of different types // -function on_stats(numberofdocuments, numberofconnections, dbsizegross, dbsizenet) +function on_stats(numberofusers, numberofconnections, dbsizegross, dbsizenet) { - document.getElementById("numberofdocuments").textContent = numberofdocuments; + document.getElementById("numberofusers").textContent = numberofusers; document.getElementById("numberofconnections").textContent = numberofconnections; document.getElementById("dbsizegross").textContent = dbsizegross; document.getElementById("dbsizenet").textContent = dbsizenet; @@ -40,7 +40,7 @@ function on_message(e) { var type = xmlDocument.getElementsByTagName("type")[0].textContent; if (type == "stats") { - on_stats(xmlDocument.getElementsByTagName("numberofdocuments")[0].textContent, + on_stats(xmlDocument.getElementsByTagName("numberofusers")[0].textContent, xmlDocument.getElementsByTagName("numberofconnections")[0].textContent, xmlDocument.getElementsByTagName("dbsizegross")[0].textContent, xmlDocument.getElementsByTagName("dbsizenet")[0].textContent); diff --git a/html/webchat.css b/html/webchat.css new file mode 100644 index 0000000..2d222d5 --- /dev/null +++ b/html/webchat.css @@ -0,0 +1,150 @@ +body { + font-family: sans-serif; +} + +figcaption { + text-align: center; + font-size: 8px; + color: #808080; +} + +figure { + display: inline-block; +} + +p { + margin: 30px 0px 30px 0px; +} + +div.status { + color: #FF0000; +} + +span.helper { + display: inline-block; + height: 100%; + vertical-align: middle; +} + +img.center-img { + vertical-align: middle; +} + +.clickable { + cursor: pointer; +} + +textarea { + /* + height: 30vh; + padding: 1em; + font-size: 1.5em; + text-align: left; + border: 1px solid #000; + */ + box-sizing: border-box; + resize: none; + + width: 100%; + height: 540px; +} + +.qrwindow { + position: fixed; + top: 50%; + left: 50%; + width: 400px; + height: 400px; + margin-top: -200px; + margin-left: -200px; + background-color: #FFFFFF; + opacity: 1; + z-index: 10; + border-width: 3px; + border-style: solid; + border-color: #FFFFFF; + padding: 10pt; + box-sizing: border-box; +} + +.qrcode { + width: 374px; + height: 374px; + + image-rendering: optimizeSpeed; /* */ + image-rendering: -moz-crisp-edges; /* Firefox */ + image-rendering: -o-crisp-edges; /* Opera */ + image-rendering: -webkit-optimize-contrast; /* Chrome (and Safari) */ + image-rendering: pixelated; /* Chrome as of 2019 */ + image-rendering: optimize-contrast; /* CSS3 Proposed */ + -ms-interpolation-mode: nearest-neighbor; /* IE8+ */ +} + +.mobile { + width: 300px; + border-width: 80px 15px 80px 15px; + border-style: solid; + border-radius: 30px; + border-color: #000000; +} + +.logo { + display: block; + margin: 0 auto; +} + +.screenshot { + width: 400px; + border: 2px solid; + border-color: #8888AA; +} + +img.banner { + vertical-align: -5px; +} + +.button { + color:#FFFFFF; + background-color:#50B050; + text-decoration: none; + padding: 15px 20px; + font-size: 16px; + border: none; + border-radius: 6px; + cursor: pointer; +} + +.buttonred { + color:#FFFFFF; + background-color:#B05050; + text-decoration: none; + padding: 15px 20px; + font-size: 16px; + border: none; + border-radius: 6px; + cursor: pointer; +} + +@media only screen and (min-width: 1px) and (max-width: 630px) { + +.qrwindow { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + margin: 0; +} + +} + +@media only screen and (min-width: 631px) and (max-width: 950px) { +} + +@media only screen and (min-width: 951px) { + div.page { + max-width: 950px; + width: 100%; + margin: 0 auto; + } +} diff --git a/html/webchat.js b/html/webchat.js new file mode 100644 index 0000000..379c757 --- /dev/null +++ b/html/webchat.js @@ -0,0 +1,351 @@ +// started on main page load +function init() { + init_board(); +} + +var revision; +var modify_in_progress = 0; +var baseline = ""; // data contents relating to revision, acknowledged by server +var baseline_candidate = ""; // will become baseline, after ack by server + +// helper for breaking feedback loop +var caretpos = 0; + +function set_status(message) +{ + if (message == "") { + document.getElementById("status").textContent = message; + document.getElementById("status").style.display = 'inline'; + } else { + document.getElementById("status").textContent = ""; + document.getElementById("status").style.display = 'none'; + } +} + +function showQRWindow() +{ + document.getElementById("qrwindow").style.display = 'block'; +} + +function hideQRWindow() +{ + document.getElementById("qrwindow").style.display = 'none'; +} + +var websocket; + +// +// Callbacks for websocket data of different types +// + +function on_getfile(data, rev, pos) +{ + var board = document.getElementById("board"); + if (board.value != data) { + board.value = data; + } + revision = rev; + baseline = data; + textAreaSetPos("board", pos); +} + +function on_getdiff(diff, rev, pos) +{ + if (rev != revision + 1) + console.log("Revision skipped on diff receive: " + rev + " after " + revision); + + var board = document.getElementById("board"); + + var old_version_ptr = allocateUTF8(board.value); + var diff_ptr = allocateUTF8(new XMLSerializer().serializeToString(diff)); + var new_version_ptr = Module._diff_apply(old_version_ptr, diff_ptr); + var data = UTF8ToString(new_version_ptr); + board.value = data; + _free(old_version_ptr); + _free(new_version_ptr); + _free(diff_ptr); + + revision = rev; + baseline = data; + textAreaSetPos("board", pos); +} + +function on_getpos(pos) +{ + textAreaSetPos("board", pos); +} + +function on_newid(id) +{ + var new_location = document.location.origin + document.location.pathname + '?id=' + id; + window.location.href = new_location; +} + +function on_qrcode(png) +{ + var url = "data:image/png;base64," + png; + var img = document.getElementById("qrcode"); + img.src = url; + showQRWindow(); +} + +function on_version(version) +{ + document.getElementById("version").textContent = version; +} + +function on_pdf(pdf) +{ + var a = document.getElementById("download-a"); + a.href = "data:application/pdf;base64," + pdf; + a.download = get_id() + ".pdf" + a.click(); +} + +function on_modify_ack(rev) +{ + if (rev != revision + 1) + console.log("Revision skipped on published local change: " + rev + " after " + revision); + + revision = rev; + baseline = baseline_candidate; + modify_in_progress = 0; +} + +function on_message(e) { + var parser = new DOMParser(); + var xmlDocument = parser.parseFromString(e.data, "text/xml"); + + var type = xmlDocument.getElementsByTagName("type")[0].textContent; + + if (type == "getfile") { + on_getfile(xmlDocument.getElementsByTagName("data")[0].textContent, + parseInt(xmlDocument.getElementsByTagName("revision")[0].textContent), + parseInt(xmlDocument.getElementsByTagName("pos")[0].textContent)); + } else if (type == "getdiff") { + on_getdiff(xmlDocument.getElementsByTagName("diff")[0], + parseInt(xmlDocument.getElementsByTagName("revision")[0].textContent), + parseInt(xmlDocument.getElementsByTagName("pos")[0].textContent)); + } else if (type == "getpos") { + on_getpos(parseInt(xmlDocument.getElementsByTagName("pos")[0].textContent)); + } else if (type == "modify") { + on_modify_ack(parseInt(xmlDocument.getElementsByTagName("revision")[0].textContent)); + } else if (type == "newid") { + on_newid(xmlDocument.getElementsByTagName("id")[0].textContent); + } else if (type == "qrcode") { + on_qrcode(xmlDocument.getElementsByTagName("png")[0].textContent); + } else if (type == "version") { + on_version(xmlDocument.getElementsByTagName("version")[0].textContent); + } else if (type == "pdf") { + on_pdf(xmlDocument.getElementsByTagName("pdf")[0].textContent); + } else if (type == "error") { + alert(xmlDocument.getElementsByTagName("message")[0].textContent); + } else { + alert("Unhandled message type: " + e.data + "|" + type); + } +} + +function handleSelection() { + const activeElement = document.activeElement + + if (activeElement && activeElement.id === 'board') { + if (caretpos != activeElement.selectionStart) { + on_selectionchange(activeElement.selectionStart); + caretpos = activeElement.selectionStart; + } + } +} + +function connect_websocket() { + document.getElementById("reconnect").style.display = 'none'; + set_status("Connecting..."); + var newlocation = location.origin + location.pathname; + newlocation = newlocation.replace(/^http/, 'ws'); + if (newlocation.slice(-1) != "/") + newlocation += "/"; + newlocation += "websocket"; + + websocket = new WebSocket(newlocation); + + websocket.onmessage = function(e) { on_message(e); }; + + websocket.onopen = function(e) { + const searchParams = (new URL(document.location)).searchParams; + if (!searchParams.has('id')) { + redirect_to_new_page(); + return; + } + + websocket.send("getversion"); + websocket.send("getfile" + get_id() + ""); + set_status(""); // ok + document.getElementById("board").focus(); + }; + + websocket.onclose = function(e) { + alert("Server connection closed."); + document.getElementById("reconnect").style.display = 'inline'; + document.getElementById("reconnect").focus(); + }; + + websocket.onerror = function(e) { + alert("Error: Server connection closed."); + document.getElementById("reconnect").style.display = 'inline'; + document.getElementById("reconnect").focus(); + }; +} + +// button in html +function on_reconnect_click() { + connect_websocket(); +} + +function init_board() { + set_status("Loading..."); + Module.onRuntimeInitialized = () => { + connect_websocket(); + }; + + var board = document.getElementById("board"); + board.addEventListener("input", function() {on_input(); }); + // Need this workaround (different from direct on_selectionchange) for Chrome. + // Otherwise, callback will not be called on Chrome. + document.addEventListener("selectionchange", handleSelection); + //board.addEventListener("selectionchange", function() {on_selectionchange(); }); + + document.getElementById("qrwindow").onclick = function() { + hideQRWindow(); + } + + document.onkeydown = function(evt) { + if (evt.key == "Escape") { + hideQRWindow(); + } + } + + document.getElementById("board").focus(); +} + +function get_id() +{ + const searchParams = (new URL(document.location)).searchParams; + return searchParams.get('id'); +} + +// from html +function on_new_page() +{ + redirect_to_new_page(); +} + +function redirect_to_new_page() +{ + websocket.send("newid"); +} + +// local change done +function on_input() +{ + if (modify_in_progress == 1) { + console.log("Deferring on_input handler by 100ms"); + setTimeout(function(){on_input();}, 100); // re-try after 100ms + return; + } + modify_in_progress = 1; + + var parser = new DOMParser(); + var xmlDocument = parser.parseFromString("", "text/xml"); + + var requestElement = xmlDocument.getElementsByTagName("request")[0]; + + var commandElement = xmlDocument.createElement("command"); + commandElement.appendChild(document.createTextNode("modify")); + requestElement.appendChild(commandElement); + + var idElement = xmlDocument.createElement("id"); + idElement.appendChild(document.createTextNode(get_id())); + requestElement.appendChild(idElement); + + baseline_candidate = document.getElementById("board").value; + + if (baseline == baseline_candidate) { + modify_in_progress = 0; + return; + } + + var revisionElement = xmlDocument.createElement("baserev"); + revisionElement.appendChild(document.createTextNode(revision)); + requestElement.appendChild(revisionElement); + + var old_version = allocateUTF8(baseline); + var new_version = allocateUTF8(baseline_candidate); + var diff = Module._diff_create(old_version, new_version); + var diffDocument = parser.parseFromString(UTF8ToString(diff), "text/xml"); + _free(old_version); + _free(new_version); + _free(diff); + requestElement.appendChild(xmlDocument.importNode(diffDocument.getElementsByTagName("diff")[0], true)); + + var posElement = xmlDocument.createElement("pos"); + posElement.appendChild(document.createTextNode(document.getElementById("board").selectionStart)); + requestElement.appendChild(posElement); + + websocket.send(new XMLSerializer().serializeToString(xmlDocument)); +} + +// for cursor position +function on_selectionchange(pos) +{ + var parser = new DOMParser(); + var xmlDocument = parser.parseFromString("", "text/xml"); + + var requestElement = xmlDocument.getElementsByTagName("request")[0]; + + var commandElement = xmlDocument.createElement("command"); + commandElement.appendChild(document.createTextNode("cursorpos")); + requestElement.appendChild(commandElement); + + var idElement = xmlDocument.createElement("id"); + idElement.appendChild(document.createTextNode(get_id())); + requestElement.appendChild(idElement); + + var posElement = xmlDocument.createElement("pos"); + posElement.appendChild(document.createTextNode(pos)); + requestElement.appendChild(posElement); + + websocket.send(new XMLSerializer().serializeToString(xmlDocument)); +} + +function textAreaSetPos(id, pos) +{ + if (document.getElementById(id).selectionStart != pos) { + document.getElementById(id).selectionStart = pos; + document.getElementById(id).selectionEnd = pos; + caretpos = pos; + } +} + +// HTML button +function on_qrcode_click() +{ + var parser = new DOMParser(); + var xmlDocument = parser.parseFromString("", "text/xml"); + + var requestElement = xmlDocument.getElementsByTagName("request")[0]; + + var commandElement = xmlDocument.createElement("command"); + commandElement.appendChild(document.createTextNode("qrcode")); + requestElement.appendChild(commandElement); + + var idElement = xmlDocument.createElement("url"); + idElement.appendChild(document.createTextNode(document.location)); + requestElement.appendChild(idElement); + + websocket.send(new XMLSerializer().serializeToString(xmlDocument)); +} + +function on_pdf_click() +{ + websocket.send("pdf" + get_id() + ""); +} + diff --git a/html/whiteboard.css b/html/whiteboard.css deleted file mode 100644 index 2d222d5..0000000 --- a/html/whiteboard.css +++ /dev/null @@ -1,150 +0,0 @@ -body { - font-family: sans-serif; -} - -figcaption { - text-align: center; - font-size: 8px; - color: #808080; -} - -figure { - display: inline-block; -} - -p { - margin: 30px 0px 30px 0px; -} - -div.status { - color: #FF0000; -} - -span.helper { - display: inline-block; - height: 100%; - vertical-align: middle; -} - -img.center-img { - vertical-align: middle; -} - -.clickable { - cursor: pointer; -} - -textarea { - /* - height: 30vh; - padding: 1em; - font-size: 1.5em; - text-align: left; - border: 1px solid #000; - */ - box-sizing: border-box; - resize: none; - - width: 100%; - height: 540px; -} - -.qrwindow { - position: fixed; - top: 50%; - left: 50%; - width: 400px; - height: 400px; - margin-top: -200px; - margin-left: -200px; - background-color: #FFFFFF; - opacity: 1; - z-index: 10; - border-width: 3px; - border-style: solid; - border-color: #FFFFFF; - padding: 10pt; - box-sizing: border-box; -} - -.qrcode { - width: 374px; - height: 374px; - - image-rendering: optimizeSpeed; /* */ - image-rendering: -moz-crisp-edges; /* Firefox */ - image-rendering: -o-crisp-edges; /* Opera */ - image-rendering: -webkit-optimize-contrast; /* Chrome (and Safari) */ - image-rendering: pixelated; /* Chrome as of 2019 */ - image-rendering: optimize-contrast; /* CSS3 Proposed */ - -ms-interpolation-mode: nearest-neighbor; /* IE8+ */ -} - -.mobile { - width: 300px; - border-width: 80px 15px 80px 15px; - border-style: solid; - border-radius: 30px; - border-color: #000000; -} - -.logo { - display: block; - margin: 0 auto; -} - -.screenshot { - width: 400px; - border: 2px solid; - border-color: #8888AA; -} - -img.banner { - vertical-align: -5px; -} - -.button { - color:#FFFFFF; - background-color:#50B050; - text-decoration: none; - padding: 15px 20px; - font-size: 16px; - border: none; - border-radius: 6px; - cursor: pointer; -} - -.buttonred { - color:#FFFFFF; - background-color:#B05050; - text-decoration: none; - padding: 15px 20px; - font-size: 16px; - border: none; - border-radius: 6px; - cursor: pointer; -} - -@media only screen and (min-width: 1px) and (max-width: 630px) { - -.qrwindow { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - margin: 0; -} - -} - -@media only screen and (min-width: 631px) and (max-width: 950px) { -} - -@media only screen and (min-width: 951px) { - div.page { - max-width: 950px; - width: 100%; - margin: 0 auto; - } -} diff --git a/html/whiteboard.js b/html/whiteboard.js deleted file mode 100644 index 379c757..0000000 --- a/html/whiteboard.js +++ /dev/null @@ -1,351 +0,0 @@ -// started on main page load -function init() { - init_board(); -} - -var revision; -var modify_in_progress = 0; -var baseline = ""; // data contents relating to revision, acknowledged by server -var baseline_candidate = ""; // will become baseline, after ack by server - -// helper for breaking feedback loop -var caretpos = 0; - -function set_status(message) -{ - if (message == "") { - document.getElementById("status").textContent = message; - document.getElementById("status").style.display = 'inline'; - } else { - document.getElementById("status").textContent = ""; - document.getElementById("status").style.display = 'none'; - } -} - -function showQRWindow() -{ - document.getElementById("qrwindow").style.display = 'block'; -} - -function hideQRWindow() -{ - document.getElementById("qrwindow").style.display = 'none'; -} - -var websocket; - -// -// Callbacks for websocket data of different types -// - -function on_getfile(data, rev, pos) -{ - var board = document.getElementById("board"); - if (board.value != data) { - board.value = data; - } - revision = rev; - baseline = data; - textAreaSetPos("board", pos); -} - -function on_getdiff(diff, rev, pos) -{ - if (rev != revision + 1) - console.log("Revision skipped on diff receive: " + rev + " after " + revision); - - var board = document.getElementById("board"); - - var old_version_ptr = allocateUTF8(board.value); - var diff_ptr = allocateUTF8(new XMLSerializer().serializeToString(diff)); - var new_version_ptr = Module._diff_apply(old_version_ptr, diff_ptr); - var data = UTF8ToString(new_version_ptr); - board.value = data; - _free(old_version_ptr); - _free(new_version_ptr); - _free(diff_ptr); - - revision = rev; - baseline = data; - textAreaSetPos("board", pos); -} - -function on_getpos(pos) -{ - textAreaSetPos("board", pos); -} - -function on_newid(id) -{ - var new_location = document.location.origin + document.location.pathname + '?id=' + id; - window.location.href = new_location; -} - -function on_qrcode(png) -{ - var url = "data:image/png;base64," + png; - var img = document.getElementById("qrcode"); - img.src = url; - showQRWindow(); -} - -function on_version(version) -{ - document.getElementById("version").textContent = version; -} - -function on_pdf(pdf) -{ - var a = document.getElementById("download-a"); - a.href = "data:application/pdf;base64," + pdf; - a.download = get_id() + ".pdf" - a.click(); -} - -function on_modify_ack(rev) -{ - if (rev != revision + 1) - console.log("Revision skipped on published local change: " + rev + " after " + revision); - - revision = rev; - baseline = baseline_candidate; - modify_in_progress = 0; -} - -function on_message(e) { - var parser = new DOMParser(); - var xmlDocument = parser.parseFromString(e.data, "text/xml"); - - var type = xmlDocument.getElementsByTagName("type")[0].textContent; - - if (type == "getfile") { - on_getfile(xmlDocument.getElementsByTagName("data")[0].textContent, - parseInt(xmlDocument.getElementsByTagName("revision")[0].textContent), - parseInt(xmlDocument.getElementsByTagName("pos")[0].textContent)); - } else if (type == "getdiff") { - on_getdiff(xmlDocument.getElementsByTagName("diff")[0], - parseInt(xmlDocument.getElementsByTagName("revision")[0].textContent), - parseInt(xmlDocument.getElementsByTagName("pos")[0].textContent)); - } else if (type == "getpos") { - on_getpos(parseInt(xmlDocument.getElementsByTagName("pos")[0].textContent)); - } else if (type == "modify") { - on_modify_ack(parseInt(xmlDocument.getElementsByTagName("revision")[0].textContent)); - } else if (type == "newid") { - on_newid(xmlDocument.getElementsByTagName("id")[0].textContent); - } else if (type == "qrcode") { - on_qrcode(xmlDocument.getElementsByTagName("png")[0].textContent); - } else if (type == "version") { - on_version(xmlDocument.getElementsByTagName("version")[0].textContent); - } else if (type == "pdf") { - on_pdf(xmlDocument.getElementsByTagName("pdf")[0].textContent); - } else if (type == "error") { - alert(xmlDocument.getElementsByTagName("message")[0].textContent); - } else { - alert("Unhandled message type: " + e.data + "|" + type); - } -} - -function handleSelection() { - const activeElement = document.activeElement - - if (activeElement && activeElement.id === 'board') { - if (caretpos != activeElement.selectionStart) { - on_selectionchange(activeElement.selectionStart); - caretpos = activeElement.selectionStart; - } - } -} - -function connect_websocket() { - document.getElementById("reconnect").style.display = 'none'; - set_status("Connecting..."); - var newlocation = location.origin + location.pathname; - newlocation = newlocation.replace(/^http/, 'ws'); - if (newlocation.slice(-1) != "/") - newlocation += "/"; - newlocation += "websocket"; - - websocket = new WebSocket(newlocation); - - websocket.onmessage = function(e) { on_message(e); }; - - websocket.onopen = function(e) { - const searchParams = (new URL(document.location)).searchParams; - if (!searchParams.has('id')) { - redirect_to_new_page(); - return; - } - - websocket.send("getversion"); - websocket.send("getfile" + get_id() + ""); - set_status(""); // ok - document.getElementById("board").focus(); - }; - - websocket.onclose = function(e) { - alert("Server connection closed."); - document.getElementById("reconnect").style.display = 'inline'; - document.getElementById("reconnect").focus(); - }; - - websocket.onerror = function(e) { - alert("Error: Server connection closed."); - document.getElementById("reconnect").style.display = 'inline'; - document.getElementById("reconnect").focus(); - }; -} - -// button in html -function on_reconnect_click() { - connect_websocket(); -} - -function init_board() { - set_status("Loading..."); - Module.onRuntimeInitialized = () => { - connect_websocket(); - }; - - var board = document.getElementById("board"); - board.addEventListener("input", function() {on_input(); }); - // Need this workaround (different from direct on_selectionchange) for Chrome. - // Otherwise, callback will not be called on Chrome. - document.addEventListener("selectionchange", handleSelection); - //board.addEventListener("selectionchange", function() {on_selectionchange(); }); - - document.getElementById("qrwindow").onclick = function() { - hideQRWindow(); - } - - document.onkeydown = function(evt) { - if (evt.key == "Escape") { - hideQRWindow(); - } - } - - document.getElementById("board").focus(); -} - -function get_id() -{ - const searchParams = (new URL(document.location)).searchParams; - return searchParams.get('id'); -} - -// from html -function on_new_page() -{ - redirect_to_new_page(); -} - -function redirect_to_new_page() -{ - websocket.send("newid"); -} - -// local change done -function on_input() -{ - if (modify_in_progress == 1) { - console.log("Deferring on_input handler by 100ms"); - setTimeout(function(){on_input();}, 100); // re-try after 100ms - return; - } - modify_in_progress = 1; - - var parser = new DOMParser(); - var xmlDocument = parser.parseFromString("", "text/xml"); - - var requestElement = xmlDocument.getElementsByTagName("request")[0]; - - var commandElement = xmlDocument.createElement("command"); - commandElement.appendChild(document.createTextNode("modify")); - requestElement.appendChild(commandElement); - - var idElement = xmlDocument.createElement("id"); - idElement.appendChild(document.createTextNode(get_id())); - requestElement.appendChild(idElement); - - baseline_candidate = document.getElementById("board").value; - - if (baseline == baseline_candidate) { - modify_in_progress = 0; - return; - } - - var revisionElement = xmlDocument.createElement("baserev"); - revisionElement.appendChild(document.createTextNode(revision)); - requestElement.appendChild(revisionElement); - - var old_version = allocateUTF8(baseline); - var new_version = allocateUTF8(baseline_candidate); - var diff = Module._diff_create(old_version, new_version); - var diffDocument = parser.parseFromString(UTF8ToString(diff), "text/xml"); - _free(old_version); - _free(new_version); - _free(diff); - requestElement.appendChild(xmlDocument.importNode(diffDocument.getElementsByTagName("diff")[0], true)); - - var posElement = xmlDocument.createElement("pos"); - posElement.appendChild(document.createTextNode(document.getElementById("board").selectionStart)); - requestElement.appendChild(posElement); - - websocket.send(new XMLSerializer().serializeToString(xmlDocument)); -} - -// for cursor position -function on_selectionchange(pos) -{ - var parser = new DOMParser(); - var xmlDocument = parser.parseFromString("", "text/xml"); - - var requestElement = xmlDocument.getElementsByTagName("request")[0]; - - var commandElement = xmlDocument.createElement("command"); - commandElement.appendChild(document.createTextNode("cursorpos")); - requestElement.appendChild(commandElement); - - var idElement = xmlDocument.createElement("id"); - idElement.appendChild(document.createTextNode(get_id())); - requestElement.appendChild(idElement); - - var posElement = xmlDocument.createElement("pos"); - posElement.appendChild(document.createTextNode(pos)); - requestElement.appendChild(posElement); - - websocket.send(new XMLSerializer().serializeToString(xmlDocument)); -} - -function textAreaSetPos(id, pos) -{ - if (document.getElementById(id).selectionStart != pos) { - document.getElementById(id).selectionStart = pos; - document.getElementById(id).selectionEnd = pos; - caretpos = pos; - } -} - -// HTML button -function on_qrcode_click() -{ - var parser = new DOMParser(); - var xmlDocument = parser.parseFromString("", "text/xml"); - - var requestElement = xmlDocument.getElementsByTagName("request")[0]; - - var commandElement = xmlDocument.createElement("command"); - commandElement.appendChild(document.createTextNode("qrcode")); - requestElement.appendChild(commandElement); - - var idElement = xmlDocument.createElement("url"); - idElement.appendChild(document.createTextNode(document.location)); - requestElement.appendChild(idElement); - - websocket.send(new XMLSerializer().serializeToString(xmlDocument)); -} - -function on_pdf_click() -{ - websocket.send("pdf" + get_id() + ""); -} - -- cgit v1.2.3