Search code examples
javascriptinternet-explorerdomhtmlcontenteditable

How to get selected textnode in contentEditable div in IE?


I am attempting to create a simple texteditor with HTML5 contenteditable on a div tag. As you know, selected text is handled quite differently in IE.

    this.retrieveAnchorNode = function() {
      var anchorNode;
      if (document.selection)
        anchorNode = document.selection.createRange().parentElement();
      else if (document.getSelection)
        anchorNode = window.getSelection().anchorNode;
    }

I am looking for a way to get the selected textnode (not the text itself), like I can do with "anchorNode" and "focusNode" on other browsers. The only alternative on IE I have found is the "parentElement()" function, which only manages to select the contenteditable div itself.

Any ideas?


Solution

  • Here's my version of the function you need from IERange, with my comments:

    function getChildIndex(node) {
      var i = 0;
      while( (node = node.previousSibling) ) {
        i++;
      }
      return i;
    }
    
    function getTextRangeBoundaryPosition(textRange, isStart) {
      var workingRange = textRange.duplicate();
      workingRange.collapse(isStart);
      var containerElement = workingRange.parentElement();
      var workingNode = document.createElement("span");
      var comparison, workingComparisonType = isStart ?
        "StartToStart" : "StartToEnd";
    
      var boundaryPosition, boundaryNode;
    
      // Move the working range through the container's children, starting at
      // the end and working backwards, until the working range reaches or goes
      // past the boundary we're interested in
      do {
        containerElement.insertBefore(workingNode, workingNode.previousSibling);
        workingRange.moveToElementText(workingNode);
      } while ( (comparison = workingRange.compareEndPoints(
        workingComparisonType, textRange)) > 0 && workingNode.previousSibling);
    
      // We've now reached or gone past the boundary of the text range we're
      // interested in so have identified the node we want
      boundaryNode = workingNode.nextSibling;
      if (comparison == -1 && boundaryNode) {
        // This must be a data node (text, comment, cdata) since we've overshot.
        // The working range is collapsed at the start of the node containing
        // the text range's boundary, so we move the end of the working range
        // to the boundary point and measure the length of its text to get
        // the boundary's offset within the node
        workingRange.setEndPoint(isStart ? "EndToStart" : "EndToEnd", textRange);
    
        boundaryPosition = {
          node: boundaryNode,
          offset: workingRange.text.length
        };
      } else {
        // We've hit the boundary exactly, so this must be an element
        boundaryPosition = {
          node: containerElement,
          offset: getChildIndex(workingNode)
        };
      }
    
      // Clean up
      workingNode.parentNode.removeChild(workingNode);
    
      return boundaryPosition;
    }
    
    var textRange = document.selection.createRange();
    var selectionStart = getTextRangeBoundaryPosition(textRange, true);
    // selectionStart has properties 'node' and 'offset'