Objeto: ter primeiro contato com JavaScript numa página Web - entender o objeto document (estrutura e métodos), a propriedade innerHTML do elementos, funções simples, variáveis locais e manipulação de cliques
Principais termos técnicos abordados: html, JavaScript, function, let, div, button, onclick
Requisitos para as instruções funcionarem: editor de texto instalados
Requisitos para compreensão das instruções: noções bem básicas de HTML
Como ler essa receita: instruções, dentro dos passos da receita e que requerem ação sua no computador, estarão escritas em cor azul. Comentários sobre os passos estarão em fonte normal, cor preta. Comandos, código-fonte, termos técnicos ou configuração explícita, estarão com fonte diferenciada.
Crianças, vamos começar a brincar de JavaScript.
Inicialmente, nosso código JavaScript (ou, abreviadamente, JS) irá rodar ao seio de uma página web - dentro de uma página web, pra usar um termo mais conhecido.
Assim a página web que abriga seu código JS funciona como um contexto, um ambiente sob o qual o seu código é executado. Esse contexto oferece ao seu código um punhado de funções e objetos já prontos para a guerra. Isso inclui, CLARO, representações em objeto para simplesmente TODAS as marcas da página web ao seio da qual o JS é executado.
Isso dá uma característica interessante ao seu código. Se ele tem acesso a uma representação de objetos para todos os elementos gráficos de sua página, é possível manipular esses elementos programaticamente - animá-los, mudar seu estilo, acrescentar novos elementos gráficos abaixo de um elemento específico, excluir elementos etc.
Dá pra acanalhar a interface gráfica da página também, então usemos o recurso com moderação.
Nesta receita a gente vai aprender a escrever scripts para transformar um vetor de objetos - um vetor de informações - em elementos de interface com o usuário e exibi-los dentro da página onde o script roda.
Salve um arquivo de nome index.html com o seguinte conteúdo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div>Carregando cervejas...</div>
</body>
</html>
A marca <div> funciona como uma divisão de uma porção da página, como se fosse uma fatia horizontal. Abrindo no navegador, você deve ver algo como...
Por enquanto, nada demais. Aquele <meta charset="UTF-8"> apenas indica ao navegador a codificação dos caracteres do texto. Você pode suprimir essa marca ou trocar a codificação, caso esteja usando alguma outra.
- Ah, mas cadê o JS, professor? Só tem HTML aí...
Calma que o Brasil é nosso.
Abra o arquivo no navegador, clique com o botão direito na página e selecione a opção "Inspecionar".
Ou selecione coisa parecida com isso, esse é um termo usado pelo Chrome. Se não estiver visível essa opção, instale a extensão de desenvolvedor. Pesquise no google ou pergunte a alguém mais esperto que você, é um procedimento simples.
Se você fez tudo direitinho, após selecionar a opção Inspecionar, vai aparecer algo como na imagem abaixo.
Agora, selecione a aba Console.
Pronto, você está programaticamente dentro da página. Pode escrever scripts, executá-los, ver e executar todos os objetos e funções que scripts de dentro da sua página veriam ou executariam. A gente vai escrever esse código inicial por aqui, depois a gente transfere o que achar interessante para a página HTML em si.
Só para brincar, escreva, no Console, o comando a seguir, dando enter em seguida.
alert("eu existo")
Teclando enter, você deve ver algo como na imagem que se segue.
Sei que não há nada mais "década de 90", no pior sentido, do que esses alert(), mas o ponto aqui é que você perceba que esse ambiente roda script dentro da sua página, que pode ter efeitos na interface dela.
Além dessa funçãozinha mequetrefe, você tem acesso a diversas outras funções e também a diversos objetos.
Um desses objetos a que o código JS tem acesso é o document.
O document é como se fosse realmente a raiz da árvore HTML. A partir desse objeto você chega a outros objetos que representam todas as marcas escritas na sua página. E, em chegando até algum deles, você pode modificá-lo, o que pode causar efeitos na interface da página.
Vamos aprender a navegar nessa árvore e chegar até esses diversos objetos.
No console, escreva document.childNodes, tecle enter, e em seguida clique sobre o retorno da chamada (um NodeList).
O console deve exibir algo do tipo...
Note que o atributo childNodes do objeto document é, essencialmente, um vetor de dois objetos, um objeto representando a marca <!DOCTYPE> e um objeto representando a marca <html>. Note que NÃO estamos falando de texto. Esses elementos que acessamos a partir do documento são objetos que foram criados a partir do processamento do texto da página web.
Ora, se document.childNodes é esse vetor com essas duas marcas, document.childNodes[1] (segundo elemento do vetor) é um objeto que representa a marca html.
Escreva document.childNodes[1] e tecle enter.
Você deve ver algo do tipo...
Note que apareceu o nosso head e o nosso body, que estão no código html. Apareceu tambem um text, e eu não tenho a menor ideia do que seja. Mas o que importa aqui é que document.childNodes[1] é também um vetor (estamos "descendo" na árvore, caso não tenha percebido), e que o terceiro elemento (índice 2) é o tal do body que escrevemos.
Escreva document.childNodes[1].childNodes[2].childNodes e tecle enter
Como document.childNodes[1].childNodes[2] é o body, essa linha Escreva document.childNodes[1].childNodes[2].childNodes deve te dar os filhos do body...
De fato, vemos na imagem o nosso querido div lá no índice 1 do vetor. Queremos mexer no conteúdo desse div, e agora sabemos que a expressão document.childNodes[1].childNodes[2].childNodes[1] deve nos dar uma referência para ele.
Escreva document.childNodes[1].childNodes[2].childNodes[1]. (escreva o ponto, SEM dar enter)
O console deve exibir tudo o que esteja acessível a partir desse objeto, que a gente sabe, com todo esse moído, que representa a nossa marca div. E por "tudo" entenda propriedades e funções.
Uma dessas propriedades é o style. Vamos mexer com essa propriedade e ver se dá em alguma coisa.
Escreva o comando a seguir e tecle enter
document.childNodes[1].childNodes[2].childNodes[1].style = "color: red;"
A cor do texto deve mudar para vermelho...
E, se quisermos, podemos mudar todo o conteúdo da marca, para isso só precisaríamos saber qual propriedade representa o conteúdo da marca e mudar essa propriedade. Felizmente, nós sabemos...
Escreva o comando a seguir e tecle enter.
document.childNodes[1].childNodes[2].childNodes[1].innerHTML = `São Paulo, time xibata!`
Não precisa ser nenhum gênio para perceber que, por mais que seja legal termos essas possibilidades, será uma chatice dos infernos navegar nessa árvore para que a gente chegue até a marca que desejamos modificar.
Há, naturalmente, um jeito de contornar isso. Lembre que o document é um objeto. Tem informações e comportamentos nele, e um desses comportamentos é justamente o de achar alguma marca na árvore que se inicia com ele.
Para ajudarmos o document a achar uma marca, precisamos chamar aquela marca div de meu amor lá no código HTML. Não é a coisa mais sutil do mundo, mas provavelmente assim você não esquece. É assim que se faz.
Modifique o código HTML e deixe-o como a seguir:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="meu amor">Carregando uma cerveja...</div>
</body>
</html>
Agora o document vai achar esse div facilmente.
Recarrege a página e, no console, escreva os seguintes comandos:
let div = document.getElementById("meu amor")
div.innerHTML = `<h1>Guinness</h1>`
Claro, você não precisa chamar de meu amor, pode escolher um identificador de nome mais adequado ao conteúdo. Esse let serve para declaração de variáveis. Note que não especificamos o tipo da variável. O let quer apenas dizer em em seguida vem uma variável.
Mas ainda temos o problema de ter que escrever esse código JS no console. Claro que isso não é legal. Normalmente recorremos ao console para resolver problemas, então é importante que saibamos como lidar com ele, mas nosso código precisa estar na nossa página ou em algum arquivo referenciado por ela.
Vamos resolver mais isso.
Reescreva sua página para que fique como o código a seguir. Em seguida, salve e recarregue a página no navegador.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="meu amor">Carregando cervejas...</div>
</body>
<script>
let div = document.getElementById("meu amor")
div.innerHTML = `<h1>Guinness</h1>`
</script>
</html>
- Tá errado, professor, mostrou direto o nome da cerveja "Guiness" sem nem mostrar a mensagem "Carregando cervejas..."
Bem, na verdade, o navegador deve ter mostrado a mensagem "Carregando cervejas...", mas logo em seguida seu script foi executado e mudou o conteúdo do div para o nome da cerveja. Isso foi tão rápido que não deu nem para você ver a mensagem inicial.
É que esse código que está dentro da marca script se trata da execução direta de código. Não há espera por um evento ou intervalo de tempo para a execução do código. Podemos mudar isso.
Defina uma função com os dois comandos do seu script dentro dela. O código deve ficar como se segue. Salve e recarregue o arquivo.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="meu amor">Carregando cervejas...</div>
</body>
<script>
function carregarDiv(){
let div = document.getElementById("meu amor")
div.innerHTML = `<h1>Guinness</h1>`
}
</script>
</html>
- Ah, mas agora a página mostra apenas a mensagem, em mostrar o nome da cerveja em seguida...
Bem isso acontece porque seu script definiu a função carregarDiv(). Definir uma função é diferente de chamá-la, e em absolutamente nenhum ponto de seu código a função carregarDiv() está sendo invocada.
Note também que é bastante simples e peculiar definir uma função JS. Escreva a palavra-chave function, o nome da função, sem tipo de retorno, abra e feche parênteses e escreva o código entre chaves. Se houver parâmetros, eles estarão listados entre os parênteses, apenas com os nomes, sem tipos. Há outras formas de escrever funções JS e voltaremos a elas em outras receitas.
Vamos fazer com que a função seja carregarDiv() chamada a partir de um clique num botão. Para isso a gente precisa, claro, escrever o botão no código html e fazer com que um clique nele invoque a função carregarDiv().
Eu consigo lembrar de ao menos 3 maneiras de fazer isso, e vamos escrever e discutir cada uma delas.
Modifique seu código para que fique como a seguir. Salve o arquivo e recarregue a página.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="meu amor"><button id="botao" onclick="carregarDiv()">Carregando cervejas...</button></div>
</body>
<script>
function carregarDiv(){
let div = document.getElementById("meu amor")
div.innerHTML = `<h1>Guinness</h1>`
}
</script>
</html>
Basicamente, e gente pôs a mensagem "Carregando cervejas..." dentro de uma marca button. O que faz, para surpresa de ninguém, com que a mensagem fique dentro de um botão, algo parecido com a imagem a seguir.
E se você clicar no botão, vem a mágica...
Bem, o que faz a tal mágica é o onclick="carregarDiv(). Estamos definindo a propriedade onclick da marca button com uma chamada à função carregarDiv(). É simples desse jeito mesmo e o navegador vai entender, quando processar o código html para exibir a página, que a função que você escreveu deve ser invocada ao clique no botão. E o que a função faz? Bem, substitui o próprio botão que gerou o evento, que está dentro da marca div identificada por meu amor, pelo cabeçalho com o nome da cerveja.
Esse é o jeito mais fácil, mas há quem não veja com bons olhos essa alternativa, em parte porque a gente está usando um literal string para chamar uma função JavaScript, não cheira lá muito bem mesmo. Vamos às demais opções.
Modifique seu código para que fique como a seguir. Salve, recarregue, clique no botão, observe.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="meu amor"><button id="botaoCarregar">Carregando cervejas...</button></div>
</body>
<script>
function carregarDiv(){
let div = document.getElementById("meu amor")
div.innerHTML = `<h1>Guinness</h1>`
}
let botao = document.getElementById("botaoCarregar")
botao.onclick = carregarDiv
</script>
</html>
Bem, o comportamento é exatamente o mesmo do código anterior. A forma de escrever mudou, no entanto.
Basicamente, chamamos a marca button de "botaoCarregar" com a linha <button id="botaoCarregar">. Note que não dá pra chamar a marca button de "meu amor" aqui, porque você já chamou outra marca de meu amor, que é aquela marca div. Nesse caso, se você chamar as duas de meu amor, deve dar problema. Na vida real, pode até funcionar, e não é que não seja até útil essa prática. Mas, aqui na programação, você deve tomar cuidado com identificadores duplicados, pois a chamada a document.getElementById() pode não retornar quem você espera.
Além de dar um identificador único à marca button, acrescentamos duas linhas, fora de qualquer função, duas linhas que serão executadas diretamente quando a página for carregada, sem outras restrições. Uma linha para obter uma referência ao objeto que representa a marca button...
let botao = document.getElementById("botaoCarregar")
... outra para atribuir à propriedade onclick deste objeto a função carregarDiv...
botao.onclick = carregarDiv
Note que esta última linha NÃO invoca a sua função carregarDiv. Preste atenção que o nome da função está sendo usado SEM parênteses, então a função não está sendo invocada. É que em JS, podemos tratar as funções como variáveis. Vamos entender a coisa assim: estamos atribuindo à propriedade onclick do objeto botao a definição da função carregarDiv e não o retorno dela, como é a única possibilidade em outras linguagens. Quando o bendito clique for dado, o navegador se encarregará de empurrar um abre/fecha parênteses e chamar a função.
Você pode testar como isso funciona, vamos lá.
Recarregue a página e abra o console sem clicar em canto nenhum.
Declare uma variável e atribua a ela a CHAMADA da função carregarDiv, assim:
let f = carregarDiv()
Veja que você chamou a função, pois abriu e fechou os parênteses. Então o que foi atrubuído à variável f foi o resultado da execução da função carregarDiv. Ora, a execução dessa função modifica o div, e é isso que a gente vê. A execução também não retorna NADA, como a gente também pode verificar (não há comando return na função). Por esta razão, o valor armazenado na variável f após a execuçào da linha é undefined. Digitando f e teclando enter você pode confirmar facilmente o falor de f.
Mas agora recarregue a página e abra novamente o console.
Vamos fazer sutilmente diferente.
Escreva assim, no console:
let f = carregarDiv
Note que a gente NÃO usou parênteses. Ou seja, a função carregarDiv NÃO foi invocada. No entando, toda a definição da função foi atribuída à variável f. Teclando f e dando enter você deve ver algo do tipo...
Ou seja, sua variável é uma função. A rigor, é um objeto do tipo função.
Não precisa fazer isso, mas se você digitar f. no console deve ver algo do tipo...
É que toda função JS é um objeto e, por isso, podemos atribuir qualquer funçõa a qualquer variável, como fazemos com qualquer objeto.
Mas as funções são objetos, digamos, especiais. Você pode empurrar um () na frente de um objeto função e o corpo da função será computado.
Escreva no console...
f()
... e veja que o efeito é o mesmo de invocar a função carregarDiv, cuja definição foi atribuída à variável f. Você observaria efeito semelhante se escrevesse f.call().
Bem, não esqueça jamais disso se quiser ser um bom programador JS. Funções podem ser tratadas como variáveis. Posso atribuí-las a variáveis e passá-las como parâmetro sem executar o código definido em seu corpo.
Mas ainda há outra alternativa para o nosso script, e depois dessa prometo que a gente encerra a receita e parte para os Exercícios.
Modifique o códico para que fique como a seguir.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="meu amor"><button id="botaoCarregar">Carregando cervejas...</button></div>
</body>
<script>
function carregarDiv(){
let div = document.getElementById("meu amor")
div.innerHTML = `<h1>Guinness</h1>`
}
let botao = document.getElementById("botaoCarregar")
botao.addEventListener("click", carregarDiv)
</script>
</html>
Abra a página, clique no botão e veja que o efeito é o mesmo.
Apenas estamos usando o método addEventListener() em vez de atribuir um valor à propriedade onclick. Note também que usamos a função carregarDiv como se fosse uma variável, um objeto. Passamos como segundo parâmetro para o método botao.addEventListener() - o primeiro parâmetro é um string identificando o tipo de evento que deve disparar a chamada da função carregarDiv.
Bem, por essa receita é só.
Vamos a alguns pontos de revisão.
Aprendemos que podemos dar identificadores às marcas e isso faz com que uma representação dela possa ser facilmente encontrada através do método document.getElementById().
Além disso, mudando a propriedade x.innerHTML de algum objeto x faz com que o valor dessa propriedade seja processado como html pelo navegador e exibido dentro da marca representada por x, na página.
Aprendemos que manipulamos cliques em botões através da propriedade onclick, que pode ser escrita diretamente na marca html, mas também pode ser manipulada programaticamente.
Aprendemos, por fim, que funções JS são especiais, podem ser invocadas ou usadas como variáveis.
Documentação do objeto document, incluindo o método getElementById()
Faça com que o botão que desencadeia o aparecimento do nome da cerveja fique num div diferente do div que exibe o nome da cerveja. O botão deve ter o mesmo comportamento, sendo que vai ficar sempre visível.
Altere o comportamento do botão. Inicialmente, o clique exibe o nome Guiness num div diferente que está inicialmente vazio. Um clique subsequente apaga o div onde o nome Guiness está escrito.
Você deve cruzar os conhecimentos desta receita com receita anterior que trata de CSS. Acontece que a mudança do conteúdo dentro do div acontece muito bruscamente. Com 1 real e 99 de esforço a gente consegue fazer um efeito de fade out na opacidade do div, apagando seu conteúdo, e um efeito de fade in, mostrando o div novamente novamente, mas já com um novo innerHTML para exibir. Há outras possibilidades, claro. Você pode pesquisar por html effects for changing innerHTML ou js css fade effects for changing innerHTML