0

I reused some of the code from a site and made a shopping cart accordion module. I have the whole code as a pen on codepen. Here is the link for the pen: http://codepen.io/applecool/pen/YXaJLa

<div class="summary">
 <button class="expand btn btn-lg">Collapse All for Summary</button>
</div>

HTML for button above : I added a button at the bottom called as "Collapse All for Summary". The purpose of this button: When a user clicks on the button, it should open all the accordion tabs and when clicked on it again, should close the accordion tabs. [i.e., a typical toggle functionality].

I wrote a small javascript function to make the accordion tabs toggle but it is very buggy. It does the job perfectly but the problem is, once I click on the button, the general click on the tab doesn't work. i.e., when you open up the codepen and click on the accordion tab, it smoothly opens up and closes. But after adding the toggle button functionality, you fire up the page, click on the "Collapse All for Summary" button, the accordion tabs work fine. Now, when you try to click on any of the closed or opened accordion tabs, the tab neither opens nor closes. I think the problem is definitely with the changing of classes which I am doing in the javascript with the CSS.

Script:

$('.expand').click(function(){

   if($('.accordionItem.is-collapsed').css('max-height')== '0px'){
    $('.accordionItem.is-collapsed').css({
      'max-height': '900px'
     });

   }else if($('.accordionItem.is-collapsed').css('max-height')== '900px'){
    $('.accordionItem.is-collapsed').css({
      'max-height': '0px'
     });

    }

});

CSS specific to the above script and the button div:

 .accordionItem.is-collapsed{
   max-height: 0px;
  }

Any help on this would be hugely appreciated. If there is any work around, I can gladly follow that too. Please let me know what idiotic mistake I am doing here. :)

Thank you.

Cheers, .SH

ShellZero
  • 3,377
  • 7
  • 33
  • 49
  • You are using `.toggleClass()` incorrectly. It does not take two strings as arguments. http://api.jquery.com/toggleclass/ – Andrew Mairose Aug 18 '15 at 13:34
  • Thanks for pointing out Andrew. I removed it. It actually doesn't do anything. I was trying out something before and I forgot to remove that buggy dumb line of code. – ShellZero Aug 18 '15 at 13:37
  • 1
    I would look into jquery's `.slideToggle()`. http://api.jquery.com/slideToggle/ – Andrew Mairose Aug 18 '15 at 13:39
  • It will handle all this for you. `$('.accordionItem').slideToggle();` – Andrew Mairose Aug 18 '15 at 13:40
  • 1
    Actually, it looks like you already have a function in your javascript to toggle these. `setAccordionAria` – Andrew Mairose Aug 18 '15 at 13:49
  • This question will help you. it has a button to expand all and collapse all http://stackoverflow.com/questions/12843418/jquery-ui-accordion-expand-collapse-all – Ganesh Yadav Aug 18 '15 at 13:51
  • @locateganesh, unfortunately, the OP's accordion is a custom implementation, not a jQuery UI accordion – Andrew Mairose Aug 18 '15 at 13:57
  • Thank you. I will try them out. – ShellZero Aug 18 '15 at 13:59
  • 1
    @ShellZero I'm guessing you found this custom accordion implementation somewhere and popped it in your code. What I would do is try to understand how the accordion actually works, that way you can implement a collapse all using the functionality already implemented in your accordion. – Andrew Mairose Aug 18 '15 at 14:00
  • @AndrewMairose Yes, I did. I mentioned that in my question itself. I did look at the existing js file. Was little bit confused, so tried to write my own script. Failed :P Will take an another look. – ShellZero Aug 18 '15 at 14:03

2 Answers2

1

I edited your code a bit to include the expand/collapse all functionality. I think it's sloppy and you should clean it up before implementing, but it gets the job done.

The additions utilize arrays to loop over either one item or all items based on whether you click an individual item or the expand/collapse all button. The good thing about this is that it's the same as the original code, but can handle toggling the classes on multiple items.

I put some comments in the JavaScript that explains more.

//uses classList, setAttribute, and querySelectorAll
//if you want this to work in IE8/9 youll need to polyfill these
(function() {
  var d = document,
    accordionToggles = d.querySelectorAll('.js-accordionTrigger'),
    setAria,
    setAccordionAria,
    switchAccordion,
    touchSupported = ('ontouchstart' in window),
    pointerSupported = ('pointerdown' in window);

  skipClickDelay = function(e) {
    e.preventDefault();
    e.target.click();
  }

  setAriaAttr = function(el, ariaType, newProperty) {
    el.setAttribute(ariaType, newProperty);
  };
  setAccordionAria = function(el1, el2, expanded) {
    switch (expanded) {
      case "true":
        setAriaAttr(el1, 'aria-expanded', 'true');
        setAriaAttr(el2, 'aria-hidden', 'false');
        break;
      case "false":
        setAriaAttr(el1, 'aria-expanded', 'false');
        setAriaAttr(el2, 'aria-hidden', 'true');
        break;
      default:
        break;
    }
  };
  //function
  switchAccordion = function(e) {
    e.preventDefault();
    
    var questions = [],
        answers = [];
    
    //if expand-all button is clicked, then push all questions and answers into respective arrays
    if($(e.target).hasClass('expand')) {
      $('.accordion-title').each( function(index) {
        questions.push(this);
        answers.push(this.parentNode.nextElementSibling);
      });
    }
    //else if an individual item is clicked, then push its question and answer into respective arrays
    else {
      questions.push(e.target);
      answers.push(e.target.parentNode.nextElementSibling);
    }
    
    //original code wrapped in "for" loop to handle single item or all items
    for (var i = 0, len = questions.length; i < len; i++) {
      var thisQuestion = questions[i];
      var thisAnswer = answers[i];
      
      if (thisAnswer.classList.contains('is-collapsed')) {
        setAccordionAria(thisQuestion, thisAnswer, 'true');
      } else {
        setAccordionAria(thisQuestion, thisAnswer, 'false');
      }
      
      thisQuestion.classList.toggle('is-collapsed');
      thisQuestion.classList.toggle('is-expanded');
      thisAnswer.classList.toggle('is-collapsed');
      thisAnswer.classList.toggle('is-expanded');

      thisAnswer.classList.toggle('animateIn');
    }
  };
  for (var i = 0, len = accordionToggles.length; i < len; i++) {
    if (touchSupported) {
      accordionToggles[i].addEventListener('touchstart', skipClickDelay, false);
    }
    if (pointerSupported) {
      accordionToggles[i].addEventListener('pointerdown', skipClickDelay, false);
    }
    accordionToggles[i].addEventListener('click', switchAccordion, false);
  }
  //add listener for the expand-all button
  $('.expand').on('click', switchAccordion);
})();
@import url(http://fonts.googleapis.com/css?family=Libre+Baskerville);
* {
  box-sizing: border-box;
  border-radius: 5px;
}

body {
  font-family: 'Libre Baskerville';
}

.heading-primary {
  font-size: 2em;
  padding: 2em;
  text-align: center;
}

.accordion dl,
.accordion-list {
  border: 1px solid #ddd;
}

.accordion dl:after,
.accordion-list:after {
  content: "";
  display: block;
  height: 1em;
  width: 100%;
  background-color: #099DF6;
}

.accordion dd,
.accordion__panel {
  background-color: #eee;
  font-size: 1em;
  line-height: 1.5em;
}

.accordion p {
  padding: 1em 2em 1em 2em;
}

.accordion {
  position: relative;
  background-color: #eee;
}

.container {
  max-width: 960px;
  margin: 0 auto;
  padding: 2em 0 2em 0;
}

.accordionTitle,
.accordion__Heading {
  background-color: #099DF6;
  /*text-align: center; */
  
  text-indent: 3px;
  font-weight: 700;
  padding: 2em;
  display: block;
  text-decoration: none;
  color: #fff;
  -webkit-transition: background-color 0.5s ease-in-out;
  transition: background-color 0.5s ease-in-out;
  border-bottom: 1px solid #30bb64;
}

.accordionTitle:before,
.accordion__Heading:before {
  content: "+";
  font-size: 1.5em;
  line-height: 0.9em;
  float: left;
  -webkit-transition: -webkit-transform 0.3s ease-in-out;
  transition: transform 0.3s ease-in-out;
}

.accordionTitle:hover,
.accordion__Heading:hover {
  background-color: #38CC70;
}

.accordionTitleActive,
.accordionTitle.is-expanded {
  background-color: #38CC70;
}

.accordionTitleActive:before,
.accordionTitle.is-expanded:before {
  -webkit-transform: rotate(-225deg);
  -ms-transform: rotate(-225deg);
  transform: rotate(-225deg);
}

.accordionItem {
  height: auto;
  overflow: auto;
  max-height: 900px;
  -webkit-transition: max-height 1s;
  transition: max-height 1s;
}

@media screen and (min-width: 48em) {
  .accordionItem {
    max-height: 900px;
    -webkit-transition: max-height 0.5s;
    transition: max-height 0.5s;
  }
}

.accordionItem.is-collapsed {
  max-height: 0;
}

.no-js .accordionItem.is-collapsed {
  max-height: 900px;
}

.animateIn {
  -webkit-animation: accordionIn 0.65s normal ease-in-out both 1;
  animation: accordionIn 0.65s normal ease-in-out both 1;
}

.animateOut {
  -webkit-animation: accordionOut 0.75s alternate ease-in-out both 1;
  animation: accordionOut 0.75s alternate ease-in-out both 1;
}

@-webkit-keyframes accordionIn {
  0% {
    opacity: 0;
    -webkit-transform: scale(0.9) rotateX(-60deg);
    transform: scale(0.9) rotateX(-60deg);
    -webkit-transform-origin: 50% 0;
    transform-origin: 50% 0;
  }
  100% {
    opacity: 1;
    -webkit-transform: scale(1);
    transform: scale(1);
  }
}

@keyframes accordionIn {
  0% {
    opacity: 0;
    -webkit-transform: scale(0.9) rotateX(-60deg);
    transform: scale(0.9) rotateX(-60deg);
    -webkit-transform-origin: 50% 0;
    transform-origin: 50% 0;
  }
  100% {
    opacity: 1;
    -webkit-transform: scale(1);
    transform: scale(1);
  }
}

@-webkit-keyframes accordionOut {
  0% {
    opacity: 1;
    -webkit-transform: scale(1);
    transform: scale(1);
  }
  100% {
    opacity: 0;
    -webkit-transform: scale(0.9) rotateX(-60deg);
    transform: scale(0.9) rotateX(-60deg);
  }
}

@keyframes accordionOut {
  0% {
    opacity: 1;
    -webkit-transform: scale(1);
    transform: scale(1);
  }
  100% {
    opacity: 0;
    -webkit-transform: scale(0.9) rotateX(-60deg);
    transform: scale(0.9) rotateX(-60deg);
  }
}
/*label styles */

.label-style {
  float: left;
  margin-right: 15px;
  padding-top: 5px;
  padding-left: 100px;
}
/* form headings */

.headings {
  text-align: center;
  font-weight: bold;
}
/* button styles */

.button-container {
  text-align: center;
  margin-bottom: 5px;
}
/* position of the hint */

.hint {
  display: inline-block;
  position: relative;
  margin-left: 0.5em;
  margin-top: 0.3em;
}
/* background style for 'i' */

.hint-icon {
  background: #099DF6;
  border-radius: 10px;
  cursor: pointer;
  display: inline-block;
  font-style: normal;
  font-family: 'Libre Baskerville';
  height: 20px;
  line-height: 1.3em;
  text-align: center;
  width: 20px;
}
/* hint icon hover style */

.hint-icon:hover {
  background: #1f8ac9;
}
/* Displays the hint. important! Do not remove. */

.hint:hover .hint-description,
.hint:focus .hint-description {
  display: inline-block;
}
/* position of the hint  */

.hint-description {
  display: none;
  background: #3b3b3b;
  border: 1px solid #099DF6;
  border-radius: 3px;
  font-size: 0.8em;
  color: #ffffff;
  font-weight: bold;
  /*padding: 1em; */
  
  position: absolute;
  left: 30px;
  top: -15px;
  width: 180px;
  height: auto;
}
/* styling for the arrow */

.hint-description:before,
.hint-description:after {
  content: "";
  position: absolute;
  left: -11px;
  top: 15px;
  border-style: solid;
  border-width: 10px 10px 10px 0;
  border-color: transparent #099DF6;
}
/* overlay styling */

.hint-description:after {
  left: -10px;
  border-right-color: #3b3b3b;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Used some part of the code from Chris Wright (http://codepen.io/chriswrightdesign/)'s Pen  -->
<div class="container">
  <h1 class="heading-primary">Accordion Checkout Form Version 0.1 </h1>
  <div class="accordion">
    <dl>
      <!-- description list -->

      <dt>
          <!-- accordion tab 1 - Delivery and Pickup Options -->
          <a href="#accordion1" aria-expanded="false" aria-controls="accordion1" class="accordion-title accordionTitle js-accordionTrigger">Delivery and Pickup Options</a>
        </dt>
      <dd class="accordion-content accordionItem is-collapsed" id="accordion1" aria-hidden="true">
        <p>One can insert a div here and add the product image and the description of the product. Quantity, Cost.</p>
      </dd>
      <!--end accordion tab 1 -->

      <dt>
          <!-- accordion tab 2 - Shipping Info -->
          <a href="#accordion2" aria-expanded="false" aria-controls="accordion2" class="accordion-title accordionTitle js-accordionTrigger">Shipping Information</a>
        </dt>
      <dd class="accordion-content accordionItem is-collapsed" id="accordion2" aria-hidden="true">
        <div class="container-fluid" style="padding-top: 20px;">
          <p class="headings">Shipping Address</p>
          <form class="main-container">
            <div class="row">
              <div class="col-xs-4">
                <label for="fullname" class="label-style">Full Name</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="fullname" class="form-control" placeholder="Enter your full name" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Enter your full name</p>
              </div>
            </div>


            <div class="row">
              <div class="col-xs-4">
                <label for="companyname" class="label-style">Company Name</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="companyname" class="form-control" placeholder="Enter Company Name (optional)" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Enter your Company name</p>
              </div>
            </div>
            <div class="row">
              <div class="col-xs-4">
                <label for="phonenumber" class="label-style">Phone Number</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="phonenumber" class="form-control" placeholder="Enter Phone Number" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">In (555)5555-555 Format</p>
              </div>
            </div>
            <div class="row">
              <div class="col-xs-4">
                <label for="address-line1" class="label-style">Address Line 1</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="address-line1" class="form-control" placeholder="Enter Address" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Address Line 1</p>
              </div>
            </div>
            <div class="row">
              <div class="col-xs-4">
                <label for="address-line2" class="label-style">Line 2</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="address-line2" class="form-control" placeholder="Apt, Suite, Bldg (optional)" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Address Line 2</p>
              </div>
            </div>
            <div class="row">
              <div class="col-xs-4">
                <label for="city" class="label-style">City</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="city" class="form-control" placeholder="Enter City" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Enter your City</p>
              </div>
            </div>
            <div class="row">
              <div class="col-xs-4">
                <label for="state" class="label-style">State</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="state" class="form-control" placeholder="Enter State" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Ex: Indiana as IN</p>
              </div>
            </div>
            <div class="row">
              <div class="col-xs-4">
                <label for="country" class="label-style">Country</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="country" class="form-control" placeholder="Enter Country" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Enter your country</p>
              </div>
            </div>
            <div class="row">
              <div class="col-xs-4">
                <label for="zipcode" class="label-style">Zip Code</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="zipcode" class="form-control" placeholder="Enter Zip Code" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Enter ZipCode.</p>
              </div>
            </div>
            <div class="button-container">
              <button class="btn btn-success" type="submit">Submit</button>
              <button class="btn btn-warning" type="reset">Reset</button>
            </div>
          </form>
        </div>
      </dd>
      <!-- end accordion tab 2 -->

      <dt>
          <!-- accordion tab 3 - Payment Info -->
          <a href="#accordion3" aria-expanded="false" aria-controls="accordion3" class="accordion-title accordionTitle js-accordionTrigger">Payment Information</a>
        </dt>
      <dd class="accordion-content accordionItem is-collapsed" id="accordion3" aria-hidden="true">
        <div class="container-fluid" style="padding-top: 20px;">
          <p class="headings">Billing Information</p>
          <form class="main-container">
            <div class="row">
              <div class="col-xs-4">
                <label for="fullname" class="label-style">Full Name</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="fullname" class="form-control" placeholder="Enter your full name" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Enter your full name</p>
              </div>
            </div>


            <div class="row">
              <div class="col-xs-4">
                <label for="companyname" class="label-style">Company Name</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="companyname" class="form-control" placeholder="Enter Company Name (optional)" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Enter your Company name</p>
              </div>
            </div>
            <div class="row">
              <div class="col-xs-4">
                <label for="phonenumber" class="label-style">Phone Number</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="phonenumber" class="form-control" placeholder="Enter Phone Number" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">In (555)5555-555 Format</p>
              </div>
            </div>
            <div class="row">
              <div class="col-xs-4">
                <label for="address-line1" class="label-style">Address Line 1</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="address-line1" class="form-control" placeholder="Enter Address" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Address Line 1</p>
              </div>
            </div>
            <div class="row">
              <div class="col-xs-4">
                <label for="address-line2" class="label-style">Line 2</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="address-line2" class="form-control" placeholder="Apt, Suite, Bldg (optional)" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Address Line 2</p>
              </div>
            </div>
            <div class="row">
              <div class="col-xs-4">
                <label for="city" class="label-style">City</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="city" class="form-control" placeholder="Enter City" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Enter your City</p>
              </div>
            </div>
            <div class="row">
              <div class="col-xs-4">
                <label for="state" class="label-style">State</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="state" class="form-control" placeholder="Enter State" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Ex: Indiana as IN</p>
              </div>
            </div>
            <div class="row">
              <div class="col-xs-4">
                <label for="country" class="label-style">Country</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="country" class="form-control" placeholder="Enter Country" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Enter your country</p>
              </div>
            </div>
            <div class="row">
              <div class="col-xs-4">
                <label for="zipcode" class="label-style">Zip Code</label>
              </div>
              <div class="form-group col-lg-4">
                <input type="text" id="address-line2" class="form-control" placeholder="Enter Zip Code" required>
              </div>
              <div class="hint">
                <i class="hint-icon">i</i>
                <p class="hint-description">Enter ZipCode.</p>
              </div>
            </div>
            <div class="button-container">
              <button class="btn btn-success" type="submit">Submit</button>
              <button class="btn btn-warning" type="reset">Reset</button>
            </div>
          </form>
        </div>
      </dd>
      <!-- end accordion tab 3 -->

    </dl>
    <!-- end description list -->
  </div>
  <!-- end accordion -->
</div>
<!-- end container -->
<div class="summary">
 <button class="expand btn btn-lg">Expand/Collapse All for Summary</button>
</div>
Jacob
  • 2,209
  • 1
  • 9
  • 17
0

You should change the elements css class using javascript (.toggleClass is my favorite way to do so), and put the relevant max-height value on your css like so:

** JS **

$('.expand').click(function(){
   $('.accordionItem').toggleClass('is-collapsed');
});

** CSS **

.accordionItem {max-height: 900px;}
.accordionItem.is-collapsed {max-height: 0px;}
Ronen Cypis
  • 20,163
  • 1
  • 17
  • 24