Search code examples
javascripttextareaselectioncaretwysihtml5

How to change the caret offset in a rich text editor textarea?


I have a wysihtml rich text editor. If certain conditions are met I want to change the offset of the caret.

Because a wysithtml textarea is not really a textarea div (it's just a regular div) I can't use the common textarea strategies to move the caret. But after some experimentation I found out that treating it as a Selection enables me to work with it as a textarea.

From what I read the correct method to change the caret offset is Range.setStart(), but I can't figure out how to use it. Anyone who can help me?

I have set up this jsfiddle. Try (in Firefox) to move the caret to offset 27. Then the value of the editor will change, and the caret will move to offset 0. But how do I move the caret to e.g. offset 35?


Solution

  • I have updated your fiddle to work like you want.
    This is the part i modified :

    if (offsets.start_offset == 27) {
        editor.setValue("This is first line.<br>This is another second line.", true);
    
       /* START OF MODIFICATION */
    
          var range = window.getSelection().getRangeAt(0);
          range.selectNodeContents(textarea);
    
            var fromPos = 27;
            var lenTotal = ( textarea.textContent || textarea.innerText ).length;
            var lenCurTextNode = range.endContainer.lastChild.nodeValue.length;
            var lenNewWord= 'another '.length ;
    
            var newPos = ( fromPos - (lenTotal - lenCurTextNode) ) + lenNewWord;
    
    
          range.setStart(range.startContainer.lastChild , newPos);
          range.setEnd(range.endContainer.lastChild , newPos);
    
      /* END OF MODIFICATION */
    
          var offsets = getOffsets(textarea);
        console.log("I want offsets.start_offset to be 35, but it is " + offsets.start_offset)
      } else {
        console.log("Offset is from " + offsets.start_offset + " to " + offsets.end_offset );
      }
    

    You have to deal with the textNode to create a range of text characters and not whith the HTMLElement. It was for that, your Range.setStart(), had no effect, it was 'ranging' divs !

    In your sample textarea is a div in which you need to find each textNode and interact with them.
    In the code above range.endContainer.lastChild is a textNode (in reality the lastChild of textarea).

    Hope this will help you !


    Tested with Firefox