Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change cursor position in the contenteditable div after changing innerHTML

I have a simple contenteditable div with some text in it. On onkeyup event i want to replace whole content (innerHTML) of the div based on regex.

For example,

HTML:

some text, more text and $even more text

Function in which i plan to get all text with $ ($even in example above) and wrap it in span tag:

div.onkeypress = function() { 
     div.innerHTML.replace(/(some_regexp)/, "<span class='class'>$1</span>"); 
}; 

The problem is after such replacement cursor jumps to the start of the div. I want it to stay where it was before.

I imagine i have to save coordinates of the cursor before change and then somehow using them set cursor back but how can i do it? :)

I tried saving range object but after editing i believe it points to nowhere.

Thanks!

like image 341
Ilya Tsuryev Avatar asked Sep 24 '10 16:09

Ilya Tsuryev


People also ask

How do you set a caret cursor position in Contenteditable element div?

To set caret position at a specific position in contenteditable div with JavaScript, we select the text node that with the text we want the cursor to be at and set the caret position there. to add a contenteditable div. Then we write: const node = document.

How do I change cursor position?

Use the SetCursorPosition method to specify where the next write operation in the console window is to begin. If the specified cursor position is outside the area that is currently visible in the console window, the window origin changes automatically to make the cursor visible.

Is it good practice to use innerHTML?

The use of innerHTML creates a potential security risk for your website. Malicious users can use cross-site scripting (XSS) to add malicious client-side scripts that steal private user information stored in session cookies. You can read the MDN documentation on innerHTML .

How do I turn off Contenteditable Div?

Just set contentEditable="false" . See this answer.


2 Answers

The problem is that you're updating the whole innerHTML, but only a small part of it is changing. You can't use a regular expression and o a bulk replace. You need to scan the div and look for matches, create text ranges out of them and wrap the content with the span. See http://www.quirksmode.org/dom/range_intro.html , Programmatically creating a Range.

However, I think this won't work if the cursor is in the text to be replaced, it's a start though.

like image 175
Juan Mendes Avatar answered Sep 20 '22 15:09

Juan Mendes


I took this from another forum. It solved my problem.

Ok, I managed to work around it, here's the solution if anyone's interested:

Store the selection x, y:

Code:

cursorPos=document.selection.createRange().duplicate();
clickx = cursorPos.getBoundingClientRect().left; 
clicky = cursorPos.getBoundingClientRect().top;

Restore the selection:

Code:

cursorPos = document.body.createTextRange();
cursorPos.moveToPoint(clickx, clicky);
cursorPos.select();

You can see it working here:

http://www.tachyon-labs.com/sharpspell/

like image 29
Serena Avatar answered Sep 17 '22 15:09

Serena