Refactor correction panel creation to support scroll functionality

This feature is not fully tested, there are still some bugs left, i.e., after scroll event the popup is unavailable
This commit is contained in:
Aljaž Grilc 2024-02-09 10:38:31 +01:00
parent 40631798d1
commit 5d9d22bfef
2 changed files with 58 additions and 19 deletions

View File

@ -7,10 +7,15 @@ class BesEditor {
this.el = edit this.el = edit
this.timer = null this.timer = null
this.children = [] this.children = []
this.correctionPanel = this.createCorrectionPanel(edit) const { correctionPanel, scrollPanel } = this.createCorrectionPanel(edit)
this.correctionPanel = correctionPanel
this.scrollPanel = scrollPanel
this.proof(edit) this.proof(edit)
edit.addEventListener('beforeinput', e => this.handleBeforeInput(e), false) edit.addEventListener('beforeinput', e => this.handleBeforeInput(e), false)
edit.addEventListener('click', e => this.handleClick(e)) edit.addEventListener('click', e => this.handleClick(e))
edit.addEventListener('scroll', () =>
this.handleScrollEvent(this.el, this.scrollPanel)
)
} }
// Register editor // Register editor
@ -104,7 +109,7 @@ class BesEditor {
matches.push({ matches.push({
range: range, range: range,
rects: this.addMistakeMarkup(range, this.correctionPanel), rects: this.addMistakeMarkup(range, this.scrollPanel),
match: match match: match
}) })
}) })
@ -140,14 +145,17 @@ class BesEditor {
createCorrectionPanel(edit) { createCorrectionPanel(edit) {
const panelParent = document.createElement('div') const panelParent = document.createElement('div')
panelParent.classList.add('bes-correction-panel-parent') panelParent.classList.add('bes-correction-panel-parent')
const panel = document.createElement('div') const correctionPanel = document.createElement('div')
this.setCorrectionPanelSize(edit, panel) const scrollPanel = document.createElement('div')
panel.classList.add('bes-correction-panel') this.setCorrectionPanelSize(edit, correctionPanel, scrollPanel)
correctionPanel.classList.add('bes-correction-panel')
scrollPanel.classList.add('bes-correction-panel-scroll')
panelParent.appendChild(panel) correctionPanel.appendChild(scrollPanel)
panelParent.appendChild(correctionPanel)
edit.parentElement.insertBefore(panelParent, edit) edit.parentElement.insertBefore(panelParent, edit)
return panel return { correctionPanel, scrollPanel }
} }
// Marks section of text that is about to change as not-yet-grammar-proofed. // Marks section of text that is about to change as not-yet-grammar-proofed.
@ -203,7 +211,7 @@ class BesEditor {
// TODO: Remove elements that are found in editor object, that way we can avoid looping through all elements. // TODO: Remove elements that are found in editor object, that way we can avoid looping through all elements.
filteredChildren[0].matches.forEach(match => { filteredChildren[0].matches.forEach(match => {
for (const rect of match.rects) { for (const rect of match.rects) {
for (let child of this.correctionPanel.children) { for (let child of this.scrollPanel.children) {
let childRect = child.getBoundingClientRect() let childRect = child.getBoundingClientRect()
const isWithinRect = const isWithinRect =
childRect.left >= rect.left && childRect.left >= rect.left &&
@ -219,21 +227,21 @@ class BesEditor {
} }
// Adds grammar mistake markup // Adds grammar mistake markup
addMistakeMarkup(range, correctionPanel) { addMistakeMarkup(range, scrollPanel) {
// TODO: Consider using range.getClientRects() instead of range.getBoundingClientRect() // TODO: Consider using range.getClientRects() instead of range.getBoundingClientRect()
const clientRects = range.getClientRects() const clientRects = range.getClientRects()
const correctionPanelRect = correctionPanel.getBoundingClientRect() const scrollPanelRect = scrollPanel.getBoundingClientRect()
for (let i = 0, n = clientRects.length; i < n; ++i) { for (let i = 0, n = clientRects.length; i < n; ++i) {
const rect = clientRects[i] 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')
const topPosition = rect.top - correctionPanelRect.top const topPosition = rect.top - scrollPanelRect.top
const leftPosition = rect.left - correctionPanelRect.left const leftPosition = rect.left - scrollPanelRect.left
highlight.style.left = `${leftPosition}px` highlight.style.left = `${leftPosition}px`
highlight.style.top = `${topPosition}px` highlight.style.top = `${topPosition}px`
highlight.style.width = `${rect.width}px` highlight.style.width = `${rect.width}px`
highlight.style.height = `${rect.height}px` highlight.style.height = `${rect.height}px`
this.correctionPanel.appendChild(highlight) this.scrollPanel.appendChild(highlight)
} }
return clientRects return clientRects
} }
@ -281,6 +289,10 @@ class BesEditor {
} }
} }
handleScrollEvent(editor, scrollPanel) {
scrollPanel.style.top = -editor.scrollTop + 'px'
}
static renderPopup(matches, popup, clientX, clientY) { static renderPopup(matches, popup, clientX, clientY) {
for (let m of matches) { for (let m of matches) {
if (m.rects) { if (m.rects) {
@ -305,7 +317,7 @@ class BesEditor {
return false return false
} }
setCorrectionPanelSize(editor, correctionPanel) { setCorrectionPanelSize(editor, correctionPanel, scrollPanel) {
const styles = window.getComputedStyle(editor) const styles = window.getComputedStyle(editor)
const totalWidth = const totalWidth =
parseFloat(styles.width) + parseFloat(styles.width) +
@ -321,6 +333,7 @@ class BesEditor {
parseFloat(styles.paddingBottom) parseFloat(styles.paddingBottom)
correctionPanel.style.width = totalWidth + 'px' correctionPanel.style.width = totalWidth + 'px'
correctionPanel.style.height = totalHeight + 'px' correctionPanel.style.height = totalHeight + 'px'
scrollPanel.style.height = editor.scrollHeight + 'px'
} }
static isPointInRect(x, y, rect) { static isPointInRect(x, y, rect) {
@ -342,14 +355,15 @@ window.onload = () => {
window.onresize = () => { window.onresize = () => {
besEditors.forEach(editor => { besEditors.forEach(editor => {
editor.setCorrectionPanelSize(editor.el, editor.correctionPanel) editor.setCorrectionPanelSize(
editor.el,
editor.correctionPanel,
editor.scrollPanel
)
editor.children.forEach(child => { editor.children.forEach(child => {
editor.clearMistakeMarkup(child.elements) editor.clearMistakeMarkup(child.elements)
child.matches.forEach(match => { child.matches.forEach(match => {
match.rects = editor.addMistakeMarkup( match.rects = editor.addMistakeMarkup(match.range, editor.scrollPanel)
match.range,
editor.correctionPanel
)
}) })
}) })
}) })

View File

@ -9,3 +9,28 @@
text-decoration-color: red; text-decoration-color: red;
cursor: text; */ cursor: text; */
} }
.bes-correction-panel-scroll {
pointer-events: none !important;
box-shadow: initial !important;
box-sizing: initial !important;
cursor: initial !important;
display: block !important;
float: initial !important;
max-height: initial !important;
min-height: initial !important;
max-width: initial !important;
min-width: initial !important;
position: absolute !important;
height: initial !important;
width: initial !important;
animation: auto ease 0s 1 normal none running none !important;
background: transparent !important;
border-width: initial !important;
border-style: none !important;
border-color: initial !important;
border-image: initial !important;
margin: 0px !important;
outline: initial !important;
padding: 0px !important;
}