Check if element has the provided parent in jQuery selector

Viewed 49

Say I have this HTML:

<div id="knownid">
  <div class="foo">
    <ul>
      <li><a><span custom-attr="custom attribute 1"></span></a></li>
      <li><a><span custom-attr="custom attribute 2"></span></a></li>
      <li><a><span custom-attr="custom attribute 3"></span></a></li>
    </ul>
  </div>
</div>

My issue is that in order to create a click event for the a > span elements, with the custom-attr attribute, I'd normally do:

$('span[custom-attr]').on('click', function(e){
// ...
});

However, that would create an event on EVERY element with that attribute name, but how would I make it so that it would only create a click event if it's a child of the knownid ID?

$('div[id="knownid"] > div > ul > li > a > span').on('click', function(e){
// ...
});

I'd like to avoid this long selector.

3 Answers

Use an id selector and your attribute selector as descendant

$('#knownid span[custom-attr]').click(function(){
   console.log('known id clicked', this.textContent)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="knownid">
  <div class="foo">

    <h3>Inside knownId</h3>
    <ul>
      <li><a><span custom-attr="custom attribute 1">One</span></a></li>
      <li><a><span custom-attr="custom attribute 2">Two</span></a></li>
      <li><a><span custom-attr="custom attribute 3">Three</span></a></li>
    </ul>
  </div>
</div>

<h3> Outside knownId</h3>

<ul>
  <li><a><span custom-attr="custom attribute 1">One</span></a></li>
  <li><a><span custom-attr="custom attribute 2">Two</span></a></li>
  <li><a><span custom-attr="custom attribute 3">Three</span></a></li>
</ul>

You can use onclick event on each span to achieve what you need.

Example:

function clicked(el) {
  alert(el.getAttribute('custom-attr'));
}
span {
  cursor: pointer;
}
<div id="knownid">
  <div class="foo">
    <ul>
      <li><a><span onclick="clicked(this)" custom-attr="custom attribute 1">1</span></a></li>
      <li><a><span onclick="clicked(this)" custom-attr="custom attribute 2">2</span></a></li>
      <li><a><span custom-attr="custom attribute 3">3 (There's no click event)</span></a></li>
    </ul>
  </div>
</div>

Best approach for performance oriented code is that listen event on parent node and if attribute exist do your job.

I have modified HTML, you can use it as you want:-

HTML

let ele = document.querySelector(".foo");
      ele.addEventListener('click', event => {
          if(event.target.dataset.attr){
            console.log(event.target.dataset.attr)
          }
      })
<div id="knownid">
      <div class="foo">
        <ul>
          <li><a><span data-attr="custom1">1</span></a></li>
          <li><a><span data-attr="custom2">2</span></a></li>
          <li><a><span data-attr="custom3">3</span></a></li>
        </ul>
      </div>
    </div>

Related