diff --git a/service.js b/service.js index 370dd6a..02817f1 100644 --- a/service.js +++ b/service.js @@ -27,6 +27,7 @@ class BesService { BesService.handleBeforeInput, false ) + this.lineChangeObserver(hostElement) } besServices.push(this) } @@ -264,18 +265,35 @@ class BesService { service.clearMistakeMarkup(block) service.removeChild(block) }) - // Not a nice way to do it, but it works for now the repositionMistakes function is called before the DOM updates are finished. - // If users will experience performance issues, we can consider debouncing this function. - // The lagginess becomes noticeable if the text is long and has many grammar mistakes. - setTimeout(() => { - service.repositionMistakes() - }, 0) service.timer = setTimeout(function () { service.abortController = new AbortController() service.proof(hostElement) }, 1000) } + /** + * This function observes added/removed lines in the host element and repositions mistakes when needed. + * It is used for contenteditable elements. The user can still experience lagginess when the text is long and + * has many grammar mistakes and adds/removes lines. But it is far less noticeable than it was before. + * + * @param {Element} hostElement DOM element to observe + */ + lineChangeObserver(hostElement) { + const lineChange = new MutationObserver(mutationsList => { + let hasMutation = false + for (let mutation of mutationsList) { + if (mutation.type === 'childList') { + if (mutation.addedNodes.length || mutation.removedNodes.length) { + hasMutation = true + } + } + } + if (hasMutation) this.repositionMistakes() + }) + + lineChange.observe(hostElement, { childList: true }) + } + /** * Tests if given block element has already been grammar-proofed. *