service2.js: Move reusable correction panel handling upstream

This commit is contained in:
Simon Rozman 2024-05-22 10:45:44 +02:00
parent 0e7e324694
commit 6eac44165f

View File

@ -161,8 +161,7 @@ class BesService {
const clientRects = range.getClientRects() const clientRects = range.getClientRects()
const scrollPanelRect = this.scrollPanel.getBoundingClientRect() const scrollPanelRect = this.scrollPanel.getBoundingClientRect()
let highlights = [] let highlights = []
for (let i = 0, n = clientRects.length; i < n; ++i) { for (let rect of clientRects) {
const rect = clientRects[i]
const highlight = document.createElement('div') const highlight = document.createElement('div')
highlight.classList.add('bes-typo-mistake') highlight.classList.add('bes-typo-mistake')
highlight.style.left = `${rect.left - scrollPanelRect.left}px` highlight.style.left = `${rect.left - scrollPanelRect.left}px`
@ -251,6 +250,41 @@ class BesService {
this.scrollPanel.style.height = `${this.hostElement.scrollHeight}px` 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. * 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 * DOM grammar-checking service
* *
*************************************************************************/ *************************************************************************/
class BesDOMService extends BesService { class BesDOMService extends BesTreeService {
constructor(hostElement) { constructor(hostElement) {
super(hostElement) super(hostElement)
this.onBeforeInput = this.onBeforeInput.bind(this) this.onBeforeInput = this.onBeforeInput.bind(this)
@ -492,7 +544,7 @@ class BesDOMService extends BesService {
* Tests if given block element has already been grammar-checked. * Tests if given block element has already been grammar-checked.
* *
* @param {Element} el DOM element to check * @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) { getProofing(el) {
return this.results.find(result => return this.results.find(result =>
@ -688,47 +740,21 @@ class BesDOMService extends BesService {
const el = this.getBlockParent(source.targetElement || source.target) const el = this.getBlockParent(source.targetElement || source.target)
if (!el) return if (!el) return
const matches = this.results.find(child => const result = this.results.find(child =>
BesDOMService.isSameParagraph(child.element, el) BesDOMService.isSameParagraph(child.element, el)
)?.matches )
if (matches) { if (result) {
for (let m of matches) { for (let m of result.matches) {
if (m.rects) {
for (let r of m.rects) { for (let r of m.rects) {
if (BesService.isPointInRect(source.clientX, source.clientY, r)) { if (BesService.isPointInRect(source.clientX, source.clientY, r)) {
const popup = document.querySelector('bes-popup-el') this.popupCorrectionPanel(el, m, source)
popup.changeMessage(m.match.message)
popup.appendReplacements(
el,
m,
this,
this.hostElement.contentEditable !== 'false'
)
popup.show(source.clientX, source.clientY)
return return
} }
} }
} }
} }
}
BesPopup.hide() 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. * Tests if given paragraph has already been grammar-checked.
* *
* @param {Range} range Paragraph range * @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) { getProofing(range) {
return this.results.find(result => return this.results.find(result =>
@ -1128,45 +1154,17 @@ class BesPlainTextService extends BesService {
if (!el) return if (!el) return
for (let result of this.results) { for (let result of this.results) {
if (result.matches) {
for (let m of result.matches) { for (let m of result.matches) {
if (m.rects) {
for (let r of m.rects) { for (let r of m.rects) {
if (BesService.isPointInRect(source.clientX, source.clientY, r)) { if (BesService.isPointInRect(source.clientX, source.clientY, r)) {
const popup = document.querySelector('bes-popup-el') this.popupCorrectionPanel(result.range, m, source)
popup.changeMessage(m.match.message)
popup.appendReplacements(
result.range,
m,
this,
this.hostElement.contentEditable !== 'false'
)
popup.show(source.clientX, source.clientY)
return return
} }
} }
} }
} }
}
}
BesPopup.hide() 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()
}
} }
/************************************************************************* /*************************************************************************