Problem with JavaScript dropdown & external JavaScript

84 views Asked by At

I have a problem to make my JavaScript dropdown work when placing my js code in an external js file. The button needs to be pressed twice to show the links. I have no problem to make the code work if i place the js code in the body section using script tags.

I have been trying to understand the difference, but not yet come up with a solution. At first I thought it would be enough to make a function of it in the js file and then use onlick="dropdownfunc()" in the html file like bellow, but seems like I am wrong.

What do I need to think about to make it work?

function dropdownfunc() {
  var dropdown = document.getElementsByClassName("dropdown-btn");
  var i;

  for (i = 0; i < dropdown.length; i++) {
    dropdown[i].addEventListener("click", function () {
      this.classList.toggle("active");
      var dropdownContent = this.nextElementSibling;
      if (dropdownContent.style.display === "block") {
        dropdownContent.style.display = "none";
      } else {
        dropdownContent.style.display = "block";
      }
    });
  }
}
.dropdown-btn {
  color: gray;
  font-size: 1.8rem;
  cursor: pointer;
}

.dropdown-container {
  display: none;
  border-left: 2px solid #818181;
}

.dropdown-links {
  display: table;
  font-size: 1.4rem;
  margin-left: 18px;
}

.active {
  color: black;
}
<button class="dropdown-btn" onclick="dropdownfunc()">Dropdown</button>

<div class="dropdown-container">
  <a class="dropdown-links" href="#">Link 1</a>
  <a class="dropdown-links" href="#">Link 2</a>
</div>

2

There are 2 answers

0
Timur On BEST ANSWER

This is becasue you are attaching the click event handler again after the click, which you already defined in onclick="dropdownfunc()". Instead, you can simply add this as a parameter to your onclick function and display the dropdown. And no need to loop thru your buttons. Here is an example:

function dropdownfunc(el) {
  el.classList.toggle("active");
  var dropdownContent = el.nextElementSibling;
  if (dropdownContent.style.display === "block") {
    dropdownContent.style.display = "none";
  } else {
    dropdownContent.style.display = "block";
  }
}
.dropdown-btn {
  color: gray;
  font-size: 1.8rem;
  cursor: pointer;
}

.dropdown-container {
  display: none;
  border-left: 2px solid #818181;
}

.dropdown-links {
  display: table;
  font-size: 1.4rem;
  margin-left: 18px;
}

.active {
  color: black;
}
<button class="dropdown-btn" onclick="dropdownfunc(this)">Dropdown</button>

<div class="dropdown-container">
  <a class="dropdown-links" href="#">Link 1</a>
  <a class="dropdown-links" href="#">Link 2</a>
</div>

0
Vincent On

This is unrelated to the js being external or not.

Here is what happens:

On the first click, dropdownfunc is called. It attaches another event listener for click, and does nothing else, so nothing happens on the UI.

On the second click, the second listener will be called and the drop list will display. By the way, dropdownfunc will also be called again!

Actually, each time the button is clicked dropdownfunc will add the same listener. So you are piling listeners. You should avoid that!