From 3b9d2dd73b7487f98e009d114139771a99d752b6 Mon Sep 17 00:00:00 2001 From: Aljaz Grilc Date: Wed, 14 Feb 2024 09:32:21 +0100 Subject: [PATCH] Implement functionality to replace text with suggestions inside popup. It is not the cleanest solution because it requires passing editor object across multiple functions. --- online-editor.js | 55 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/online-editor.js b/online-editor.js index 05a22ff..7a01f52 100644 --- a/online-editor.js +++ b/online-editor.js @@ -175,7 +175,11 @@ class BesEditor { if (mutation.type === 'characterData') { this.clearProofed(this.getBlockParent(mutation.target)) } - if (mutation.type === 'childList' && mutation.removedNodes.length) { + if ( + mutation.type === 'childList' && + mutation.removedNodes.length && + !mutation.addedNodes.length + ) { mutation.removedNodes.forEach(node => { // TODO: This is a temporary solution. We need to handle all cases such as

,
, etc. if (node.nodeName === 'DIV') { @@ -312,11 +316,12 @@ class BesEditor { } if ( BesEditor.renderPopup( + targetEl, matches, popup, e.clientX, e.clientY, - this.offsetTop + this ) ) return @@ -329,17 +334,19 @@ class BesEditor { this.offsetTop = editor.scrollTop } - static renderPopup(matches, popup, clientX, clientY, offsetTop) { + static renderPopup(el, matches, popup, clientX, clientY, editor) { for (let m of matches) { if (m.rects) { for (let r of m.rects) { - if (BesEditor.isPointInRect(clientX, clientY, r, offsetTop)) { + if (BesEditor.isPointInRect(clientX, clientY, r, editor.offsetTop)) { popup.changeText(m.match.message) m.match.replacements.forEach(replacement => { popup.appendReplacements( + el, + r, + m.match, replacement.value, - m.match.offset, - m.match.length + editor ) }) popup.show(clientX, clientY) @@ -353,6 +360,35 @@ class BesEditor { return false } + static replaceText(el, rect, match, replacement, editor) { + const text = el.textContent + const newText = + text.substring(0, match.offset) + + replacement + + text.substring(match.offset + match.length) + el.textContent = newText + BesEditor.clearSingleMistake(editor, el, rect) + } + + // This function clears a single mistake + static clearSingleMistake(editor, el, rect) { + const childToDelete = editor.children.filter( + child => child.elements === el + )[0] + childToDelete.isProofed = false + childToDelete.matches = childToDelete.matches.filter( + match => !BesEditor.isPointInRect(rect.left, rect.top, match.rects[0]) + ) + + // TODO: find a better way to remove elements from the DOM + Array.from(editor.scrollPanel.children) + .filter(child => { + const childRect = child.getBoundingClientRect() + return BesEditor.isPointInRect(childRect.left, childRect.top, rect) + }) + .forEach(child => child.remove()) + } + setCorrectionPanelSize(editor, correctionPanel, scrollPanel) { const styles = window.getComputedStyle(editor) const totalWidth = @@ -526,14 +562,15 @@ class BesPopupEl extends HTMLElement { this.shadowRoot.querySelector('.popup-text').textContent = text } - appendReplacements(replacement, offset, length) { + appendReplacements(el, rect, match, replacement, editor) { const replacementDiv = this.shadowRoot.querySelector('.bes-replacement-div') const replacementBtn = document.createElement('button') replacementBtn.classList.add('bes-replacement-btn') - replacementBtn.dataset.length = length - replacementBtn.dataset.offset = offset replacementBtn.textContent = replacement replacementBtn.classList.add('bes-replacement') + replacementBtn.addEventListener('click', () => { + BesEditor.replaceText(el, rect, match, replacement, editor) + }) replacementDiv.appendChild(replacementBtn) } }