From 5aaf30934a4e4df06c7f56ac77af847870caf1dd Mon Sep 17 00:00:00 2001 From: Aljaz Grilc Date: Fri, 2 Feb 2024 11:03:37 +0100 Subject: [PATCH] Rename classes to follow 'bes-xyz' naming convention and apply JavaScript formatter --- index.html | 30 ++++++++--- online-editor.js | 133 +++++++++++++++++++++++++++++------------------ styles.css | 27 +--------- 3 files changed, 106 insertions(+), 84 deletions(-) diff --git a/index.html b/index.html index 4f2b3a4..85bed43 100644 --- a/index.html +++ b/index.html @@ -9,15 +9,31 @@ - - + +
-
Popravite kar želite.
Na mizo nisem položil knjigo. Popravite kar želite.
+
Popravite kar želite.
Na mizo nisem položil knjigo. Popravite kar želite.
+ \ No newline at end of file diff --git a/online-editor.js b/online-editor.js index d5813fe..50d688a 100644 --- a/online-editor.js +++ b/online-editor.js @@ -4,21 +4,24 @@ let besEditors = {} // Collection of all editors on page window.onload = () => { // Search and prepare all our editors found in the document. - document.querySelectorAll('.online-editor').forEach(edit => { + document.querySelectorAll('.bes-online-editor').forEach(edit => { let editor = { timer: null } besEditors[edit.id] = editor besProof(edit) - edit.addEventListener('beforeinput', e => besHandleBeforeInput(edit.id, e), false) + edit.addEventListener( + 'beforeinput', + e => besHandleBeforeInput(edit.id, e), + false + ) edit.addEventListener('click', e => besHandleClick(e)) // TODO: Handle editor resizes. }) } // Recursively grammar-proofs one node. -async function besProof(el) -{ +async function besProof(el) { switch (el.nodeType) { case Node.TEXT_NODE: return [{ text: el.textContent, el: el, markup: false }] @@ -27,7 +30,7 @@ async function besProof(el) if (besIsBlockElement(el)) { // Block elements are grammar-proofed independently. if (besIsProofed(el)) { - return [{ text: '<'+el.tagName+'/>', el: el, markup: true }] + return [{ text: '<' + el.tagName + '/>', el: el, markup: true }] } besClearAllMistakes(el) let data = [] @@ -37,7 +40,11 @@ async function besProof(el) if (data.some(x => !x.markup && !/^\s*$/.test(x.text))) { const requestData = { format: 'plain', - data: JSON.stringify({annotation: data.map(x => x.markup ? { markup: x.text } : { text: x.text })}), + data: JSON.stringify({ + annotation: data.map(x => + x.markup ? { markup: x.text } : { text: x.text } + ) + }), language: 'sl', level: 'picky' } @@ -59,8 +66,16 @@ async function besProof(el) let range = document.createRange() // Locate start of the grammar mistake. - for (let idx = 0, startingOffset = 0; ; startingOffset += data[idx++].text.length) { - if (!data[idx].markup && /*startingOffset <= match.offset &&*/ match.offset < startingOffset + data[idx].text.length) { + for ( + let idx = 0, startingOffset = 0; + ; + startingOffset += data[idx++].text.length + ) { + if ( + !data[idx].markup && + /*startingOffset <= match.offset &&*/ match.offset < + startingOffset + data[idx].text.length + ) { range.setStart(data[idx].el, match.offset - startingOffset) break } @@ -68,8 +83,16 @@ async function besProof(el) // Locate end of the grammar mistake. let endOffset = match.offset + match.length - for (let idx = 0, startingOffset = 0; ; startingOffset += data[idx++].text.length) { - if (!data[idx].markup && /*startingOffset <= endOffset &&*/ endOffset <= startingOffset + data[idx].text.length) { + for ( + let idx = 0, startingOffset = 0; + ; + startingOffset += data[idx++].text.length + ) { + if ( + !data[idx].markup && + /*startingOffset <= endOffset &&*/ endOffset <= + startingOffset + data[idx].text.length + ) { range.setEnd(data[idx].el, endOffset - startingOffset) break } @@ -82,61 +105,67 @@ async function besProof(el) }) .catch(error => { // TODO: Make parsing issues non-fatal. But show an error sign somewhere in the UI. - throw new Error('Parsing backend server response failed: ' + error) + throw new Error( + 'Parsing backend server response failed: ' + error + ) }) - } - return [{ text: '<'+el.tagName+'/>', el: el, markup: true }] - } - else { + } + return [{ text: '<' + el.tagName + '/>', el: el, markup: true }] + } else { // Surround inline element with dummy .... - let data = [{ text: '<'+el.tagName+'>', el: el, markup: true }] + let data = [{ text: '<' + el.tagName + '>', el: el, markup: true }] for (const el2 of el.childNodes) { data = data.concat(await besProof(el2)) } - data.splice(data.length, 0, { text: '', markup: true }) - return data; + data.splice(data.length, 0, { + text: '', + markup: true + }) + return data } default: - return [{ text: '', el: el, markup: true }] + return [{ text: '', el: el, markup: true }] } } // Marks section of text that is about to change as not-yet-grammar-proofed. -function besHandleBeforeInput(editorId, event) -{ +function besHandleBeforeInput(editorId, event) { let editor = besEditors[editorId] if (editor.timer) clearTimeout(editor.timer) - editor.timer = setTimeout(function(){ besProof(edit) }, 1000) + editor.timer = setTimeout(function () { + besProof(edit) + }, 1000) // No need to invalidate elements after range.startContainer since they will // get either deleted or replaced. let edit = document.getElementById(editorId) - event.getTargetRanges().forEach(range => besClearProofed(besGetBlockParent(range.startContainer, edit))) + event + .getTargetRanges() + .forEach(range => + besClearProofed(besGetBlockParent(range.startContainer, edit)) + ) } // Test if given block element has already been grammar-proofed. -function besIsProofed(el) -{ +function besIsProofed(el) { return el.getAttribute('besProofed') === 'true' } // Mark given block element as grammar-proofed. -function besMarkProofed(el) -{ +function besMarkProofed(el) { el.setAttribute('besProofed', 'true') } // Mark given block element as not grammar-proofed. -function besClearProofed(el) -{ +function besClearProofed(el) { el?.removeAttribute('besProofed') } // Remove all grammar mistakes markup for given block element. function besClearAllMistakes(el) { for (const el2 of el.childNodes) { - if (el2.tagName === 'SPAN' && el2.classList.contains('typo-mistake')) { + if (el2.tagName === 'SPAN' && el2.classList.contains('bes-typo-mistake')) { el2.replaceWith(...el2.childNodes) el2.remove() } @@ -145,47 +174,49 @@ function besClearAllMistakes(el) { // Adds grammar mistake markup function besAddMistake(range, match) { - const correctionPanel = document.getElementById('correction-panel'); + const correctionPanel = document.getElementById('correction-panel') const clientRects = range.getClientRects() for (let i = 0, n = clientRects.length; i < n; ++i) { const rect = clientRects[i] - const highlight = document.createElement("div"); - highlight.classList.add("typo-mistake"); - highlight.dataset.info = match.message; - highlight.style.left = `${rect.left}px`; - highlight.style.top = `${rect.top}px`; - highlight.style.width = `${rect.width}px`; - highlight.style.height = `${rect.height}px`; - correctionPanel.appendChild(highlight); + const highlight = document.createElement('div') + highlight.classList.add('bes-typo-mistake') + highlight.dataset.info = match.message + highlight.style.left = `${rect.left}px` + highlight.style.top = `${rect.top}px` + highlight.style.width = `${rect.width}px` + highlight.style.height = `${rect.height}px` + correctionPanel.appendChild(highlight) // TODO: Find a solution to handle click events on the highlights - // const editor = document.querySelector('.online-editor') + // const editor = document.querySelector('.bes-online-editor') // highlight.addEventListener("click", function(e) { - // console.log(e); - // editor.focus(); - // besHandleClick(e); - // return true; + // console.log(e); + // editor.focus(); + // besHandleClick(e); + // return true; // }); } } // Tests if given element is block element. -function besIsBlockElement(el) -{ +function besIsBlockElement(el) { const defaultView = document.defaultView - switch (defaultView.getComputedStyle(el, null).getPropertyValue('display').toLowerCase()) - { + switch ( + defaultView + .getComputedStyle(el, null) + .getPropertyValue('display') + .toLowerCase() + ) { case 'inline': case 'inline-block': - return false; + return false default: return true } } // Returns first block parent element -function besGetBlockParent(el, edit) -{ +function besGetBlockParent(el, edit) { for (; el && el !== edit; el = el.parentNode) { if (el.nodeType === Node.ELEMENT_NODE && besIsBlockElement(el)) return el } diff --git a/styles.css b/styles.css index 3b7ff05..d8f868c 100644 --- a/styles.css +++ b/styles.css @@ -1,25 +1,5 @@ -/* Besana online editor */ - -/* TODO: Rename classes to "bes-..." */ - -/* TODO: In the release version, .online-editor should not contain any formatting. Let users format editor at will. */ -.online-editor { - width: 80%; - height: 300px; - margin: 0 auto; - padding: 20px; - border-radius: 10px; - background-color: #f5f5f5; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); - line-height: 1.6; - white-space: pre-wrap; - overflow-y: auto; - font-family: Arial, Helvetica, sans-serif; - z-index: 2; -} - /* Mistake types styles */ -.typo-mistake { +.bes-typo-mistake { border-bottom: 2px solid red; position: absolute; z-index: 2; @@ -29,8 +9,3 @@ text-decoration-color: red; cursor: text; */ } - -.other-mistake { - text-decoration: underline; - text-decoration-color: blue; -}