-
-
Save islishude/6ccd1fbf42d1eaac667d6873e7b134f8 to your computer and use it in GitHub Desktop.
/** | |
* @file get/set caret position and insert text | |
* @author islishude | |
* @license MIT | |
*/ | |
export class Caret { | |
/** | |
* get/set caret position | |
* @param {HTMLColletion} target | |
*/ | |
constructor(target) { | |
this.isContentEditable = target && target.contentEditable | |
this.target = target | |
} | |
/** | |
* get caret position | |
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Range} | |
* @returns {number} | |
*/ | |
getPos() { | |
// for contentedit field | |
if (this.isContentEditable) { | |
this.target.focus() | |
let _range = document.getSelection().getRangeAt(0) | |
let range = _range.cloneRange() | |
range.selectNodeContents(this.target) | |
range.setEnd(_range.endContainer, _range.endOffset) | |
return range.toString().length; | |
} | |
// for texterea/input element | |
return this.target.selectionStart | |
} | |
/** | |
* set caret position | |
* @param {number} pos - caret position | |
*/ | |
setPos(pos) { | |
// for contentedit field | |
if (this.isContentEditable) { | |
this.target.focus() | |
document.getSelection().collapse(this.target, pos) | |
return | |
} | |
this.target.setSelectionRange(pos, pos) | |
} | |
} | |
/** | |
* insert text or orther to editor | |
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand | |
* @module Editor | |
*/ | |
export class Editor { | |
constructor() { | |
} | |
/** | |
* @param {string} content - your insert text | |
* @returns {boolean} | |
*/ | |
insertText(content) { | |
document.execCommand('insertText', false, content) | |
} | |
} |
My code is like this :
let caret = new Caret(document.getElementById('myDiv'));
var previousPos = caret.getPos();
//Doing some stuff in the contenteditable div...
caret.setPos(previousPos);
However the result is... Strange. I get an error on line 42 document.getSelection().collapse(this.target, pos)
while typing (without moving the caret myself) - The number here represents the pos
variable passed to the collapse()
function :
1
2 -> Crash
1
4 -> Crash
1
6 -> Crash
1
8 -> Crash
1
10 -> Crash
1
9 -> Crash
1
11 -> Crash
1
13 -> Crash
1
12 -> Crash
1
14 -> Crash
1
16 -> Crash
1
15 -> Crash
1
17 -> Crash
1
19 -> Crash
So what I typed :
TESTESTESTESTESTEST
What I got :
STESTESTESTESTETSETSETSETSET
I'm currently trying to understand where the error comes from.
EDIT :
sel.collapse()
second parameter corresponds to the end of which word you want to set the caret to if the selection lenth is 0.
@JeanMarcZimmer have you been able to figure out how to make this work?
I'm getting the same issue as you. The code crashes every now and then when I type; usually at around 3-4 characters in.
@Grandclosing no, in the end I used a dirty solution for my syntax colouring.
I struggled with my project for two days. That's clear now. Thank you very much. 😍
@Grandclosing, the second argument to Selection#collapse
looks wrong, see https://developer.mozilla.org/en-US/docs/Web/API/Selection/collapse
Hey, did anyone managed to get it to work or have found an alternative solution to get/set caret position inside the text with Html tags?
@abohomol, I think, something like in https://stackoverflow.com/a/41034697/839199 should work
@Yaffle Unfortunately, this one has an unsolved bug where the cursor doesn't account line breaks and the position is shifted. I've been trying to fix it with no luck for a day or two and gave up.
@abohomol, I have my own similar solution at https://gist.github.com/Yaffle/117a0f6f92976b5cc6a6f570d911d912 , to handle
It just checks the tagName and considers it is like one new line character.
Thanks for the breadcrumbs. I put the above stackoverflow snippet with minor modifications into a codepen demo -- I didn't see any problems with <br>
.
Unlike some solutions, it doesn't maintain the selection range, but that's ok for my use case.
_rang
instead of_range
on line 27 ? 🙂