Skip to content

Commit 5687b0f

Browse files
committed
fix: Fix cursor.isAtLastLine and cursor.isAtFirstLine calculations to respect line breaks
This fixes some issue with range.getClientBoundingRect() that doesn't respect newlines at the start and at the end of a block. By inserting a temporary element, we get the exact position of current range. ``` <br> <br> <!-- The cursor offset basically starts here instead of two lines above with range.getClientBoundingRect() --> <p>| Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> <p>Curabitur vitae lobortis ante. Vivamus metus magna<p> ```
1 parent 420dfef commit 5687b0f

File tree

1 file changed

+22
-7
lines changed

1 file changed

+22
-7
lines changed

src/cursor.js

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,19 @@ export default class Cursor {
9393
isAtLastLine () {
9494
const hostRange = this.win.document.createRange()
9595
hostRange.selectNodeContents(this.host)
96-
const hostCoords = hostRange.getBoundingClientRect()
97-
const cursorCoords = getCursorBoundingClientRect(this.range.nativeRange, this.win)
98-
96+
hostRange.collapse(false)
97+
const hostCoords = getRangeBoundingClientRect(hostRange, this.win)
98+
const cursorCoords = getRangeBoundingClientRect(this.range.nativeRange, this.win)
9999
return hostCoords.bottom === cursorCoords.bottom
100100
}
101101

102102
isAtFirstLine () {
103103
const hostRange = this.win.document.createRange()
104104
hostRange.selectNodeContents(this.host)
105-
const hostCoords = hostRange.getBoundingClientRect()
106-
const cursorCoords = getCursorBoundingClientRect(this.range.nativeRange, this.win)
105+
hostRange.collapse(true)
106+
const hostCoords = getRangeBoundingClientRect(hostRange, this.win)
107+
const cursorCoords = getRangeBoundingClientRect(this.range.nativeRange, this.win)
108+
console.log(hostCoords.top, cursorCoords.top)
107109
return hostCoords.top === cursorCoords.top
108110
}
109111

@@ -345,10 +347,23 @@ export default class Cursor {
345347
}
346348
}
347349

348-
function getCursorBoundingClientRect (range, win) {
350+
351+
/**
352+
* Get position of the range or cursor
353+
*
354+
* Can be used to reliably get the boundingClientRect without
355+
* some any of the drawbacks that the native range has.
356+
*
357+
* With the native range.getClientBoundingRect(), newlines are
358+
* not considered when calculating the position
359+
*
360+
* @param {Range} range
361+
* @param {Window} win
362+
*/
363+
function getRangeBoundingClientRect (range, win) {
349364
if (range.startContainer.nodeType !== elementNode) return range.getBoundingClientRect()
350365
const el = win.document.createElement('span')
351-
el.setAttribute('doc-editable', 'remove')
366+
el.setAttribute('doc-editable', 'unwrap')
352367
range.insertNode(el)
353368
const coords = el.getBoundingClientRect()
354369
el.remove()

0 commit comments

Comments
 (0)