Revise scrolling
This commit is contained in:
parent
d246d07d7f
commit
51099347f2
183
service.js
183
service.js
@ -73,6 +73,9 @@ class BesService {
|
|||||||
})
|
})
|
||||||
|
|
||||||
besServices.push(this)
|
besServices.push(this)
|
||||||
|
|
||||||
|
// Initial sync the scroll as hostElement may be scrolled by non-(0, 0) at the time of BesService registration.
|
||||||
|
this.onScroll()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -360,11 +363,13 @@ class BesService {
|
|||||||
*/
|
*/
|
||||||
drawMistakeMarkup(match) {
|
drawMistakeMarkup(match) {
|
||||||
const range = match.range
|
const range = match.range
|
||||||
const canvasPanelRect = this.canvasPanel.getBoundingClientRect()
|
|
||||||
const scrollX = canvasPanelRect.left
|
|
||||||
const scrollY = canvasPanelRect.top
|
|
||||||
match.highlights = Array.from(range.getClientRects())
|
match.highlights = Array.from(range.getClientRects())
|
||||||
if (match.highlights.length === 0) return
|
if (match.highlights.length === 0) return
|
||||||
|
const canvasPanelRect = this.canvasPanel.getBoundingClientRect()
|
||||||
|
for (let rect of match.highlights) {
|
||||||
|
rect.x -= canvasPanelRect.x
|
||||||
|
rect.y -= canvasPanelRect.y
|
||||||
|
}
|
||||||
const dpr = window.devicePixelRatio
|
const dpr = window.devicePixelRatio
|
||||||
this.ctx.lineWidth = 2 * dpr // Use 2 for clearer visibility
|
this.ctx.lineWidth = 2 * dpr // Use 2 for clearer visibility
|
||||||
const ruleId = match.match.rule.id
|
const ruleId = match.match.rule.id
|
||||||
@ -386,7 +391,7 @@ class BesService {
|
|||||||
const scale = (markerY2 - markerY1) / 18
|
const scale = (markerY2 - markerY1) / 18
|
||||||
const x = match.highlights[0].left
|
const x = match.highlights[0].left
|
||||||
const y = match.highlights[0].bottom
|
const y = match.highlights[0].bottom
|
||||||
this.drawMissingComma(x - scrollX, y - scrollY, scale, '?')
|
this.drawMissingComma(x, y, scale, '?')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,25 +418,20 @@ class BesService {
|
|||||||
// in another line, making a confusing UX.
|
// in another line, making a confusing UX.
|
||||||
const x = match.highlights[0].left
|
const x = match.highlights[0].left
|
||||||
const y = match.highlights[0].bottom
|
const y = match.highlights[0].bottom
|
||||||
this.drawMissingComma(x - scrollX, y - scrollY, scale)
|
this.drawMissingComma(x, y, scale)
|
||||||
} else if (/^\s+$/.test(toInsert)) {
|
} else if (/^\s+$/.test(toInsert)) {
|
||||||
const x = match.highlights[0].left
|
const x = match.highlights[0].left
|
||||||
const y1 = match.highlights[0].bottom - 2 * scale
|
const y1 = match.highlights[0].bottom - 2 * scale
|
||||||
const y2 = match.highlights[0].top + 2 * scale
|
const y2 = match.highlights[0].top + 2 * scale
|
||||||
this.drawWrongSpacing(
|
this.drawWrongSpacing(x, y1, y2, scale)
|
||||||
x - scrollX,
|
|
||||||
y1 - scrollY,
|
|
||||||
y2 - scrollY,
|
|
||||||
scale
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
const x = match.highlights[0].left - 1 * scale
|
const x = match.highlights[0].left - 1 * scale
|
||||||
const y1 = match.highlights[0].bottom
|
const y1 = match.highlights[0].bottom
|
||||||
const y2 = match.highlights[0].top
|
const y2 = match.highlights[0].top
|
||||||
this.drawMissingText(
|
this.drawMissingText(
|
||||||
x - scrollX,
|
x,
|
||||||
y1 - scrollY,
|
y1,
|
||||||
y2 - scrollY,
|
y2,
|
||||||
scale,
|
scale,
|
||||||
replacement.substr(lengthDiff).trim()
|
replacement.substr(lengthDiff).trim()
|
||||||
)
|
)
|
||||||
@ -446,25 +446,20 @@ class BesService {
|
|||||||
if (toInsert === ',') {
|
if (toInsert === ',') {
|
||||||
const x = match.highlights.at(-1).right
|
const x = match.highlights.at(-1).right
|
||||||
const y = match.highlights.at(-1).bottom
|
const y = match.highlights.at(-1).bottom
|
||||||
this.drawMissingComma(x - scrollX, y - scrollY, scale)
|
this.drawMissingComma(x, y, scale)
|
||||||
} else if (/^\s+$/.test(toInsert)) {
|
} else if (/^\s+$/.test(toInsert)) {
|
||||||
const x = match.highlights.at(-1).right
|
const x = match.highlights.at(-1).right
|
||||||
const y1 = match.highlights.at(-1).bottom - 2 * scale
|
const y1 = match.highlights.at(-1).bottom - 2 * scale
|
||||||
const y2 = match.highlights.at(-1).top + 2 * scale
|
const y2 = match.highlights.at(-1).top + 2 * scale
|
||||||
this.drawWrongSpacing(
|
this.drawWrongSpacing(x, y1, y2, scale)
|
||||||
x - scrollX,
|
|
||||||
y1 - scrollY,
|
|
||||||
y2 - scrollY,
|
|
||||||
scale
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
const x = match.highlights.at(-1).right + 1 * scale
|
const x = match.highlights.at(-1).right + 1 * scale
|
||||||
const y1 = match.highlights.at(-1).bottom
|
const y1 = match.highlights.at(-1).bottom
|
||||||
const y2 = match.highlights.at(-1).top
|
const y2 = match.highlights.at(-1).top
|
||||||
this.drawMissingText(
|
this.drawMissingText(
|
||||||
x - scrollX,
|
x,
|
||||||
y1 - scrollY,
|
y1,
|
||||||
y2 - scrollY,
|
y2,
|
||||||
scale,
|
scale,
|
||||||
replacement.substr(-lengthDiff).trim()
|
replacement.substr(-lengthDiff).trim()
|
||||||
)
|
)
|
||||||
@ -488,12 +483,7 @@ class BesService {
|
|||||||
const x = (rect.left + rect.right) / 2
|
const x = (rect.left + rect.right) / 2
|
||||||
const y1 = rect.top
|
const y1 = rect.top
|
||||||
const y2 = rect.bottom
|
const y2 = rect.bottom
|
||||||
this.drawWrongSpacing(
|
this.drawWrongSpacing(x, y1, y2, scale)
|
||||||
x - scrollX,
|
|
||||||
y1 - scrollY,
|
|
||||||
y2 - scrollY,
|
|
||||||
scale
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
for (let rect of this.makeRange(
|
for (let rect of this.makeRange(
|
||||||
match.data,
|
match.data,
|
||||||
@ -501,10 +491,10 @@ class BesService {
|
|||||||
match.match.offset - lengthDiff
|
match.match.offset - lengthDiff
|
||||||
)?.getClientRects())
|
)?.getClientRects())
|
||||||
this.drawExcessiveText(
|
this.drawExcessiveText(
|
||||||
rect.left - scrollX,
|
rect.left,
|
||||||
rect.bottom - scrollY,
|
rect.bottom,
|
||||||
rect.right - scrollX,
|
rect.right,
|
||||||
rect.top - scrollY
|
rect.top
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if (context.substr(0, replacement.length) === replacement) {
|
} else if (context.substr(0, replacement.length) === replacement) {
|
||||||
@ -523,12 +513,7 @@ class BesService {
|
|||||||
const x = (rect.left + rect.right) / 2
|
const x = (rect.left + rect.right) / 2
|
||||||
const y1 = rect.top
|
const y1 = rect.top
|
||||||
const y2 = rect.bottom
|
const y2 = rect.bottom
|
||||||
this.drawWrongSpacing(
|
this.drawWrongSpacing(x, y1, y2, scale)
|
||||||
x - scrollX,
|
|
||||||
y1 - scrollY,
|
|
||||||
y2 - scrollY,
|
|
||||||
scale
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
for (let rect of this.makeRange(
|
for (let rect of this.makeRange(
|
||||||
match.data,
|
match.data,
|
||||||
@ -536,10 +521,10 @@ class BesService {
|
|||||||
match.match.offset + match.match.length
|
match.match.offset + match.match.length
|
||||||
)?.getClientRects())
|
)?.getClientRects())
|
||||||
this.drawExcessiveText(
|
this.drawExcessiveText(
|
||||||
rect.left - scrollX,
|
rect.left,
|
||||||
rect.bottom - scrollY,
|
rect.bottom,
|
||||||
rect.right - scrollX,
|
rect.right,
|
||||||
rect.top - scrollY
|
rect.top
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -559,20 +544,20 @@ class BesService {
|
|||||||
for (let rect of match.highlights) {
|
for (let rect of match.highlights) {
|
||||||
if (first) {
|
if (first) {
|
||||||
this.drawWrongText(
|
this.drawWrongText(
|
||||||
rect.left - scrollX,
|
rect.left,
|
||||||
rect.bottom - scrollY,
|
rect.bottom,
|
||||||
rect.right - scrollX,
|
rect.right,
|
||||||
rect.top - scrollY,
|
rect.top,
|
||||||
scale,
|
scale,
|
||||||
replacement
|
replacement
|
||||||
)
|
)
|
||||||
first = false
|
first = false
|
||||||
} else {
|
} else {
|
||||||
this.drawExcessiveText(
|
this.drawExcessiveText(
|
||||||
rect.left - scrollX,
|
rect.left,
|
||||||
rect.bottom - scrollY,
|
rect.bottom,
|
||||||
rect.right - scrollX,
|
rect.right,
|
||||||
rect.top - scrollY
|
rect.top
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -600,22 +585,11 @@ class BesService {
|
|||||||
if (/^\s+$/.test(toInsert)) {
|
if (/^\s+$/.test(toInsert)) {
|
||||||
const y1 = rects[0].bottom - 2 * scale
|
const y1 = rects[0].bottom - 2 * scale
|
||||||
const y2 = rects[0].top + 2 * scale
|
const y2 = rects[0].top + 2 * scale
|
||||||
this.drawWrongSpacing(
|
this.drawWrongSpacing(x, y1, y2, scale)
|
||||||
x - scrollX,
|
|
||||||
y1 - scrollY,
|
|
||||||
y2 - scrollY,
|
|
||||||
scale
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
const y1 = rects[0].bottom
|
const y1 = rects[0].bottom
|
||||||
const y2 = rects[0].top
|
const y2 = rects[0].top
|
||||||
this.drawMissingText(
|
this.drawMissingText(x, y1, y2, scale, toInsert.trim())
|
||||||
x - scrollX,
|
|
||||||
y1 - scrollY,
|
|
||||||
y2 - scrollY,
|
|
||||||
scale,
|
|
||||||
toInsert.trim()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else if (lengthL + lengthR === replacement.length) {
|
} else if (lengthL + lengthR === replacement.length) {
|
||||||
// Something to remove
|
// Something to remove
|
||||||
@ -629,19 +603,14 @@ class BesService {
|
|||||||
const x = (rects[0].left + rects[0].right) / 2
|
const x = (rects[0].left + rects[0].right) / 2
|
||||||
const y1 = rects[0].top
|
const y1 = rects[0].top
|
||||||
const y2 = rects[0].bottom
|
const y2 = rects[0].bottom
|
||||||
this.drawWrongSpacing(
|
this.drawWrongSpacing(x, y1, y2, scale)
|
||||||
x - scrollX,
|
|
||||||
y1 - scrollY,
|
|
||||||
y2 - scrollY,
|
|
||||||
scale
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
for (let rect of rects)
|
for (let rect of rects)
|
||||||
this.drawExcessiveText(
|
this.drawExcessiveText(
|
||||||
rect.left - scrollX,
|
rect.left,
|
||||||
rect.bottom - scrollY,
|
rect.bottom,
|
||||||
rect.right - scrollX,
|
rect.right,
|
||||||
rect.top - scrollY
|
rect.top
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -655,20 +624,20 @@ class BesService {
|
|||||||
for (let rect of rects) {
|
for (let rect of rects) {
|
||||||
if (first) {
|
if (first) {
|
||||||
this.drawWrongText(
|
this.drawWrongText(
|
||||||
rect.left - scrollX,
|
rect.left,
|
||||||
rect.bottom - scrollY,
|
rect.bottom,
|
||||||
rect.right - scrollX,
|
rect.right,
|
||||||
rect.top - scrollY,
|
rect.top,
|
||||||
scale,
|
scale,
|
||||||
toReplace
|
toReplace
|
||||||
)
|
)
|
||||||
first = false
|
first = false
|
||||||
} else {
|
} else {
|
||||||
this.drawExcessiveText(
|
this.drawExcessiveText(
|
||||||
rect.left - scrollX,
|
rect.left,
|
||||||
rect.bottom - scrollY,
|
rect.bottom,
|
||||||
rect.right - scrollX,
|
rect.right,
|
||||||
rect.top - scrollY
|
rect.top
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -684,19 +653,14 @@ class BesService {
|
|||||||
const x2 = rect.right
|
const x2 = rect.right
|
||||||
const y = rect.bottom
|
const y = rect.bottom
|
||||||
const scale = (rect.bottom - rect.top) / 18
|
const scale = (rect.bottom - rect.top) / 18
|
||||||
this.drawAttentionRequired(
|
this.drawAttentionRequired(x1, x2, y, scale)
|
||||||
x1 - scrollX,
|
|
||||||
x2 - scrollX,
|
|
||||||
y - scrollY,
|
|
||||||
scale
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
markerY1 = Math.min(...match.highlights.map(rect => rect.top))
|
markerY1 = Math.min(...match.highlights.map(rect => rect.top))
|
||||||
markerY2 = Math.max(...match.highlights.map(rect => rect.bottom))
|
markerY2 = Math.max(...match.highlights.map(rect => rect.bottom))
|
||||||
}
|
}
|
||||||
|
|
||||||
this.drawSideMarker(markerY1 - scrollY, markerY2 - scrollY)
|
this.drawSideMarker(markerY1, markerY2)
|
||||||
}
|
}
|
||||||
|
|
||||||
static commonPrefixLength(s1, s2) {
|
static commonPrefixLength(s1, s2) {
|
||||||
@ -872,15 +836,11 @@ class BesService {
|
|||||||
*/
|
*/
|
||||||
setCorrectionPanelSize() {
|
setCorrectionPanelSize() {
|
||||||
this.disableMutationObserver()
|
this.disableMutationObserver()
|
||||||
|
|
||||||
const styles = window.getComputedStyle(this.hostElement)
|
const styles = window.getComputedStyle(this.hostElement)
|
||||||
const hostRect = this.hostElement.getBoundingClientRect()
|
this.textFont = styles.fontFamily
|
||||||
// Sync margins one by one. Firefox is not happy when syncing all at once.
|
|
||||||
this.scrollPanel.style.marginLeft = styles.marginLeft
|
// Resize canvas if needed.
|
||||||
this.scrollPanel.style.marginTop = styles.marginTop
|
|
||||||
this.scrollPanel.style.marginRight = styles.marginRight
|
|
||||||
this.scrollPanel.style.marginBottom = styles.marginBottom
|
|
||||||
this.scrollPanel.style.boxSizing = styles.boxSizing
|
|
||||||
this.scrollPanel.style.scrollBehavior = styles.scrollBehavior
|
|
||||||
this.canvasPanel.style.width = `${this.hostElement.scrollWidth}px`
|
this.canvasPanel.style.width = `${this.hostElement.scrollWidth}px`
|
||||||
this.canvasPanel.style.height = `${this.hostElement.scrollHeight}px`
|
this.canvasPanel.style.height = `${this.hostElement.scrollHeight}px`
|
||||||
const dpr = window.devicePixelRatio
|
const dpr = window.devicePixelRatio
|
||||||
@ -895,6 +855,14 @@ class BesService {
|
|||||||
this.canvasPanel.height = newCanvasHeight
|
this.canvasPanel.height = newCanvasHeight
|
||||||
this.redrawAllMistakeMarkup()
|
this.redrawAllMistakeMarkup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: Firefox is not happy when syncing all margins at once.
|
||||||
|
this.scrollPanel.style.marginLeft = styles.marginLeft
|
||||||
|
this.scrollPanel.style.marginTop = styles.marginTop
|
||||||
|
this.scrollPanel.style.marginRight = styles.marginRight
|
||||||
|
this.scrollPanel.style.marginBottom = styles.marginBottom
|
||||||
|
this.scrollPanel.style.boxSizing = styles.boxSizing
|
||||||
|
this.scrollPanel.style.scrollBehavior = styles.scrollBehavior
|
||||||
if (this.isHostElementInline()) {
|
if (this.isHostElementInline()) {
|
||||||
const totalWidth =
|
const totalWidth =
|
||||||
parseFloat(styles.paddingLeft) +
|
parseFloat(styles.paddingLeft) +
|
||||||
@ -905,9 +873,11 @@ class BesService {
|
|||||||
this.scrollPanel.style.width = `${totalWidth}px`
|
this.scrollPanel.style.width = `${totalWidth}px`
|
||||||
this.scrollPanel.style.height = styles.height
|
this.scrollPanel.style.height = styles.height
|
||||||
} else {
|
} else {
|
||||||
|
const hostRect = this.hostElement.getBoundingClientRect()
|
||||||
this.scrollPanel.style.width = `${hostRect.width}px`
|
this.scrollPanel.style.width = `${hostRect.width}px`
|
||||||
this.scrollPanel.style.height = `${hostRect.height}px`
|
this.scrollPanel.style.height = `${hostRect.height}px`
|
||||||
}
|
}
|
||||||
|
|
||||||
this.enableMutationObserver()
|
this.enableMutationObserver()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -934,6 +904,7 @@ class BesService {
|
|||||||
* @param {*} match Grammar checking rule match
|
* @param {*} match Grammar checking rule match
|
||||||
*/
|
*/
|
||||||
highlightMistake(match) {
|
highlightMistake(match) {
|
||||||
|
const canvasPanelRect = this.canvasPanel.getBoundingClientRect()
|
||||||
match.highlights.forEach(rect => {
|
match.highlights.forEach(rect => {
|
||||||
const el = document.createElement('div')
|
const el = document.createElement('div')
|
||||||
el.classList.add('bes-highlight-rect')
|
el.classList.add('bes-highlight-rect')
|
||||||
@ -942,8 +913,8 @@ class BesService {
|
|||||||
? 'bes-highlight-spelling-rect'
|
? 'bes-highlight-spelling-rect'
|
||||||
: 'bes-highlight-grammar-rect'
|
: 'bes-highlight-grammar-rect'
|
||||||
)
|
)
|
||||||
el.style.left = `${rect.x + window.scrollX}px`
|
el.style.left = `${rect.x + canvasPanelRect.x + window.scrollX}px`
|
||||||
el.style.top = `${rect.y + window.scrollY}px`
|
el.style.top = `${rect.y + canvasPanelRect.y + window.scrollY}px`
|
||||||
el.style.width = `${rect.width}px`
|
el.style.width = `${rect.width}px`
|
||||||
el.style.height = `${rect.height}px`
|
el.style.height = `${rect.height}px`
|
||||||
document.body.appendChild(el)
|
document.body.appendChild(el)
|
||||||
@ -1357,12 +1328,14 @@ class BesTreeService extends BesService {
|
|||||||
const source = event?.detail !== 1 ? event?.detail : event
|
const source = event?.detail !== 1 ? event?.detail : event
|
||||||
const el = this.getBlockParent(source.targetElement || source.target)
|
const el = this.getBlockParent(source.targetElement || source.target)
|
||||||
if (!el) return
|
if (!el) return
|
||||||
// TODO: Adjust source.clientX and source.clientY for scrolling offset.
|
const canvasPanelRect = this.canvasPanel.getBoundingClientRect()
|
||||||
|
let x = source.clientX - canvasPanelRect.x
|
||||||
|
let y = source.clientY - canvasPanelRect.y
|
||||||
const pointsInRect = []
|
const pointsInRect = []
|
||||||
for (let result of this.results) {
|
for (let result of this.results) {
|
||||||
for (let m of result.matches) {
|
for (let m of result.matches) {
|
||||||
for (let rect of m.highlights) {
|
for (let rect of m.highlights) {
|
||||||
if (BesService.isPointInRect(source.clientX, source.clientY, rect)) {
|
if (BesService.isPointInRect(x, y, rect)) {
|
||||||
pointsInRect.push({ el, match: m })
|
pointsInRect.push({ el, match: m })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2022,12 +1995,14 @@ class BesPlainTextService extends BesService {
|
|||||||
const source = event?.detail !== 1 ? event?.detail : event
|
const source = event?.detail !== 1 ? event?.detail : event
|
||||||
const el = source.targetElement || source.target || this.hostElement
|
const el = source.targetElement || source.target || this.hostElement
|
||||||
if (!el) return
|
if (!el) return
|
||||||
// TODO: Adjust source.clientX and source.clientY for scrolling offset.
|
const canvasPanelRect = this.canvasPanel.getBoundingClientRect()
|
||||||
|
let x = source.clientX - canvasPanelRect.x
|
||||||
|
let y = source.clientY - canvasPanelRect.y
|
||||||
const pointsInRect = []
|
const pointsInRect = []
|
||||||
for (let result of this.results) {
|
for (let result of this.results) {
|
||||||
for (let m of result.matches) {
|
for (let m of result.matches) {
|
||||||
for (let rect of m.highlights) {
|
for (let rect of m.highlights) {
|
||||||
if (BesService.isPointInRect(source.clientX, source.clientY, rect)) {
|
if (BesService.isPointInRect(x, y, rect)) {
|
||||||
pointsInRect.push({ el: result.range, match: m })
|
pointsInRect.push({ el: result.range, match: m })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user