Search code examples
javascriptcontenteditable

Javascript: Get text in a contenteditable up to the caret


I'm surprised I'm having trouble with this and unable to find an answer. I'm trying to get the text in a contenteditable, from the start of the contenteditable to the users cursor/caret.

Here's a jsFiddle of what I've attempted (click around the contenteditable and watch console.log).

I get the caret location and then I attempt to get the content:

I tried using textContent of the contenteditable which works but if there's content like foo<br>bar it outputs foobar when ideally it should output foo\r\nbar (Note: This is for a chrome extension I have no control over the content of the contenteditable).

innerText works as expected outputting foo\r\nbar, but as can be seen in the jsFiddle once the html in contenteditable gets a little complex the caret position doesn't seem to match the location in innerText and I have trouble outputting up to the caret.

Found some code using the Range interface and modified it to meet my needs in this jsFiddle but had the same problem with <br> as textContent did.

Note: The user will continue typing as I get the content, so looking for something that doesn't break this flow.

Just looking for direction, any quick tips on what I should try?


Solution

  • In your fiddle I replaced the JavaScript content with:

    document.querySelector("#edit").addEventListener("click", function(){
      var target = document.querySelector('#edit');
      var sel = document.getSelection();
      if(!sel.toString()) {
        var range = document.getSelection().getRangeAt(0);
        var container = range.startContainer;
        var offset = range.startOffset;
        range.setStart(target, 0);
        //do your stuff with sel.toString()
        console.log(sel.toString());
        //restore the range
        range.setStart(container, offset);
      }
    });
    

    Hope this helps.

    Edit: since you said

    Note: The user will continue typing as I get the content, so looking for something that doesn't break this flow.

    I thought that the click event was just an example; getting the text while user is typing implies:

    1. the entry point can't be click event but probably a setInterval function
    2. while user is typing there is no selections, only the caret

    To solve the reported bug is enough changing the code as I did, anyway this is only an example to get the result you are interested in; than you have to work on it to achieve the desired behavior for all the possible case of your real scenario.