Add click event on elements of an embedded SVG in javascript

62,347

Solution 1

Okay using your comments I found an answer to my problem. I added this code in the svg itself.

<script type="text/javascript"> <![CDATA[
    function addClickEvents() {
        var countries = document.getElementById('svg1926').childNodes;
        var i;
        for (i=0;i<countries.length;i++){
            countries[i].addEventListener('click', showCountry);
        }
    }

    function showCountry(e) {
        var node = e.target;
        if (node.id != 'ocean') {
            node = getCorrectNode(node);
        }
        alert(node.id);
    }

    function getCorrectNode(node) {
        if (node.id.length == 2 || node.id == 'lakes') {
            return node;
        }
        return getCorrectNode(node.parentNode);
    }
]]> </script>

The function addClickEvents is triggered when the svg loads. But I still have another problem with this. I have to embed this svg (with the code) into a HTML document using

<embed src="circle1.svg" type="image/svg+xml" />

Instead of alerting the id, I have to place it into a div in the HTML document. How do I get this id from the svg?

Solution 2

Here's an example that should be very similar to what you're trying to do. It uses <object> instead of <embed>, but that's only a minor detail. See this other example for how to get to the DOM of the embedded document from the parent document, it differs just a bit between the two.

Also note that the svg maps that wikipedia have are quite large, so you will want to optimize the svgs before actual usage on a live website, try e.g SVG Cleaner or SVG Scour.

Solution 3

If your SVG is contained in the DOM, you can attach event listeners to separate elements in the same manner as basic HTML. Using jQuery one example would be: http://jsfiddle.net/EzfwV/

Update: Most modern browsers support inline svg, so to load your source into the DOM, all you have to do is load it in from a resource, (using something like jQuery's load()).

Edit: more specific example http://jsfiddle.net/EzfwV/3/

Solution 4

Update July 2016

It is possible to respond to events from embed elements now, under the condition that you embed something from the same domain. I have created a quick demonstration of this as a JSFiddle. The most important part is that it is possible to access the embedded document through embeddingElement.contentDocument. From there, the SVG element can be accessed and click event handlers can be installed.

Implementation note: in the demo, I add event handlers to all path elements. For performance reasons, you would probably want to add a single event handler to the SVG and then use the event target in the handler. Edit: like in this updated Fiddle.

Old answer

A quick Google search brought me here. I think that's the answer to your problem, right?

To summarize here: it is not possible to capture events on an embed element, unfortunately the only solution is modifying the SVG file.

Here is a small example of how to embed JavaScript into an SVG file (JSFiddle). It is based on an example from IBM developerWorks.

<svg>
  <script type="text/javascript">
    <![CDATA[
    var redVal = 0;
    var greenVal = 0;
    var blueVal = 0;

    function changeCol(evt) {
       redVal = Math.round(Math.random() * 255);
       greenVal = Math.round(Math.random() * 255);
       blueVal = Math.round(Math.random() * 255);
       evt.target.setAttribute("fill",
             "rgb(" + redVal + "," + greenVal + "," + blueVal + ")");

    }
    // ]]>
  </script>
  <circle cx="200" cy="200" r="100" fill="blue"
          onclick="changeCol(evt)" />
</svg>

Solution 5

A simple method is

  • Creating Path dynamically in SVG with javascript
  • Adding Styles Dynamically
  • Adding Events to Path
  • Appending to existing SVG.

Script

 <svg id="mySvg"></svg>

var XMAX = 500;
var YMAX = 500;
var _xx=10;
var _reg=100;
var _l=10;
// Create PATH element
for(var x=1;x<20;x++)
{
var pathEl = document.createElementNS("http://www.w3.org/2000/svg", "path");
pathEl.setAttribute('d','M'+_l+' 100 Q 100  300 '+_l+' 500' );
pathEl.style.stroke = 'rgb('+(_reg)+',0,0)';
pathEl.style.strokeWidth = '5';
pathEl.style.fill = 'none';
    $(pathEl).mousemove(function(evt){$(this).css({"strokeWidth":"3","stroke":"#ff7200"}).hide(100).show(500).css({"stroke":"#51c000"})});

$('#mySvg').append(pathEl);
_l+=50;
}

Live Demo in JSFiddle

Share:
62,347

Related videos on Youtube

Daan Lambrechts
Author by

Daan Lambrechts

Updated on July 09, 2022

Comments

  • Daan Lambrechts
    Daan Lambrechts almost 2 years

    I got this SVG image from Wikipedia and embedded it into a website using this code:

    <embed src="circle1.svg" type="image/svg+xml"/>
    

    If you run this, you can inspect the element and see the source code. All countries in the image are separate elements. If I click on a country, I want to alert the id of that country, since every country has an id of two letters in the SVG. Does anyone know a way to do this? Would it be easier if I place it into a element?

  • Daan Lambrechts
    Daan Lambrechts about 12 years
    No. I don't want to add a click event to the entire svg, but multiple click events on each layer in it
  • Linus Thiel
    Linus Thiel about 12 years
    Daan: Are you sure? According to the answer, you can't handle the click events without embedding the javascript in your SVG document. In fact, you can't even see events on the embed element, let alone the events on SVG elements. I don't know about licensing and so on for that file, but if you can, I suggest you edit the document to add click handlers.
  • Just a student
    Just a student about 12 years
    That's exactly what I was thinking. I have edited my answer to include yet another tutorial that explains how to do this.
  • Daan Lambrechts
    Daan Lambrechts about 12 years
    I tried this to load the svg into the div with the id 'map'. However i get the alert, i can't see the svg image $('#map').svg(); var svg = $('#map').svg('get'); svg.load('images/world.svg',{onLoad: function(){ alert('ready'); }});
  • Daan Lambrechts
    Daan Lambrechts about 12 years
    So I have to manually add click events on each country in the svg and than paste the code into the html document?
  • Daan Lambrechts
    Daan Lambrechts about 12 years
    Yes, this is almost exactly what I want to do. But is it just me or does the first example only work in Internet Explorer?
  • Erik Dahlström
    Erik Dahlström about 12 years
    It worked fine in Opera too. But webkit and gecko don't seem to calculate bboxes correctly on elements in a display:none subtree. I've replaced those with visibility:hidden and now the hover labels are displayed in all the browsers.
  • RestingRobot
    RestingRobot about 12 years
    You problem is that you are trying to load the world.svg into an existing svg tag? (I think). Try something like $('#map').load('images/world.svg', function(){ alert('ready')});
  • chessweb
    chessweb about 12 years
    When I try this code I get "evt.getTarget is not a function". I have to use evt.target instead.
  • Just a student
    Just a student almost 8 years
    Which browser are you using? Do you get an error on the console?
  • Roman
    Roman over 7 years
    Safari 10 fails to set colors of embedded SVGs
  • Erik Dahlström
    Erik Dahlström almost 7 years
    @BrianStallter ok, yes, in Chrome Canary v61 the export button just pops open an empty window, perhaps some new policy in Chrome? It works fine in Chrome v59.