简体   繁体   中英

Place caret back where it was after changing innerHTML of a contenteditable element

I need to update the innerHTML of a contenteditable P element after each keystroke, in JavaScript

(no jQuery)

I can't use an input or textarea instead of the P element.

It works fine, but the caret always goes back at the beginning of the paragraph when the innerHTML is reset.

I tried to use the solutions of the other SO questions that talk about carets and contenteditable but it doesn't seem to work in my case: I want to put the caret back exactly where it was before the update of innerHTML.

 p.oninput=function(){ // Get caret position c = window.getSelection(). getRangeAt(0). startOffset; console.log(c); // Update innerHTML p.innerHTML = p.innerHTML.toUpperCase(); // Place caret back // ??? }
 p{ border: 1px dotted red }
 <p contenteditable id=p>type here

BTW, It doesn't need to work on IE, but if you have a cross-browser solution, I'll take it too.

Thanks for your help!

Consider stepping away from the problem.

Solution 1: do not convert to uppercase until finished typing.

Solution 2: set P to monospaced font. Make the P transparent. Have div behind that updates with values as uppercase. Not sure how to show caret ... ?

Remember seeing article a year or so ago where a coding interface used similar method to have colour coded code in a textarea.

I added

const range = window.getSelection();
range.selectAllChildren(p);
range.collapseToEnd();

to your code and it seems solve the problem.

 p.oninput=function(){ // Get caret position c = window.getSelection(). getRangeAt(0). startOffset; console.log(c); // Update innerHTML p.innerHTML = p.innerHTML.toUpperCase(); const range = window.getSelection(); range.selectAllChildren(p); range.collapseToEnd(); } 
 p{ border: 1px dotted red } 
 <p contenteditable id=p>type here 

How late do you want to be to the party? "Yes"

If someone is still looking for a solution, maybe this works for you?

 p.oninput=function(){ // Get caret position c = window.getSelection(). getRangeAt(0). startOffset; console.log(c); // Update innerHTML p.innerHTML = p.innerHTML.toUpperCase(); var range = document.createRange(); var sel = window.getSelection(); range.setStart(p.childNodes[0], c); range.collapse(true); sel.removeAllRanges(); sel.addRange(range); }
 p{ border: 1px dotted red }
 <p contenteditable id=p>type here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM