Refactor CKEditor event handling
This commit is contained in:
parent
970b43b8d6
commit
c54366e95f
129
service.js
129
service.js
@ -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) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user