1

I have the HTML below:

<!DOCTYPE html>
        <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
        <head>
            <meta charset="utf-8" />
            <title></title>
        </head>
        <body>
            <div>
                <section>
                    <a>first</a>
                    <a>second</a>
                </section>
            </div>
            <section>
                <a>third</a>
                <a>fourth</a>
            </section>
            <section>
                <div>
                    <a>fifth</a>
                    <a>sixth</a>
                </div>
            </section>
        <script src="ex-2-a.js"></script>
        <!--<script src="ex-2-b.js"></script>-->
        </body>
        </html>

I'm looking to add only one event listener to the whole document that would catch only 'a' tags that have a 'div' as ancestors. This means that if I click first, second, fifth and sixth I would get a message saying "cool".

Any ideas on that matter since there's no id and working with only tagnames?

1
  • well if you want one listener, than you need to look into event delegation. Commented May 21, 2018 at 16:23

2 Answers 2

1

Thanks to @Scott Marcus for helping out. I submitted the answer and it worked. I also found a new approach using .closest(). let me know your thoughts

document.addEventListener('click',(e)=>{
let currElm = e.target;
if (currElm.closest('div')) {
  console.log(currElm);
 }
});
Sign up to request clarification or add additional context in comments.

Comments

0

Using "event delegation" (setting an event handler on an element high up in the DOM tree and allowing events from elements lower in the tree to bubble up and be caught), we can set up just one event handler at the body level and then we can check the actual source of the bubbled event against a collection of elements that match your criteria.

See inline comments for more:

// Set the event listener at the <body> and wait for other
// events to bubble up to it.
document.body.addEventListener("click", function(evt){
  // Get an array of all the <a> elements that are descendants of <div> elements
  let matches = Array.prototype.slice.call(document.querySelectorAll("div a"));
  
  // Test to see if array contains the one that was clicked
  if(matches.includes(evt.target)){
    console.log("You clicked an <a> that is a descendant of a <div>!");
  }
});
<div>
  <section>
    <a>first</a>
    <a>second</a>
  </section>
</div>

<section>
  <a>third</a>
  <a>fourth</a>
</section>

<section>
  <div>
    <a>fifth</a>
    <a>sixth</a>
  </div>
</section>

5 Comments

@YannB Actually, I just thought of a more simplified approach. I will update the answer.
document.addEventListener('click',(e)=>{ let divA = document.querySelectorAll('div a'); divA.forEach((evt)=>{ if (evt === e.target) { console.log(e.target); } }) });
here's what I did
@YannB See updated answer. We don't even need the loop.
Ohh wow I didn't even know about the include. Thanks a bunch!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.