asso asso - 6 months ago 10
HTML Question

My Javascript doesn't work when I put a script element in the head to load it from a URL

I have written the code for a simple function inline, but when i created a separate js.file it doesn't want to work for some reason. I've tried everything it feels like, but maybe my tired eyes can't something!

<!DOCTYPE html>

<html>
<head>
<title>Test</title>
<script type="text/javascript" src="menu.js"></script>
</head>
<body>
<div class="container">
<button name="one">Button 1</button>
<p>
Lorem ipsum dolor sit amet
</p>

</div>
<div class="container">
<button name="two">Button 2</button>
<p>
Lorem ipsum dolor sit amet
</p>

</div>
<div class="container">
<button name="three">Button 3</button>
<p>
Lorem ipsum dolor sit amet
</p>
</div>





The idea is to have three buttons that when you click on one of them only one of the divs will be shown, and the other two will be hidden.

Here is the JavaScript (that worked perfectly fine inline):

var first_container = document.querySelectorAll(' div:not(:first-child) p');

for (var i = 0; i < first_container.length; i++) {
first_container[i].style.visibility = 'hidden';
}
var buttons = document.querySelectorAll('button');

for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', clickHandler);
}

function clickHandler(e) {

e.preventDefault();

var text = document.querySelectorAll('p');

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

if (text[i] === event.target.nextElementSibling) {
text[i].style.visibility = 'visible';

} else {
text[i].style.visibility = 'hidden';
}
}
}

Answer

When you put the script in an external file and then load that external script from the <head>, it loads BEFORE the DOM is ready. That means that if your script tries to reference elements in the page like you are with document.querySelectorAll(), those elements will not exist yet.

The simpleset way to fix that is to simply move the script tag:

<script type="text/javascript" src="menu.js"></script>

to right before </body>. Then, all the elements of the page will be parsed and in the DOM before your script runs like this:

<!DOCTYPE html>

<html>
  <head>
    <title>Test</title>
  </head>
 <body>
<div class="container">
  <button name="one">Button 1</button>
  <p>
    Lorem ipsum dolor sit amet
  </p>

</div>
<div class="container">
  <button name="two">Button 2</button>
  <p>
    Lorem ipsum dolor sit amet
  </p>

</div>
<div class="container">
  <button name="three">Button 3</button>
  <p>
    Lorem ipsum dolor sit amet
  </p>
</div>
<script type="text/javascript" src="menu.js"></script>
</body>
</html>

Alternately, you can use a script that will notify you when the DOM is ready and you can then call your code.

See this reference and highly voted answer for a plain Javascript and cross browser way of waiting until the DOM is ready if you'd rather keep your code in the <head> section or make it so you code can be located anywhere.