-1

I have created the code snippet and the buttons should slide up and down by click but that doesn't happen for some reason. Does it look like some subtle syntax error? Please let me know if I need to provide some extra information.

Can some one please guide me why my script is not working?

Thanks in advance.

My code is here:

(function() {
  'use strict';
  var accItem = document.getElementsByClassName('accordionItem');
  var accHD = document.getElementsByClassName('accordionItemHeading');
  for (i = 0; i < accHD.length; i++) {
    accHD[i].addEventListener('click', toggleItem, false);
  }

  function toggleItem() {
    var itemClass = this.parentNode.className;
    for (i = 0; i < accItem.length; i++) {
      accItem[i].className = 'accordionItem close';
    }
    if (itemClass == 'accordionItem close') {
      this.parentNode.className = 'accordionItem open';
    }
  }

}(window, document));
body {
  background: -webkit-linear-gradient(left, #25c481, #25b7c4);
  background: linear-gradient(to right, #25c481, #25b7c4);
}

.accordionWrapper {
  padding: 30px;
  background: #fff;
  float: left;
  width: 80%;
  box-sizing: border-box;
  margin: 10%;
  box-shadow: 0 1.5em 85px 0 rgba(0, 0, 0, 0.2);
}

.accordionItem {
  float: left;
  display: block;
  width: 100%;
  box-sizing: border-box;
  font-family: 'Open-sans', Arial, sans-serif;
}

.accordionItemHeading {
  cursor: pointer;
  margin: 0px 0px 10px 0px;
  padding: 10px;
  background: #2980b9;
  color: #fff;
  width: 100%;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
  box-sizing: border-box;
}

.close .accordionItemContent {
  height: 0px;
  transition: height 1s ease-out;
  -webkit-transform: scaleY(0);
  -o-transform: scaleY(0);
  -ms-transform: scaleY(0);
  transform: scaleY(0);
  float: left;
  display: block;
}

.open .accordionItemContent {
  padding: 20px;
  background-color: #fff;
  border: 1px solid #ddd;
  width: 100%;
  margin: 0px 0px 10px 0px;
  display: block;
  -webkit-transform: scaleY(1);
  -o-transform: scaleY(1);
  -ms-transform: scaleY(1);
  transform: scaleY(1);
  -webkit-transform-origin: top;
  -o-transform-origin: top;
  -ms-transform-origin: top;
  transform-origin: top;
  -webkit-transition: -webkit-transform 0.4s ease-out;
  -o-transition: -o-transform 0.4s ease;
  -ms-transition: -ms-transform 0.4s ease;
  transition: transform 0.4s ease;
  box-sizing: border-box;
}

.open .accordionItemHeading {
  margin: 0px;
  -webkit-border-top-left-radius: 3px;
  -webkit-border-top-right-radius: 3px;
  -moz-border-radius-topleft: 3px;
  -moz-border-radius-topright: 3px;
  border-top-left-radius: 3px;
  border-top-right-radius: 3px;
  -webkit-border-bottom-right-radius: 0px;
  -webkit-border-bottom-left-radius: 0px;
  -moz-border-radius-bottom-right: 0px;
  -moz-border-radius-bottom-left: 0px;
  border-bottom-right-radius: 0px;
  border-bottom-left-radius: 0px;
  background-color: #bdc3c7;
  color: #7f8c8d;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title></title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div class="accordionWrapper">
    <div class="accordionItem open">
      <h2 class="accordionItemHeading">About accordions</h2>
      <div class="accordionItemContent">
        <p>JavaScript accordions let you squeeze a lot of content into a small space in a Web page.</p>
        <p>This simple accordion degrades gracefully in browsers that don't support JavaScript or CSS.</p>
      </div>
    </div>

    <div class="accordionItem close">
      <h2 class="accordionItemHeading">Accordion items</h2>
      <div class="accordionItemContent">
        <p>A JavaScript accordion is made up of a number of expandable/collapsible items. Only one item is ever shown at a time.</p>
        <p>You can include any content you want inside an accordion item. Here's a bullet list:</p>
        <ul>
          <li>List item #1</li>
          <li>List item #2</li>
          <li>List item #3</li>
        </ul>
      </div>
    </div>

    <div class="accordionItem close">
      <h2 class="accordionItemHeading">How to use a JavaScript accordion</h2>
      <div class="accordionItemContent">
        <p>Click an accordion item's heading to expand it. To collapse the item, click it again, or click another item heading.</p>
      </div>
    </div>
  </div>
  <script src="custom.js"></script>
</body>

</html>
Ronan Quillevere
  • 3,699
  • 1
  • 29
  • 44

2 Answers2

2

When you transition your code from "sloppy mode", which is a no strict mode, to the strict mode than previously some mistakes, which were acceptable in the sloppy mode are treated as an error on the strict mode.

This is why your code was not working.

Mistake:

"i",. the variable used in the loop was not defined and was treated as an error in the strict mode.

Debugging in console was giving this error:

"message": "Uncaught ReferenceError: i is not defined",

Solution→

for (i = 0; i < accHD.length; i++)

should be changed to

for (var i = 0; i < accHD.length; i++)

or

for (let i = 0; i < accHD.length; i++)

I also wish to clarify that as let is block scoped, these are two different variables (just with the same name). You could also call the second one j to avoid confusion.

this image will clear your doubts further →

enter image description here

Suggested Further readings

I will also suggest you that you understand few concepts moving forward.

  1. suggested reading #1
  2. suggested reading #2
  3. Also study closure

Additionally,

You can read in detail about strict mode here on this page.

Community
  • 1
  • 1
WordCent
  • 725
  • 3
  • 18
  • 1
    thank you for the guidance and those links were amazingly wonderful. You have clearly explained why the code was not woking in strict mode which otherwise were working fine. – wordpressgirl Jan 27 '18 at 13:46
1

You're missing the i var declaration in the for loops as stated in the error

"message": "Uncaught ReferenceError: i is not defined",

To solve it, declare i var inside the for-loop

for (var i = 0; i < accHD.length; i++) {

Working code: https://jsfiddle.net/q8pyfem8/

(function() {
  'use strict';
  var accItem = document.getElementsByClassName('accordionItem');
  var accHD = document.getElementsByClassName('accordionItemHeading');
  for (var i = 0; i < accHD.length; i++) {
    accHD[i].addEventListener('click', toggleItem, false);
  }

  function toggleItem() {
    var itemClass = this.parentNode.className;
    for (var i = 0; i < accItem.length; i++) {
      accItem[i].className = 'accordionItem close';
    }
    if (itemClass == 'accordionItem close') {
      this.parentNode.className = 'accordionItem open';
    }
  }

}(window, document));
body {
  background: -webkit-linear-gradient(left, #25c481, #25b7c4);
  background: linear-gradient(to right, #25c481, #25b7c4);
}

.accordionWrapper {
  padding: 30px;
  background: #fff;
  float: left;
  width: 80%;
  box-sizing: border-box;
  margin: 10%;
  box-shadow: 0 1.5em 85px 0 rgba(0, 0, 0, 0.2);
}

.accordionItem {
  float: left;
  display: block;
  width: 100%;
  box-sizing: border-box;
  font-family: 'Open-sans', Arial, sans-serif;
}

.accordionItemHeading {
  cursor: pointer;
  margin: 0px 0px 10px 0px;
  padding: 10px;
  background: #2980b9;
  color: #fff;
  width: 100%;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
  box-sizing: border-box;
}

.close .accordionItemContent {
  height: 0px;
  transition: height 1s ease-out;
  -webkit-transform: scaleY(0);
  -o-transform: scaleY(0);
  -ms-transform: scaleY(0);
  transform: scaleY(0);
  float: left;
  display: block;
}

.open .accordionItemContent {
  padding: 20px;
  background-color: #fff;
  border: 1px solid #ddd;
  width: 100%;
  margin: 0px 0px 10px 0px;
  display: block;
  -webkit-transform: scaleY(1);
  -o-transform: scaleY(1);
  -ms-transform: scaleY(1);
  transform: scaleY(1);
  -webkit-transform-origin: top;
  -o-transform-origin: top;
  -ms-transform-origin: top;
  transform-origin: top;
  -webkit-transition: -webkit-transform 0.4s ease-out;
  -o-transition: -o-transform 0.4s ease;
  -ms-transition: -ms-transform 0.4s ease;
  transition: transform 0.4s ease;
  box-sizing: border-box;
}

.open .accordionItemHeading {
  margin: 0px;
  -webkit-border-top-left-radius: 3px;
  -webkit-border-top-right-radius: 3px;
  -moz-border-radius-topleft: 3px;
  -moz-border-radius-topright: 3px;
  border-top-left-radius: 3px;
  border-top-right-radius: 3px;
  -webkit-border-bottom-right-radius: 0px;
  -webkit-border-bottom-left-radius: 0px;
  -moz-border-radius-bottomright: 0px;
  -moz-border-radius-bottomleft: 0px;
  border-bottom-right-radius: 0px;
  border-bottom-left-radius: 0px;
  background-color: #bdc3c7;
  color: #7f8c8d;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title></title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div class="accordionWrapper">
    <div class="accordionItem open">
      <h2 class="accordionItemHeading">About accordions</h2>
      <div class="accordionItemContent">
        <p>JavaScript accordions let you squeeze a lot of content into a small space in a Web page.</p>
        <p>This simple accordion degrades gracefully in browsers that don't support JavaScript or CSS.</p>
      </div>
    </div>

    <div class="accordionItem close">
      <h2 class="accordionItemHeading">Accordion items</h2>
      <div class="accordionItemContent">
        <p>A JavaScript accordion is made up of a number of expandable/collapsible items. Only one item is ever shown at a time.</p>
        <p>You can include any content you want inside an accordion item. Here's a bullet list:</p>
        <ul>
          <li>List item #1</li>
          <li>List item #2</li>
          <li>List item #3</li>
        </ul>
      </div>
    </div>

    <div class="accordionItem close">
      <h2 class="accordionItemHeading">How to use a JavaScript accordion</h2>
      <div class="accordionItemContent">
        <p>Click an accordion item's heading to expand it. To collapse the item, click it again, or click another item heading.</p>
      </div>
    </div>
  </div>
  <script src="custom.js"></script>
</body>

</html>
Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109
  • yes, you can include it in each for loop (which will create the variable just inside the loop) or you can include `var i;` in the begining of the file and the variable will have function scope.... – Jordi Castilla Jan 26 '18 at 11:24
  • I would even say it should be `let i`, even if running ES5 before anyone say's. – Keith Jan 26 '18 at 11:24
  • I am a beginner why is siome one downvoting me?I ma not aspammer just 21 years old girl. this may look silly to someone but this is how we learn by doing mistakes. – wordpressgirl Jan 26 '18 at 11:25
  • @Keith agree.... and I will do that if other variables where declared as `let` or `const` I am just following same notation as OP – Jordi Castilla Jan 26 '18 at 11:25
  • @paymaverick you're being downvoted because you don't seem to have put the effort of debugging your code (or even just looking at the console) before asking the question. See [this guide](https://stackoverflow.com/help/how-to-ask). – Federico klez Culloca Jan 26 '18 at 11:31
  • Ok sir I have checked that guide. Please bear with me I am a new member here. I will take care in the future. – wordpressgirl Jan 26 '18 at 11:33