Tanya Arora
Tanya Arora

Reputation: 113

How to select the html tags with their contents when using selectNodeContents?

I have this bit of code, which I use to get the cursor's position in an editable div :

   function getMeCurPos(element){
       if (typeof window.getSelection != "undefined") {
          var range = window.getSelection().getRangeAt(0);
          var preCaretRange = range.cloneRange(); 
          preCaretRange.selectNodeContents(element);
          preCaretRange.setEnd(range.endContainer, range.endOffset); 
          caretOffset = preCaretRange.toString().length;  
          return caretOffset;
       }                        
   }

The problem is that, the caretOffset returned only counts the textual contents and not the html tags. For eg :

Consider this string in my editable div : Hey <b>jony</b>, whats goin on in the | party

*Cursor is denoted by | character.

Doing getMeCurPos(ele) returns : 30 but it should return 37. It doesn't count b tags

Upvotes: 9

Views: 4041

Answers (3)

Sanjeev S
Sanjeev S

Reputation: 626

For getting the selection both as text and as DOM nodes you can use the cloneContents() in the Javascript selection-range. HTML as below

function getMeCurPos(element) {
  if (typeof window.getSelection != "undefined") {
    var range = window.getSelection();
    cloned.innerHTML = '';
    for (let i = 0; i < range.rangeCount; i++) {
      cloned.append(range.getRangeAt(i).cloneContents());
    }

    var sanitized = cloned.innerHTML;
    caretOffset = sanitized.length;
    return caretOffset;
  }
}
<p contenteditable="true" id="test" onclick="alert(getMeCurPos(this))">Test1<br>Test2<br>Test3<br>Test4</p>
<br>
Cloned: <span id="cloned"></span>

Upvotes: 1

Affilnost
Affilnost

Reputation: 329

I've taken the code from this article: Select all DIV text with single mouse click

            <script type="text/javascript">
                function selectText(containerid) {
                    if (document.selection) {
                        var range = document.body.createTextRange();
                        range.moveToElementText(document.getElementById(containerid));
                        range.select();
                    } else if (window.getSelection) {
                        var range = document.createRange();
                        range.selectNode(document.getElementById(containerid));
                        window.getSelection().addRange(range);
                    }
                }
            </script>

            <div id="selectable" onclick="selectText('selectable')">http://example.com/page.htm</div>

Upvotes: 0

Shikiryu
Shikiryu

Reputation: 10219

You may create a temp div in which you can put your preCaretRange and where you can use textContent or innerText on it. This won't take the HTML length, but the text around it.

 function getMeCurPos(element){
       if (typeof window.getSelection != "undefined") {
          var range = window.getSelection().getRangeAt(0);
          var preCaretRange = range.cloneRange(); 
          preCaretRange.selectNodeContents(element);
          preCaretRange.setEnd(range.endContainer, range.endOffset); 
          var temp = document.createElement("div");
          temp.innerHTML = preCaretRange.toString();
          var sanitized = temp.textContent || temp.innerText;
          caretOffset = sanitized.length;
          return caretOffset;
       }                        
}

See this fiddle

Upvotes: 1

Related Questions