Home > Back-end >  Javascript event delegation with unknown selector and children
Javascript event delegation with unknown selector and children

Time:01-08

I have a dynamic selector (linkTrigger) which is supposed to capture click on element. I dont know what linkTrigger might be and dont know if it will have some children. When I used jQuery everything was fine.

If you click on the first green rectangle (not on numbers part), you will see all 3 handlers working as expected, but if you click on numbers in first green rectangle, only jQuery and javascript2 handlers are working, again as expected, because clicking on span in green box does not satisfy following condition:

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

I cant use css point-events none on children I dont want to be clicked on because I dont know what linkTrigger is, neither I want to mess with its contents.

and the problem is javascript2 handler is not dynamic, meaning I have to add this handler to every new ".a" box I add inside dom later.

Is there a better solution to all this?

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 >

  <div  data-id="0">
    <div >
      <div ><span>657567645</span></div>
    </div>
  </div>

  <div  data-id="1">
    <div >
      <div ></div>
    </div>
  </div>

</div>

CodePudding user response:

event.target is what you clicked on exactly. So when you click on the span in the element, you are getting the span, not the parent element.

So to get the click on the span to register, you can use closest() like you do to get the 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;
  
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div >

  <div  data-id="0">
    <div >
      <div ><span>657567645</span></div>
    </div>
  </div>

  <div  data-id="1">
    <div >
      <div ></div>
    </div>
  </div>

</div>

  • Related