'Javascript works in codepen but not on browser

const toggleButton = document.getElementsByClassName('navbar-toggle')[0];
const navbarLinks = document.getElementsByClassName('navbar-links');
toggleButton.addEventListener('click', function() {
  for(var i=0; i<navbarLinks.length; i++)
    navbarLinks[i].classList.toggle('active');
});
* {
  margin: 0px;
  padding: 0px;
  box-sizing: border-box;
  font-family: "Montserrat", sans serif;
}

.navbar ul {
  display: flex;
  width: 100%;
  align-items: center;
  background-color: none;
  color: black;
}

.navbar li {
  list-style-type: none;
  padding: 1rem;
}

.navbar a {
  text-decoration: none;
}
.navbar-logo {
  margin-right: auto;
  width: 250px;
  height: 150px;
  user-select: none;
}
.navbar-toggle {
  display: none;
}
.navbar-links:hover {
  color: rgba(245, 40, 145, 0.8);
  transition: all 0.3s ease 0s;
}
    button {
      padding: 9px 25px;
      color:white;
      background-color: rgba(245, 40, 145, 0.8);
      border: none;
      border-radius: 50px;
      cursor: pointer;
      transition: all 0.3s ease 0s;
    }
    button:hover {
      background-color: rgba(245, 40, 145, 0.5);
    }


  @media (max-width: 600px) {
    .navbar ul {
      flex-wrap: wrap;
    }
    .navbar-toggle {
      display: block;
      cursor:pointer;
    }
    .navbar-links {
      display: none;
      width: 100%;
      text-align: center;
    }
    .active {
      display: block;
    }
  }




.slideshow {
    max-width: auto;
    height: 600px;
    display: block;
    position: relative;
    overflow: hidden;
}

img.mySlides {
  max-width: 100%;
          max-height: 100%;
          display: block;
          object-fit: cover;
 top: 0;
 left: 0;

}
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>KK Beauty Parlor </title>
    <link rel="stylesheet" href="CSS/homestyle.css">
    <link rel="stylesheet" href="https://www.w3schools.com/w3css/3/w3.css">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet">
    <script src="https://kit.fontawesome.com/a37ae7cae6.js" crossorigin="anonymous"></script>
    <script src="JS/myScript.js"></script>
  </head>
    <body>
      <nav class="navbar">
      <ul>
        <img class="navbar-logo" src="images/KKLogo.svg">
        <li class="navbar-toggle"><i class="fa-solid fa-bars"></i></li>
        <li class="navbar-links"><a href="kkbp.html">Home</a></li>
        <li class="navbar-links"><a href="products.html">Products</a></li>
        <li class="navbar-links"><a href="services.html">Services</a></li>
        <li class="navbar-links"><a href="Appointments.html">Appointments</a></li>
        <li class="navbar-links"><a href="learnmore.html">Learn More</a></li>
        <li class="navbar-links"><a href="#Login"><button>Login</button></a></li>
        <li class="navbar-links"><a href="#Register"><button>Register</button></a></li>


      </ul>
    </nav>
      <section class="slideshow">
        <img class="mySlides" src="images/slideshow1.jpg" style="width:100%">
        <img class="mySlides" src="images/slideshow2.jpg" style="width:100%">
        <img class="mySlides" src="images/slideshow3.jpg" style="width:100%">
        <img class="mySlides" src="images/slideshow4.jpg" style="width:100%">
      </section>
      <script>
        // Automatic Slideshow - change image every 3 seconds
        var myIndex = 0;
        carousel();

        function carousel() {
          var i;
          var x = document.getElementsByClassName("mySlides");
          for (i = 0; i < x.length; i++) {
            x[i].style.display = "none";
        }
      myIndex++;
      if (myIndex > x.length) {myIndex = 1}
        x[myIndex-1].style.display = "block";
        setTimeout(carousel, 3000);
}
    </script>
    
  </body>
</html>

In the snippet, the hamburger icon does what its supposed to do, however, when I try to run it locally on my browser the hamburger icon doesn't work at all. Has anyone ever had an issue with this? Not sure why it's happening or how to fix it. Any ideas/advice? I'm working inside of Visual Studio Code and have tried both Safari and Google Chrome as a browser. JavaScript is enabled in both.



Solution 1:[1]

Your JavaScript is loading before the HTML does, which means that the following code will be undefined, as it doesn't exist yet.

console.log(document.getElementsByClassName('navbar-toggle')[0]);
<!-- It's like there's nothing here for JavaScript! -->

To fix this, you can do two things.


You can add the JavaScript at the end of the <body> tag. This makes the JavaScript load after all of the HTML has, as HTML loads line by line.

<body>
  <!-- Some HTML here... -->

  <script src="JS/myScript.js"></script>
</body>

If you want to leave the JavaScript in the <head>, then you can add the defer attribute.

According to MDN...

This Boolean attribute is set to indicate to a browser that the script is meant to be executed after the document has been parsed, but before firing DOMContentLoaded.

So, you can simply change your code to below.

<head>
  <!-- Some HTML here... -->

  <script defer src="JS/myScript.js"></script>
</head>

Both of these will work, but it's up to you what you want to do.

Solution 2:[2]

I think it is happening because you're importing js file in the head tag. And that's why it is getting rendered before the HTML code does. And because of that the values of toggleButton and navbarLinks will be undefined.

So try moving your js import at the bottom after the body tag.

<body>...</body>
<script src="https://kit.fontawesome.com/a37ae7cae6.js" crossorigin="anonymous"></script>
<script src="JS/myScript.js"></script>

Solution 3:[3]

What is actually happening here... First the page started loading.Then it found the js. it executes js when you are in head tag. but your elements are inside the body that isn't loaded yet. So the script found nothing.

const toggleButton = document.getElementsByClassName('navbar-toggle')[0];

const navbarLinks = document.getElementsByClassName('navbar-links');

Here:

toggleButton = undefined;

navbarLinks = undefined;

This means you don't have navbarLinks and toggleButton. Then it will never work. To solve this you need to execute this javascript code after these elements. It is better to use script tag just before the end of body tag or inside head tag using defer or async attribute.

In codepen or codeply this is automatically configured.

// Tips:

Why are you using ....

document.getElementsByClassName('navbar-toggle')[0]

Try this:

document.querySelector('.navbar-toggle')

Docs: https://www.w3schools.com/jsref/met_document_queryselector.asp

Solution 4:[4]

There are many ways to select an element.

document.getElementById()
document.getElementsByClassName()
document.getElementsByName()
document.getElementsByTagName()
document.querySelector()
document.querySelectorAll()

Here is an example.

<section class="parent-class" id="parent-id">
  <div class="child">
  </div>
  <div class=child2>
  </div>
</section>

If you want to select the child div using getElementById, then you can't do this normally because the div has no id.

getElementById finds just one element that contains all the id given here.

document.getElementById('a b c')

it will find an element that has a,b and c id. Thinking using getElementsByClassName? Well you can do this, but if you want to select a div that is under a section then again you can't do this. It also works similar with id, it find an element with all the class names given here. there is also a big problem. this returns an array not a single element.

getElementsByName, getElementsByTagName are also similar, these find all elements with the tag given here. But querySelector querySelectorAll is a magic. It works similar with css.

document.querySelector('#parent-id .child'); // <div class='child'> document.querySelector('.parent-class .child'); // <div class='child'>      document.querySelector('.child'); // <div class='child'> document.querySelector('.child2'); // <div class='child2'>      document.querySelectorAll('#parent-id div'); // [div,div] document.querySelectorAll('.parent-class div'); // [div,div]

https://www.w3schools.com/jsref/met_document_getelementbyid.asp https://www.w3schools.com/jsref/met_document_getelementsbyclassname.asp https://www.w3schools.com/jsref/met_doc_getelementsbyname.asp https://www.w3schools.com/jsref/met_document_getelementsbytagname.asp https://www.w3schools.com/jsref/met_document_queryselector.asp https://www.w3schools.com/jsref/met_document_queryselectorall.asp

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Dharmik Patel
Solution 3
Solution 4