I'm trying to do buttons like the upvote buttons here, a button tag, with svg and path inside.
The appearance is ok, no problems with that. The problem is that the path tag has an attribute that I want to get when I click the button, I'm not very good at this, so to get the attribute that I want I used:
e.target.children[0].children[0].attributes.
And it gets to an error that I know the reason: the element has no children nor attributes, the error depends on where I click, if I click the path, the error is that it's child doesn't have a child (cause path's child is undefined), and if I click the svg, the problem is that the svg's child's child doesn't have attributes (again because it's undefined). So to don't get those errors, I have to click in the button, where there isn't path nor svg.
What should I do to being able to click in any pixel of the button and getting the same answer? I don't even know why it detects that I'm clicking on the svg or path even when those elements haven't any event listener.
When I started doing those buttons, I didn't use the button tag, it was just svg, and the eventListener was in the path element, the problem is that with small paths, is hard to click, so I started trying to use the click listener in the svg and now I put all inside a button tag and tried using the listener in the button, and I got the errors that I mentioned.
My apologies for not posting the code, it's a little long and horrible.
Edit:
I tried to take the most important of the code:
<body>
<div id="buttonCont">
</div>
<script>
//Function that adds around 40 buttons.
function addButtons(){
buttonCont = document.getElementById("buttonCont");
i = 0;
while (paths(i) != ``) {
buttonCont.innerHTML += `
<button class="exButton">
<svg class="exSVG">
<path class="exPath" pathNumber="${i}" d=""/>
</svg>
</button>`;
i++;
}
}
function on_load(){
addButtons();
exButtons = document.getElementsByClassName("exButton");
for(let i = 0; i < exButtons.length; i++){
exButtons[i].addEventListener("click", getNumber, false);
}
}
//This is the function with the problem.
function getNumber(e){
pNumber = e.target.children[0].children[0].attributes.pathNumber.nodeValue;
console.log(pNumber);
}
window.addEventListener("load", on_load, false);
</script>
After some hours I noticed that e.target returns the element that I clicked, not the element that has the listener, so anything inside the button is a different target. I'm looking a solution in javascript that allows me to get the button element with the click eventListener.
Passing in this
with your listener will always ensure your starting point is the same. For example:
<div onClick="getKey(this)">
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path
data-key="12345"
d="M 10,30
A 0,10 0,0,1 30,40
A 0,10 0,0,1 90,40"/>
</svg>
</div>
<script>
function getKey(button) {
let key = button.querySelectorAll('path')[0].dataset.key;
alert('key is ' + key)
}
</script>
In the above code, getKey()
will always receive the div
element so that you can reliably know how many children deep you need to dig.
Additionally, you can use button.querySelectorAll('path')[0]
to isolate the path
tag within the button so you don't have to cascade down the children
properties.
Here's a working JSFiddle: https://jsfiddle.net/sLp2qtde/1/