1
votes

I am using a jQuery accordion with a collapse/hide all option that works well with exactly one instance. As soon as a second (or even more) instance(s) is/are being put in, the script toggles all panels on all accordions, since it doesn’t 'know' it should differentiate between different accordions for toggling. Is there an easy way of getting the script to recognise on what accordion the toggle button is being used upon? Possibly through a temporary ID?

HTML

<h2>First accordion</h2>
<div class="accordion">
    <a class="toggle_open" id="button_toggle">Toggle all</a>
    <h5>Which is the first question?</h5>
    <div class="accordion_text">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima adipisci natus quas quod doloremque, dolore aliquid, blanditiis eligendi nemo cum tenetur earum. Suscipit ea enim consequuntur vero totam, impedit veritatis.</p>
    </div>
    <h5>What is the second question?</h5>
    <div class="accordion_text">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima adipisci natus quas quod doloremque, dolore aliquid, blanditiis eligendi nemo cum tenetur earum. Suscipit ea enim consequuntur vero totam, impedit veritatis.</p>
    </div>
    <h5>And the third?</h5>
    <div class="accordion_text">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima adipisci natus quas quod doloremque, dolore aliquid, blanditiis eligendi nemo cum tenetur earum. Suscipit ea enim consequuntur vero totam, impedit veritatis.</p>
    </div>
</div>

<h2>Second accordion</h2>
<div class="accordion">
    <a class="toggle_open" id="button_toggle">Toggle all</a>
    <h5>Which is another question?</h5>
    <div class="accordion_text">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima adipisci natus quas quod doloremque, dolore aliquid, blanditiis eligendi nemo cum tenetur earum. Suscipit ea enim consequuntur vero totam, impedit veritatis.</p>
    </div>
    <h5>What is the next-to-another question?</h5>
    <div class="accordion_text">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima adipisci natus quas quod doloremque, dolore aliquid, blanditiis eligendi nemo cum tenetur earum. Suscipit ea enim consequuntur vero totam, impedit veritatis.</p>
    </div>
    <h5>Tell me about the last!</h5>
    <div class="accordion_text">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima adipisci natus quas quod doloremque, dolore aliquid, blanditiis eligendi nemo cum tenetur earum. Suscipit ea enim consequuntur vero totam, impedit veritatis.</p>
    </div>
</div>

CSS

.accordion {
  .accordion_text {
    display: none;
  }
}

JS

    jQuery('document').ready(function(){

    /* Accordion for pages */

    var headers = jQuery('.accordion h5');
    var contentAreas = jQuery('.accordion_text').hide();
    var expandLink = jQuery('.toggle_open');

    // add the accordion functionality
    headers.click(function() {
        var panel = jQuery(this).next();
        var isOpen = panel.is(':visible');

        // open or close as necessary
        panel[isOpen? 'slideUp': 'slideDown']()
            // trigger the correct custom event
            .trigger(isOpen? 'hide': 'show');

        // stop the link from causing a pagescroll
        return false;
    });

    // hook up the expand/collapse all
    expandLink.click(function(){
        var isAllOpen = jQuery(this).data('isAllOpen');

        contentAreas[isAllOpen? 'hide': 'show']()
            .trigger(isAllOpen? 'hide': 'show');
    });

    // when panels open or close, check to see if they're all open
    contentAreas.on({
        // whenever we open a panel, check to see if they're all open
        // if all open, swap the button to collapser
        show: function(){
            var isAllOpen = !contentAreas.is(':hidden');   
            if(isAllOpen){
                expandLink.text('Hide all')
                    .data('isAllOpen', true);
            }
        },
        // whenever we close a panel, check to see if they're all open
        // if not all open, swap the button to expander
        hide: function(){
            var isAllOpen = !contentAreas.is(':hidden');
            if(!isAllOpen){
                expandLink.text('Collapse all')
                .data('isAllOpen', false);
            } 
        }
    });
}); 

You can find this code example at http://codepen.io/enoversum/pen/EKQmeL

1

1 Answers

1
votes

The following might help you.

You can use closest() function to get the parent .accordion and then make the functions take effect on the children only.

jQuery('document').ready(function() {

  /* Accordion for pages */

  var headers = jQuery('.accordion h5');
  var contentAreas = jQuery('.accordion_text').hide();
  var expandLink = jQuery('.toggle_open');

  // add the accordion functionality
  headers.click(function() {
    var panel = jQuery(this).next();
    var isOpen = panel.is(':visible');

    // open or close as necessary
    panel[isOpen ? 'slideUp' : 'slideDown']()
      // trigger the correct custom event
      .trigger(isOpen ? 'hide' : 'show');

    // stop the link from causing a pagescroll
    return false;
  });

  // hook up the expand/collapse all
  expandLink.click(function() {
    var isAllOpen = jQuery(this).data('isAllOpen');

    $(this).closest('.accordion').find(contentAreas)[isAllOpen ? 'hide' : 'show']()
      .trigger(isAllOpen ? 'hide' : 'show');
  });

  // when panels open or close, check to see if they're all open
  contentAreas.on({
    // whenever we open a panel, check to see if they're all open
    // if all open, swap the button to collapser
    show: function() {
      var isAllOpen = !$(this).is(':hidden');
      if (isAllOpen) {
        $(this).closest('.accordion').find('.toggle_open').text('Hide all')
          .data('isAllOpen', true);
      }
    },
    // whenever we close a panel, check to see if they're all open
    // if not all open, swap the button to expander
    hide: function() {
      var isAllOpen = !$(this).is(':hidden');
      if (!isAllOpen) {
        $(this).closest('.accordion').find('.toggle_open').text('Collapse all')
          .data('isAllOpen', false);
      }
    }
  });
});
.accordion {
  .accordion_text {
    display: none;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<h2>First accordion</h2>
<div class="accordion">
  <a class="toggle_open" id="button_toggle">Toggle all</a>
  <h5>Which is the first question?</h5>
  <div class="accordion_text">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima adipisci natus quas quod doloremque, dolore aliquid, blanditiis eligendi nemo cum tenetur earum. Suscipit ea enim consequuntur vero totam, impedit veritatis.</p>
  </div>
  <h5>What is the second question?</h5>
  <div class="accordion_text">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima adipisci natus quas quod doloremque, dolore aliquid, blanditiis eligendi nemo cum tenetur earum. Suscipit ea enim consequuntur vero totam, impedit veritatis.</p>
  </div>
  <h5>And the third?</h5>
  <div class="accordion_text">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima adipisci natus quas quod doloremque, dolore aliquid, blanditiis eligendi nemo cum tenetur earum. Suscipit ea enim consequuntur vero totam, impedit veritatis.</p>
  </div>
</div>

<h2>Second accordion</h2>
<div class="accordion">
  <a class="toggle_open" id="button_toggle">Toggle all</a>
  <h5>Which is another question?</h5>
  <div class="accordion_text">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima adipisci natus quas quod doloremque, dolore aliquid, blanditiis eligendi nemo cum tenetur earum. Suscipit ea enim consequuntur vero totam, impedit veritatis.</p>
  </div>
  <h5>What is the next-to-another question?</h5>
  <div class="accordion_text">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima adipisci natus quas quod doloremque, dolore aliquid, blanditiis eligendi nemo cum tenetur earum. Suscipit ea enim consequuntur vero totam, impedit veritatis.</p>
  </div>
  <h5>Tell me about the last!</h5>
  <div class="accordion_text">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima adipisci natus quas quod doloremque, dolore aliquid, blanditiis eligendi nemo cum tenetur earum. Suscipit ea enim consequuntur vero totam, impedit veritatis.</p>
  </div>
</div>