jquery's append not working with svg element?

Viewed 146301

Assuming this:

<html>
<head>
 <script type="text/javascript" src="jquery.js"></script>
 <script type="text/javascript">
 $(document).ready(function(){
  $("svg").append('<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>');
 });
 </script>
</head>
<body>
 <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" width="200px" height="100px">
 </svg>
</body>

Why don't I see anything?

16 Answers

I would suggest it might be better to use ajax and load the svg element from another page.

$('.container').load(href + ' .svg_element');

Where href is the location of the page with the svg. This way you can avoid any jittery effects that might occur from replacing the html content. Also, don't forget to unwrap the svg after it's loaded:

$('.svg_element').unwrap();
 var svg; // if you have variable declared and not assigned value.
 // then you make a mistake by appending elements to that before creating element    
 svg.appendChild(document.createElement("g"));
 // at some point you assign to svg
 svg = document.createElementNS('http://www.w3.org/2000/svg', "svg")
 // then you put it in DOM
 document.getElementById("myDiv").appendChild(svg)
 // it wont render unless you manually change myDiv DOM with DevTools

// to fix assign before you append
var svg = createElement("svg", [
    ["version", "1.2"],
    ["xmlns:xlink", "http://www.w3.org/1999/xlink"],
    ["aria-labelledby", "title"],
    ["role", "img"],
    ["class", "graph"]
]);
function createElement(tag, attributeArr) {
      // .createElementNS  NS is must! Does not draw without
      let elem = document.createElementNS('http://www.w3.org/2000/svg', tag);             
      attributeArr.forEach(element => elem.setAttribute(element[0], element[1]));
      return elem;
}
// extra: <circle> for example requires attributes to render. Check if missing.

I have made a small function for that. As for jQuery append method, the problem is the requirement for specifying namespace for SVG which is "http://www.w3.org/2000/svg" More

So what if I prepare it for append method? In that case the only thing you need to offer is some parameters like:

tagName: It can be every SVG element like rect, circle, text, g etc.

text: If you are using something like text tagname, you'll need to specify text

And other known attributes for an SVG elements.

Thus what I'm going to do is defining a function named createSvgElem() which uses document.createElementNS() internally.

Here is an example:

$("svg").append(
   createSvgElem({tagName: "text", x: 10, y: 10, text: "ABC", style: "fill: red"})
)

And here's the function:

   function createSvgElem(options){
        var settings = $.extend({
            }, options);

        if(!$.isEmptyObject(settings.tagName)){
            var el = document.createElementNS('http://www.w3.org/2000/svg', settings.tagName);
            for (var k in settings)
                if(k != "tagName" && k != "text" && settings[k] != "")//If attribute has value
                    el.setAttribute(k, settings[k]);

            if ("text" in settings)
                el.textContent = settings.text; //el.innerText; For IE
            return el;
        }
    }

Here you can try it yourself:

//Definition:
        function createSvgElem(options){
            var settings = $.extend({
                }, options);

            if(!$.isEmptyObject(settings.tagName)){
                var el = document.createElementNS('http://www.w3.org/2000/svg', settings.tagName);
                for (var k in settings)
                    if(k != "tagName" && k != "text" && settings[k] != "")//If attribute has value
                        el.setAttribute(k, settings[k]);

                if ("text" in settings)
                    el.textContent = settings.text; //el.innerText; For IE
                return el;
            }
        }

        //Usage:
        $(function(){

          $("#svg-elem").append(
            createSvgElem({tagName: "rect", width: 130, height: 500, style: "fill: #000000a3;"})
            )
          
          $("#svg-elem").append(
            createSvgElem({tagName: "text", x: 30, y: 30, text: "ABCD", style: "fill: red"})
            )

        })
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<svg id="svg-elem" width="200" height="200">
</svg>

With jquery you can do just that. setting the DataType to 'text'.

$.ajax({
    url: "url-to-svg.svg",
    dataType : 'text'
})
.done(function(svg) { 
    let svg_live = $(svg);
    svg_live.append('<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>');
    $('#selector-id').html(svg_live); 
});

Related