Home  >  Q&A  >  body text

Javascript event delegate with unknown selector and children

I have a dynamic selector (linkTrigger) which is supposed to capture clicks on an element. I don't know what linkTrigger might be or if it will have some children. When I use jQuery everything is fine.

If you click on the first green rectangle (not the number part) you will see all 3 handlers working as expected, but if you click on the number in the first green rectangle only jQuery and javascript2 The handler is working, again as expected, because clicking the span in the green box does not meet the following conditions:

if (e.target.classList.contains(linkTrigger.substring(1))) {

I can't use css point-events none with children I don't want to be clicked because I don't know what linkTrigger is and I don't want to mess with its content.

The problem is that the javascript2 handler is not dynamic, which means I have to add this handler to every new ".a" box I add later inside the dom.

Is there a better solution?

var linkTrigger = '.c'

//jquery works fine and its live

$('.wrap').on('click', linkTrigger, function(e) {

  var parent = $(this).closest('.a'),
    id = parent.attr('data-id')

  console.log('jquery: ' + id)

})

//javscript works but not if we click on child (number span inside green rectangle) and its live. I cant use **css point-events none** on children I dont want to be clicked because I dont knwo what **linkTrigger** is, neither I want to mess with its contents.

document.querySelector('.wrap').addEventListener('click', function(e){

  if (e.target.classList.contains(linkTrigger.substring(1))) {
    var parent = e.target.closest('.a'),
      id = parent.getAttribute('data-id')

    console.log('js: ' + id)
  }

})

//javscript2 works but its not live, meaning if I add more ".a" containers I have to attach this function call to each item.

document.querySelectorAll(linkTrigger).forEach(function(el){

   el.addEventListener('click', function(e){

       var parent = e.target.closest('.a'),
      id = parent.getAttribute('data-id')

        console.log('js2: ' + id)

   })
})
.a{
  
  width:300px;
  height:300px;
  background:red;
  margin:1px;
  
}
.b{
  
  width:200px;
  height:200px;
  background:blue;
  
}
.c{
  
  width:100px;
  height:100px;
  background:green;
  
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="wrap">

  <div class="a" data-id="0">
    <div class="b">
      <div class="c"><span>657567645</span></div>
    </div>
  </div>

  <div class="a" data-id="1">
    <div class="b">
      <div class="c"></div>
    </div>
  </div>

</div>

P粉187677012P粉187677012179 days ago436

reply all(1)I'll reply

  • P粉022285768

    P粉0222857682024-04-04 13:37:49

    event.target is exactly what you clicked on. So when you click on a span within an element you get the span, not the parent element.

    So to get clicks on a span to be registered, you can use closest() just like you would get an anchor tag.

    var linkTrigger = '.c'
    
    //jquery works fine and its live
    
    $('.wrap').on('click', linkTrigger, function(e) {
    
      var parent = $(this).closest('.a'),
        id = parent.attr('data-id')
    
      console.log('jquery: ' + id)
    
    })
    
    
    
    document.querySelector('.wrap').addEventListener('click', function(e){
    
      if (e.target.closest(linkTrigger)) {
        var parent = e.target.closest('.a'),
          id = parent.getAttribute('data-id')
    
        console.log('js: ' + id)
      }
    
    })
    .a{
      
      width:300px;
      height:300px;
      background:red;
      margin:1px;
      
    }
    .b{
      
      width:200px;
      height:200px;
      background:blue;
      
    }
    .c{
      
      width:100px;
      height:100px;
      background:green;
      
    }
    sssccc
    
    657567645

    reply
    0
  • Cancelreply