TransWikia.com

How do I target the nearest div of a class with this nested HTML?

Stack Overflow Asked by m0a on December 9, 2021

I have a structure like so:

<header class="entry-header">
    <div class="entry-before-title">
    <h3 class="entry-title">
        <div class="playTag">
            <img/>
        </div>
        </h3>
        </div>
</header>
<div class="entry-summary"></div>
<footer>
    <p class="entry-byline"></p>
</footer>

And I have code for the playTag class which is trying to toggle margin-left of entry-byline:

$('.playTag').click(function() {            
        $(this).parent().parent().nextAll('.entry-byline').css({marginLeft:'200px'});
        return false;
});

My problem is that this is not successfully targeting the entry-byline nearest to playTag. (It’s not targeting an entry-byline at all actually). Can I please get help with targeting the nearest entry-byline successfully in this click code?

2 Answers

I'd suggest working with a delegate listener so it also works for dynamically added elements.

Here's the vanilla JS version:

document.addEventListener('click', function(event) {
  if (event.target.matches('.playTag')) {
    const byLine = event.target
      .closest('.entry-header')
      .nextElementSibling
      .nextElementSibling
      .querySelector('.entry-byline');
    byLine.classList.toggle('ml-200');
  }
  return false;
});
.ml-200 {
  margin-left: 200px;
}
<header class="entry-header">
  <div class="entry-before-title">
    <h3 class="entry-title">
      <div class="playTag">
        playTag
      </div>
    </h3>
  </div>
</header>
<div class="entry-summary"></div>
<footer>
  <p class="entry-byline">entry-byline</p>
</footer>
<header class="entry-header">
  <div class="entry-before-title">
    <h3 class="entry-title">
      <div class="playTag">
        playTag
      </div>
    </h3>
  </div>
</header>
<div class="entry-summary"></div>
<footer>
  <p class="entry-byline">entry-byline</p>
</footer>

Answered by connexo on December 9, 2021

Your DOM traversal isn't quite right. You need to find the parent header to the clicked .playTag, which can be done more simply and robustly using closest() instead of chaining parent() calls.

From there you can retrieve the sibling footer element and then find() the .entry-byline within that.

I would also suggest using CSS classes to amend the styling through JS. This is to avoid having to place CSS logic within JS, which is a violation of the Separation of Concerns principle.

$('.playTag').click(function() {
  $(this).closest('header').siblings('footer').find('.entry-byline').toggleClass('foo');
});
.foo { margin-left: 200px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header class="entry-header">
  <div class="entry-before-title">
    <h3 class="entry-title">
      <div class="playTag">
        playTag
        <img/>
      </div>
    </h3>
  </div>
</header>
<div class="entry-summary">entry-summary</div>
<footer>
  <p class="entry-byline">entry-byline</p>
</footer>

Answered by Rory McCrossan on December 9, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP