1

I'm using js to replace SVGs as images with inline SVG.

loadInlineSvg: function(className) {
        var svgImgs = [].slice.call(document.getElementsByClassName(className));
        svgImgs.forEach(function(img) {
            var svg = document.createElement('svg'),
            src = img.getAttribute('src'),
            req = new XMLHttpRequest();
            req.addEventListener('readystatechange', function(evt) {
                if(req.readyState === 4) {
                    if(req.status === 200) {
                        svgXML = req.responseXML.getElementsByTagName('svg')[0];
                        for(var j = 0; j < svgXML.children.length; j++) {
                            svg.appendChild(svgXML.children[j]);
                        }
                        for(var i = 0; i < svgXML.attributes.length; i++) {
                            svg.setAttribute(svgXML.attributes[i].name, svgXML.attributes[i].value);
                        }
                        svg.setAttribute('width', img.getAttribute('width'));
                        svg.setAttribute('height', img.getAttribute('height'));
                        img.parentNode.replaceChild(svg, img);
                    }
                }
            });
            req.open('POST', src, true);
            req.send();
        });
    }

The resulting XML response from the ajax request is exactly as expected:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="100" viewbox="0 0 145 160" version="1.1"><g id="compass" fill="#ffffff">
        <path d="M77.804878,14.0915556 L77.804878,10.6666667 L82.2256098,10.6666667 L82.2256098,2.81288889 C82.2256098,2.81288889 79.9896037,0.0244444444 72.7572866,0.0244444444 C65.5245274,0.0244444444 63.6585366,2.81288889 63.6585366,2.81288889 L63.6585366,10.6666667 L68.0792683,10.6666667 L68.0792683,14.008 C30.0609756,16.2248889 0.0477439024,47.9373333 0.0477439024,86.7386667 C0.0477439024,126.977333 32.5843293,159.597333 72.6083079,159.597333 C112.632287,159.597333 144.894345,126.977333 144.894345,86.7386667 C144.894345,48.3822222 115.381098,16.9488889 77.804878,14.0915556 L77.804878,14.0915556 Z M72.6984909,151.152889 C37.313628,151.152889 8.62794207,122.313778 8.62794207,86.7386667 C8.62794207,51.1635556 37.313628,22.3244444 72.6984909,22.3244444 C108.083796,22.3244444 136.769482,51.1635556 136.769482,86.7386667 C136.769482,122.313778 108.083796,151.152889 72.6984909,151.152889 L72.6984909,151.152889 Z" id="Fill-1"></path>
        <path d="M70.3745122,82.2062222 C67.9983689,83.8395556 67.38875,87.0995556 69.0133689,89.4884444 C70.6375457,91.8773333 73.8805945,92.4897778 76.2567378,90.8564444 C78.6328811,89.2235556 79.2420579,85.9631111 77.617439,83.5746667 C75.9932622,81.1857778 72.7502134,80.5733333 70.3745122,82.2062222" id="Fill-2"></path>
        <path d="M115.190122,44.0191111 C103.840335,32.6084444 88.7497256,26.3244444 72.6984909,26.3244444 C56.6476982,26.3244444 41.5570884,32.6084444 30.2073018,44.0191111 C18.8570732,55.4297778 12.6066006,70.6013333 12.6066006,86.7386667 C12.6066006,102.875556 18.8570732,118.047111 30.2073018,129.457778 C41.5570884,140.868889 56.6476982,147.152889 72.6984909,147.152889 C88.7497256,147.152889 103.840335,140.868889 115.190122,129.457778 C126.539909,118.047111 132.790823,102.875556 132.790823,86.7386667 C132.790823,70.6013333 126.539909,55.4297778 115.190122,44.0191111 L115.190122,44.0191111 Z M65.7000305,92.1311111 L43.2683537,43.0666667 L81.0934604,81.1937778 L103.475625,130.517778 L65.7000305,92.1311111 L65.7000305,92.1311111 Z" id="Fill-3"></path>
    </g></svg>

However, when appended to the page the svg and its child g element has client dimensions of 0px, 0px and nothing is displaying. Testing in Chrome (38.0.2125.104) and Firefox (32.0.3). Any suggestions?

Even stranger, if I copy the above svg output from a web inspector and paste it into the actual html, it works. Is the problem related to the fact that I'm appending the svg after page load???

Robert Longson
  • 118,664
  • 26
  • 252
  • 242
Jbird
  • 2,839
  • 1
  • 21
  • 28
  • maybe show the code you're using to append svg? – Christophe Oct 17 '14 at 22:39
  • @Christophe Edited w/code – Jbird Oct 17 '14 at 22:41
  • Once I get this portion working, the plan is to add additional paths to the new svg element that will be used for animation in browser which support it. HOWEVER, even in that case, you just made me realize that I should be appending to the existing svg instead of creating a new one. None the less, I'm still very curious as to why this newly created svg element wouldn't display. – Jbird Oct 17 '14 at 23:07
  • Only thing I can think of: `img.getAttribute('width')` returns 0 – Christophe Oct 17 '14 at 23:17
  • possible duplicate of [Add SVG element to existing SVG using DOM](http://stackoverflow.com/questions/16488884/add-svg-element-to-existing-svg-using-dom) – Paul LeBeau Oct 18 '14 at 03:00
  • See also http://stackoverflow.com/a/7986519/405017, especially: "The responseXML is in another DOM document, and you can't normally just move nodes from one document to another. You are supposed to use `document.importNode` to import a node from one document to another." – Phrogz Oct 18 '14 at 03:31

1 Answers1

2

You can't use document.createElement('svg'), to create an svg element. You can only use createElement to create html elements.

It needs to go in the SVG namespace which means using createElementNS('http://www.w3.org/2000/svg', 'svg')

Robert Longson
  • 118,664
  • 26
  • 252
  • 242