10

I know I can grab the element of an individual ID.

Anyway I can attach a listener to the parent div and pass the ID of the individual span that was clicked?

<div id = "divId">
  <span id="one"></span>
  <span id="two"> </span>
 </div>

JS

document.getElementById("two").addEventListener("click", someFunction);
Suman Bogati
  • 6,289
  • 1
  • 23
  • 34
Doc Holiday
  • 9,928
  • 32
  • 98
  • 151

4 Answers4

30

You can use the event object and access its target property

document.getElementById("divId").addEventListener("click", someFunction);

function someFunction(event) {
  console.log(event.target.id);
}
<div id="divId">
  <span id="one">one</span>
  <span id="two"> two</span>
</div>
AmmarCSE
  • 30,079
  • 5
  • 45
  • 53
  • @Teemu, `event` is a default object bound to handlers in js – AmmarCSE Jun 11 '15 at 16:21
  • @Teemu, I may be wrong, but I thought `event` was like `arguments` where you can access it without passing it in – AmmarCSE Jun 11 '15 at 16:23
  • It is not. In older IEs it was a global object though. – Teemu Jun 11 '15 at 16:24
  • @Teemu, out of curiosity, how was it working before when I did not pass it in? – AmmarCSE Jun 11 '15 at 16:25
  • 1
    It wasn't, I saw "ReferenceError: event is not defined" on my console. Now it works. - Sorry I forgot, Chrome has implemented the global `event` too, but it's not a part of any standard. I'm on FF, which gave the error – Teemu Jun 11 '15 at 16:27
  • @Teemu, oh ok. It was working for me on chrome. So this definately seems like an unstable usage for cross-browsers... thanks again for the useful tip – AmmarCSE Jun 11 '15 at 16:28
  • if i do an alert...it will only give me the ID of the div. If I click on the spans the alert pops up and its empty??? – Doc Holiday Jun 11 '15 at 17:07
  • @DocHoliday, interesting. Are you using the code from my most recent answer? what browser? can you replicate it in a fiddle? – AmmarCSE Jun 11 '15 at 17:13
  • @DocHoliday, ok, figured it out. For the cases of an empty alert, it was alerting an inner span which was clicked that had no id. For other cases of alerting 'divId' this is because the span real estate did not cover that area. To know span real estate, inspect the element and look at its highlihgt. Always remember the inner most span clicked will be the event.target. See it alerting the sub spans here http://jsfiddle.net/8t9cqyqd/1/ – AmmarCSE Jun 11 '15 at 17:26
  • @AmmarCSEI was just about to come post that I had the ID's on the wrong spans!! Thanks for helping me with this! – Doc Holiday Jun 11 '15 at 17:28
  • 1
    This is exactly what I needed. Thanks :) – MatthewSzurkowski Jul 19 '20 at 05:31
4

If the user clicked on a node that was a child of the element the user wanted to test e.target will be a different node. The sensible way to check this nowadays is to listen at the document level and iterate the path (or use some delegation library, of which there are many):

Add one event listener to the document:

const isOnId = (path,id) => path.some(element => element.id === id);

document.addEventListener('click',function(e) {
  if(isOnId(e.path,'two')) {
    //you clicked on or in element with an id two
  } else {
    //you clicked on something else
  }
});
Adam Jenkins
  • 51,445
  • 11
  • 72
  • 100
2

Adam's answer is correct and saves a lot of headaches. However there's a better and easiest way to acieve this. Please check this answer

Makes use of Event.currentTarget and it goes like this:

<ul>
  <li class="list_item" data-mydata="hello there!">
    <img src="..." alt="" width="50", height="50">
  </li>
  <li class="list_item" data-mydata="hello world">
    <img src="..." alt="" width="50", height="50">
  </li>
</ul>

<script>
  const items = document.querySelectorAll(".list_item");
  items.forEach(node => {
    node.addEventListener("click", e => {
      let myvalue = e.currentTarget.dataset.mydata;
      console.log(myvalue); //hello there! || hello world It depends on which element the user has clicked
    })
  })
</script>

I hope this is useful

CubeInTheBox
  • 56
  • 1
  • 6
2

Since I do not have enough credits to comment, adding a new answer.

Unlike the answer shared by @CubeInTheBox, I think leveraging the concept of event capturing/bubbling for the respective element makes for a better implementation rather than adding an event listener to each of the target elements. For the example shared above, the alternative would be:

 <ul>
     <li class="list_item" data-mydata="hello there!">
         <img src="..." alt="" width="50", height="50">
     </li>
     <li class="list_item" data-mydata="hello world">
        <img src="..." alt="" width="50", height="50">
     </li>
 </ul>
 
 <script>
     const parentElement = document.querySelector('ul');
     parentElement.addEventListener('click', e => {
         // If you want to add the listener on li alone and not on image
         if (e.target.className === 'list_item') {
             const myvalue = e.target.dataset.mydata;
             console.log(myvalue);
         }
     });
 </script>

NOTE that e.currentTarget wouldn’t work for this case, as it would return the parent ul to which the event is bound.

ManjuRam
  • 21
  • 2