16

I'm having some trouble getting the html content of a svg-tag, with javascript in Internet Explorer.

My javascript code is as follow:

console.log($('.icon')[0].innerHTML);

and my tag in my html document:

<svg class="icon"><use>testing</use></svg>

This works well in Chrome, Firefox and what have we, but in Internet Explorer I'm left with an undefined error. Is it my mixture of Javascript and jQuery?

How come I can't seem to fetch the content of my svg-tag? I've tried some different things and often I end up with an "SCRIPT5007: Unable to set property 'innerHTML' of undefined or null reference"

Help me :) thanks in regards!

aventic
  • 1,494
  • 2
  • 16
  • 23
  • I just tried with document.getElementsByTagName('svg')[0].innerHTML solely. Still same error of undefined. – aventic Jan 24 '15 at 20:34
  • On IE11, I was able to simple append the SVG element to an empty div and get _its_ innterHTML which _does_ return the correct stuff. Includes the `` tag itself but that isn't to hard to regex out. – somethinghere Sep 20 '17 at 13:01
  • `outerHTML` is also a problem for IE with SVG elements: https://stackoverflow.com/q/29888050/633107. – Splaktar Feb 09 '19 at 01:11

9 Answers9

18

How about using XMLSerializer. Get yourself the element somehow and then do this...

console.log(new XMLSerializer().serializeToString(element));
Robert Longson
  • 118,664
  • 26
  • 252
  • 242
15

Internet Explorer doesn't currently support the innerHTML method on SVG Elements. We do however have an issue opened internally to track our consideration of this feature. In the meantime I would explore alternative solutions like the InnerSVG polyfill which allegedly works in Internet Explorer 9 and newer.

Sampson
  • 265,109
  • 74
  • 539
  • 565
  • 1
    Yeah I saw the InnerSVG polyfill. But figured that had to be a simpler way, atleast for my tiny project. I just came up with my answer which fixes it for me. – aventic Jan 24 '15 at 21:57
  • The Polyfill is pretty simple; you just reference it and you're done. Internet Explorer, Chrome, and Firefox all proceed to use the same exact code. – Sampson Jan 24 '15 at 22:08
  • We use an object tag and get our svg from a separate url. innerSVG doesn't seem to work for that for me. Does anyone have any ideas about that? – nroose Jun 26 '15 at 23:16
  • @Sampson, do you maybe have a link where we can follow the status of the issue to support innerHTML for svg elements? – ThdK Dec 18 '18 at 15:16
  • Hi @Samspon :-) – Tom Roggero May 06 '19 at 15:16
3

The following code will give you the content as string from the given SVG. It is based on the great answer of Robert Longson.

const svgNode = document.getElementsByTagName('svg')[0];
const serializer = new XMLSerializer();

const svgContent = Array.prototype.map.call(
  svgNode.childNodes, 
  (child) => serializer.serializeToString(child)
).join('');
jantimon
  • 36,840
  • 23
  • 122
  • 185
2

Eventually I found some sort of solution to this. A hacky way perhaps? But works for me atleast.

Instead of getting the raw innerhtml which I can't in IE. I try to get each element-node inside my svg-tag by doing so:

var element = document.getElementsByTagName('svg')[0].childNodes;
for (i = 0; i < element.length; i++) {
    if (element[i].nodeName != '#text') {
        console.log(element[i]);
    }
}
aventic
  • 1,494
  • 2
  • 16
  • 23
1

console.log($('.icon').parent().html()); works fine for me in IE11.

The delivered string starts with a XML declaration <?xml version="1.0" encoding="iso-8859-1" ?> which seems to be handled as the parent of the svg node.

PC100-Fan
  • 11
  • 2
1
(function () {
    var svg = document.createElementNS("http://www.w3.org/2000/svg","svg");
    if(typeof svg["innerHTML"] !== "undefined") {
        return;
    }

    var node = $('<script type="text/svg_template"></script>');

    Object.defineProperty(SVGElement.prototype, 'innerHTML', {
        get: function() {           
            try {
                var childNode = this.firstChild;
                while (childNode) {
                    node.append($.clone(childNode));
                    childNode = childNode.nextSibling;
                }
                return node.html();
            } finally {
                node.empty();
            }
        }
    })
})();

set html use:

$(svg).html()

test on IE11

RunningEgg
  • 11
  • 1
1

As a workaround, you can append the SVG element to a temporary DIV, take the inner html of that DIV and remove the SVG opening and closing tag from that string.

let parentHtml = $('<div />').append($('svg')).html();
let svgInner = parentHtml.replace(/(<svg)([^<]*|[^>]*)/g, '').replace('</svg>', '');
alert(svgInner);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink">
    <rect x="10" y="10" height="100" width="100"
          style="stroke:#ff0000; fill: #0000ff"/>
</svg>
Ibrahim Benzer
  • 498
  • 6
  • 10
0

You can create your own innerHTML, like the following setSVGenter image description here

In fact, you only need to pay attention to two steps: creating the SVG context label and setting properties (with context)

createElementNS and setAttributeNS are two methods you may need!

Common namespaces are as follows:

0

For actual tags inner content, you can use the following:

function innerHTML(anySvgElement) {
  var d = document.createElement('div');
  d.appendChild(anySvgElement);
  // Given all SVG tags contain only letters and no numbers, we can strip out the outer tag (the anySvgElement itself)
  return d.innerHTML.replace(/<([a-z]+)[^>]+>(.*)(<\/\1>)/i, '$2')
}

For text only inner content, use node.textContent instead.

Tom Roggero
  • 5,777
  • 1
  • 32
  • 39