Implement text replacement feature for CKEditor cases

This commit is contained in:
Aljaž Grilc 2024-03-12 16:49:27 +01:00
parent 259fc25f6f
commit 41c5954e89
2 changed files with 31 additions and 15 deletions

View File

@ -13,9 +13,13 @@
</div>
<bes-popup-el></bes-popup-el>
<script>
ClassicEditor.create(document.querySelector('#editor')).catch(error => {
console.error(error)
})
ClassicEditor.create(document.querySelector('#editor'))
.then(newEditor => {
BesEditor.register(newEditor.ui.view.editable.element, newEditor)
})
.catch(error => {
console.error(error)
})
</script>
</body>

View File

@ -11,7 +11,9 @@ class BesEditor {
this.correctionPanel = correctionPanel
this.scrollPanel = scrollPanel
this.offsetTop = null
// TODO: consider simplfing ckeditor handling by using a single constructor parameter
this.isCKeditor = !!isCkeditor
this.CKEditorInstance = isCkeditor
edit.classList.add('bes-online-editor')
this.originalSpellcheck = edit.spellcheck
edit.spellcheck = false
@ -169,7 +171,7 @@ class BesEditor {
})
this.markProofed(el, matches)
// This is a solution for CKEditor. It is not the best solution, but it works for now.
// This is a solution for displaying mistakes in CKEditor. It is not the best solution, but it works for now.
if (this.isCKeditor) {
const resizeEvent = new Event('resize')
window.dispatchEvent(resizeEvent)
@ -283,7 +285,7 @@ class BesEditor {
if (!child) return
child.isProofed = false
child.matches.forEach(match => {
match.highlights.forEach(h => h.remove())
match?.highlights.forEach(h => h.remove())
delete match.highlights
})
}
@ -487,7 +489,10 @@ class BesEditor {
*/
static findParent(el) {
for (; el; el = el.parentNode) {
if (el.classList?.contains('bes-online-editor')) {
if (
el.classList?.contains('bes-online-editor') ||
el.classList?.contains('ck-editor__editable') // Find a better way to handle CKEditor
) {
return el
}
}
@ -503,9 +508,7 @@ class BesEditor {
*/
renderPopup(el, clientX, clientY) {
const popup = document.querySelector('bes-popup-el')
const matches = this.children.find(
child => child.elements === el
)?.matches
const matches = this.children.find(child => child.elements === el)?.matches
if (matches) {
for (let m of matches) {
if (m.rects) {
@ -541,6 +544,21 @@ class BesEditor {
replacement +
text.substring(match.offset + match.length)
el.textContent = newText
if (editor.isCKeditor) {
const { CKEditorInstance } = editor
CKEditorInstance.model.change(writer => {
// Find the corresponding element in the model.
const viewElement =
CKEditorInstance.editing.view.domConverter.mapDomToView(el)
const modelElement =
CKEditorInstance.editing.mapper.toModelElement(viewElement)
if (modelElement) {
writer.remove(writer.createRangeIn(modelElement))
writer.insertText(newText, modelElement, 'end')
}
})
}
BesEditor.clearSingleMistake(editor, el, rect)
// In my opinion, this approach provides the most straightforward solution for repositioning mistakes after a change.
// It maintains reasonable performance as it only checks the block element that has been modified,
@ -615,12 +633,6 @@ window.onload = () => {
document
.querySelectorAll('.bes-online-editor')
.forEach(edit => BesEditor.register(edit))
// TODO: not the most optimal solution, but it works for now
// Find contenteditable element inside ckeditor and prepare it
document.querySelectorAll('.ck-editor__editable').forEach(edit => {
BesEditor.register(edit, true)
})
}
window.onresize = () => {