diff --git a/service2.js b/service2.js index a3ef4bb..425c941 100644 --- a/service2.js +++ b/service2.js @@ -161,8 +161,7 @@ class BesService { const clientRects = range.getClientRects() const scrollPanelRect = this.scrollPanel.getBoundingClientRect() let highlights = [] - for (let i = 0, n = clientRects.length; i < n; ++i) { - const rect = clientRects[i] + for (let rect of clientRects) { const highlight = document.createElement('div') highlight.classList.add('bes-typo-mistake') highlight.style.left = `${rect.left - scrollPanelRect.left}px` @@ -251,6 +250,41 @@ class BesService { this.scrollPanel.style.height = `${this.hostElement.scrollHeight}px` } + /** + * Displays correction panel. + * + * @param {*} el Block element/paragraph containing grammar checking rule match + * @param {*} match Grammar checking rule match + * @param {PointerEvent} source Click event source + */ + popupCorrectionPanel(el, match, source) { + const popup = document.querySelector('bes-popup-el') + popup.changeMessage(match.match.message) + popup.appendReplacements( + el, + match, + this, + this.hostElement.contentEditable !== 'false' + ) + popup.show(source.clientX, source.clientY) + } + + /** + * Replaces grammar checking match with a suggestion provided by grammar checking service. + * + * @param {*} el Block element/paragraph containing grammar checking rule match + * @param {*} match Grammar checking rule match + * @param {String} replacement Text to replace grammar checking match with + */ + replaceText(el, match, replacement) { + if (this.timer) clearTimeout(this.timer) + if (this.abortController) this.abortController.abort() + this.clearProofing(el) + match.range.deleteContents() + match.range.insertNode(document.createTextNode(replacement)) + this.proofAll() + } + /** * Repositions status DIV element. */ @@ -282,12 +316,30 @@ class BesService { } } +/************************************************************************* + * + * Grammar-checking service base class for tree-organized editors + * + *************************************************************************/ +class BesTreeService extends BesService { + constructor(hostElement) { + super(hostElement) + } + + /** + * Unregisters grammar checking service. + */ + unregister() { + super.unregister() + } +} + /************************************************************************* * * DOM grammar-checking service * *************************************************************************/ -class BesDOMService extends BesService { +class BesDOMService extends BesTreeService { constructor(hostElement) { super(hostElement) this.onBeforeInput = this.onBeforeInput.bind(this) @@ -492,7 +544,7 @@ class BesDOMService extends BesService { * Tests if given block element has already been grammar-checked. * * @param {Element} el DOM element to check - * @returns {*} Result of grammar check if the element has already been grammar-checked; null otherwise. + * @returns {*} Result of grammar check if the element has already been grammar-checked; undefined otherwise. */ getProofing(el) { return this.results.find(result => @@ -688,47 +740,21 @@ class BesDOMService extends BesService { const el = this.getBlockParent(source.targetElement || source.target) if (!el) return - const matches = this.results.find(child => + const result = this.results.find(child => BesDOMService.isSameParagraph(child.element, el) - )?.matches - if (matches) { - for (let m of matches) { - if (m.rects) { - for (let r of m.rects) { - if (BesService.isPointInRect(source.clientX, source.clientY, r)) { - const popup = document.querySelector('bes-popup-el') - popup.changeMessage(m.match.message) - popup.appendReplacements( - el, - m, - this, - this.hostElement.contentEditable !== 'false' - ) - popup.show(source.clientX, source.clientY) - return - } + ) + if (result) { + for (let m of result.matches) { + for (let r of m.rects) { + if (BesService.isPointInRect(source.clientX, source.clientY, r)) { + this.popupCorrectionPanel(el, m, source) + return } } } } BesPopup.hide() } - - /** - * Replaces grammar checking match with a suggestion provided by grammar checking service. - * - * @param {Element} el Block element containing grammar checking rule match - * @param {*} match Grammar checking rule match - * @param {String} replacement Text to replace grammar checking match with - */ - replaceText(el, match, replacement) { - if (this.timer) clearTimeout(this.timer) - if (this.abortController) this.abortController.abort() - this.clearProofing(el) - match.range.deleteContents() - match.range.insertNode(document.createTextNode(replacement)) - this.proofAll() - } } /************************************************************************* @@ -1021,7 +1047,7 @@ class BesPlainTextService extends BesService { * Tests if given paragraph has already been grammar-checked. * * @param {Range} range Paragraph range - * @returns {*} Result of grammar check if the element has already been grammar-checked; null otherwise. + * @returns {*} Result of grammar check if the element has already been grammar-checked; undefined otherwise. */ getProofing(range) { return this.results.find(result => @@ -1128,45 +1154,17 @@ class BesPlainTextService extends BesService { if (!el) return for (let result of this.results) { - if (result.matches) { - for (let m of result.matches) { - if (m.rects) { - for (let r of m.rects) { - if (BesService.isPointInRect(source.clientX, source.clientY, r)) { - const popup = document.querySelector('bes-popup-el') - popup.changeMessage(m.match.message) - popup.appendReplacements( - result.range, - m, - this, - this.hostElement.contentEditable !== 'false' - ) - popup.show(source.clientX, source.clientY) - return - } - } + for (let m of result.matches) { + for (let r of m.rects) { + if (BesService.isPointInRect(source.clientX, source.clientY, r)) { + this.popupCorrectionPanel(result.range, m, source) + return } } } } BesPopup.hide() } - - /** - * Replaces grammar checking match with a suggestion provided by grammar checking service. - * - * @param {Range} range Paragraph range - * @param {*} match Grammar checking rule match - * @param {String} replacement Text to replace grammar checking match with - */ - replaceText(range, match, replacement) { - if (this.timer) clearTimeout(this.timer) - if (this.abortController) this.abortController.abort() - this.clearProofing(range) - match.range.deleteContents() - match.range.insertNode(document.createTextNode(replacement)) - this.proofAll() - } } /*************************************************************************