The Selection API can be used to detect the cursor’s position in a contenteditable container. However, if a cursor is placed at the very end of a line, or at the very beginning, I can not find a way to detect the difference as the index is the same. Even if I use the getBoundingClientRect()
method on the range, it still returns the call bounding box for the two separate locations.
I have two screenshots showing the cursor in both positions and the details showing the same information
The snippet below can also demonstrate this
const updateRange = () => {
const range = document.getSelection()?.getRangeAt(0);
const rect = range.getBoundingClientRect();
let res = {
startOffset: range.startOffset,
endOffset: range.endOffset,
top: rect.top,
bottom: rect.bottom,
left: rect.left,
right: rect.right,
};
document.querySelector('code').textContent = JSON.stringify(res, null, 2);
};
const div = document.querySelector('div');
div.addEventListener('click', updateRange);
div.addEventListener('keyup', updateRange);
main {
display: grid;
grid-template-columns: 1fr 1fr;
}
div {
font-family: monospace;
font-size: 4rem;
width: 200px;
padding: 1rem;
word-wrap: break-word;
}
code {
white-space: pre;
float: right;
}
<main>
<div contenteditable>CONTENT</div>
<code></code>
</main>
I’m implementing a method to remove the entire visual line (deleteEntireSoftLine
from here). Obviously this should behave differently depending on these two different scenarios.
I’ve tested this both on Brave/Chromium and Firefox. Both had the same functionality. Using getClientRects()
performed the same as getBoundingClientRect()
.
I did notice that if I set the div
to display: inline-block
, I can no longer forcefully place the cursor at the clear end of the line, however I want the user to be able to place the cursor at the end of the line.