JavaScript does not work if placed in the head tag

6

Well, I need the Tag Script to be inside the Tag Head, but unfortunately it's only working when I put it in the end of the html. Please, if anyone knows why this is happening, please give some help.

This is HTML:

<!DOCTYPE html>
<html>
<head>
    <title>Artistic Pizzeria</title>
    <meta charset="utf-8" />
    <meta name="description" content="Pizzas artisticas">
    <meta name="keywords" content="Pizza,Pizzaria,Pizzeria,Artistic,Art">
    <meta name="author" content="Larissa Mourullo">
    <link rel="stylesheet" type="text/css" href="style.css">
    <script type="text/javascript" src="script.js"></script>
</head>
<body>
    <header>
        <a href="index.html"><img src="LOGO" title="LOGO" alt="LOGO" /></a>
        <nav>
            <a href="index.html">HOME</a>
            <a href="historia.html">HISTÓRIA</a>
            <a href="cardapio.html">CARDÁPIO</a>
            <a href="contato.html">CONTATO</a>
            <a href="login.html">LOGIN</a>
            <a href="cadastrar.html">CADASTRO</a>
        </nav>
    </header>
    <article>
        <h1>Pizza 3</h1>
        <form>
            <p>Sabores:</p>
            <select id="sabores">
                <option value="">Nenhum</option>
                <option value="1">Goiaba</option>
                <option value="2">Tutifruti</option>
                <option value="3">Mangericão</option>
            </select>
            <p>Tamanho da Pizza:</p>
            <select id="tmhpizza">
                <option value="{&quot;preco&quot;:20,&quot;desc&quot;:&quot;R$20,00&quot;}">Brotinho - R$20,00</option>
                <option value="{&quot;preco&quot;:45,&quot;desc&quot;:&quot;R$45,00&quot;}">Pequena - R$45,00</option>
                <option value="{&quot;preco&quot;:70,&quot;desc&quot;:&quot;R$70,00&quot;}">Média - R$70,00</option>
                <option value="{&quot;preco&quot;:95,&quot;desc&quot;:&quot;R$95,00&quot;}">Grande - R$95,00</option>
                <option value="{&quot;preco&quot;:120,&quot;desc&quot;:&quot;R$120,00&quot;}">Gigante - R$120,00</option>
            </select>
            <p>Quantidade de Pizzas:</p>
            <select id="qntpizza" data-rel="tmhpizza">
                <option value="0">Nenhum</option>
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
                <option value="4">4</option>
                <option value="5">5</option>
                <option value="6">6</option>
                <option value="7">7</option>
                <option value="8">8</option>
                <option value="9">9</option>
                <option value="10">10</option>
            </select>
            <p>Refrigerante:</p>
            <select id="refri">
                <option value="">Nenhum</option>
                <option value="Kuat">Kuat</option>
                <option value="Soda">Soda</option>
                <option value="Pepsi">Pepsi</option>
                <option value="Sprite">Sprite</option>
                <option value="Coca Zero">Coca Zero</option>
                <option value="Fanta Uva">Fanta Uva</option>
                <option value="Coca-Cola">Coca-Cola</option>
                <option value="Mineirinho">Mineirinho</option>
                <option value="Pepsi Twist">Pepsi Twist</option>
                <option value="Guaraná Zero">Guaraná Zero</option>
                <option value="Fanta Laranja">Fanta Laranja</option>
                <option value="Guaraná Black">Guaraná Black</option>
                <option value="Guaraná Antarctica">Guaraná Antarctica</option>
            </select>
            <p>Tamanho do Refrigerante:</p>
            <select id="tmhrefri">
                <option value="{&quot;preco&quot;:4.5,&quot;desc&quot;:&quot;R$4,50&quot;}">350ml - R$4,50</option>
                <option value="{&quot;preco&quot;:6.3,&quot;desc&quot;:&quot;R$6,30&quot;}">750ml - R$6,30</option>
                <option value="{&quot;preco&quot;:8.1,&quot;desc&quot;:&quot;R$8,10&quot;}">1L - R$8,10</option>
                <option value="{&quot;preco&quot;:9.9,&quot;desc&quot;:&quot;R$9,90&quot;}">2L - R$9,90</option>
                <option value="{&quot;preco&quot;:11.7,&quot;desc&quot;:&quot;R$11,70&quot;}">2,5L - R$11,70</option>
            </select>
            <p>Quantidade de Refrigerante:</p>
            <select id="qntrefri" data-rel="tmhrefri">
                <option value="0">Nenhum</option>
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
                <option value="4">4</option>
                <option value="5">5</option>
                <option value="6">6</option>
                <option value="7">7</option>
                <option value="8">8</option>
                <option value="9">9</option>
                <option value="10">10</option>
            </select>

            <p>Preço:</p>
            <input id="total" type="text" name="preco" />
            <input type="button" id="calcular" value="Calcular" />
        </form>
    </article>
    <footer>
        <p>© 2015 Artistic Pizzeria. Todos os direitos reservados.</p>
    </footer>
</body>
</html>

This is JavaScript:

var calcular = document.getElementById('calcular');
calcular.addEventListener('click', function () {
    var selects = document.querySelectorAll('select[data-rel]');
    var precos = [].map.call(selects, function (select) {
        var multiplicador = parseInt(select.value, 10);
        var json = document.getElementById(select.dataset.rel).value;
        var produto = JSON.parse(json);
        return parseFloat(produto.preco) * multiplicador;
    });
    document.querySelector('input[name="preco"]').value = precos.reduce(function (a, b) {
        return a + b;
    }, 0);
});
    
asked by anonymous 08.07.2015 / 21:00

2 answers

6

Your JavaScript code in the current form ends up being read before the elements are available in the DOM, which does not work giving a type error:

  

TypeError: calculate is null

Ideally, when we talk about performance, it is to have JavaScript just before the closing of the </body> tag:

    <!-- ... -->
    <script type="text/javascript" src="script.js"></script>
</body>
</html>

The alternative, when it is required to be between the <head></head> tags is to place the code inside a function, so that it is not read immediately, but when the function is called.

Then we call the function at the most appropriate time, in your case, as soon as the DOM is available we can call it:

/**
 * A função com o código
 */
function calculando() {

  var calcular = document.getElementById('calcular');
  calcular.addEventListener('click', function() {
    var selects = document.querySelectorAll('select[data-rel]');
    var precos = [].map.call(selects, function(select) {
      var multiplicador = parseInt(select.value, 10);
      var json = document.getElementById(select.dataset.rel).value;
      var produto = JSON.parse(json);
      return parseFloat(produto.preco) * multiplicador;
    });
    document.querySelector('input[name="preco"]').value = precos.reduce(function(a, b) {
      return a + b;
    }, 0);
  });
}

// Chamar a função imediatamente assim que o DOM estiver disponível
document.addEventListener('DOMContentLoaded', calculando, false);

Example:

<!DOCTYPE html>
<html>

<head>
  <title>Artistic Pizzeria</title>
  <meta charset="utf-8" />
  <meta name="description" content="Pizzas artisticas">
  <meta name="keywords" content="Pizza,Pizzaria,Pizzeria,Artistic,Art">
  <meta name="author" content="Larissa Mourullo">
  <link rel="stylesheet" type="text/css" href="style.css">
  <script>
    function calculando() {

      var calcular = document.getElementById('calcular');
      calcular.addEventListener('click', function() {
        var selects = document.querySelectorAll('select[data-rel]');
        var precos = [].map.call(selects, function(select) {
          var multiplicador = parseInt(select.value, 10);
          var json = document.getElementById(select.dataset.rel).value;
          var produto = JSON.parse(json);
          return parseFloat(produto.preco) * multiplicador;
        });
        document.querySelector('input[name="preco"]').value = precos.reduce(function(a, b) {
          return a + b;
        }, 0);
      });
    }
    document.addEventListener('DOMContentLoaded', calculando, false);
  </script>
</head>

<body>
  <header>
    <a href="index.html">
      <img src="LOGO" title="LOGO" alt="LOGO" />
    </a>
    <nav>
      <a href="index.html">HOME</a>
      <a href="historia.html">HISTÓRIA</a>
      <a href="cardapio.html">CARDÁPIO</a>
      <a href="contato.html">CONTATO</a>
      <a href="login.html">LOGIN</a>
      <a href="cadastrar.html">CADASTRO</a>
    </nav>
  </header>
  <article>
    <h1>Pizza 3</h1>
    <form>
      <p>Sabores:</p>
      <select id="sabores">
        <option value="">Nenhum</option>
        <option value="1">Goiaba</option>
        <option value="2">Tutifruti</option>
        <option value="3">Mangericão</option>
      </select>
      <p>Tamanho da Pizza:</p>
      <select id="tmhpizza">
        <option value="{&quot;preco&quot;:20,&quot;desc&quot;:&quot;R$20,00&quot;}">Brotinho - R$20,00</option>
        <option value="{&quot;preco&quot;:45,&quot;desc&quot;:&quot;R$45,00&quot;}">Pequena - R$45,00</option>
        <option value="{&quot;preco&quot;:70,&quot;desc&quot;:&quot;R$70,00&quot;}">Média - R$70,00</option>
        <option value="{&quot;preco&quot;:95,&quot;desc&quot;:&quot;R$95,00&quot;}">Grande - R$95,00</option>
        <option value="{&quot;preco&quot;:120,&quot;desc&quot;:&quot;R$120,00&quot;}">Gigante - R$120,00</option>
      </select>
      <p>Quantidade de Pizzas:</p>
      <select id="qntpizza" data-rel="tmhpizza">
        <option value="0">Nenhum</option>
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4">4</option>
        <option value="5">5</option>
        <option value="6">6</option>
        <option value="7">7</option>
        <option value="8">8</option>
        <option value="9">9</option>
        <option value="10">10</option>
      </select>
      <p>Refrigerante:</p>
      <select id="refri">
        <option value="">Nenhum</option>
        <option value="Kuat">Kuat</option>
        <option value="Soda">Soda</option>
        <option value="Pepsi">Pepsi</option>
        <option value="Sprite">Sprite</option>
        <option value="Coca Zero">Coca Zero</option>
        <option value="Fanta Uva">Fanta Uva</option>
        <option value="Coca-Cola">Coca-Cola</option>
        <option value="Mineirinho">Mineirinho</option>
        <option value="Pepsi Twist">Pepsi Twist</option>
        <option value="Guaraná Zero">Guaraná Zero</option>
        <option value="Fanta Laranja">Fanta Laranja</option>
        <option value="Guaraná Black">Guaraná Black</option>
        <option value="Guaraná Antarctica">Guaraná Antarctica</option>
      </select>
      <p>Tamanho do Refrigerante:</p>
      <select id="tmhrefri">
        <option value="{&quot;preco&quot;:4.5,&quot;desc&quot;:&quot;R$4,50&quot;}">350ml - R$4,50</option>
        <option value="{&quot;preco&quot;:6.3,&quot;desc&quot;:&quot;R$6,30&quot;}">750ml - R$6,30</option>
        <option value="{&quot;preco&quot;:8.1,&quot;desc&quot;:&quot;R$8,10&quot;}">1L - R$8,10</option>
        <option value="{&quot;preco&quot;:9.9,&quot;desc&quot;:&quot;R$9,90&quot;}">2L - R$9,90</option>
        <option value="{&quot;preco&quot;:11.7,&quot;desc&quot;:&quot;R$11,70&quot;}">2,5L - R$11,70</option>
      </select>
      <p>Quantidade de Refrigerante:</p>
      <select id="qntrefri" data-rel="tmhrefri">
        <option value="0">Nenhum</option>
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4">4</option>
        <option value="5">5</option>
        <option value="6">6</option>
        <option value="7">7</option>
        <option value="8">8</option>
        <option value="9">9</option>
        <option value="10">10</option>
      </select>

      <p>Preço:</p>
      <input id="total" type="text" name="preco" />
      <input type="button" id="calcular" value="Calcular" />
    </form>
  </article>
  <footer>
    <p>© 2015 Artistic Pizzeria. Todos os direitos reservados.</p>
  </footer>
</body>

</html>
    
08.07.2015 / 21:32
2

You can do this with window.load , see below:

<!DOCTYPE html>
<html>
<head>
    <title>Artistic Pizzeria</title>
    <meta charset="utf-8" />
    <meta name="description" content="Pizzas artisticas">
    <meta name="keywords" content="Pizza,Pizzaria,Pizzeria,Artistic,Art">
    <meta name="author" content="Larissa Mourullo">
    <link rel="stylesheet" type="text/css" href="style.css">
    <script type="text/javascript" src="script.js"></script>
  <script>
  window.onload = function() {
    
    var calcular = document.getElementById('calcular');
calcular.addEventListener('click', function () {
    var selects = document.querySelectorAll('select[data-rel]');
    var precos = [].map.call(selects, function (select) {
        var multiplicador = parseInt(select.value, 10);
        var json = document.getElementById(select.dataset.rel).value;
        var produto = JSON.parse(json);
        return parseFloat(produto.preco) * multiplicador;
    });
    document.querySelector('input[name="preco"]').value = precos.reduce(function (a, b) {
        return a + b;
    }, 0);
});
    
    }
  
  </script>
  
  
</head>
<body>
    <header>
        <a href="index.html"><img src="LOGO" title="LOGO" alt="LOGO" /></a>
        <nav>
            <a href="index.html">HOME</a>
            <a href="historia.html">HISTÓRIA</a>
            <a href="cardapio.html">CARDÁPIO</a>
            <a href="contato.html">CONTATO</a>
            <a href="login.html">LOGIN</a>
            <a href="cadastrar.html">CADASTRO</a>
        </nav>
    </header>
    <article>
        <h1>Pizza 3</h1>
        <form>
            <p>Sabores:</p>
            <select id="sabores">
                <option value="">Nenhum</option>
                <option value="1">Goiaba</option>
                <option value="2">Tutifruti</option>
                <option value="3">Mangericão</option>
            </select>
            <p>Tamanho da Pizza:</p>
            <select id="tmhpizza">
                <option value="{&quot;preco&quot;:20,&quot;desc&quot;:&quot;R$20,00&quot;}">Brotinho - R$20,00</option>
                <option value="{&quot;preco&quot;:45,&quot;desc&quot;:&quot;R$45,00&quot;}">Pequena - R$45,00</option>
                <option value="{&quot;preco&quot;:70,&quot;desc&quot;:&quot;R$70,00&quot;}">Média - R$70,00</option>
                <option value="{&quot;preco&quot;:95,&quot;desc&quot;:&quot;R$95,00&quot;}">Grande - R$95,00</option>
                <option value="{&quot;preco&quot;:120,&quot;desc&quot;:&quot;R$120,00&quot;}">Gigante - R$120,00</option>
            </select>
            <p>Quantidade de Pizzas:</p>
            <select id="qntpizza" data-rel="tmhpizza">
                <option value="0">Nenhum</option>
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
                <option value="4">4</option>
                <option value="5">5</option>
                <option value="6">6</option>
                <option value="7">7</option>
                <option value="8">8</option>
                <option value="9">9</option>
                <option value="10">10</option>
            </select>
            <p>Refrigerante:</p>
            <select id="refri">
                <option value="">Nenhum</option>
                <option value="Kuat">Kuat</option>
                <option value="Soda">Soda</option>
                <option value="Pepsi">Pepsi</option>
                <option value="Sprite">Sprite</option>
                <option value="Coca Zero">Coca Zero</option>
                <option value="Fanta Uva">Fanta Uva</option>
                <option value="Coca-Cola">Coca-Cola</option>
                <option value="Mineirinho">Mineirinho</option>
                <option value="Pepsi Twist">Pepsi Twist</option>
                <option value="Guaraná Zero">Guaraná Zero</option>
                <option value="Fanta Laranja">Fanta Laranja</option>
                <option value="Guaraná Black">Guaraná Black</option>
                <option value="Guaraná Antarctica">Guaraná Antarctica</option>
            </select>
            <p>Tamanho do Refrigerante:</p>
            <select id="tmhrefri">
                <option value="{&quot;preco&quot;:4.5,&quot;desc&quot;:&quot;R$4,50&quot;}">350ml - R$4,50</option>
                <option value="{&quot;preco&quot;:6.3,&quot;desc&quot;:&quot;R$6,30&quot;}">750ml - R$6,30</option>
                <option value="{&quot;preco&quot;:8.1,&quot;desc&quot;:&quot;R$8,10&quot;}">1L - R$8,10</option>
                <option value="{&quot;preco&quot;:9.9,&quot;desc&quot;:&quot;R$9,90&quot;}">2L - R$9,90</option>
                <option value="{&quot;preco&quot;:11.7,&quot;desc&quot;:&quot;R$11,70&quot;}">2,5L - R$11,70</option>
            </select>
            <p>Quantidade de Refrigerante:</p>
            <select id="qntrefri" data-rel="tmhrefri">
                <option value="0">Nenhum</option>
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
                <option value="4">4</option>
                <option value="5">5</option>
                <option value="6">6</option>
                <option value="7">7</option>
                <option value="8">8</option>
                <option value="9">9</option>
                <option value="10">10</option>
            </select>

            <p>Preço:</p>
            <input id="total" type="text" name="preco" />
            <input type="button" id="calcular" value="Calcular" />
        </form>
    </article>
    <footer>
        <p>© 2015 Artistic Pizzeria. Todos os direitos reservados.</p>
    </footer>
</body>
</html>

But the script will only work after the page is fully loaded.

    
08.07.2015 / 21:14