Compare commits

..

No commits in common. "bf7b844e1cf34548b45a85a90c8bad847e70cd03" and "0ed93fb9b29664ca759567b97724ea3797bd7fd7" have entirely different histories.

3 changed files with 182 additions and 230 deletions

View File

@ -8,33 +8,9 @@
<link rel="stylesheet" href="styles.css" /> <link rel="stylesheet" href="styles.css" />
<script>const besUrl = 'http://localhost:225/api/v2';</script> <script>const besUrl = 'http://localhost:225/api/v2';</script>
<script src="../service.js"></script> <script src="../service.js"></script>
<style>
.mock-resizable {
overflow-x: scroll;
position: relative;
display: inline-block;
border: 1px solid #ccc;
width: 300px;
height: 400px;
border-radius: 3px;
background-color: #f9f9f9;
}
.mock-content {
width: 1000px;
height: 600px;
background-color: #f9f9f9;
}
.mock-flex {
display: flex;
justify-content: center;
align-items: center;
}
</style>
</head> </head>
<body> <body>
<div class="mock-flex"> <div class="flex">
<div class="mock-content"> <div class="mock-content">
<p>Element to delete</p> <p>Element to delete</p>
<p>Element to delete</p> <p>Element to delete</p>
@ -42,7 +18,7 @@
<p>Element to delete</p> <p>Element to delete</p>
<p>Element to delete</p> <p>Element to delete</p>
</div> </div>
<div class="mock-resizable"> <div class="resizable">
<div class="my-block my-control bes-service" contenteditable="true"> <div class="my-block my-control bes-service" contenteditable="true">
<p>Tukaj vpišite besedilo ki ga želite popraviti.</p> <p>Tukaj vpišite besedilo ki ga želite popraviti.</p>
<p>Prišla je njena lepa hčera. Smatram da tega nebi bilo potrebno storiti. Predavanje je trajalo dve ure. S njim grem v Kamnik. Janez jutri nebo prišel. Prišel je z 100 idejami.</p> <p>Prišla je njena lepa hčera. Smatram da tega nebi bilo potrebno storiti. Predavanje je trajalo dve ure. S njim grem v Kamnik. Janez jutri nebo prišel. Prišel je z 100 idejami.</p>

View File

@ -73,9 +73,6 @@ 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()
} }
/** /**
@ -201,7 +198,7 @@ class BesService {
*/ */
setMarkupStyle(style) { setMarkupStyle(style) {
this.markupStyle = style this.markupStyle = style
this.redrawAllMistakeMarkup() this.repositionAllMarkup()
} }
/** /**
@ -357,19 +354,17 @@ class BesService {
} }
/** /**
* Draws grammar mistake markup on canvas and populates collection of highlight rectangles. * Creates grammar mistake markup in DOM and populates collection of highlight rectangles.
* *
* @param {*} match Grammar checking rule match * @param {*} match Grammar checking rule match
*/ */
drawMistakeMarkup(match) { addMistakeMarkup(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
@ -391,7 +386,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, y, scale, '?') this.drawMissingComma(x - scrollX, y - scrollY, scale, '?')
break break
} }
@ -418,20 +413,25 @@ 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, y, scale) this.drawMissingComma(x - scrollX, y - scrollY, 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(x, y1, y2, scale) this.drawWrongSpacing(
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, x - scrollX,
y1, y1 - scrollY,
y2, y2 - scrollY,
scale, scale,
replacement.substr(lengthDiff).trim() replacement.substr(lengthDiff).trim()
) )
@ -446,20 +446,25 @@ 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, y, scale) this.drawMissingComma(x - scrollX, y - scrollY, 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(x, y1, y2, scale) this.drawWrongSpacing(
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, x - scrollX,
y1, y1 - scrollY,
y2, y2 - scrollY,
scale, scale,
replacement.substr(-lengthDiff).trim() replacement.substr(-lengthDiff).trim()
) )
@ -483,7 +488,12 @@ 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(x, y1, y2, scale) this.drawWrongSpacing(
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,
@ -491,10 +501,10 @@ class BesService {
match.match.offset - lengthDiff match.match.offset - lengthDiff
)?.getClientRects()) )?.getClientRects())
this.drawExcessiveText( this.drawExcessiveText(
rect.left, rect.left - scrollX,
rect.bottom, rect.bottom - scrollY,
rect.right, rect.right - scrollX,
rect.top rect.top - scrollY
) )
} }
} else if (context.substr(0, replacement.length) === replacement) { } else if (context.substr(0, replacement.length) === replacement) {
@ -513,7 +523,12 @@ 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(x, y1, y2, scale) this.drawWrongSpacing(
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,
@ -521,10 +536,10 @@ class BesService {
match.match.offset + match.match.length match.match.offset + match.match.length
)?.getClientRects()) )?.getClientRects())
this.drawExcessiveText( this.drawExcessiveText(
rect.left, rect.left - scrollX,
rect.bottom, rect.bottom - scrollY,
rect.right, rect.right - scrollX,
rect.top rect.top - scrollY
) )
} }
} else { } else {
@ -544,20 +559,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, rect.left - scrollX,
rect.bottom, rect.bottom - scrollY,
rect.right, rect.right - scrollX,
rect.top, rect.top - scrollY,
scale, scale,
replacement replacement
) )
first = false first = false
} else { } else {
this.drawExcessiveText( this.drawExcessiveText(
rect.left, rect.left - scrollX,
rect.bottom, rect.bottom - scrollY,
rect.right, rect.right - scrollX,
rect.top rect.top - scrollY
) )
} }
} }
@ -585,11 +600,22 @@ 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(x, y1, y2, scale) this.drawWrongSpacing(
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(x, y1, y2, scale, toInsert.trim()) this.drawMissingText(
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
@ -603,14 +629,19 @@ 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(x, y1, y2, scale) this.drawWrongSpacing(
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, rect.left - scrollX,
rect.bottom, rect.bottom - scrollY,
rect.right, rect.right - scrollX,
rect.top rect.top - scrollY
) )
} }
} else { } else {
@ -624,20 +655,20 @@ class BesService {
for (let rect of rects) { for (let rect of rects) {
if (first) { if (first) {
this.drawWrongText( this.drawWrongText(
rect.left, rect.left - scrollX,
rect.bottom, rect.bottom - scrollY,
rect.right, rect.right - scrollX,
rect.top, rect.top - scrollY,
scale, scale,
toReplace toReplace
) )
first = false first = false
} else { } else {
this.drawExcessiveText( this.drawExcessiveText(
rect.left, rect.left - scrollX,
rect.bottom, rect.bottom - scrollY,
rect.right, rect.right - scrollX,
rect.top rect.top - scrollY
) )
} }
} }
@ -653,22 +684,36 @@ 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(x1, x2, y, scale) this.drawAttentionRequired(
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, markerY2) this.drawSideMarker(markerY1 - scrollY, markerY2 - scrollY)
}
static commonPrefixLength(s1, s2) {
let i = 0
let len = Math.min(s1.length, s2.length)
while (i < len && s1[i] === s2[i]) i++
return i
}
static commonSuffixLength(s1, s2) {
let i = 0
let i1 = s1.length
let i2 = s2.length
while (0 < i1-- && 0 < i2-- && s1[i1] === s2[i2]) i++
return i
} }
/**
* Draws the marker that helps visualize lines of text where grammar mistakes were detected
*
* @param {Number} y1 Marker top [px]
* @param {Number} y2 Marker bottom [px]
*/
drawSideMarker(y1, y2) { drawSideMarker(y1, y2) {
const dpr = window.devicePixelRatio const dpr = window.devicePixelRatio
const markerX = this.canvasPanel.width - 5 * dpr const markerX = this.canvasPanel.width - 5 * dpr
@ -678,14 +723,6 @@ class BesService {
this.ctx.stroke() this.ctx.stroke()
} }
/**
* Draws the missing comma sign
*
* @param {Number} x Sign center [px]
* @param {Number} y Sign bottom [px]
* @param {Number} scale Sign scale
* @param {String} comment Text to display above the marker
*/
drawMissingComma(x, y, scale, comment) { drawMissingComma(x, y, scale, comment) {
const dpr = window.devicePixelRatio const dpr = window.devicePixelRatio
this.ctx.beginPath() this.ctx.beginPath()
@ -702,14 +739,6 @@ class BesService {
} }
} }
/**
* Draws the wrong spacing sign. Control direction of chevrons by reversing y1 and y2.
*
* @param {Number} x Sign center [px]
* @param {Number} y1 Sign top/bottom [px]
* @param {Number} y2 Sign bottom/top [px]
* @param {Number} scale Sign scale
*/
drawWrongSpacing(x, y1, y2, scale) { drawWrongSpacing(x, y1, y2, scale) {
const dpr = window.devicePixelRatio const dpr = window.devicePixelRatio
this.ctx.beginPath() this.ctx.beginPath()
@ -724,14 +753,6 @@ class BesService {
this.ctx.stroke() this.ctx.stroke()
} }
/**
* Strikes out the excessive text
*
* @param {Number} x1 Strike line start X [px]
* @param {Number} y1 Strike line start Y [px]
* @param {Number} x2 Strike line end X [px]
* @param {Number} y2 Strike line end Y [px]
*/
drawExcessiveText(x1, y1, x2, y2) { drawExcessiveText(x1, y1, x2, y2) {
const dpr = window.devicePixelRatio const dpr = window.devicePixelRatio
this.ctx.beginPath() this.ctx.beginPath()
@ -740,16 +761,6 @@ class BesService {
this.ctx.stroke() this.ctx.stroke()
} }
/**
* Strikes out the text and draws the replacement text above
*
* @param {Number} x1 Strike line start X [px]
* @param {Number} y1 Strike line start Y [px]
* @param {Number} x2 Strike line end X [px]
* @param {Number} y2 Strike line end Y [px]
* @param {Number} scale Sign scale
* @param {String} text Text to display above
*/
drawWrongText(x1, y1, x2, y2, scale, text) { drawWrongText(x1, y1, x2, y2, scale, text) {
const dpr = window.devicePixelRatio const dpr = window.devicePixelRatio
this.ctx.beginPath() this.ctx.beginPath()
@ -774,15 +785,6 @@ class BesService {
) )
} }
/**
* Draws the sign some text is missing
*
* @param {Number} x Sign center [px]
* @param {Number} y1 Sign bottom [px]
* @param {Number} y2 Sign top [px]
* @param {Number} scale Sign scale
* @param {String} text Text to display above
*/
drawMissingText(x, y1, y2, scale, text) { drawMissingText(x, y1, y2, scale, text) {
const dpr = window.devicePixelRatio const dpr = window.devicePixelRatio
this.ctx.beginPath() this.ctx.beginPath()
@ -809,14 +811,6 @@ class BesService {
) )
} }
/**
* Draws zig-zag line
*
* @param {Number} x1 Sign left [px]
* @param {Number} x2 Sign right [px]
* @param {Number} y Sign baseline [px]
* @param {Number} scale Sign scale
*/
drawAttentionRequired(x1, x2, y, scale) { drawAttentionRequired(x1, x2, y, scale) {
const dpr = window.devicePixelRatio const dpr = window.devicePixelRatio
this.ctx.beginPath() this.ctx.beginPath()
@ -830,35 +824,6 @@ class BesService {
this.ctx.stroke() this.ctx.stroke()
} }
/**
* Calculates common string prefix length
*
* @param {String} s1 First string
* @param {String} s2 Second string
* @returns Number of characters the beginnings of the strings are equal
*/
static commonPrefixLength(s1, s2) {
let i = 0
let len = Math.min(s1.length, s2.length)
while (i < len && s1[i] === s2[i]) i++
return i
}
/**
* Calculates common string suffix length
*
* @param {String} s1 First string
* @param {String} s2 Second string
* @returns Number of characters the endings of the strings are equal
*/
static commonSuffixLength(s1, s2) {
let i = 0
let i1 = s1.length
let i2 = s2.length
while (0 < i1-- && 0 < i2-- && s1[i1] === s2[i2]) i++
return i
}
/** /**
* Tests if given coordinate is inside of a rectangle. * Tests if given coordinate is inside of a rectangle.
* *
@ -875,21 +840,21 @@ class BesService {
* Creates auxiliary DOM elements for text adornments. * Creates auxiliary DOM elements for text adornments.
*/ */
createCorrectionPanel() { createCorrectionPanel() {
this.panelParent = document.createElement('div')
this.panelParent.classList.add('bes-correction-panel-parent')
this.correctionPanel = document.createElement('div') this.correctionPanel = document.createElement('div')
this.correctionPanel.classList.add('bes-correction-panel') this.correctionPanel.classList.add('bes-correction-panel')
this.scrollPanel = document.createElement('div')
this.scrollPanel.classList.add('bes-scroll-panel')
this.canvasPanel = document.createElement('canvas') this.canvasPanel = document.createElement('canvas')
this.canvasPanel.classList.add('bes-canvas') this.canvasPanel.classList.add('bes-canvas')
this.ctx = this.canvasPanel.getContext('2d') this.ctx = this.canvasPanel.getContext('2d')
this.ctx.scale(1, 1) this.ctx.scale(1, 1)
this.correctionPanel.appendChild(this.scrollPanel) this.panelParent.appendChild(this.correctionPanel)
this.scrollPanel.appendChild(this.canvasPanel) this.correctionPanel.appendChild(this.canvasPanel)
this.textElement.parentElement.insertBefore( this.textElement.parentElement.insertBefore(
this.correctionPanel, this.panelParent,
this.textElement this.textElement
) )
this.setCorrectionPanelSize() this.setCorrectionPanelSize()
@ -899,7 +864,7 @@ class BesService {
* Clears auxiliary DOM elements for text adornments. * Clears auxiliary DOM elements for text adornments.
*/ */
clearCorrectionPanel() { clearCorrectionPanel() {
this.correctionPanel.remove() this.panelParent.remove()
} }
/** /**
@ -907,11 +872,15 @@ class BesService {
*/ */
setCorrectionPanelSize() { setCorrectionPanelSize() {
this.disableMutationObserver() this.disableMutationObserver()
const styles = window.getComputedStyle(this.hostElement) const styles = window.getComputedStyle(this.hostElement)
this.textFont = styles.fontFamily const hostRect = this.hostElement.getBoundingClientRect()
// Sync margins one by one. Firefox is not happy when syncing all at once.
// Resize canvas if needed. this.correctionPanel.style.marginLeft = styles.marginLeft
this.correctionPanel.style.marginTop = styles.marginTop
this.correctionPanel.style.marginRight = styles.marginRight
this.correctionPanel.style.marginBottom = styles.marginBottom
this.correctionPanel.style.boxSizing = styles.boxSizing
this.correctionPanel.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
@ -924,16 +893,8 @@ class BesService {
) { ) {
this.canvasPanel.width = newCanvasWidth this.canvasPanel.width = newCanvasWidth
this.canvasPanel.height = newCanvasHeight this.canvasPanel.height = newCanvasHeight
this.redrawAllMistakeMarkup() this.repositionAllMarkup()
} }
// 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) +
@ -941,14 +902,12 @@ class BesService {
parseFloat(styles.width) + parseFloat(styles.width) +
parseFloat(styles.marginRight) + parseFloat(styles.marginRight) +
parseFloat(styles.paddingRight) parseFloat(styles.paddingRight)
this.scrollPanel.style.width = `${totalWidth}px` this.correctionPanel.style.width = `${totalWidth}px`
this.scrollPanel.style.height = styles.height this.correctionPanel.style.height = styles.height
} else { } else {
const hostRect = this.hostElement.getBoundingClientRect() this.correctionPanel.style.width = `${hostRect.width}px`
this.scrollPanel.style.width = `${hostRect.width}px` this.correctionPanel.style.height = `${hostRect.height}px`
this.scrollPanel.style.height = `${hostRect.height}px`
} }
this.enableMutationObserver() this.enableMutationObserver()
} }
@ -970,12 +929,11 @@ class BesService {
} }
/** /**
* Highlights given grammar mistake. * Removes previously highlighted grammar mistake and highlights new one.
* *
* @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')
@ -984,8 +942,8 @@ class BesService {
? 'bes-highlight-spelling-rect' ? 'bes-highlight-spelling-rect'
: 'bes-highlight-grammar-rect' : 'bes-highlight-grammar-rect'
) )
el.style.left = `${rect.x + canvasPanelRect.x + window.scrollX}px` el.style.left = `${rect.x + window.scrollX}px`
el.style.top = `${rect.y + canvasPanelRect.y + window.scrollY}px` el.style.top = `${rect.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)
@ -1017,12 +975,12 @@ class BesService {
} }
/** /**
* Redraws all grammar mistake markup. * Updates all grammar mistake markup positions.
*/ */
redrawAllMistakeMarkup() { repositionAllMarkup() {
this.ctx.clearRect(0, 0, this.canvasPanel.width, this.canvasPanel.height) this.ctx.clearRect(0, 0, this.canvasPanel.width, this.canvasPanel.height)
this.results.forEach(result => { this.results.forEach(result => {
result.matches.forEach(match => this.drawMistakeMarkup(match)) result.matches.forEach(match => this.addMistakeMarkup(match))
}) })
} }
@ -1178,7 +1136,7 @@ class BesTreeService extends BesService {
), ),
match: match match: match
} }
this.drawMistakeMarkup(m) this.addMistakeMarkup(m)
matches.push(m) matches.push(m)
}) })
this.markProofed(node, matches) this.markProofed(node, matches)
@ -1263,7 +1221,7 @@ class BesTreeService extends BesService {
this.results = this.results.filter( this.results = this.results.filter(
result => !BesTreeService.isSameParagraph(result.element, el) result => !BesTreeService.isSameParagraph(result.element, el)
) )
this.redrawAllMistakeMarkup() this.repositionAllMarkup()
} }
/** /**
@ -1399,16 +1357,12 @@ 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
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(x, y, rect)) { if (BesService.isPointInRect(source.clientX, source.clientY, rect)) {
pointsInRect.push({ el, match: m }) pointsInRect.push({ el, match: m })
break
} }
} }
} }
@ -1498,7 +1452,7 @@ class BesDOMService extends BesTreeService {
*/ */
onInput() { onInput() {
// Now that the text is done changing, we can correctly calculate markup position. // Now that the text is done changing, we can correctly calculate markup position.
this.redrawAllMistakeMarkup() this.repositionAllMarkup()
this.dismissPopup() this.dismissPopup()
// Defer grammar-checking to reduce stress on grammar-checking server. // Defer grammar-checking to reduce stress on grammar-checking server.
this.scheduleProofing(1000) this.scheduleProofing(1000)
@ -1580,7 +1534,7 @@ class BesCKService extends BesTreeService {
// element, it will not be updated immediately. // element, it will not be updated immediately.
setTimeout(() => { setTimeout(() => {
// Now that the text is done changing, we can correctly calculate markup position. // Now that the text is done changing, we can correctly calculate markup position.
this.redrawAllMistakeMarkup() this.repositionAllMarkup()
// Defer grammar-checking to reduce stress on grammar-checking server. // Defer grammar-checking to reduce stress on grammar-checking server.
this.scheduleProofing(1000) this.scheduleProofing(1000)
@ -1747,7 +1701,7 @@ class BesQuillService extends BesTreeService {
this.clearProofing(domElement) this.clearProofing(domElement)
setTimeout(() => { setTimeout(() => {
this.redrawAllMistakeMarkup() this.repositionAllMarkup()
this.scheduleProofing(1000) this.scheduleProofing(1000)
}, 0) }, 0)
} }
@ -1933,7 +1887,7 @@ class BesPlainTextService extends BesService {
), ),
match: match match: match
} }
this.drawMistakeMarkup(m) this.addMistakeMarkup(m)
matches.push(m) matches.push(m)
}) })
this.markProofed(paragraphRange, matches) this.markProofed(paragraphRange, matches)
@ -2024,7 +1978,7 @@ class BesPlainTextService extends BesService {
this.results = this.results.filter( this.results = this.results.filter(
result => !BesPlainTextService.isSameParagraph(result.range, range) result => !BesPlainTextService.isSameParagraph(result.range, range)
) )
this.redrawAllMistakeMarkup() this.repositionAllMarkup()
} }
/** /**
@ -2067,16 +2021,12 @@ 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
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(x, y, rect)) { if (BesService.isPointInRect(source.clientX, source.clientY, rect)) {
pointsInRect.push({ el: result.range, match: m }) pointsInRect.push({ el: result.range, match: m })
break
} }
} }
} }
@ -2196,7 +2146,7 @@ class BesDOMPlainTextService extends BesPlainTextService {
delete this.textBeforeChange delete this.textBeforeChange
// Now that the text is done changing, we can correctly calculate markup position. // Now that the text is done changing, we can correctly calculate markup position.
this.redrawAllMistakeMarkup() this.repositionAllMarkup()
this.dismissPopup() this.dismissPopup()
// Defer grammar-checking to reduce stress on grammar-checking server. // Defer grammar-checking to reduce stress on grammar-checking server.
this.scheduleProofing(1000) this.scheduleProofing(1000)
@ -2274,6 +2224,9 @@ class BesTAService extends BesPlainTextService {
*/ */
constructor(hostElement, eventSink) { constructor(hostElement, eventSink) {
super(hostElement, BesTAService.createTextElement(hostElement), eventSink) super(hostElement, BesTAService.createTextElement(hostElement), eventSink)
this.textElement.replaceChildren(
document.createTextNode(this.hostElement.value)
)
} }
/** /**
@ -2313,7 +2266,6 @@ class BesTAService extends BesPlainTextService {
static createTextElement(hostElement) { static createTextElement(hostElement) {
const textElement = document.createElement('div') const textElement = document.createElement('div')
textElement.classList.add('bes-text-panel') textElement.classList.add('bes-text-panel')
textElement.replaceChildren(document.createTextNode(hostElement.value))
BesTAService.setTextElementSize(hostElement, textElement) BesTAService.setTextElementSize(hostElement, textElement)
hostElement.parentNode.insertBefore(textElement, hostElement) hostElement.parentNode.insertBefore(textElement, hostElement)
return textElement return textElement
@ -2463,7 +2415,7 @@ class BesTAService extends BesPlainTextService {
}) })
// Now that the text is done changing, we can correctly calculate markup position. // Now that the text is done changing, we can correctly calculate markup position.
this.redrawAllMistakeMarkup() this.repositionAllMarkup()
// Defer grammar-checking to reduce stress on grammar-checking server. // Defer grammar-checking to reduce stress on grammar-checking server.
this.scheduleProofing(1000) this.scheduleProofing(1000)

View File

@ -22,8 +22,14 @@
background: rgb(255, 115, 0); background: rgb(255, 115, 0);
} }
.bes-canvas {
position: relative;
z-index: 3;
cursor: text;
}
/* Styles required to ensure full functionality and optimal user experience. */ /* Styles required to ensure full functionality and optimal user experience. */
.bes-correction-panel { .bes-correction-panel-parent {
position: relative; position: relative;
overflow: visible; overflow: visible;
float: left; float: left;
@ -34,7 +40,7 @@
z-index: 1; z-index: 1;
} }
.bes-scroll-panel { .bes-correction-panel {
position: relative; position: relative;
overflow: hidden; overflow: hidden;
border-color: transparent; border-color: transparent;
@ -42,12 +48,6 @@
pointer-events: none; pointer-events: none;
} }
.bes-canvas {
position: relative;
z-index: 3;
cursor: text;
}
.bes-text-panel { .bes-text-panel {
position: absolute; position: absolute;
overflow: hidden; overflow: hidden;
@ -56,3 +56,27 @@
border-color: transparent; border-color: transparent;
background: none; background: none;
} }
/* TODO: Styles below should be removed after testing period is over */
.resizable {
overflow-x: scroll;
position: relative;
display: inline-block;
border: 1px solid #ccc;
width: 300px;
height: 400px;
border-radius: 3px;
background-color: #f9f9f9;
}
.mock-content {
width: 1000px;
height: 600px;
background-color: #f9f9f9;
}
.flex {
display: flex;
justify-content: center;
align-items: center;
}