Search code examples
rangecontenteditabletagname

Get tag name of start container in range


I'm an absolute newb at this so forgive the simplicity of this question. I have a contenteditable div. All the text in this div are wrapped in link tags.

If the user makes a selection that spans 2 or more of these link nodes, I'd like to identify the name of the link tag at the startContainer and also at the endContainer.

Unfortunately, more often than not, the startContainer node is a formatting node such a paragraph or a bold tag as seen in the example html below.

<div id="myarea" onmouseup="getSelectionHtml();" contenteditable="true">

<a id="1" href=#>text1 <b>text1 text1 </b></a>
<a id="2" href=#>text2 <b>text2 text2 </b></a>
<a id="3" href=#>text3 <b>text3 text3 </b></a>

</div>

So I figure my approach should be to first find the nameTag of the startContainer. If it is not a link tag, then query for it's parent node. If that is not a link tag, query again for the next node up the hierarchy until I find the link tag and can get it's id.

As pitifully short as it is, this is all the code that I have so far. I wish to find tagName of the startContainer, but I'm getting an alert of "undefined". I've been reading as much documentation on the range object as I can but it's all scattered and a little difficult for me to comprehend.

function getSelectionHtml() {
    var userSelection;
       if (window.getSelection) {
          userSelection = window.getSelection();        
          var selRange = userSelection.getRangeAt(0);   
              alert(selRange.startContainer.tagName);
       }

By the way, if anyone has a better conceptual solution for grabbing the link tag of the beginning and end of a contentEditable selection, I'd be much obliged.

tia


Solution

  • A range's startContainer and endContainer properties may be references to either text nodes or elements. When you're getting an undefined tagName property, it's because you've got a text node.

    Here's a simple function for getting hold of the <a> element containing a node:

    function getAncestorWithTagName(node, tagName) {
        tagName = tagName.toUpperCase();
        while (node) {
            if (node.nodeType == 1 && node.tagName.toUpperCase() == tagName) {
                return node;
            }
            node = node.parentNode;
        }
        return null;
    }
    

    Example:

    var link = getAncestorWithTagName(selRange.startContainer);
    if (link) {
       alert("Start is inside link with ID " + link.id);
    }