jquery's append not working with svg element?
Asked Answered
T

17

221

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?

Thumbsdown answered 4/9, 2010 at 11:24 Comment(0)
W
269

When you pass a markup string into $, it's parsed as HTML using the browser's innerHTML property on a <div> (or other suitable container for special cases like <tr>). innerHTML can't parse SVG or other non-HTML content, and even if it could it wouldn't be able to tell that <circle> was supposed to be in the SVG namespace.

innerHTML is not available on SVGElement—it is a property of HTMLElement only. Neither is there currently an innerSVG property or other way(*) to parse content into an SVGElement. For this reason you should use DOM-style methods. jQuery doesn't give you easy access to the namespaced methods needed to create SVG elements. Really jQuery isn't designed for use with SVG at all and many operations may fail.

HTML5 promises to let you use <svg> without an xmlns inside a plain HTML (text/html) document in the future. But this is just a parser hack(**), the SVG content will still be SVGElements in the SVG namespace, and not HTMLElements, so you'll not be able to use innerHTML even though they look like part of an HTML document.

However, for today's browsers you must use XHTML (properly served as application/xhtml+xml; save with the .xhtml file extension for local testing) to get SVG to work at all. (It kind of makes sense to anyway; SVG is a properly XML-based standard.) This means you'd have to escape the < symbols inside your script block (or enclose in a CDATA section), and include the XHTML xmlns declaration. example:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
</head><body>
    <svg id="s" xmlns="http://www.w3.org/2000/svg"/>
    <script type="text/javascript">
        function makeSVG(tag, attrs) {
            var el= document.createElementNS('http://www.w3.org/2000/svg', tag);
            for (var k in attrs)
                el.setAttribute(k, attrs[k]);
            return el;
        }

        var circle= makeSVG('circle', {cx: 100, cy: 50, r:40, stroke: 'black', 'stroke-width': 2, fill: 'red'});
        document.getElementById('s').appendChild(circle);
        circle.onmousedown= function() {
            alert('hello');
        };
    </script>
</body></html>

*: well, there's DOM Level 3 LS's parseWithContext, but browser support is very poor. Edit to add: however, whilst you can't inject markup into an SVGElement, you could inject a new SVGElement into an HTMLElement using innerHTML, then transfer it to the desired target. It'll likely be a bit slower though:

<script type="text/javascript"><![CDATA[
    function parseSVG(s) {
        var div= document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
        div.innerHTML= '<svg xmlns="http://www.w3.org/2000/svg">'+s+'</svg>';
        var frag= document.createDocumentFragment();
        while (div.firstChild.firstChild)
            frag.appendChild(div.firstChild.firstChild);
        return frag;
    }

    document.getElementById('s').appendChild(parseSVG(
        '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" onmousedown="alert(\'hello\');"/>'
    ));
]]></script>

**: I hate the way the authors of HTML5 seem to be scared of XML and determined to shoehorn XML-based features into the crufty mess that is HTML. XHTML solved these problems years ago.

Wincer answered 4/9, 2010 at 12:26 Comment(10)
This answer is still relevant! I just had a bizarre bug where added elements show in the Chrome element inspector, but would not render. If I RMB>edit as html on the html tag and hit enter everything displays (but all event listeners vanish). After reading this answer I changed my createElement calls to createElementNS and now everything works!Dunlop
You can manipulate the SVG elements with jquery once they are created using the DOM method createElementNS. You can change the makeSVG function to 'return $(el)' and now you have a svg element that can use jquery methods.Fiddle
How can i use the function for polygon instead of circle pls.Idealistic
Ah! So that's why it won't work. I tried the exact same thing with two different libraries, one in jQuery and one in D3.js. I got exactly the same source output in HTML using both, but the jQuery-generated elements would not render while the D3-generated ones did! I recommend using D3: d3.select('body').append('svg').attr('width','100%');Radburn
@bobince: You mention DOM3 and that it had poor browser support. Now it's been 5 years, does that mean that there is an easier solution now?Pindling
@MadsSkjern: DOM Level 3 LS never made it to browsers. The originally-Mozilla-only DOMParser is now more widely supported, though, and jQuery has $.parseXML.Wincer
It's still relevant. bobince hates the mess of HTML5, I hate the mess of the whole web, because nowhere you can find good code without hacks because of that mess. WWW should be renamed to WWM World Wide Mess.Ungracious
@Wincer The code sample you've provided doesn't work (anymore?).Ungracious
@Wincer can you help me in this post? #37843239Calvinna
@Wincer I tried and tested your script code - from the first code sample / function makeSVG - in relevant actual major browsers, without any xml or xhtml declarations, just as regular javascript in a regular HTML5 web project. And it works perfect. Thanks. 1+Blah
A
176

The accepted answer shows too complicated way. As Forresto claims in his answer, "it does seem to add them in the DOM explorer, but not on the screen" and the reason for this is different namespaces for html and svg.

The easiest workaround is to "refresh" whole svg. After appending circle (or other elements), use this:

$("body").html($("body").html());

This does the trick. The circle is on the screen.

Or if you want, use a container div:

$("#cont").html($("#cont").html());

And wrap your svg inside container div:

<div id="cont">
    <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>
</div>

The functional example:
http://jsbin.com/ejifab/1/edit

The advantages of this technique:

  • you can edit existing svg (that is already in DOM), eg. created using Raphael or like in your example "hard coded" without scripting.
  • you can add complex element structures as strings eg. $('svg').prepend('<defs><marker></marker><mask></mask></defs>'); like you do in jQuery.
  • after the elements are appended and made visible on the screen using $("#cont").html($("#cont").html()); their attributes can be edited using jQuery.

EDIT:

The above technique works with "hard coded" or DOM manipulated ( = document.createElementNS etc.) SVG only. If Raphael is used for creating elements, (according to my tests) the linking between Raphael objects and SVG DOM is broken if $("#cont").html($("#cont").html()); is used. The workaround to this is not to use $("#cont").html($("#cont").html()); at all and instead of it use dummy SVG document.

This dummy SVG is first a textual representation of SVG document and contains only elements that are needed. If we want eg. to add a filter element to Raphael document, the dummy could be something like <svg id="dummy" style="display:none"><defs><filter><!-- Filter definitons --></filter></defs></svg>. The textual representation is first converted to DOM using jQuery's $("body").append() method. And when the (filter) element is in DOM, it can be queried using standard jQuery methods and appended to the main SVG document which is created by Raphael.

Why this dummy is needed? Why not to add a filter element strictly to Raphael created document? If you try it using eg. $("svg").append("<circle ... />"), it is created as html element and nothing is on screen as described in answers. But if the whole SVG document is appended, then the browser handles automatically the namespace conversion of all the elements in SVG document.

An example enlighten the technique:

// Add Raphael SVG document to container element
var p = Raphael("cont", 200, 200);
// Add id for easy access
$(p.canvas).attr("id","p");
// Textual representation of element(s) to be added
var f = '<filter id="myfilter"><!-- filter definitions --></filter>';

// Create dummy svg with filter definition 
$("body").append('<svg id="dummy" style="display:none"><defs>' + f + '</defs></svg>');
// Append filter definition to Raphael created svg
$("#p defs").append($("#dummy filter"));
// Remove dummy
$("#dummy").remove();

// Now we can create Raphael objects and add filters to them:
var r = p.rect(10,10,100,100);
$(r.node).attr("filter","url(#myfilter)");

Full working demo of this technique is here: http://jsbin.com/ilinan/1/edit.

( I have (yet) no idea, why $("#cont").html($("#cont").html()); doesn't work when using Raphael. It would be very short hack. )

Arlina answered 30/11, 2012 at 23:28 Comment(10)
I am using my (Home made) solution for handling SVG and have the same Problem as Raphael, when using the "reparsing trick" with $(#picture).html ..., but my solution was to re-init some cached SVG elements (marking rectangle, transformataion and so on)Broadminded
You are a wizard. I was looking at the accepted answer and I was like man this is gonna be a pain. Then, I saw this and it does everything I need it to in one short line. Thank you!Reedbuck
THIS WAS CAUSING ME TO LOSE MY MARBLES... thought I could magically use js DOM elms on the SVG namespace like one might think... got the tag inspector to recognize the insertions... but not dice till now!Obel
Worked great for me when appending my existing polygon and path tags to a newly created parent svg tag. Thanks!Augusto
in general, I like your approach a lot better, unfortunately, I've got events/listeners I hook up to the individual svg elements at creation time and refreshing the svg element would clear them. Thanks for helpingHomeless
I like this solution, very straight forwardOptimistic
Yeah, this answer is perfect solution also :)Ulu
@Homeless The solution works in the case in question. In your case, you can attach handlers to the parent of svg or even to the document.body. The event target should then be the clicked element inside svg. I haven't tested, but give it a try.Hospitalization
@Homeless I'm trying to hack the SVG of a Google Chart and I think I'm running into this issue. This solution shows my changes to the google chart, but breaks the charts interactions. :(Sharla
$("#cont").html($("#cont").html()); worked great in Chrome, but didn't work in IE 11 for me.Cherilyncherilynn
R
40

The increasingly popular D3 library handles the oddities of appending/manipulating svg very nicely. You may want to consider using it as opposed to the jQuery hacks mentioned here.

HTML

<svg xmlns="http://www.w3.org/2000/svg"></svg>

Javascript

var circle = d3.select("svg").append("circle")
    .attr("r", "10")
    .attr("style", "fill:white;stroke:black;stroke-width:5");
Roebuck answered 20/5, 2013 at 3:6 Comment(2)
nice answer. it helped me for some issue here.Michi
jQuery also chokes on setting/getting classes from SVG as well. Just an aside.Storekeeper
J
27

JQuery can't append elements to <svg> (it does seem to add them in the DOM explorer, but not on the screen).

One workaround is to append an <svg> with all of the elements that you need to the page, and then modify the attributes of the elements using .attr().

$('body')
  .append($('<svg><circle id="c" cx="10" cy="10" r="10" fill="green" /></svg>'))
  .mousemove( function (e) {
      $("#c").attr({
          cx: e.pageX,
          cy: e.pageY
      });
  });

http://jsfiddle.net/8FBjb/1/

Johnathan answered 11/9, 2011 at 20:35 Comment(4)
Thanks, helped me a lot! This is a very good approach. Instead of appending <circle> or other elements individually using complex and slow DOM-methods (eg. createDocumentFragment() or createElementNS()), append the whole svg document in to container. Instead of $('body') it can be of course some $('div') also. And after that the svg document is on DOM and can be queried in familiar way using eg. $('c').attr('fill','red').Hospitalization
I made an additional example of this: jsbin.com/inevaz/1 . It gets tiger.svg source code from internet to iframe and it can be Copy-Pasted to textarea. The content of textarea is then used as a source for inline svg which is then accessible through DOM (to change stroke style).Hospitalization
This is great, I dont know why everyone is voting for those other answers that simply do not work.Keever
This was the best answer for me too. I needed an svg with a <use xlink:href="#icon"> and this was the shortest working answer.Concerted
C
22

I haven't seen someone mention this method but document.createElementNS() is helpful in this instance.

You can create the elements using vanilla Javascript as normal DOM nodes with the correct namespace and then jQuery-ify them from there. Like so:

var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
    circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');

var $circle = $(circle).attr({ //All your attributes });

$(svg).append($circle);

The only down side is that you have to create each SVG element with the right namespace individually or it won't work.

Cornew answered 31/12, 2013 at 5:6 Comment(3)
Timo's answer (top voted) worked in Chrome, but not IE. This answer solved the issue for both browsers!Cherilyncherilynn
Nice! Good to knowCornew
using jquery .attr({}) is simpler, tksMaseru
K
19

Found an easy way which works with all browsers I have (Chrome 49, Edge 25, Firefox 44, IE11, Safari 5 [Win], Safari 8 (MacOS)) :

// Clean svg content (if you want to update the svg's objects)
// Note : .html('') doesn't works for svg in some browsers
$('#svgObject').empty();
// add some objects
$('#svgObject').append('<polygon class="svgStyle" points="10,10 50,10 50,50 10,50 10,10" />');
$('#svgObject').append('<circle class="svgStyle" cx="100" cy="30" r="25"/>');

// Magic happens here: refresh DOM (you must refresh svg's parent for Edge/IE and Safari)
$('#svgContainer').html($('#svgContainer').html());
.svgStyle
{
  fill:cornflowerblue;
  fill-opacity:0.2;
  stroke-width:2;
  stroke-dasharray:5,5;
  stroke:black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="svgContainer">
  <svg id="svgObject" height="100" width="200"></svg>
</div>

<span>It works if two shapes (one square and one circle) are displayed above.</span>
Keenankeene answered 30/3, 2016 at 10:0 Comment(2)
That refresh line is exactly what I was looking for. Silly browsers. Thanks!Streeter
$('#svgObject').empty() will also remove existing svg elements – otherwise you could as well create the whole svg element at once via html(). BTW. I've used jquery for quite some time but – stupid jquery. These svg inserting issues could/should have been fixed in jquery 3.x.Caruso
M
10

I can see circle in firefox, doing 2 things:

1) Renaming file from html to xhtml

2) Change script to

<script type="text/javascript">
$(document).ready(function(){
    var obj = document.createElementNS("http://www.w3.org/2000/svg", "circle");
    obj.setAttributeNS(null, "cx", 100);
    obj.setAttributeNS(null, "cy", 50);
    obj.setAttributeNS(null, "r",  40);
    obj.setAttributeNS(null, "stroke", "black");
    obj.setAttributeNS(null, "stroke-width", 2);
    obj.setAttributeNS(null, "fill", "red");
    $("svg")[0].appendChild(obj);
});
</script>
Madsen answered 4/9, 2010 at 12:9 Comment(1)
Eight years later and this is still helpful!Erwin
I
7

Based on @chris-dolphin 's answer but using helper function:

// Creates svg element, returned as jQuery object
function $s(elem) {
  return $(document.createElementNS('http://www.w3.org/2000/svg', elem));
}

var $svg = $s("svg");
var $circle = $s("circle").attr({...});
$svg.append($circle);
Incendiarism answered 12/3, 2015 at 18:40 Comment(1)
You can of course also do: $svg.append($s('<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>'));Incendiarism
B
3

The accepted answer by Bobince is a short, portable solution. If you need to not only append SVG but also manipulate it, you could try the JavaScript library "Pablo" (I wrote it). It will feel familiar to jQuery users.

Your code example would then look like:

$(document).ready(function(){
    Pablo("svg").append('<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>');
});

You can also create SVG elements on the fly, without specifying markup:

var circle = Pablo.circle({
    cx:100,
    cy:50,
    r:40
}).appendTo('svg');
Beaverette answered 2/10, 2013 at 19:45 Comment(0)
Y
3

If the string you need to append is SVG and you add the proper namespace, you can parse the string as XML and append to the parent.

var xml = jQuery.parseXML('<circle xmlns="http://www.w3.org/2000/svg" cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>');
$("svg").append(xml.documentElement)
Yonkers answered 8/4, 2016 at 19:1 Comment(0)
A
1

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();
Araminta answered 21/6, 2018 at 19:19 Comment(0)
E
0

A much simpler way is to just generate your SVG into a string, create a wrapper HTML element and insert the svg string into the HTML element using $("#wrapperElement").html(svgString). This works just fine in Chrome and Firefox.

Epistyle answered 12/12, 2014 at 10:14 Comment(0)
E
0
 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.
Eer answered 21/4, 2018 at 12:41 Comment(0)
C
0

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>
Cadet answered 1/3, 2021 at 18:51 Comment(0)
B
0

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); 
});
Belgrade answered 13/4, 2022 at 20:52 Comment(0)
C
0

Alternative 1: native js insertAdjacentHTML()

Provided you don't consider switching to native JavaScript at all ...
You could also use native javaScript method insertAdjacentHTML() for similarly convenient notation.

  $("#svg")[0].insertAdjacentHTML(
    "beforeend",
    '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>'
  );

$("#svg")[0] makes your jQuery object selectable in native JS.

Alternative 2: write a native js DOMParser() helper

mdn web docs: DOMParser.parseFromString()

  function createSvgEl(markup) {
    markup = `<svg xmlns="http://www.w3.org/2000/svg">
  ${markup}</svg>`;
    const svgEl = new DOMParser().parseFromString(markup, "image/svg+xml")
      .documentElement.children[0];
    return svgEl;
  }

Usage in jQuery:

  $("#svgXML").append(
    createSvgEl(
      '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>'
    )
  );

Demo

// native js helper
function createSvgEl(markup) {
  markup = `<svg xmlns="http://www.w3.org/2000/svg">
  ${markup}</svg>`;
  const svgEl = new DOMParser().parseFromString(markup, "image/svg+xml")
    .documentElement.children[0];
  return svgEl;
}


$(document).ready(function() {

  // works - but will remove existing children
  $("#svg1").html(
    '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>'
  );

  // works
  // $("#svg")[0] makes your jQueryObject selectable in native JS
  $("#svg")[0].insertAdjacentHTML(
    "beforeEnd",
    '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>'
  );

  $("#svgXML").append(
    createSvgEl(
      '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>'
    )
  );
  // jquery still works! Vanilla doesn't harm!
  $("#svgXML circle:nth-of-type(2)").attr('fill', 'orange');

  //insert after()
  $("#svgAfter circle").after(
    createSvgEl(
      '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>'
    )
  );

  //insert after native
  $("#svgAfterNative circle")[0].insertAdjacentHTML(
    "afterEnd",
    '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>'
  );

});
svg {
  border: 1px solid red;
  overflow: visible;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p>Append via native js insertAdjacentHTML()</p>
<svg id="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">
  <circle cx="10" cy="10" r="5" fill="green" />
</svg>

<p>Append via DOMParser() helper</p>
<svg id="svgXML" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" width="200px" height="100px">
  <circle cx="10" cy="10" r="5" fill="green" />
</svg>

<p>Append via jquery html() - will strip existing child nodes</p>
<svg id="svg1" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" width="200px" height="100px">
  <circle cx="10" cy="10" r="5" fill="green" />
</svg>

<p>Insert after existing element with jQuery after() using DOMParser() helper</p>
<svg id="svgAfter" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" width="200px" height="100px">
  <circle cx="10" cy="10" r="5" fill="green" />
</svg>

<p>Insert after existing element with native js insertAdjacentHTML()</p>
<svg id="svgAfterNative" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" width="200px" height="100px">
  <circle cx="10" cy="10" r="5" fill="green" />
</svg>

jquery's after() or before() methods will also fail to add a SVG DOM (depending on the correct namespace) element.

Using the aforementioned workarounds will fix this issue as well.

Caruso answered 14/12, 2022 at 18:51 Comment(1)
Corrected "beforeEnd" to "beforeend"Permanency
A
-1

This is working for me today with FF 57:

function () {
    // JQuery, today, doesn't play well with adding SVG elements - tricks required
    $(selector_to_node_in_svg_doc).parent().prepend($(this).clone().text("Your"));
    $(selector_to_node_in_svg_doc).text("New").attr("x", "340").text("New")
        .attr('stroke', 'blue').attr("style", "text-decoration: line-through");
}

Makes:

this SVG image as seen in Firefox 57

Ayers answered 5/1, 2018 at 19:50 Comment(4)
That's not SVG elements you're appending, that's text content.Pelotas
That may be, but it rendered after initial page load of statically inlined SVG.Ayers
So what, it's not the question being asked, which is about svg elements and not text content.Pelotas
$(this).clone() is cloning a SVG element (and it's children if it had any). Look past the use of text(). I'm taking a single tspan that had "Your New" in it, and ending up with two tspans, one with "Your" in it (black) and one with "New in it" (blue w/ line-through). Jeez, down from 0 votes to -1 :-(Ayers

© 2022 - 2024 — McMap. All rights reserved.