Which .js file is appropriate to add script for animated button?

I’m working with a theme I’ve created that’s a modification of Seasons, and I’m attempting to make accordion buttons that display a panel of text when clicked on (example of code below). My question is which JavaScript file would my JS code go into in order for the effect to work? Is it one of the theme files like seasons.js?

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.accordion {
    background-color: #A4C4E9;
    color: #000;
    cursor: pointer;
    padding: 18px;
    width: 75%;
    border: none;
    text-align: left;
    outline: none;
    font-size: 15px;
    transition: 0.4s;
	margin: 2px;
}

.active, .accordion:hover {
    background-color: #999;
}

.panel {
    padding: 0 18px;
    background-color: white;
    max-height: 0;
	width: 75%;
    overflow: hidden;
    transition: max-height 0.2s ease-out;
}
</style>
</head>
<body>

<h2>Animated Accordion</h2>
<p>Click on the buttons to open the collapsible content.</p>

<button class="accordion">Section 1</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<button class="accordion">Section 2</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<button class="accordion">Section 3</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<script>
var acc = document.getElementsByClassName("accordion");
var i;

for (i = 0; i < acc.length; i++) {
  acc[i].addEventListener("click", function() {
    this.classList.toggle("active");
    var panel = this.nextElementSibling;
    if (panel.style.maxHeight){
      panel.style.maxHeight = null;
    } else {
      panel.style.maxHeight = panel.scrollHeight + "px";
    } 
  });
}
</script>

</body>
</html>

Update: I’ve created a separate accordion.js file with the code from the < script > tags, and added it to the list of JavaScript files in my theme’s header.php file, but it isn’t creating the effect of the panel appearing when clicking on the button as it does in my HTML document.

If you’re going to separate the code you’ve got there into a separate JS file and load it in the page’s head, you’ll need to do something to make it wait until the page is actually loaded to run. (Otherwise, when your code first tries to find all the elements with class accordion, there won’t be any, because they haven’t loaded yet.)

With “vanilla” JS that would mean wrapping something like this:

document.addEventListener("DOMContentLoaded", function () {
    // your original code here
});

You could also rewrite it to listen for the click event “higher up” in the DOM hierarchy rather than attaching directly to each node as you’re doing now, but that’s not as simple of a conversion.

I added your code to my file and got this error: Uncaught TypeError: Cannot read property ‘style’ of null on my panel element. I added panel to document.getElementsByClassName (see below) and no longer get the error but I’m still not getting the effect of the panel appearing when I click on the button.

/*
 * Script for accordion buttons
 */

document.addEventListener("DOMContentLoaded", function () { 
 
var acc = document.getElementsByClassName("accordion panel");
var i;

for (i = 0; i < acc.length; i++) {
  acc[i].addEventListener("click", function() {
    this.classList.toggle("active");
    var panel = this.nextElementSibling;
    if (panel.style.maxHeight){
      panel.style.maxHeight = null;
    } else {
      panel.style.maxHeight = panel.scrollHeight + "px";
    } 
  });
}
});

Your error didn’t really have to do with the little addition I suggested… what that error is saying is that you’ve got (at least) one .accordion on your page that doesn’t have a “next” element after it, but your code assumes it always will.

As for adding panel stopping the error, does your accordion element actually have both of those classes? What you changed the code to requires that; it will only find elements with both those classes set.

I’m pretty new to JS, but in my CSS file I have accordion and panel declared as separate classes, which I assume is why my JS isn’t working as it should, but I’m unsure of what I need to change in my JS file in order to get it to run properly.

I went to Stack Overflow for some assistance with the JavaScript but I am still getting the following error: “Uncaught TypeError: Cannot read property ‘style’ of null” in my .js file at this line of code: if (panel.style.maxHeight == “”) {

Updated .js file:

/*
 * Script for accordion buttons
 */

document.addEventListener("DOMContentLoaded", function() {
  var acc = document.getElementsByClassName("accordion");
  var i;

  for (i = 0; i < acc.length; i++) {
    acc[i].addEventListener("click", function() {

      /* Toggle between adding and removing the "active" class,
      to highlight the button that controls the panel */
      this.classList.toggle("active");

      /* Toggle between hiding and showing the active panel */
      var panel = this.nextElementSibling; //.classList.toggle('active');

      if (panel.style.maxHeight == "") {
        panel.style.maxHeight = panel.scrollHeight + "px";
      } else {
        panel.style.maxHeight = "";
      }
    });
  }


});

Updated CSS:

 /* --- Accordion Menu Buttons --- */

.accordion {
    background-color: #A4C4E9 !important;
    color: #000;
    cursor: pointer;
    width: 75%;
    border: none;
    text-align: left;
    outline: none;
    font-size: 15px;
    transition: 0.4s;
}

.accordion:hover {
    background-color: #999 !important;
}

.panel {
    padding: 0 18px;
    background-color: white;
    max-height: 0;
	width: 75%;
    overflow: hidden;
    transition: max-height 0.2s ease-out;
} 

.panel.active {
  max-height: 100%;
}

HTML:

Section 1

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

The code itself works when its run on Stack Overflow, but I’m unsure of why I can’t get it to work on my Omeka site.

Sorry the HTML code didn’t display correctly:

<button class="accordion">Section 1</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>