JSFiddle - React, Tailwind, and code Playground

by Joel Peterson

HTML

<!-- 
    Bug Details:
        The selection range's startContainer and endContainer are inconsistent when the range starts or ends on a text node boundary.
        Case 1:  If the range boundary starts or ends on a pre-existing text node boundary, the start/end container is the text node with an offset relative to the beginning of the text node.
        Case 2:  If the range boundary starts or ends on a dynamically created text node's boundary, the start/end container is the parent element to the text node.
        Case 3:  If a text node has splitText(offset) called on it to create a new text node, and the boundary of the new text node is used as the boundary for a new range, the parent element of the text node is used as the start/end container.
        
        Shouldn't the new text node still be used as the container with an offset relative to the beginning of that text node?  
    
-->
<div id="description">
    The behavior of window.getSelection() in IE11 is inconsistent when dealing with dynamically added Text nodes.  The startContainer and endContainer when starting or ending at a boundary is the Text node with the appropriate offset.  However, when starting or ending on the boundary of a dynamically added Text node, then the parent element to that Text node becomes the container and not the Text node itself.  Here are the instructions to reproduce this in IE11.
<ol id="instructions">
    <li>Highlight a word and click "Log Selection Details" to see the Range object in the console.</li>
    <li>Look at the startContainer and endContainer of the Range to see that they reference the current Text node with offsets relative to the start of that Text node.</li>
    <li>Highlight the same word and click "Split Selection" to break that word into its own Text node.</li>
    <li>Highlight the same word again and click "Log Selection Details".  You will see that div#rangeIssue is now the startContainer and endContainer.</li>
    <li>Highlight the same word, but...

JavaScript

document.getElementById("AppendChild").addEventListener("click", function() {
    var div = document.getElementById("rangeIssue");
    div.appendChild(document.createTextNode(" Created Text Node "));
});

document.getElementById("LogSelection").addEventListener("click", function() {
    var range = window.getSelection().getRangeAt(0);
    console.log(range);
});

document.getElementById("SplitSelection").addEventListener("click", function() {
    var range = window.getSelection().getRangeAt(0);
    range.endContainer.splitText(range.endOffset);
    range.startContainer.splitText(range.startOffset);
});