Reputation: 123
const countries = Array.from(document.getElementsByClassName('country'));
countries.forEach(c => {
c.addEventListener('click', function() {
console.log('you clicked:', c.getAttribute('title'));
})
})
.map {
background: #88aaaa;
}
.map {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
position: relative;
visibility: visible;
width: 100%;
height: 100%;
padding: 3rem 1rem;
opacity: 1;
transition: opacity 0.5s;
z-index: -1;
margin-top: -90px;
}
.map_svg {
display: block;
width: 100%;
height: auto;
max-height: 100%;
margin-left: 1rem;
}
.map_svg path {
fill-opacity: 1;
stroke: #21252b;
stroke-opacity: 1;
stroke-width: 0.5;
transition: 0.5s;
}
<section class="map">
<svg class="map_svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1" viewBox="0 0 1008 651">
<path class="country" id="AT" title="Austria"
d="M522.861,309.853L522.648,311.557L521.069,311.565L521.613,312.464L520.682,315.111L520.147,315.8L517.695,315.901L516.28,316.823L513.964,316.509L509.955,315.458L509.329,314.034L506.558,314.746L506.231,315.523L504.533,314.943L503.102,314.832L501.833,314.085L502.262,313.078L502.154,312.344L503,312.116L504.419,313.264L504.818,312.173L507.291,312.35L509.295,311.606L510.64,311.733L511.514,312.582L511.775,311.878L511.378,309.158L512.385,308.624L513.374,306.673L515.457,308.037L517.034,306.302L518.021,305.983L520.198,307.281L521.515,307.061L522.807,307.861L522.582,308.396z" />
<path class="country" id="AU" title="Australia"
d="M882.928,588.16l2.709,1.277l1.526,-0.508l2.188,-0.71l1.682,0.248l0.199,4.425l-0.961,1.3l-0.289,3.064l-0.98,-1.047l-1.946,2.675l-0.58,-0.208l-1.725,-0.12l-1.729,-3.276l-0.384,-2.496l-1.617,-3.254l0.071,-1.695L882.928,588.16zM877.779,502.097l1.01,2.254l1.799,-1.084l0.929,1.218l1.346,1.125l-0.288,1.28l0.598,2.484l0.426,1.452l0.706,0.355l0.761,2.495l-0.271,1.52l0.908,1.995l3.038,1.542l1.98,1.407l1.881,1.292l-0.367,0.721l1.604,1.872l1.09,3.249l1.119,-0.662l1.137,1.306l0.686,-0.464l0.483,3.208l1.989,1.871l1.302,1.167l2.191,2.488l0.788,2.487l0.072,1.774l-0.193,1.937l1.336,2.676l-0.16,2.811l-0.485,1.48l-0.757,2.871l0.057,1.859l-0.555,2.34l-1.238,2.996l-2.077,1.631l-1.023,2.59l-0.936,1.666l-0.831,2.932l-1.082,1.707l-0.709,2.583l-0.362,2.401l0.144,1.109l-1.607,1.224l-3.139,0.128l-2.588,1.454l-1.288,1.38l-1.694,1.539l-2.322,-1.584l-1.718,-0.629l0.436,-1.851l-1.533,0.67l-2.455,2.582l-2.424,-0.97l-1.59,-0.564l-1.604,-0.254l-2.714,-1.027l-1.813,-2.175l-0.521,-2.655l-0.651,-1.752l-1.378,-1.398l-2.697,-0.414l0.922,-1.661l-0.679,-2.522l-1.369,2.351l-2.495,0.627l1.467,-1.885l0.425,-1.953l1.083,-1.646l-0.225,-2.472l-2.28,2.849l-1.752,1.15l-1.074,2.693l-2.189,-1.396l0.087,-1.791l-1.754,-2.43l-1.479,-1.247l0.527,-0.766l-3.598,-2.001l-1.971,-0.094l-2.696,-1.597l-5.021,0.31l-3.631,1.175l-3.19,1.1l-2.676,-0.219l-2.972,1.696l-2.432,0.766l-0.54,1.75l-1.035,1.363l-2.38,0.082l-1.761,0.299l-2.478,-0.613l-2.017,0.367l-1.925,0.154l-1.668,1.801l-0.817,-0.153l-1.406,0.959l-1.348,1.082l-2.046,-0.134l-1.879,-0.001l-2.975,-2.168l-1.507,-0.642l0.061,-1.927l1.393,-0.456l0.476,-0.761l-0.1,-1.196l0.343,-2.302l-0.313,-1.948l-1.482,-3.294l-0.46,-1.845l0.121,-1.83l-1.116,-2.079l-0.071,-0.934l-1.242,-1.262l-0.35,-2.468l-1.603,-2.477l-0.388,-1.327l1.231,1.346l-0.946,-2.881l1.391,0.898l0.83,1.203l-0.047,-1.59l-1.388,-2.43l-0.269,-0.968l-0.65,-0.917l0.305,-1.767l0.574,-0.75l0.383,-1.519l-0.3,-1.768l1.159,-2.165l0.211,2.292l1.185,-2.071l2.278,-1.002l1.366,-1.276l2.143,-1.095l1.274,-0.232l0.772,0.367l2.209,-1.109l1.701,-0.33l0.425,-0.65l0.742,-0.271l1.55,0.07l2.947,-0.867l1.524,-1.313l0.716,-1.575l1.645,-1.491l0.126,-1.169l0.073,-1.589l1.962,-2.474l1.181,2.514l1.193,-0.582l-0.998,-1.375l0.88,-1.409l1.237,0.629l0.34,-2.205l1.532,-1.421l0.676,-1.138l1.41,-0.491l0.044,-0.804l1.232,0.335l0.049,-0.722l1.233,-0.412l1.355,-0.387l2.071,1.318l1.556,1.705l1.755,0.02l1.783,0.271l-0.594,-1.582l1.343,-2.303l1.264,-0.749l-0.437,-0.715l1.218,-1.632l1.698,-1.006l1.435,0.339l2.355,-0.537l-0.051,-1.455l-2.054,-0.936l1.493,-0.413l1.857,0.704l1.489,1.167l2.361,0.729l0.801,-0.288l1.738,0.875l1.638,-0.815l1.054,0.248l0.656,-0.547l1.287,1.41l-0.747,1.528l-1.064,1.155l-0.964,0.096l0.325,1.146l-0.824,1.435l-0.996,1.414l0.201,0.814l2.229,1.596l2.16,0.928l1.443,0.999l2.027,1.722l0.79,-0.003l1.468,0.746l0.426,0.901l2.677,0.992l1.852,-0.999l0.549,-1.566l0.568,-1.289l0.349,-1.59l0.853,-2.3l-0.39,-1.394l0.202,-0.837l-0.324,-1.643l0.367,-2.157l0.538,-0.581l-0.437,-0.953l0.678,-1.511l0.532,-1.563l0.07,-0.81l1.042,-1.063l0.791,1.388l0.194,1.783l0.699,0.344l0.119,1.197l1.02,1.452l0.21,1.62L877.779,502.097z" />
</svg>
</section>
<p class="country" title="p1">one</p>
<p class="country" title="p2">two</p>
<p class="country" title="p3">three</p>
I have a page with an SVG containing multiple paths (this is for a world map), and wanted to make a script to add an event listener to each path, so you can click on an individual country and make things happen, though I am having trouble and not sure why.
I created a very simple script:
const countries = Array.from(document.getElementsByClassName('country'));
countries.forEach(c => {
console.log(c);
c.addEventListener('click', function() {
console.log('you clicked:', c.getAttribute('title'));
})
})
The script does loop through the elements array and each element is output to the console, mousing over the element in the console highlights the area on the page... but it appears no event listener is created, or bound to the path.
I did check the script is working by creating a set of paragraphs on the page:
<p class="country" title="p1">one</p>
<p class="country" title="p2">two</p>
<p class="country" title="p3">three</p>
These are now picked up by the same script and have event listeners that log the expected results on click... but nothing happens when the paths are clicked on. It seems like chrome just doesn't want to add event listeners to path elements, but I know it should be possible.
for reference the svg is inline defined like this:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 1008 651">
<path class="country" id="AE" title="United Arab Emirates"
d="M619.874,393.722L620.373,393.573L620.477,394.411L622.671,393.93L624.99,394.009L626.684,394.1L628.604,392.028L630.695,390.054L632.467,388.146L633.001,389.202L633.382,391.639L631.949,391.651L631.72,393.648L632.216,394.073L630.947,394.674L630.939,395.919L630.122,397.175L630.049,398.394L629.484,399.032L621.056,397.508L619.981,394.428z" />
<path class="country" id="AF" title="Afghanistan"
d="M646.879,356.901L649.738,358.201L651.853,357.745L652.438,356.188L654.651,355.669L656.231,354.617L656.791,351.832L659.154,351.154L659.594,349.902L660.917,350.843L661.762,350.952L663.323,350.975L665.438,351.716L666.295,352.143L668.324,351.017L669.27,351.694L670.174,350.085L671.85,350.159L672.281,349.641L672.578,348.213L673.785,346.975L675.303,347.785L674.998,348.869L675.846,349.038L675.585,351.994L676.694,353.137L677.672,352.404L678.916,352.057L680.663,350.486L682.594,350.745L685.486,350.751L685.985,351.758L684.353,352.15L682.928,352.795L679.71,353.2L676.699,353.931L675.063,355.439L675.725,356.899L676.046,358.603L674.649,360.033L674.766,361.335L673.995,362.549L671.328,362.444L672.43,364.663L670.646,365.507L669.455,367.511L669.609,369.491L668.514,370.415L667.477,370.109L665.334,370.537L665.027,371.451L662.939,371.446L661.377,373.289L661.278,376.039L657.635,377.374L655.682,377.092L655.114,377.794L653.438,377.386L650.634,377.865L645.936,376.228L648.479,373.298L648.249,371.202L646.125,370.65L645.905,368.565L644.987,365.921L646.187,364.094L644.966,363.599L645.736,361.148z" />
<path class="country" id="AL" title="Albania"
d="M532.985,334.657L532.629,335.93L533.027,337.524L534.19,338.425L534.134,339.393L533.223,339.925L533.054,341.115L531.75,342.88L531.274,342.626L531.218,341.826L529.665,340.601L529.421,338.851L529.658,336.323L530.041,335.164L529.568,334.573L529.38,333.377L530.596,331.512L530.774,332.227L531.528,331.891L532.125,332.907L532.796,333.293z" />
// etc..
I have also tried hardcoding an event listener to a specific path id but that also does not do anything on click, i.e:
const oz = document.getElementById("AU");
console.log(oz);
oz.addEventListener("click", () => {
console.log('clicked on oz');
});
While trying to find a solution I have seen examples of the same approach working, e.g. https://svg-tutorial.com/svg/interaction
And I can't realistically see where I am doing anything different that would cause a problem
As per request have tried adding a snippet: Edit: Shrunk & updated snippet to avoid issues:
Upvotes: 1
Views: 78
Reputation: 7324
Incorrect Stacking Context
The problem is caused by applying css z-index: -1
to the wrapper element. This reorders the stacking context so that the document body masks pointer events on the svg paths within the wrapper, i.e., the svg appears behind the body.
The stacking order can be corrected by removing either z-index: -1
(defaults to "auto") or position: relative
(defaults to "static").
Run the snippet and click on the rectangle path. Then check z-index option and repeat.
addEventListener('click', (e) => {
console.log(e.type, e.target.tagName, e.target.getAttribute('title'));
})
document.querySelector('input').addEventListener('change', (e) => {
document.querySelector('section').classList.toggle('map');
})
.map {
position: relative;
z-index: -1;
}
<input type="checkbox"> Use Z-Index -1
<section>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<path class="country" id="AT" title="Austria" d="M0,0 L100,0 L100,100 L0,100 L0,0"/>
</svg>
</section>
Upvotes: 7
Reputation: 22432
I think your problem comes from the fact that you are using the getElementsByClassName()
method
use querySelector()
or querySelectorAll()
instead.
In your case, prefer to use the event delegation mechanism
(explained many times elsewhere here)
in HTML5
xmlns
andxmlns:xlink=
attributes are no longer in use
document.querySelector('svg').addEventListener('click', e =>
{
if (!e.target.matches('path.country')) return // ignore other clicked
console.log (`${e.target.getAttribute('title')} <> ${e.target.id}`);
setTimeout(console.clear,2500);
})
svg {
width : 300px;
background : lightgrey;
}
svg path.country {
cursor : pointer;
fill : orange;
}
svg path.country:hover {
fill : crimson;
}
<svg viewBox="600 340 100 70">
<path class="country"
title="United Arab Emirates"
id="AE"
d="M619.874,393.722L620.373,393.573L620.477,394.411L622.671,393.93
L624.99,394.009L626.684,394.1L628.604,392.028L630.695,390.054
L632.467,388.146L633.001,389.202L633.382,391.639L631.949,391.651
L631.72,393.648L632.216,394.073L630.947,394.674L630.939,395.919
L630.122,397.175L630.049,398.394L629.484,399.032L621.056,397.508
L619.981,394.428z" />
<path id="AF"
title="Afghanistan"
class="country"
d="M646.879,356.901L649.738,358.201L651.853,357.745L652.438,356.188
L654.651,355.669L656.231,354.617L656.791,351.832L659.154,351.154
L659.594,349.902L660.917,350.843L661.762,350.952L663.323,350.975
L665.438,351.716L666.295,352.143L668.324,351.017L669.27,351.694
L670.174,350.085L671.85,350.159L672.281,349.641L672.578,348.213
L673.785,346.975L675.303,347.785L674.998,348.869L675.846,349.038
L675.585,351.994L676.694,353.137L677.672,352.404L678.916,352.057
L680.663,350.486L682.594,350.745L685.486,350.751L685.985,351.758
L684.353,352.15L682.928,352.795L679.71,353.2L676.699,353.931
L675.063,355.439L675.725,356.899L676.046,358.603L674.649,360.033
L674.766,361.335L673.995,362.549L671.328,362.444L672.43,364.663
L670.646,365.507L669.455,367.511L669.609,369.491L668.514,370.415
L667.477,370.109L665.334,370.537L665.027,371.451L662.939,371.446
L661.377,373.289L661.278,376.039L657.635,377.374L655.682,377.092
L655.114,377.794L653.438,377.386L650.634,377.865L645.936,376.228
L648.479,373.298L648.249,371.202L646.125,370.65L645.905,368.565
L644.987,365.921L646.187,364.094L644.966,363.599
L645.736,361.148z" />
</svg>
Upvotes: -1