Search code examples
javascriptinternet-explorersvgnewlineinnerhtml

Using JavaScript, insert a line break into a HTML textContent attribute (IE specific)


I am generating a dynamic SVG image using JavaScript. My intention is for specific regions to have information contained in a ToolTip. What I have so far works in both Chrome and Firefox, but only partially in IE 11.

If I use textContent, "\r\n" is ignored in IE and <br /> is displayed literally.

innerHTML appears to be the answer from previously asked similar questions:
Question 9330671
Question 9980416

Typically, switching to innerHTML would solve this, but IE does not support innerHTML for this particular use, so no text is displayed at all.

Using either innerHTML or textContent works for Chrome or Firefox, so again, this is only an issue in IE (tested with IE 11). Apologies to anyone who has to use this browser in the testing of the code provided.

Interactive code is available at http://jsfiddle.net/rnhy9pus/.

Alternatively, full code is included below:

function createPathContent(svgID, popupText, pathDirections)
{
  var path = document.createElementNS("http://www.w3.org/2000/svg","path");
  path.setAttribute("d",pathDirections);
  var popup = document.createElementNS("http://www.w3.org/2000/svg","title");
  popup.textContent = popupText; // <-- LINE TO FOCUS ON
  path.appendChild(popup);
  document.getElementById(svgID).appendChild(path);
}
function createPathHTML(svgID, popupText, pathDirections)
{
  var path = document.createElementNS("http://www.w3.org/2000/svg","path");
  path.setAttribute("d",pathDirections);
  var popup = document.createElementNS("http://www.w3.org/2000/svg","title");
  popup.innerHTML = popupText; // <-- LINE TO FOCUS ON
  path.appendChild(popup);
  document.getElementById(svgID).appendChild(path);
}
function createExample(svgID)
{
  document.getElementById(svgID).setAttribute("xmlns", "http://www.w3.org/2000/svg");
  document.getElementById(svgID).setAttribute("version", "1.1");
  document.getElementById(svgID).setAttribute("width", "300");
  document.getElementById(svgID).setAttribute("viewBox", "0 0 100 100");
  document.getElementById(svgID).setAttribute("preserveAspectRatio", "xMinYMin meet");

  var style = document.createElement("style");
  style.setAttribute("type","text/css");
  style.innerHTML = "path { fill: #ccc; } path:hover { fill: #ff0; }";
  document.getElementById(svgID).appendChild(style);

  var NEW_LINE = "\r\n";
  //var NEW_LINE = "<br />"; // This displays literally in textContent and as a new line in innerHTML.

  createPathContent(svgID, "Tooltip text using textContent:" + NEW_LINE + "New Line", "M 10 10 L 90 10 L 90 45 L 10 45 Z");
  // Works correctly in Chrome or Firefox.  Displays in IE 11, but only on a single line.

  createPathHTML(svgID,    "Tooltip text using innerHTML:"   + NEW_LINE + "New Line", "M 10 55 L 90 55 L 90 90 L 10 90 Z");
  // Works correctly in Chrome or Firefox.  Does not display in IE 11.
}

createExample("exampleSVG");
<svg id="exampleSVG" xmlns="http://www.w3.org/2000/svg"></svg>


Solution

  •     function createPathContent(svgID, popupText, pathDirections)
        {
            var path = document.createElementNS("http://www.w3.org/2000/svg","path");
            path.setAttribute("d",pathDirections);
            var popup = document.createElementNS("http://www.w3.org/2000/svg","title");
         // popup.textContent = popupText; // <-- LINE TO FOCUS ON
    popup.textContent=" "
    //popup.firstChild.nodeValue=popupText
    popup.firstChild.nodeValue='Edgar'
    Node.prototype.appendChild.call(popup, document.createElement("br"))
    Node.prototype.appendChild.call(popup, document.createTextNode('Allen Poe.'))
            path.appendChild(popup);
            document.getElementById(svgID).appendChild(path);
        }
    


    It always makes my head spin when I try to figure out if textContent is officially supposed to interpret \n (\x0A \u000A ...) as anything except whitespace.

    textContent:
    http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Node3-textContent

    Interface Text:
    http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-1312295772

    Interface CharacterData:
    http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-FF21A306

    Anyway, I made an exercise with some primitives, above. I hope you'll find this as instructive as I did. It produces the tooltip with "Edgar" on one line, and "Allen Poe." on the next.


    function createPathContent(svgID, popupText, pathDirections)
    {
        var path = document.createElementNS("http://www.w3.org/2000/svg","path");
        path.setAttribute("d",pathDirections);
        var popup = document.createElementNS("http://www.w3.org/2000/svg","title");
        //popup.textContent = popupText; // <-- LINE TO FOCUS ON
    
              popupText= popupText.split('\n')                                                  // note: firefox needs "\r" passed in "\r\n".
              while (true) { popup.appendChild(document.createTextNode(popupText.shift()))      // note: "" here is ok, will be appended as empty #text node
                             if (popupText.length) popup.appendChild(document.createElement("br"))
                             else break }
    
        path.appendChild(popup);
        document.getElementById(svgID).appendChild(path);
    }
    


    Here's a working patch within the function itself. It makes use of Jonathan's slick trick, that Firefox needs the "\r" whereas IE and Chrome are happy with <br>.