-
-
Save lexeek/ad4dd93f71d9717c626fc6ac3b96f95a to your computer and use it in GitHub Desktop.
Small script to detect caret pixel position in contenteditable div
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Get the caret position in all cases | |
* | |
* @returns {object} left, top distance in pixels | |
*/ | |
getCaretTopPoint () { | |
const sel = document.getSelection() | |
const r = sel.getRangeAt(0) | |
let rect | |
let r2 | |
// supposed to be textNode in most cases | |
// but div[contenteditable] when empty | |
const node = r.startContainer | |
const offset = r.startOffset | |
if (offset > 0) { | |
// new range, don't influence DOM state | |
r2 = document.createRange() | |
r2.setStart(node, (offset - 1)) | |
r2.setEnd(node, offset) | |
// https://developer.mozilla.org/en-US/docs/Web/API/range.getBoundingClientRect | |
// IE9, Safari?(but look good in Safari 8) | |
rect = r2.getBoundingClientRect() | |
return { left: rect.right, top: rect.top } | |
} else if (offset < node.length) { | |
r2 = document.createRange() | |
// similar but select next on letter | |
r2.setStart(node, offset) | |
r2.setEnd(node, (offset + 1)) | |
rect = r2.getBoundingClientRect() | |
return { left: rect.left, top: rect.top } | |
} else { // textNode has length | |
// https://developer.mozilla.org/en-US/docs/Web/API/Element.getBoundingClientRect | |
rect = node.getBoundingClientRect() | |
const styles = getComputedStyle(node) | |
const lineHeight = parseInt(styles.lineHeight) | |
const fontSize = parseInt(styles.fontSize) | |
// roughly half the whitespace... but not exactly | |
const delta = (lineHeight - fontSize) / 2 | |
return { left: rect.left, top: (rect.top + delta) } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment