9

Snap.svg doesn't work in this case :

$('body').append($('<svg>').attr('id', 'test')) ;
console.log($('#test').length) ; // 1

var svg = Snap('#test') ;
svg.circle(100, 100, 50) ;
// Uncaught TypeError: Object [object Object] has no method 'circle'

... but works when the element is already in the HTML :

<body>
    <svg id="test"></svg>
</body>

The SVG element is successfully in the HTML but can't be found with Snap.svg. Am I doing it wrong with the first example or is it a bug ?

Tot
  • 873
  • 2
  • 13
  • 30
  • Did the other question have answers that actually helped here? – gotohales Nov 21 '13 at 15:32
  • Nope, the SVG element is correctly in the HTML. The problem is not the content of the SVG, it's the SVG itself not being detected by Snap.svg. – Tot Nov 21 '13 at 19:32
  • 2
    Yeah it looks like they didn't really look at the question closely before closing it :| Sorry. Anyway, it looks like when creating an svg, there needs to be a little more info. For example, if you do `$('body').append($('').attr('id', 'test'));` then it seems to work. – gotohales Nov 21 '13 at 22:47
  • Excellent, it works ! So post an answer if you are able and I'll mark it. In fact, I tested some other ways, and it works if we give just give one random attribute to the svg `$('')`, Snap.svg can find it. However, I suggest to put the default attributes you gave. Thanks again ! – Tot Nov 22 '13 at 10:48

1 Answers1

5

It looks like you found a workaround, but I thought you, or anyone reading this question, might want an explanation.

To create SVG elements, you have to use document.createElementNS() because svg elements are part of different namespace than html elements. For example:

var elementHTML = document.createElement("svg"); //does not work
var elementSVG = document.createElementNS("http://www.w3.org/2000/svg", "svg"); //works!

and internally, jquery uses document.createElement() when you give it just a tag name. Once you have the element, you can wrap it as a jquery object, and use it as normal.

$(elementSVG).attr("width", 100); //etc.

Using $("<svg data-blah='asdf'>") or similar works because anything beyond a simple tag is put into an element via .innerHTML and then extracted out. By doing it this way, the same engine is used as if it were in the page's HTML markup. And the HTML5 spec now has special cases for what to do when encountering a <svg> element in the markup.

Some things to look out for when working with svg in jquery are:

  • attributes are not case sensitive, but some svg attributes are! For example, doing $element.attr("attributeName", "stroke") will not work.
  • .animate() has some problems, but you can use a custom step function to get around it.

More details about it here

jcbelanger
  • 539
  • 3
  • 15