MattHamer5
MattHamer5

Reputation: 1491

Add class to multiple of the same elements individually

I have a long list of team members; when a user clicks a CTA on an individual member, a class is added to a modal box that sets it visible. However, currently every single modal window opens at the same time as they're all using the same classes.

I am wondering if it's possible to look to add the new class to the specific team member that was pressed, I know this is possible through giving each their own class and having multiple of the same jQuery functions - but this isn't really a solution I want to go down as there are a lot, and more will be added in the future (meaning I'll have to update the Js code for them).

Note: I'm using WordPress so am able to use PHP variables and the like.

$('.modal-toggle').on('click', function(e) {
  e.preventDefault();
  $('.modal').toggleClass('visible');
});
.main {
  position:relative;
}

article {
  background: red;
  position: relative;
  border-top: 2px solid red;
  display: flex;
  align-items: center;
  margin-bottom: 20px;
  width: 100%;
  height: 180px;
  }

img {
  height: auto;
  width: 180px;
}
.content {
  padding: 30px 35px;
}
h3 {
  font-weight: 400;
  margin-bottom: 10px;
  text-decoration: underline;
  font-size: 22pt;
  line-height: 28pt;
}
& > span {
  font-style: italic;
}
aside {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 25px;
}   
div.button {
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: $red;
  width: 35px;
  height: 35px;
}
    
 
.modal {
  position: absolute;
  z-index: 10;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  visibility: hidden;
}
.modal-overlay {
  position: fixed;
  z-index: 5;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.3);
  visibility: hidden;
  opacity: 0;
  transition: visibility 0s linear 0.3s, opacity 0.3s;
}
.modal.visible {
  visibility: visible;
}
.modal.visible .modal-overlay {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}
.modal.visible .modal-window {
  transform: translate(-50%, -50%);
  opacity: 1;
}
.modal-window {
  position: absolute;
  z-index: 11;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -100%);
  opacity: 0;
  transition: all 0.3s 0.15s;
  background: $white;
  border-top: 2px solid red;
  width: 900px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">

  <article class="team-member filter-result result-1">
    <img src="https://via.placeholder.com/85" alt="" />
    <div class="content">
      <h3>Name</h3>
      <aside>
        <div class="modal-toggle button" href="#">CLICK</div>
      </aside>
    </div>
  </article>
  <div class="modal">
    <div class="modal-overlay modal-toggle"></div>
    <div class="modal-window">
      <h1>Lorem Ipsum</h1>
    </div>
  </div>
  
  <article class="team-member filter-result result-2">
    <img src="https://via.placeholder.com/85" alt="" />
    <div class="content">
      <h3>Name</h3>
      <aside>
        <div class="modal-toggle" href="#">CLICK</div>
      </aside>
    </div>
  </article>
  <div class="modal">
    <div class="modal-overlay modal-toggle"></div>
    <div class="modal-window">
      <h1>Lorem Ipsum</h1>
    </div>
  </div>
  
  <article class="team-member filter-result result-3">
    <img src="https://via.placeholder.com/85" alt="" />
    <div class="content">
      <h3>Name</h3>
      <aside>
        <div class="modal-toggle" href="#">CLICK</div>
      </aside>
    </div>
  </article>
  <div class="modal">
    <div class="modal-overlay modal-toggle"></div>
    <div class="modal-window">
      <h1>Lorem Ipsum</h1>
    </div>
  </div>  
  
</div>

Upvotes: 0

Views: 50

Answers (2)

BenTheHumanMan
BenTheHumanMan

Reputation: 327

Quick solution is to place .modal in the same article parent of modal-toggle. This way you can adjust your listener to target the .modal corresponding to the .modal-toggle that was clicked.

 $('.modal-toggle').on('click', function(e) {
   e.preventDefault();
   //this way
  $(this).siblings('.modal').toggleClass('visible');
   // or this way or other ways too
  $(this).parent().find('.modal').toggleClass('visible');
 });

Upvotes: 2

T.J. Crowder
T.J. Crowder

Reputation: 1075755

Yes, you can traverse the DOM to find the modal:

$('.modal-toggle').on('click', function(e) {
    e.preventDefault();
    $(this).closest("article").next().toggleClass('visible');
});

$(this) gets a jQuery wrapper for just the element that was clicked, .closest("article") finds its wrapping article element, and .next() goes to the element after it (the modal).

It would be better if the article and the modal were both in the same wrapper element because using .next() is a bit fragile (what if you add an element between the article and the modal?). Then you could do .closest("the-container").find(".modal"). If you can't do that, you can mitigate it slightly by using .nextAll(".modal").first() instead:

$('.modal-toggle').on('click', function(e) {
    e.preventDefault();
    $(this).closest("article").nextAll(".modal").first().toggleClass('visible');
});

The jQuery object from .nextAll is in order from the nearest matching following sibling to the furthers, so first reliably gets the first one.

This is all covered in the traversing section of the jQuery API documentation, which is very thorough.

Upvotes: 3

Related Questions