Andrew Newby
Andrew Newby

Reputation: 5187

Trigger click on SVG image

I'm having a play with a SVG image to see if I can create a map for my website. I grabbed the image from a 3rd party site, and now I'm just trying to implement it. Here is a fiddle of what I have:

https://jsfiddle.net/hL1weg3o/1/

So basically the CSS is:

svg, svg * {
    pointer-events: none;
}
#map {
  display: block;
  text-indent: -9999px;
  width: 100% ;
  height: 600px;
}

HTML:

<!DOCTYPE html>
<html lang="en">
  <head>
  </head>
  <body>

    <div id="mapContainer">
        <object id="map" data="https://chambresdhotes.org/2018/franceHigh.svg" type="image/svg+xml"></object>
    </div>


  </body>
</html>

..and then I'm trying to capture the clicks with:

document.getElementById("FR-A").addEventListener('click', function (event) { test() });

The paths in the SVG look something like:

<path id="FR-A" title="Alsace" class="land"
 d="M498.91,208.16L502.37,206.45L501.41,203.92L502.77,202.75L502.05,202.16L503.38,197.19L505.73,195.84L508.91,190.38L508.19,188.16L513.99,177.9L513.19,176.07L510.57,176.47L508.87,175.28L510.21,173.71L509.24,172.42L510.58,167.67L509.44,165.85L511.28,166.21L508.42,164.55L512.58,164.35L514.79,162.8L518.37,156.06L516.75,155.91L515.79,154.05L518.79,149.33L516.06,146.78L516.51,145.88L512.08,144.43L510.96,147.15L508.96,148.25L509.41,146.56L507.87,146.28L507.83,144.51L509.66,143.35L507.81,143.57L507.73,142.59L503.83,141.4L503.38,138.89L504.82,138.9L505.31,137.13L507.05,137.45L508.51,130.56L509.79,129.8L510.96,134.31L517.94,136.33L517.8,137.48L519.26,138.25L524.5,136.67L528.02,138.94L529.75,137.39L532.17,131.3L532.17,131.3L536.13,131.11L536.25,131.93L538.69,130.52L541.69,132.56L544.49,131.02L551.1,135.31L556.89,136.82L553.43,140.7L550.96,147.12L546.08,149.96L545.75,152.17L540.57,157.24L538.95,160.81L539.2,165.15L537.64,166.68L536.15,172.66L536.66,176.85L534.52,178.43L533.41,183.41L529.69,189.69L529.39,195.05L531.58,198.9L528.85,204.64L527.73,210.8L528.49,213.6L526.98,215.84L530.29,221.55L529.95,223.31L526.45,225.53L527.76,226.24L526.39,226.69L526.95,228.06L526.01,229.02L523.64,228.23L523.2,229.14L524.64,229.71L521.77,232.09L519.37,231.53L515.83,232.75L515.37,231.65L512.79,231.37L514.11,228.3L511.23,227.75L511.23,227.75L511.67,226.42L509.3,222.24L505.95,221.67L507.63,217.4L507.24,214.26L503.23,211.3L500.16,210.59z"/>

Am I misunderstanding how you capture a click on a div? Basically I need to grab the value of "title" from the path clicked on, and then my JS can work out where to send the user.

Thanks!

Upvotes: 2

Views: 2235

Answers (2)

Dave B
Dave B

Reputation: 1800

@MSC's answer was what I needed. (Upvoted the OP's question and @MSC's answer.) Here's a vanilla JavaScript version in case anyone needs a quick cut and paste:

function fetchAndAssignSvg(url, element) {

    // Validate parameters
    if (typeof url !== "string" || url.length === 0) { return; }
    if (typeof element === "undefined") { return; }

    // See the following link to use 'XMLHttpRequest' instead of Fetch API
    // stackoverflow.com/questions/17901116/i-need-the-equivalent-of-load-to-js/17901198

    fetch(url)
        .then(response => {
            if (!response.ok) {
                console.log(response);
                return;
            }
            response.text().then(text => {
                element.innerHTML = text;
                element.addEventListener("pointerdown", pointerdownListener);
            });
        })
        .catch(error => {
            console.log(error);
        });
}

function pointerdownListener(e) {
    let target = e.target;
    if (target.tagName.toLowerCase() === "path") {
        console.log(target.id);
    }
}

// Sample call:
fetchAndAssignSvg("https://chambresdhotes.org/2018/franceHigh.svg", document.querySelector("#map-container"));

Upvotes: 0

MSC
MSC

Reputation: 3386

You'll need to load the SVG into the page's DOM if you want to attach your event listener to shapes within it, otherwise your JS won't be able to see them.

One way to do this is to cut and paste the SVG into your HTML. Another way is to load the SVG's DOM into a wrapper element - such as a DIV - through JS / jQuery:

<div id="mapContainer"></div>

<script>
$(function() {
  $('#mapContainer').load("https://chambresdhotes.org/2018/franceHigh.svg", function() {
    $("#FR-A").click(function(event) {
      test();
     });
  });
});
</script>

(Apologies for the jQuery; my JS is a little rusty.)

Note that I have this inside the DOM loaded block to make sure it runs only after the #mapContainer is loaded. You can see this in action on the Interspan website. Instead of clicking, hover over the logo in the top left corner. The principle is the same, it's just using the hover event instead of the click event.

Upvotes: 2

Related Questions