Получите innerHTML результата svg-tag в undefined в IE

У меня возникли проблемы с получением html-содержимого svg-тега с помощью javascript в Internet Explorer.

Мой код javascript выглядит следующим образом:

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

и мой тег в документе html:

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

Это хорошо работает в Chrome, Firefox и что у нас есть, но в Internet Explorer я остался с ошибкой undefined. Это моя смесь Javascript и jQuery?

Почему я не могу получить содержимое моего svg-тега? Я пробовал разные вещи, и часто я получаю "SCRIPT5007: невозможно установить свойство" innerHTML "из undefined или нулевую ссылку"

Помогите мне:) спасибо в привет!

Ответ 1

В конце концов я нашел какое-то решение для этого. Возможно, хакерский путь? Но работает для меня по крайней мере.

Вместо того, чтобы получать исходный innerhtml, который я не могу в IE. Я пытаюсь получить каждый элемент node внутри моего svg-тега, сделав так:

var element = document.getElementsByTagName('svg')[0].childNodes;
for (i = 0; i < element.length; i++) {
    if (element[i].nodeName != '#text') {
        console.log(element[i]);
    }
}

Ответ 2

Как насчет использования XMLSerializer. Получите элемент как-то, а затем сделайте это...

console.log(new XMLSerializer().serializeToString(element));

Ответ 3

В настоящее время Internet Explorer не поддерживает метод innerHTML в SVG Elements. Тем не менее у нас есть проблема, открытая внутри, чтобы отслеживать наше рассмотрение этой функции. Тем временем я бы рассмотрел альтернативные решения, такие как InnerSVG polyfill, который предположительно работает в Internet Explorer 9 и новее.

Ответ 4

Следующий код предоставит вам содержимое в виде строки из данного SVG. Он основан на отличном ответе Роберта Лонгсона.

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

const svgContent = Array.prototype.map.call(
  svgNode.childNodes, 
  (child) => serializer.serializeToString(child)
).join('');

Ответ 5

console.log($('.icon').parent().html()); отлично работает для меня в IE11.

Поставляемая строка начинается с объявления XML <?xml version="1.0" encoding="iso-8859-1" ?> который, по-видимому, обрабатывается как родительский элемент svg node.

Ответ 6

(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()

тест на IE11

Ответ 7

В качестве обходного пути вы можете добавить элемент SVG во временный DIV, взять внутренний html этого DIV и удалить тег открытия и закрытия SVG из этой строки.

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>

Ответ 8

Для реальных тегов внутреннего содержимого вы можете использовать следующее:

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')
}

Для текстового только внутреннего содержимого, используйте вместо этого node.textContent.

Ответ 9

console.log($('.icon')[0].html()); jQuery сглаживает различия между браузерами.

Ответ 10

Почему бы не добавить свой собственный innerHTML в прототип, как показано ниже:

// 针对IE浏览器进行加强
if (_IE >= 9) {
    var _innerHTML = {
        get: function () {
            var frame = document.createElement("div"), i;
            for (i = 0; i < this.childNodes.length; i++) {
                // 深度克隆,克隆节点以及节点下面的子内容
                frame.appendChild(this.childNodes[i].cloneNode(true));
            }
            return frame.innerHTML;
        },
        set: function (svgstring) {
            var frame = document.createElement("div"), i;
            frame.innerHTML = svgstring;
            var toSvgNode = function (htmlNode) {
                var svgNode = document.createElementNS(_namespace.svg, (htmlNode.tagName + "").toLowerCase());
                var attrs = htmlNode.attributes, i, svgNodeClay = clay(svgNode);
                for (i = 0; attrs && i < attrs.length; i++) {
                    svgNodeClay.attr(attrs[i].nodeName, htmlNode.getAttribute(attrs[i].nodeName));
                }
                return svgNode;
            };
            var rslNode = toSvgNode(frame.firstChild);
            (function toSVG(pnode, svgPnode) {
                var node = pnode.firstChild;
                if (node && node.nodeType == 3) {
                    svgPnode.textContent = pnode.innerText;
                    return;
                }
                while (node) {
                    var svgNode = toSvgNode(node);
                    svgPnode.appendChild(svgNode);
                    if (node.firstChild) toSVG(node, svgNode);
                    node = node.nextSibling;
                }
            })(frame.firstChild, rslNode);
            this.appendChild(rslNode);
        }
    };
    Object.defineProperty(SVGElement.prototype, 'innerHTML', _innerHTML);
    Object.defineProperty(SVGSVGElement.prototype, 'innerHTML', _innerHTML);
}