42

Good Day,

I am having incredible difficulty in creating a path and displaying it using "appendChild" within an SVG element.

I have to be missing something critically simple as I have poured over W3C's specs, w3schools.com, various posts here and trying to ninja google in various ways.

I am testing within FireFox and Chrome.

I have a simple svg file thus:

<svg xmlns:svg ... id="fullPageID">
 <image id="timer1" x="100" y="100" width="100px" height="100px" xlink:href="../component/timer/timer1.svg" />  
 <image id="battery1" x="200" y="200" width="100px" height="100px" xlink:href="../component/battery/30x20_ochre.svg" />
 <script xlink:href="pathMaker.js" type="text/javascript" id="pathMaker" />  
</svg>

The script I am attempting to use looks like:

newpath = document.createElementNS("SVG","path");  
newpath.setAttribute("id", "pathIdD");  
newpath.setAttribute("d", "M 1,97.857143 C 19.285714,96.428571 24.016862,131.64801 90.714286,132.85714 140.78762,133.7649 202.79376,66.16041 202.79376,66.16041");  
newpath.setAttribute("stroke", "black");  
newpath.setAttribute("stroke-width", 3);  
newpath.setAttribute("opacity", 1);  
newpath.setAttribute("fill", "none");

document.getElementById("fullPageID").appendChild(newpath);

I just want to make something simple work. Am I wrong to think that I don't require a solution as complicated as the one found at Library to generate SVG Path with Javascript??

Thanks Kindly.

1
  • 6
    You might like to 'Accept' one of the answers. Commented Jun 24, 2014 at 1:40

3 Answers 3

59

There are two issues:

  1. As already pointed out, you have to use the full namespace uri, so in this case:

    newpath = document.createElementNS('http://www.w3.org/2000/svg',"path");  
    
  2. Attributes also need to be set with namespace in mind. The good news is that you can pass in null as the namespace uri, so:

    newpath.setAttributeNS(null, "d", "M 1,97.857143 C 19.285714,96.428571 24.016862,131.64801 90.714286,132.85714 140.78762,133.7649 202.79376,66.16041 202.79376,66.16041");
    

Also, here are two ways to make dealing with the svg namespace easier (assuming that it is a standalone svg, not embedded in HTML):

  • To refer to the svg element, instead of giving it an ID, you can use document.rootElement.
  • document.rootElement.getAttribute(null, "xmlns") returns an empty string (while requesting other attributes does work using this method. Instead, use document.rootElement.namespaceURI.

So in your code, you could make the following rewrites:

From:

 newpath = document.createElementNS("http://www.w3.org/2000/svg","path");

To:

 newpath = document.createElementNS(document.rootElement.namespaceURI,"path");  

And to append the element, you can go from:

document.getElementById("fullPageID").appendChild(newpath);

to:

document.rootElement.appendChild(newpath);

So the final script would be:

newpath = document.createElementNS(document.rootElement.namespaceURI,"path");  
newpath.setAttributeNS(null, "id", "pathIdD");  
newpath.setAttributeNS(null, "d", "M 1,97.857143 C 19.285714,96.428571 24.016862,131.64801 90.714286,132.85714 140.78762,133.7649 202.79376,66.16041 202.79376,66.16041");  
newpath.setAttributeNS(null, "stroke", "black"); 
newpath.setAttributeNS(null, "stroke-width", 3);  
newpath.setAttributeNS(null, "opacity", 1);  
newpath.setAttributeNS(null, "fill", "none");

document.rootElement.appendChild(newpath);
Sign up to request clarification or add additional context in comments.

4 Comments

#2 is not correct; using setAttribute(a,b) is equivalent to setAttributeNS(null,a,b): it works just as well.
Confirming the comment above -- I have always been successful using setAttribute(a,b). Runs successfully on Safari, Firefox, and Chrome, at least.
#2 is not incorrect, in so far as it the 'official' way to add a non-html attribute with the newer DOM spec. I have had issues with Chrome where the attribute exists in the source inspector, but not compiled into the style. Even if it works, it's because WebKit and Gecko are allowing it for compatibility,not because it's truly equivalent. Point being: if you don't want your script to break at some point, it's best to use the expected method, not one that has been adapted for legacy-proofing. I'm sure at some point createElement worked in those engines as well.
Thanks for the quick answers and confirmations. I should comprehend a great deal more now as I have a basic understanding of the rootElemement. Small things one forgets when only finding few minutes a day to learn new things.
4

The namespace needs to be "http://www.w3.org/2000/svg", not "SVG" in the createElementNS call.

Comments

0

You can get a free namespace and be sneaky by just putting a path element in, using an id to hide it, and then cloning it. Here's an example using jQuery:

HTML

<svg ...>
  <path id="pathFactory"></path>
</svg>

CSS

#pathFactory {
  display: none;
}

Javascript

var path = $('#pathFactory').clone().removeAttr('id');

Your path variable is now a fully working path, with proper namespace, unhidden and ready to be appended to the svg.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.