简体   繁体   中英

jQuery stop all elements with the same class opening on click when element is a parent

I have written this function as a click event callback on a button, which when clicked toggles the class to provide a dropdown. This works if the dropdown element is next, but not if the element is outside of the clicked element's parent. The problem is is that I have multiple buttons on the same page that have the same functionality, and they all fire when one is clicked:

https://jsfiddle.net/21xj96up/7/

 $('.direction-button').on('click', function() { $(this).next('.direction-dropdown').toggleClass('active'); }); 
 .fade-in { visibility: hidden; opacity: 0; transition: visibility 0s, opacity .3s ease-in-out, all .3s ease-in-out; } .active { visibility: visible; opacity: 1; transform: translate(0, 0); } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js"></script> <div class="contact-card"> <div class="contact-directions"> <a href="#" title="#" class="direction-button link-button animate-after">Directions</a> </div> <!-- end .contact-directions --> <div class="contact-info"></div> <!-- .contact-info --> <div class="contact-partner"></div> <!-- end .contact-info --> </div> <!-- end .contact-card --> <div class="direction-dropdown fade-in"> <p>Display #1</p> </div> <div class="contact-card"> <div class="contact-directions"> <a href="#" title="#" class="direction-button link-button animate-after">Directions</a> </div> <!-- end .contact-directions --> <div class="contact-info"></div> <!-- .contact-info --> <div class="contact-partner"></div> <!-- end .contact-info --> </div> <!-- end .contact-card --> <div class="direction-dropdown fade-in"> <p>Display #1</p> </div> 

Any and all help greatly appreciated :)

Check if it has a "parent-container" named contact-card if so take next from that one else do what you did already:

https://jsfiddle.net/21xj96up/12/

$('.direction-button').on('click', function(){
    if( 1 === $(this).closest('.contact-card').next('.direction-dropdown').length) {
        $(this).closest('.contact-card').next('.direction-dropdown').toggleClass('active');
    } else {
        $(this).next('.direction-dropdown').toggleClass('active');
    }
});

Update with "shorter" version https://jsfiddle.net/21xj96up/21/ Now this is even a bit better cause we use the same

$(this).closest('.contact-card').next('.direction-dropdown')

twice. So we can save it to a variable and then use the variable.

$('.direction-button').on('click', function(){
    var parentElement = $(this).closest('.contact-card').next('.direction-dropdown');
    if( 1 === parentElement.length) {
        parentElement.toggleClass('active');
    } else {
        $(this).next('.direction-dropdown').toggleClass('active');
    }
});

I wold suggest this code, since selection conditions are not the same :

$('.direction-button').on('click', function(){
  var b = $(this);
  if(b.parents('div').length>0) {
        b.parents('div').next('.direction-dropdown').toggleClass('active');
  } else {
  b.next('.direction-dropdown').toggleClass('active');
  }   
});

In cases like those, when there is an inconsistent element-hierarchy, you can work with data-attributes and IDs, which makes toggler and content hierarchy-independent.

Attribute for the Toggler:

data-toggle-target="display1"

ID for the target

`id="display1"`

The jQuery-Code

$( '#' + $(this).attr('data-toggle-target')).toggleClass('active');

https://jsfiddle.net/s57zk5hb/

On your code, since $(this) is inside the context of $('.direction-button') , this really means the "direction-button". There is no next "direction-dropdown" present for "direction-button" in the same level of "direction-button".

div
    div
        direction button
        <it looks for the item here>
    /div
/div
<item is actually here>

you can try,

$(this).parent().parent().next().toggleClass('active');

to achieve the functionality in the second case.

It would obviously be better if the structure were consistent. Assuming that you have little control over that, though, would mean you also have little control over additional classes or ids that would provide a better solution. In light of this, you can find the index of the current button in a collection of all the buttons and dropdowns and find the next dropdown in that list.

var idx = $(this).index('.direction-button, .direction-dropdown');

$('.direction-button, .direction-dropdown')
    .slice(idx)
    .filter('.direction-dropdown')
    .first()
    .toggleClass('active');

Like so: https://jsfiddle.net/j7h32w90/1/

This will work in nearly any DOM structure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM