Home > other >  Getting data on click on button with svg path
Getting data on click on button with svg path

Time:08-28

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 >
                <svg >
                    <path  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.

CodePudding user response:

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/

CodePudding user response:

Well, I found a solution, using querySelectorAll as verl suggested, I changed the function getNumber, original:

function getNumber(e){
    pNumber = e.target.children[0].children[0].attributes.pathNumber.nodeValue;
    console.log(pNumber);
}

New one:

function getNumber(e){
    var object;
    if(e.target.querySelectorAll('path')[0] == undefined){
        object = e.target;
    } else {
        object = e.target.querySelectorAll('path')[0];
    }
    pNumber = object.attributes.pathNumber.nodeValue;
    console.log(pNumber);
}

So now I don't modify the HTML, just the function that was giving problems to me.

  • Related