Dynamic creation of SVG links in JavaScript
Asked Answered
T

1

5

I am dynamically creating SVG elements from JavaScript. It's working fine for visual objects like a rectangle, but I'm having trouble producing functioning xlinks. In the example below the first rectangle (which is statically defined) works correctly when clicked on, but the other two (created in JavaScript) ignore clicks... even though inspecting the elements in Chrome seems to show the same structure.

I've seen multiple similar questions come up, but none that exactly address this. The closest I found was [ adding image namespace in svg through JS still doesn't show me the picture ] but that's not working (as noted below). My goal is to do this purely in JavaScript, without depending on JQuery or other libraries.


<!-- Static - this rectangle draws and responds to click -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svgTag">
    <a xlink:href="page2.html" id="buttonTemplate">
        <rect x="20" y="20" width="200" height="50" fill="red" class="linkRect"/>
    </a>
</svg>

<script>
    var svgElement = document.getElementById ("svgTag");

    // Dynamic attempt #1 - draws but doesn't respond to clicks
    var link = document.createElementNS("http://www.w3.org/2000/svg", "a");  // using http://www.w3.org/1999/xlink for NS prevents drawing
    link.setAttribute ("xlink:href", "page2.html");  // no improvement with setAttributeNS
    svgElement.appendChild(link);

    var box = document.createElementNS("http://www.w3.org/2000/svg", "rect");
    box.setAttribute("x", 30); 
    box.setAttribute("y", 30);
    box.setAttribute("width", 200);
    box.setAttribute("height", 50);
    box.setAttribute("fill", "blue");
    link.appendChild(box);

    // Dynamic attempt #2 (also draws & doesn't respond) - per https://stackoverflow.com/questions/6893391
    box = document.createElementNS("http://www.w3.org/2000/svg", "rect");
    box.setAttribute("x", 40); 
    box.setAttribute("y", 40);
    box.setAttribute("width", 200);
    box.setAttribute("height", 50);
    box.setAttribute("fill", "green");
    box.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', "page2.html");
    svgElement.appendChild(box);

Tally answered 2/10, 2013 at 8:1 Comment(1)
Per the comment in the link, I had tried it with setAttributeNS as well. Looks like the problem, though, was I was using the wrong namespace (svg instead of xlink).Tally
C
9

Only an <a> can be a link so adding an xlink:href attribute to a <rect> element will have no effect.

You need to use setAttributeNS which you say doesn't work but it does for me so perhaps there was some other issue.

This example works for me:

var svgElement = document.getElementById ("svgTag");

var link = document.createElementNS("http://www.w3.org/2000/svg", "a");
link.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', "page2.html");
svgElement.appendChild(link);

var box = document.createElementNS("http://www.w3.org/2000/svg", "rect");
box.setAttribute("x", 30); 
box.setAttribute("y", 30);
box.setAttribute("width", 200);
box.setAttribute("height", 50);
box.setAttribute("fill", "blue");
link.appendChild(box);
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svgTag">
</svg>
Coz answered 2/10, 2013 at 8:37 Comment(1)
Thanks, that indeed solved it. Looks like the issue was that when I had previously tried createElementNS I was using the wrong namespace: w3.org/2000/svg instead of w3.org/2000/svg. My (incorrect) thinking was that the "a" element is part of the sag namespace, when I now see that the namespace should have been determined at the attribute level (xlink).Tally

© 2022 - 2024 — McMap. All rights reserved.