Capítulo 11

JavaScript e interatividade na Web

"Design não é só como uma coisa aparenta, é como ela funciona." -- Steve Jobs

11.1 Porque usamos JavaScript?

Na página de produto havíamos criado um input range para selecionar o tamanho da roupa. O problema é que não há feedback visual de qual valor está selecionado. Podemos então criar um outro elemento visual na página apenas para mostrar o valor atualmente selecionado no range.

Mas que tag usar pra representar esse elemento cujo valor é resultado do valor escolhido no range?

No HTML5, temos uma tag nova com valor semântico exato pra essa situação: o <output>. Essa tag representa a saída de algum cálculo ou valor simples obtido a partir de um ou mais campos de um formulário. Ele tem um atributo for que aponta de qual elemento saiu o seu valor.

<output for="tamanho" name="valortamanho">42</output>

Visualmente, é como se fosse um DIV simples. Depois vamos estilizar esse componente do jeito que quisermos com CSS. A grande sacada é o valor semântico da tag e o que ela representa.

O valor em si está como 42 porque colocamos na mão, dentro da tag. O que precisamos é atualizar esse valor toda vez que o valor do input range mudar, ou seja, toda vez que o usuário arrastar o input range.

O HTML vem pronto para o navegador com todo seu conteúdo e tags. Mudar o conteúdo de uma tag baseado numa ação do usuário (dentro do navegador) não é função do HTML. Pra isso, precisamos de JavaScript.

Saber inglês é muito importante em TI

Na Alura Língua você reforça e aprimora seu inglês! Usando a técnica Spaced Repetitions o aprendizado naturalmente se adapta ao seu conhecimento. Exercícios e vídeos interativos fazem com que você pratique em situações cotidianas. Além disso, todas as aulas possuem explicações gramaticais, para você entender completamente o que está aprendendo. Aprender inglês é fundamental para o profissional de tecnologia de sucesso!

Pratique seu inglês na Alura Língua.

11.2 Um pouquinho da história do JavaScript

No início da Internet as páginas eram pouco ou nada interativas, eram documentos que apresentavam seu conteúdo exatamente como foram criados para serem exibidos no navegador. Existiam algumas tecnologias para a geração de páginas no lado do servidor, mas havia limitações no que diz respeito a como o usuário consumia aquele conteúdo. Navegar através de links e enviar informações através de formulários era basicamente tudo o que se podia fazer.

Nasce o JavaScript

Visando o potencial da Internet para o público geral e a necessidade de haver uma interação maior do usuário com as páginas, a Netscape, criadora do navegador mais popular do início dos anos 90, de mesmo nome, criou o Livescript, uma linguagem simples que permitia a execução de scripts contidos nas páginas dentro do próprio navegador.

Aproveitando o iminente sucesso do Java, que vinha conquistando cada vez mais espaço no mercado de desenvolvimento de aplicações corporativas, a Netscape logo rebatizou o Livescript como JavaScript num acordo com a Sun para alavancar o uso das duas. A então vice-líder dos navegadores, Microsoft, adicionou ao Internet Explorer o suporte a scripts escritos em VBScript e criou sua própria versão de JavaScript, o JScript.

JavaScript é a linguagem de programação mais popular no desenvolvimento Web. Suportada por todos os navegadores, a linguagem é responsável por praticamente qualquer tipo de dinamismo que queiramos em nossas páginas.

Se usarmos todo o poder que ela tem para oferecer, podemos chegar a resultados impressionantes. Excelentes exemplos disso são aplicações Web complexas como Gmail, Google Maps e Google Docs.

11.3 Características da linguagem

O JavaScript, como o próprio nome sugere, é uma linguagem de scripting. Uma linguagem de scripting é comumente definida como uma linguagem de programação que permite ao programador controlar uma ou mais aplicações de terceiros. No caso do JavaScript, podemos controlar alguns comportamentos dos navegadores através de trechos de código que são enviados na página HTML.

Outra característica comum nas linguagens de scripting é que normalmente elas são linguagens interpretadas, ou seja, não dependem de compilação para serem executadas. Essa característica é presente no JavaScript: o código é interpretado e executado conforme é lido pelo navegador, linha a linha, assim como o HTML.

O JavaScript também possui grande tolerância a erros, uma vez que conversões automáticas são realizadas durante operações. Como será visto no decorrer das explicações, nem sempre essas conversões resultam em algo esperado, o que pode ser fonte de muitos bugs, caso não conheçamos bem esse mecanismo.

O script do programador é enviado com o HTML para o navegador, mas como o navegador saberá diferenciar o script de um código html? Para que essa diferenciação seja possível, é necessário envolver o script dentro da tag <script>.

11.4 Console do navegador

Existem várias formas de executar códigos javascript em um página. Uma delas é executar códigos no que chamamos de Console. A maioria dos navegadores desktop já vem com essa ferramenta instalada. No Chrome, é possível chegar ao Console apertando F12 e em seguida acessar a aba "Console" ou por meio do atalho de teclado Control + Shift + C; no Firefox, pelo atalho Control + Shift + K.

Developer Tools

O console faz parte de uma série de ferramentas embutidas nos navegadores especificamente para nós que estamos desenvolvendo um site. Essa série de ferramentas é o que chamamos de Developer Tools.

Para aprender mais javascript, na próxima seção executaremos alguns códigos no console.

Aprenda se divertindo na Alura Start!

Você conhece alguém que tem potencial para tecnologia e programação, mas que nunca escreveu uma linha de código? Pode ser um filho, sobrinho, amigo ou parente distante. Na Alura Start ela vai poder criar games, apps, sites e muito mais! É o começo da jornada com programação e a porta de entrada para uma possível carreira de sucesso. Ela vai estudar em seu próprio ritmo e com a melhor didática. A qualidade da conceituada Alura, agora para Starters.

Conheça os cursos online da Alura Start!

11.5 Sintaxe básica

Operadores

Podemos somar, subtrair, multiplicar e dividir como em qualquer linguagem:

Teste algumas contas digitando diretamente no console:

> 12 + 13
  25
> 14 * 3
  42
> 10 - 4
  6
> 25 / 5
  5
> 23 % 2
  1

Variáveis

Para armazenarmos um valor para uso posterior, podemos criar uma variável:

> var resultado = 102 / 17;
undefined

No exemplo acima, guardamos o resultado de 102 / 17 na variável resultado. O resultado de criar uma variável é sempre undefined. Para obter o valor que guardamos nela ou mudar o seu valor, podemos fazer o seguinte:

> resultado
6

> resultado = resultado + 10
16

>resultado
16

Também podemos alterar o valor de uma variável usando essas operações com uma sintaxe bem compacta:

> var idade = 10;
> idade += 10; // idade vale 20
> idade -= 5; // idade vale 15
> idade /= 3; // idade vale 5
> idade *= 10; // idade vale 50

Tipos de dados

Não são apenas números que podemos salvar numa variável. O Javascript tem vários tipos de dados.

Number

Com esse tipo de dados é possível executar todas as operações que vimos anteriormente

var pi = 3.14159;
var raio = 20;
var perimetro = 2 * pi * raio

String

Uma string em JavaScript é utilizada para armazenar trechos de texto:

var empresa = "Caelum";

Para exibirmos o valor da variável empresa fora do console, podemos executar o seguinte comando:

alert(empresa);

O comando alert serve para criação de popups com algum conteúdo de texto que colocarmos dentro dos parênteses. O que acontece com o seguinte código?

var numero = 30;
alert(numero)

O número é exibido sem problemas dentro do popup. O que acontece é que qualquer variável pode ser usada no alert. O javascript não irá diferenciar o tipo de dados que está armazenado numa variável, e se necessário, tentará converter o dado para o tipo desejado, como ocorreu no alert.

Automatic semicolon insertion (ASI)

É possível omitir o ponto e vírgula no final de cada declaração. A omissão de ponto e vírgula funciona no Javascript devido ao mecanismo chamado automatic semicolon insertion (ASI).

11.6 A tag script

O console nos permite testar códigos diretamente no navegador. Porém, não podemos pedir aos usuários do site que sempre abram o console, copiem um código e colem para ele ser executado.

Para inserirmos um código JavaScript em uma página, é necessário utilizar a tag <script>:

<script>
  alert("Olá, Mundo!");
</script>

A tag <script> pode ser declarada dentro da tag <head> assim como na tag <body>, mas devemos ficar atentos, porque o código é lido imediatamente dentro do navegador. Veja a consequência disso nos dois exemplos abaixo:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Aula de JS</title>
    <script>
       alert("Olá, Mundo!");
    </script>
  </head>
  <body>
    <h1>JavaScript</h1>
    <h2>Linguagem de programação</h2>
  </body>
</html>

Repare que, ao ser executado, o script trava o processamento da página. Imagine um script que demore um pouco mais para ser executado ou que exija alguma interação do usuário como uma confirmação. Não seria interessante carregar a página toda primeiro antes de sua execução por uma questão de performance e experiência para o usuário?

Para fazer isso, basta removermos o script do head, colocando-o no final do body:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Aula de JS</title>
  </head>
  <body>
    <h1>JavaScript</h1>
    <h2>Linguagem de Programação</h2>
    <script>
      alert("Olá, Mundo!");
    </script>
  </body>
</html>

Devemos sempre colocar o script antes de fecharmos a tag </body>? Na maioria esmagadora das vezes sim.

JavaScript em arquivo externo

Imagine ter que escrever o script toda vez que ele for necessário. Se ele for utilizado em outra página? Por isso é possível importar scripts dentro da página utilizando também a tag <script>:

No arquivo HTML

<script src="js/hello.js"></script>

Arquivo externo js/hello.js

alert("Olá, Mundo!");

Com a separação do script em arquivo externo é possível reaproveitar alguma funcionalidade em mais de uma página.

Mensagens secretas no console

É comum querermos dar uma olhada no valor de alguma varíavel ou resultado de alguma operação durante a execução do código. Nesses casos, poderíamos usar um alert. Porém, se esse conteúdo deveria somente ser mostrado para o desenvolvedor, o console do navegador pode ser utilizado no lugar do alert para imprimir essa mensagem:

var mensagem = "Olá mundo";
console.log(mensagem);

Impressão de variáveis diretamente do console

Quando você estiver com o console aberto, não é necessário chamar console.log(nomeDavariavel): você pode chamar o nome da variável diretamente que ela será impressa no console.

11.7 DOM: sua página no mundo JavaScript

Para permitir alterações na página, ao carregar o HTML da página, os navegadores carregam em memória uma estrutura de dados que representa cada uma das nossas tags no javascript. Essa estrutura é chamada de DOM (Document Object Model). Essa estrutura pode ser acessada através da variável global document.

O termo "documento" é frequentemente utilizado em referências à nossa página. No mundo front-end, documento e página são sinônimos.

querySelector

Antes de sair alterando nossa página, precisamos em primeiro lugar acessar no JavaScript o elemento que queremos alterar. Como exemplo, vamos alterar o conteúdo de um título da página. Para acessar ele:

document.querySelector("h1")

Esse comando usa os seletores CSS para encontrar os elementos na página. Usamos um seletor de nome de tag mas poderíamos ter usado outros:

document.querySelector(".class")
document.querySelector("#id")

Elemento da página como variável

Se você vai utilizar várias vezes um mesmo elemento da página, é possível salvar o resultado de qualquer querySelector numa variável:

var titulo = document.querySelector("h1")

Executando no console, você vai perceber que o elemento correspondente é selecionado. Podemos então manipular seu conteúdo. Você pode ver o conteúdo textual dele com:

titulo.textContent

Essa propriedade inclusive pode receber valores e ser alterada:

titulo.textContent = "Novo título"

querySelectorAll

Ás vezes você precisa selecionar vários elementos na página. Várias tags com a classe .secao por exemplo. Se o retorno esperado é mais de um elemento, usamos querySelectorAll que devolve uma lista de elementos (array).

document.querySelectorAll(".cartao")

Podemos então acessar elementos nessa lista através da posição dele (começando em zero) e usando o colchetes:

// primeiro cartão
document.querySelectorAll(".cartao")[0]

Alterações no DOM

Ao alterarmos os elementos da página, o navegador sincroniza as mudanças e alteram a aplicação em tempo real.

Seus livros de tecnologia parecem do século passado?

Conheça a Casa do Código, uma nova editora, com autores de destaque no mercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntos atuais.
Com a curadoria da Caelum e excelentes autores, é uma abordagem diferente para livros de tecnologia no Brasil.

Casa do Código, Livros de Tecnologia.

11.8 Funções e os eventos do DOM

Apesar de ser interessante a possibilidade de alterar o documento todo por meio do JavaScript, é muito comum que as alterações sejam feitas quando o usuário executa alguma ação, como por exemplo, mudar o conteúdo de um botão ao clicar nele e não quando a página carrega. Porém, por padrão, qualquer código colocado no script, como fizemos anteriormente, é executado assim que o navegador lê ele.

Para guardarmos um código para ser executado em algum outro momento, por exemplo, quando o usuário clicar num botão, é necessário utilizar de dois recursos do JavaScript no navegador. O primeiro é a a criação de uma função:

function mostraAlerta() {
  alert("Funciona!");
}

Ao criarmos uma função, simplesmente guardamos o que estiver dentro da função, e esse código guardado só será executado quando chamarmos a função, como no seguinte exemplo:

function mostraAlerta() {
  alert("Funciona!");
}

//fazendo uma chamada para a função mostraAlerta, que será executada nesse momento
mostraAlerta()

Para chamar a função mostraAlerta só precisamos utilizar o nome da função e logo depois abrir e fechar parênteses.

Agora, para que essa nossa função seja chamada quando o usuário clicar no botão da nossa página, precisamos do seguinte código:

function mostraAlerta() {
  alert("Funciona!");
}

// obtendo um elemento através de um seletor de ID
var titulo = document.querySelector("button");

titulo.onclick = mostraAlerta;

Note que primeiramente foi necessário selecionar o botão e depois definir no onclick que o que vai ser executado é a função mostraAlerta. Essa receita será sempre a mesma para qualquer código que tenha que ser executado após alguma ação do usuário em algum elemento. O que mudará sempre é qual elemento você está selecioando, a qual evento você está reagindo e qual função será executada.

Quais eventos existem?

Existem diversos eventos que podem ser utilizados em diversos elementos para que a interação do usuário dispare alguma função:

Existem também uma série de outros eventos mais avançados que permitem a criação de interações para drag-and-drop, e até mesmo a criação de eventos customizados.

11.9 Exercícios: mostrando tamanho do produto com javascript

  1. Na página produto.php, adicione o elemento output do HTML5 logo após o input range, ainda dentro do fieldset de escolha de tamanho.

     <output for="tamanho" name="valortamanho">42</output>
    

    Repare que esse elemento não tem visual específico e também não atualiza seu valor sozinho. Vamos implementar isso via JavaScript.

  2. O preenchimento inicial e atualização do valor no output deve ser feita via JavaScript. Quando o input range mudar de valor (evento oninput), pegamos seu valor e jogamos no output.

    Para escrever o JavaScript, você pode criar um novo arquivo produto.js e importá-lo na página. Ou, como o código é bem pequeno, se preferir, pode escrever direto num elemento <script> na página.

    O nosso código é:

     var inputTamanho = document.querySelector('[name=tamanho]')
     var outputTamanho = document.querySelector('[name=valortamanho]')
    
     function mostraTamanho(){
         outputTamanho.value = inputTamanho.value
     }
    
     inputTamanho.oninput = mostraTamanho
    

    Teste o funcionamento no slider no range, veja se o output atualiza de valor corretamente.

    IE10

    Para suportar o IE10, precisamos colocar o evento onchange. O correto no HTML5 seria usar o evento oninput, que até funciona melhor nos browsers modernos.

    inputTamanho.oninput = mostraTamanho
    inputTamanho.onchange = mostraTamanho
    

    Além disso, como o elemento output não é corretamente reconhecido pelo navegador, alterar a propriedade value dele não vai ter o resultado esperado. Para o nosso código funcionar nele, precisamos mexer diretamente no texto do elemento:

    function mostraTamanho(){
       outputTamanho.value = inputTamanho.value
       outputTamanho.textContent = event.target.value
    }
    
  3. Estilize o output para ter um design mais ajustado a nossa página de produto:

     .tamanhos output {
         display: inline-block;
         height: 44px;
         width: 44px;
    
         line-height: 44px;
         text-align: center;
    
         border: 3px solid #666;
         border-radius: 50%;
         color: #555;
     }
    

11.10 Funções Anônimas

No exercício anterior nós indicamos que a função mostraTamanho deveria ser executada no momento em que o usuário inserir o tamanho do produto no <input type="range">. Note que não estamos executando a função mostraTamanho, já que não colocamos os parênteses. Estamos apenas indicando o nome da função que deve ser executada.

inputTamanho.oninput = mostraTamanho

function mostraTamanho(){
    outputTamanho.value = inputTamanho.value
}

Há algum outro lugar do código no qual chamemos essa função? Não! Porém, é pra isso que damos um nome à uma função, para que seja possível usá-la em mais de um ponto do código.

É muito comum que algumas funções tenham uma única referência no código. É o nosso caso com a function mostraTamanho. Nesses casos, o javascript permite que criemos a função no lugar onde antes estávamos indicando seu nome.

inputTamanho.oninput = function(){
    outputTamanho.value = inputTamanho.value
}

Transformamos a função mostraTamanho em uma função sem nome, uma função anônima. Ela continua sendo executada normalmente quando o usuário inserir algum valor para o tamanho.

Agora é a melhor hora de respirar mais tecnologia!

Se você está gostando dessa apostila, certamente vai aproveitar os cursos online que lançamos na plataforma Alura. Você estuda a qualquer momento com a qualidade Caelum. Programação, Mobile, Design, Infra, Front-End e Business! Ex-aluno da Caelum tem 15% de desconto, siga o link!

Conheça a Alura Cursos Online.

11.11 Manipulando strings

Uma variável que armazena um string faz muito mais que isso! Ela permite, por exemplo, consultar o seu tamanho e realizar transformações em seu valor.

var empresa = "Caelum";

empresa.length; // tamanho da string

empresa.replace("lum","tano"); // retorna Caetano

A partir da variável empresa, usamos o operador ponto seguido da ação replace.

Imutabilidade

String é imutável. Logo, no exemplo abaixo, se a variável empresa for impressa após a chamada da função replace, o valor continuará sendo "Caelum". Para obter uma String modificada, é necessário receber o retorno de cada função que manipula a String, pois uma nova String modificada é retornada:

var empresa = "Caelum";

// substitui a parte "lum" por "tano"
empresa.replace("lum","tano");
console.log(empresa); // imprime Caelum, não mudou

empresa = empresa.replace("lum","tano");
console.log(empresa); // imprime Caetano, mudou!

Conversões

O JavaScript possui funções de conversão de string para number:

var textoInteiro = "10";
var inteiro = parseInt(textoInteiro);

var textoFloat = "10.22";
var float = parseFloat(textoFloat);

11.12 Manipulando números

Number, assim como String, também é imutável. O exemplo abaixo altera o número de casas decimais com a função toFixed. Esta função retorna uma string mas, para ela funcionar corretamente, seu retorno precisa ser capturado:

var milNumber = 1000;
var milString = milNumber.toFixed(2); // recebe o retorno da função
console.log(milString); // imprime a string "1000.00"

11.13 Concatenações

É possível concatenar (juntar) tipos diferentes e o JavaScript se encarregará de realizar a conversão entre os tipos, podendo resultar em algo não esperado.

String com String

var s1 = "Caelum";
var s2 = "Inovação";
console.log(s1 + s2); // imprime CaelumInovação

String com outro tipo de dados

Como vimos, o JavaScript tentará ajudar realizando conversões quando tipos diferentes forem envolvidos numa operação, mas é necessário estarmos atentos na maneira como ele as realiza:

var num1 = 2;
var num2 = 3;
var nome = "Caelum"

// Exemplo 1: O que ele imprimirá?
console.log(num1 + nome + num2); // imprime 2Caelum3

// E agora? O que ele imprimirá?
// Exemplo 2:
console.log(num1 + num2 + nome); // imprime 5Caelum

// E agora? O que ele imprimirá?
// Exemplo 3:
console.log(nome + num1 + num2); // imprime Caelum23

// Exemplo 4:
console.log(nome + (num1 + num2)); // imprime Caelum5

// Exemplo 5:
console.log(nome + num1 * num2); // imprime Caelum6.
// A multiplicação tem precedência

NaN

Veja o código abaixo:

  console.log(10-"curso")

O resultado é NaN (not a number). Isto significa que todas operações matemáticas, exceto subtração, que serão vistas mais a frente, só podem ser feitas com números. O valor NaN ainda possui uma peculiaridade, definida em sua especificação:

var resultado = 10-"curso"; // retorna NaN
resultado == NaN; // false
NaN == NaN; // false

Não é possível comparar uma variável com NaN, nem mesmo NaN com NaN! Para saber se uma variável é NaN, deve ser usada a função isNaN:

var resultado = 10-"curso";
isNaN(resultado); // true

Editora Casa do Código com livros de uma forma diferente

Editoras tradicionais pouco ligam para ebooks e novas tecnologias. Não dominam tecnicamente o assunto para revisar os livros a fundo. Não têm anos de experiência em didáticas com cursos.
Conheça a Casa do Código, uma editora diferente, com curadoria da Caelum e obsessão por livros de qualidade a preços justos.

Casa do Código, ebook com preço de ebook.

11.14 Exercício: Calculando o total da compra

  1. Para que o usuário possa escolher a quantidade do produto que ele quer comprar, criaremos um campo para a quantidade e outro para exibição do valor total.

    Os campos serão inseridos dentro da div.panel-body na página checkout.php. Antes de inserirmos, procure a div.panel-body no seu código. Se você seguiu os exercícios anteriores, ela deve estar assim:

    <div class="panel-body">
         <img src="img/produtos/foto1-<?= $_POST["cor"] ?>.png" class="img-thumbnail img-responsive">
         <dl>
             <dt>Produto</dt>
             <dd><?= $_POST["nome"] ?></dd>
             <dt>Preço</dt>
             <dd>R$ <?= $_POST["preco"] ?></dd>
             <dt>Cor</dt>
             <dd><?= $_POST["cor"] ?></dd>
             <dt>Tamanho</dt>
             <dd><?= $_POST["tamanho"] ?></dd>
         </dl>
         <!-- Aqui virá o código -->
    </div>
    

    Agora, podemos adicionar os campos citados no panel-body, que ficará assim:

    <div class="panel-body">
     <img src="img/produtos/foto1-<?= $_POST["cor"] ?>.png" class="img-thumbnail img-responsive">
     <dl>
         <dt>Produto</dt>
         <dd><?= $_POST["nome"] ?></dd>
         <dt>Preço</dt>
         <dd>R$ <?= $_POST["preco"] ?></dd>
         <dt>Cor</dt>
         <dd><?= $_POST["cor"] ?></dd>
         <dt>Tamanho</dt>
         <dd><?= $_POST["tamanho"] ?></dd>
     </dl>
    
     <div class="form-group">
         <label for="qt">Quantidade</label>
         <input id="qt" class="form-control" type="number" min="0" max="99" value="1">
     </div>
     <div class="form-group">
         <label for="total">Total</label>
         <output id="total" class="form-control">
             <?= $_POST["preco"] ?>
         </output>
     </div>
    </div>
    
  2. Ainda dentro da div.painel-body, adicione um id à <dd> do preço para que o preço unitário seja acessível de forma mais simples quando implementarmos nosso javascript.

         <dd id="preco">R$ <?= $_POST["preco"] ?></dd>
    

    Agora que tanto o <dd> do preço e o <input> da quantidade têm ids, é possível dizer que nossa tag <output> é resultado de alguma operação dos dois:

     <output for="qt preco" id="total" class="form-control">
         <?= $_POST["preco"] ?>
     </output>
    
  3. O usuário já consegue inserir a quantidade que ele deseja, porém, nada acontece. Para que o valor total da compra seja alterado quando o usuário alterar a quantidade, precisaremos de javascript.

    Crie o arquivo total.js dentro da pasta js e importe ele na sua página.

         <script src="js/total.js"></script>
    
  4. Agora, dentro de total.js precisamos acessar os elementos da nossa página. Pegaremos o conteúdo da <dd> de preço do produto e multiplicaremos pela quantidade que o usuário digitar no <input> de quantidade.
  var $input_quantidade = document.querySelector("#qt");
  var $output_total = document.querySelector("#total");

  $input_quantidade.oninput = function(){
    var preco = document.querySelector("#preco").textContent;
    preco = preco.replace("R$ ", "");
    preco = preco.replace(",", ".");
    preco = parseFloat(preco);

    var quantidade = $input_quantidade.value;
    var total = quantidade * preco;
    total = "R$ " + total.toFixed(2)
    total = total.replace(".", ",");

    $output_total.value = total;
  }
Agora, teste sua página, o cálculo do total já deve estar funcionando.

Argumentos em funções

É possível definir que a função vai ter algum valor variável que vamos definir quando quisermos executá-la:

function mostraAlerta(texto) {
  // Dentro da função "texto" conterá o valor passado na execução.
  alert(texto);
}

// Ao chamar a função é necessário definir o valor do "texto"
mostraAlerta("Funciona com argumento!");

11.15 Array

O array é útil quando precisamos trabalhar com diversos valores armazenados:

var palavras = ["Caelum", "Ensino"];
palavras.push("Inovação"); // adiciona a string "Inovação"

Também é possível guardar valores de tipos diferentes:

var variosTipos = ["Caelum", 10, [1,2]];

Como obter um valor agora? Lembre-se que o tamanho de um array vai de 0 até o seu tamanho - 1.

console.log(variosTipos[1]) // imprime 10!

Adicionando elemento pelo índice

No lugar de usar a função push, que adiciona o elemento como último do array é possível fazer:

var palavras = ["Caelum", "Ensino"];
palavras[9] = "Inovação";

Isso alterará o tamanho do array para dez e adicionará na última posição a string "Inovação", deixando as posições intermediárias com o valor undefined.

Outros aspecto interessante é o tamanho do array: podemos adicionar quantos elementos quisermos que seu tamanho aumentará quando necessário.

11.16 Blocos de Repetição

Muitas vezes precisamos executar um trecho de código repetidamente até que uma condição seja contemplada, ou enquanto uma condição for verdadeira. Para isso, o JavaScript oferece uma série de blocos de repetição. O mais comum é o for.

for

O bloco for precisa de algumas informações de controle para evitar que ele execute infinitamente:

for (/* variável de controle */; /* condição */; /* pós execução */) {
  // código a ser repetido
}

Das informações necessárias, somente a condição é obrigatória, mas normalmente utilizamos todas as informações:

var palavras = ["Caelum", "Ensino"];

for (var i = 0; i < palavras.length; i++) {
  alert(palavras[i]);
}

while

O bloco while executa determinado código repetitivamente enquanto uma condição for verdadeira. Diferente do bloco for, a variável de controle, bem como sua manipulação, não são responsabilidades do bloco em si:

var contador = 1;

while (contador <= 10) {
  alert(contador + " Mississípi...");
  contador++;
}

alert("Valor do contador: " + contador);

Já conhece os cursos online Alura?

A Alura oferece centenas de cursos online em sua plataforma exclusiva de ensino que favorece o aprendizado com a qualidade reconhecida da Caelum. Você pode escolher um curso nas áreas de Programação, Front-end, Mobile, Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex aluno da Caelum tem 15% de desconto neste link!

Conheça os cursos online Alura.

11.17 Funções temporais

Em JavaScript, podemos criar um timer para executar um trecho de código após um certo tempo, ou ainda executar algo de tempos em tempos.

A função setTimeout permite que agendemos alguma função para execução no futuro e recebe o nome da função a ser executada e o número de milissegundos a esperar:

    // executa a minhaFuncao daqui um segundo
    setTimeout(minhaFuncao, 1000);

Se for um código recorrente, podemos usar o setInterval que recebe os mesmos argumentos mas executa a função indefinidamente de tempos em tempos:

    // executa a minhaFuncao de um em um segundo
    setInterval(minhaFuncao, 1000);

É uma função útil para, por exemplo, implementar um banner rotativo, como faremos no exercício a seguir.

clearInterval

As funções temporais devolvem um objeto que representa o agendamento que foi feito. É possível usá-lo para cancelar a execução no futuro. É especialmente interessante para o caso do interval que pode ser cancelado de sua execução infinita:

        // agenda uma execução qualquer
        var timer = setInterval(minhaFuncao, 1000);

        // cancela execução
        clearInterval(timer);

11.18 Exercício opcional: banner rotativo

  1. Implemente um banner rotativo na home page da Mirror Fashion usando JavaScript.

    Temos duas imagens, a destaque-home.png e a destaque-home-2.png que queremos trocar a cada 4 segundos; use o setInterval para isso.

    Há várias formas de implementar essa troca de imagens. Uma sugestão é manter um array com os valores possíveis para a imagem e um inteiro que guarda qual é o banner atual.

         var banners = ["img/destaque-home.png", "img/destaque-home-2.png"];
         var bannerAtual = 0;
    
         function trocaBanner() {
             bannerAtual = (bannerAtual + 1) % 2;
             document.querySelector('.destaque img').src = banners[bannerAtual];
         }
    
         setInterval(trocaBanner, 4000);
    
  2. (opcional, avançado) Faça um botão de pause que pare a troca do banner.

    Dica: use o clearInterval para interromper a execução.

  3. (opcional, avançado) Faça um botão de play para reativar a troca dos banners.

Para saber mais: sugestão para o desafio de pause/play

Podemos criar no HTML um novo link para controlar a animação:

    <a href="#" class="pause"></a>

O JavaScript deve chamar clearInterval para pausar ou novamente o setInterval para continuar a animação.

Precisamos editar o código anterior que chamava o setInterval para pegar o seu retorno. Será um objeto que controla aquele interval e nos permitirá desligá-lo depois:

var timer = setInterval(trocaBanner, 4000);

Com isso, nosso código que controla o pause e play ficaria assim:

    var timer = setInterval(trocaBanner, 4000);
    var controle = document.querySelector('.pause');

    controle.onclick = function() {
        if (controle.className == 'pause') {
            clearInterval(timer);
            controle.className = 'play';
        } else {
            timer = setInterval(trocaBanner, 4000);
            controle.className = 'pause';
        }

        return false;
    };

Por fim, podemos estilizar o botão como pause ou play apenas trabalhando com bordas no CSS:

    .destaque {
      position: relative;
    }
    .pause,
    .play {
      display: block;
      position: absolute;
      right: 15px;
      top: 15px;
    }
    .pause {
      border-left: 10px solid #900;
      border-right: 10px solid #900;
      height: 30px;
      width: 5px;
    }
    .play {
      border-left: 25px solid #900;
      border-bottom: 15px solid transparent;
      border-top: 15px solid transparent;
    }

11.19 Para saber mais: vários callbacks no mesmo elemento

Nos exercícios que trabalhamos com eventos, usamos o onclick e o onsubmit diretamente no elemento que estávamos manipulando:

    document.querySelector('#destaque').onclick = function() {
        // tratamento do evento
    };

É uma forma fácil e portável de se tratar eventos, mas não muito comum na prática. O maior problema do código acima é que só podemos atrelar uma única função ao evento. Se tentarmos, em outra parte do código, colocar uma segunda função para executar no mesmo evento, ela sobrescreverá a anterior.

A maneira mais recomendada de se associar uma função a eventos é com o uso de addEventListener:

    document.querySelector('#destaque').addEventListener('click', function() {
        // tratamento do evento
    });

Dessa maneira, conseguimos adicionar vários listeners ao mesmo evento, deixando o código mais flexível. Só há um porém: embora seja o modo oficial de se trabalhar com eventos, o addEventListener não é suportado do IE8 pra baixo.

Para atender os IEs velhos, usamos a função attachEvent, semelhante:

    document.querySelector('#destaque').attachEvent('onclick', function() {
        // tratamento do evento
    });

O problema é ter que fazer sempre as duas coisas para garantir a portabilidade da nossa página. Essa questão é resolvida pelos famosos frameworks JavaScript, como o jQuery, que veremos mais adiante no curso.

Saber inglês é muito importante em TI

Na Alura Língua você reforça e aprimora seu inglês! Usando a técnica Spaced Repetitions o aprendizado naturalmente se adapta ao seu conhecimento. Exercícios e vídeos interativos fazem com que você pratique em situações cotidianas. Além disso, todas as aulas possuem explicações gramaticais, para você entender completamente o que está aprendendo. Aprender inglês é fundamental para o profissional de tecnologia de sucesso!

Pratique seu inglês na Alura Língua.

11.20 Para saber mais: controlando as validações HTML5

A ideia da nova validação do HTML5 é permitir que os navegadores já possuam uma forma simples de prover validações sem que os desenvolvedores precisem recorrer a complicadas bibliotecas JavaScript (algo comum em muitas páginas).

No entanto, muitas vezes, as opções padrão do navegador não são exatamente o que precisamos, e queremos mudar o comportamento da validação ou executar validações personalizadas e diferentes.

Podemos, então, usando JavaScript, desabilitar a validação padrão e fazer a nossa própria:

<script type="text/javascript">
document.querySelector('form input').oninvalid = function(event) {
    // cancela comportamento padrão do browser
    event.preventDefault();

    // verifica a validade e mostra o alert
    if (!this.validity.valid) {
        alert("Nome obrigatório!");
    }
};
</script>

Isso nos permite trocar, por exemplo, todo o visual e forma de apresentação dos erros. E, o melhor, caso o usuário esteja com JavaScript desabilitado, será executada a validação padrão sem problemas. Um ótimo fallback. (nas soluções tradicionais de validação dom jQuery, por exemplo, tudo se perde quando o usuário desabilita JavaScript).

Outra forma de desabilitar a validação, afetando o formulário inteiro, é colocando o atributo novalidate na tag <form>.

Além de desabilitar completamente a validação do navegador, podemos apenas trocar a mensagem de erro mas ainda usar o mecanismo e design padrão:

<script type="text/javascript">
document.querySelector('input[type=email]').oninvalid = function() {

  // remove mensagens de erro antigas
  this.setCustomValidity("");

  // executa novamente a validação
  if (!this.validity.valid) {

      // se inválido, coloca mensagem de erro
      this.setCustomValidity("Email inválido");
  }
};
</script>