Refactor CKEditor event handling

This commit is contained in:
Aljaž Grilc 2024-05-14 13:33:01 +02:00
parent 970b43b8d6
commit c54366e95f

View File

@ -699,49 +699,53 @@ class BesCKService extends BesService {
super(hostElement) super(hostElement)
this.ckEditorInstance = ckEditorInstance this.ckEditorInstance = ckEditorInstance
this.disableCKEditorSpellcheck(this.ckEditorInstance) this.disableCKEditorSpellcheck(this.ckEditorInstance)
hostElement.addEventListener(
'beforeinput',
e => this.handleBeforeCKInput(e),
false
)
this.ckEditorInstance.model.document.on('change:data', () => { this.ckEditorInstance.model.document.on('change:data', () => {
const differ = this.ckEditorInstance.model.document.differ const differ = this.ckEditorInstance.model.document.differ
const changes = Array.from(differ.getChanges()) const changes = Array.from(differ.getChanges())
for (const entry of changes) { for (const entry of changes) {
if (entry.type === 'attribute') { let element =
const parentElement = entry.range.start.parent entry.type === 'attribute'
? entry.range.start.parent
: entry._element || entry.position.parent
const domElement = this.getDomElement(element)
const child = this.children.find(child => child.element === domElement)
this.clearMistakeMarkup(domElement)
if (entry.type === 'attribute') child.isProofed = false
else if (entry.type === 'remove') this.removeChildFromChildren(child)
let service = besServices.find(e => e.hostElement === hostElement)
if (!service) return
service.clearMistakeMarkup(domElement)
service.removeChild(domElement)
if (service.timer) clearTimeout(service.timer)
service.abortController.abort()
service.timer = setTimeout(function () {
service.abortController = new AbortController()
service.proof(hostElement)
window.dispatchEvent(new Event('resize'))
}, 1000)
}
})
}
removeChildFromChildren(child) {
let index = this.children.indexOf(child)
if (index !== -1) {
this.children.splice(index, 1)
}
}
/**
* This function converts a CKEditor element to a DOM element.
*
* @param {CKEditor} element
* @returns domElement
*/
getDomElement(element) {
const viewElement = const viewElement =
this.ckEditorInstance.editing.mapper.toViewElement(parentElement) this.ckEditorInstance.editing.mapper.toViewElement(element)
const domElement = const domElement =
this.ckEditorInstance.editing.view.domConverter.mapViewToDom( this.ckEditorInstance.editing.view.domConverter.mapViewToDom(viewElement)
viewElement return domElement
)
const child = this.children.find(
child => child.element === domElement
)
if (child) {
child.matches.forEach(match => {
console.log(match)
match.highlights.forEach(highlight => {
highlight.remove()
delete match.highlights
})
})
delete child.matches
child.isProofed = false
}
setTimeout(() => {
this.proof(domElement)
window.dispatchEvent(new Event('resize'))
}, 500)
} else {
setTimeout(() => {
this.proof(hostElement)
window.dispatchEvent(new Event('resize'))
}, 500)
}
}
})
} }
/** /**
@ -757,55 +761,6 @@ class BesCKService extends BesService {
return service return service
} }
handleBeforeCKInput(event) {
const hostElement = event.target
let service = besServices.find(e => e.hostElement === hostElement)
if (!service) return
if (service.timer) clearTimeout(service.timer)
service.abortController.abort()
let blockElements = new Set()
event.getTargetRanges().forEach(range => {
BesService.getNodesInRange(range).forEach(el => {
if (el === hostElement || hostElement?.contains(el)) {
blockElements.add(service.getBlockParent(el))
}
})
})
blockElements.forEach(block => {
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()
window.dispatchEvent(new Event('resize'))
}, 100)
service.timer = setTimeout(function () {
service.abortController = new AbortController()
service.proof(hostElement)
}, 1000)
}
clearAllMistakes(el) {
while (el.firstChild) {
el.removeChild(el.firstChild)
}
}
clearChildren() {
this.children = []
}
proofCKEditor() {
this.clearAllMistakes(this.scrollPanel)
this.clearChildren()
setTimeout(() => {
this.proof(this.hostElement)
}, 500)
}
/** /**
* This function disables the CKEditor spellcheck. * This function disables the CKEditor spellcheck.
* *
@ -882,7 +837,7 @@ class BesCKService extends BesService {
// It maintains reasonable performance as it only checks the block element that has been modified, // It maintains reasonable performance as it only checks the block element that has been modified,
// rather than re-evaluating the entire document or a larger set of elements. // rather than re-evaluating the entire document or a larger set of elements.
this.abortController = new AbortController() this.abortController = new AbortController()
this.proofCKEditor() this.proof(this.hostElement)
} }
setStatusDivPosition(hostElement, statusDiv) { setStatusDivPosition(hostElement, statusDiv) {