Skip to content

Latest commit

 

History

History

js2

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

JavaScript parte 2

Template strings, Função seta,
Alterando o DOM e Exploração Espacial 👽


Na última aula... (1/3)

  • Vimos novos elementos HTML para interação com o usuário:
    <label for="numero-de-pasteis">Pastéis: </label>
    <input type="number" value="1" id="numero-de-pasteis"> <!-- não fecha! -->
    
    <button id="calcular">Calcular Conta</button>
    • Para atribuir algum comportamento ao clique do <button>, é necessário usar JavaScript

Na última aula... (2/3)

  • Assim como em CSS, há 3 formas para incluir código JavaScript
    1. Arquivo externo com <script src="arquivo.js"></script> 👍
    2. Embutido na tag <script>...</script> 👎
    3. Inline em atributos onclick 👎👎👎
  • A preferida é arquivo externo, porque ela:
    • Promove reutilização de código JavaScript por mais de um arquivo HTML
    • Respeita o princípio da separação de responsabilidades

Na última aula... (3/3)

  • O DOM é a visão que o JavaScript tem dos elementos da página
  • Dá para recuperar/alterar elementos do DOM com o objeto document:
    // cria uma variável e recupera o elemento da logo (id="logomarca")
    let logoEl = document.querySelector('#logomarca');
    
    // atribui um evento de 'click' ao elemento da logo
    logoEl.addEventListener('click', function() {
      alert('Logo clicada!!'); 👹
    });

[DOM]: Document Object Model


Hoje veremos

  1. Template strings
  2. Função seta
  3. Alterando o DOM
  4. Exploração Espacial 👽

Template Strings

Criando strings bacanudas


O tipo 3. String

  • Representa um texto codificado em UTF-8
  • Não existe o tipo char como em C/C++ e Java, apenas string 😉
  • Usamos aspas simples ou duplas
    "Abc" === 'Abc'   // simples é mais legal!! mas basta ser consistente
  • Possui uma propriedade chamada length com o seu comprimento:
    console.log('Cachorro'.length); // 8
  • Exemplos:
    let aranhas = 'fofofauna';
    const caminhoVideo = 'videos/a.mp4';
    const nomeCompleto = primeiro + ' ' + ultimo;     // concatenou

Template Strings: interpolação de valores (1/2)

  • É uma forma mais recente para criar strings
  • Formato: usa-se crase para delimitar. Exemplo:
  • // template string
    let fruta = `Kiwi`;
    // string normal
    let fruta =  'Kiwi';
  • Permite interpolar (substituir) variáveis dentro de strings:
  • const peso = 82;
    const nome = 'Kagaro Nakama';
    
    // com template strings
    const frase = `${nome} pesa ${peso}kg`;
    // "Kagaro Nakama pesa 82kg"
    const peso = 82;
    const nome = 'Kagaro Nakama';
    
    // concatenando strings normais
    const frase = nome + ' pesa ' + peso + 'kg';
    // "Kagaro Nakama pesa 82kg"
  • A sintaxe é mais sucinta e legível
    • Vejamos outros exemplos...

Template Strings: interpolação de valores (2/2)

  • É possível colocar expressões dentre de ${...}. Exemplo:
    // supondo que existem variáveis preco=5 e qtde=2
    let aConta = `Sua conta é R$ ${preco * qtde - 3}`;
    //           "Sua conta é R$ 7"
  • // supondo variáveis dia, mês, ano e func. obtemMes
    const data = `${dia} de ${obtemMes(mes)} de ${ano}`;
    // Ex:       "20 de janeiro de 2021"
    const tom = 128;
    const corCinza = `rgb(${tom}, ${tom}, ${tom})`;
    // Ex:           "rgb(128, 128, 128)"
  • Mas qual é o tipo de dados??
    console.log(typeof "texto"); // imprime "string"
    console.log(typeof `texto`); // imprime "string"
    • É String mesmo! Só muda a sintaxe pra escrever
  • Ou seja, a interpolação é apenas uma sintaxe mais legal para concatenar strings com variáveis/expressões

Template Strings: texto multilinha

  • Digamos que você queira que uma variável string contenha uma poesia (ocupando várias linhas)
  • As template strings permitem que uma string ocupe mais do que uma linha no código fonte
  • // com template string
    let poesia = `Cavei cavei cavei
      Isto não é um poema
      Mas é profundo.`;
    // com string normal
    let poesia = 'Cavei cavei cavei\n' +
      'Isto não é um poema\n' +
      'Mas é profundo.';
  • Nesse caso, quando há uma quebra de linha no código fonte, é colocado um \n dentro da template string

Função Seta

A 3ª forma para funções

  • 3 Formas:
    • Função tradicional
    • Função anônima
    • Função seta (anônima também)

Função tradicional e anônima

  • function cadastrar() {
      // ...
    }
    const cadastrar = function() {
      // ...
    };
  • Função seta é uma sintaxe mais nova e sucinta para as anônimas ⬆
  • const cadastrar = () => {
      // ...
    };
    1. Omitir function
    2. Seta entre parâmetros e corpo
    3. return implícito
    4. Mantém o valor do ponteiro this
  • Os três primeiros itens já são legais o suficiente pra preferirmos a forma da função seta
    • Vejamos alguns exemplos

Função seta: sintaxe

  • function ciao() {
      return 'Ciao';
    }
    
    function oi(prim, ult) {
      return 'Oi ' + prim + ' ' + ult;
    }
    
    function hi(name) {
      return 'Hi ' + name;
    }
    
    function fatorial(n) {
      let resultado = 1;
      while (n > 1) {
        resultado *= n;
        n--;
      }
      return resultado;  
    }
    
    let ciao = () => 'Ciao';
    
    
    
    let oi = (prim, ult) => 'Oi ' + prim + ' ' + ult;
    
    
    
    let hi = name => 'Hi ' + name;
    
    
    
    let fatorial = n => {
      let resultado = 1;
      while (n > 1) {
        resultado *= n;
        n--;
      }
      return resultado;  
    }

Exemplo: funções seta com vetores

let usuarios = ['Joel', 'Fani', 'Fúlvio'];
let alunos = [{ matricula: '...' }];
let numeros = [1, 4, 2, 5];
  1. Pegar apenas usuários que começam com letra 'F':
    • usuarios.filter(function(nome) {
        return nome.startsWith('F');
      });
      usuarios.filter(nome => nome.startsWith('F'));
      
  2. Buscar pelo aluno com uma matrícula:
    • alunos.find(function(aluno) {
        return aluno.matricula === '2005046102';
      });
      alunos.find(al => al.matricula === '2005046102');
      
  3. Vetor com os quadrados do original:
    • numeros.map(function(numero) {
        return numero ** 2;
      });
      numeros.map(numero => numero ** 2);
      

Alterando o DOM

Mudando os elementos HTML

  • Relembrando document.querySelector()
  • Selecionando vários elementos
  • Alterando o contéudo
  • Alterando atributos
  • Colocando/removendo classes

Selecionando um elemento

  • O método document.querySelector(seletor) permite que, a partir de um código JavaScript, recuperemos um elemento do DOM
    • Ele recebe um único argumento que é um seletor CSS. Exemplo:
      let logoEl = document.querySelector('#logomarca');
      let tabelaEl = document.querySelector('#tesouros-pirata');
      let principalEl = document.querySelector('main');
      • Ele retorna um elemento HTML que pode ser alterado
    • Também existe document.querySelectorAll(seletor) (repare o all), que retorna mais de um elemento, mas veremos ele depois

Selecionando vários elementos

  • O document.querySelector retorna apenas 1 elemento
    • Se tiver mais de um, retorna o primeiro encontrado
  • O document.querySelectorAll retorna todos que forem selecionados:
    let inputs = document.querySelectorAll('input');  // retornou um 'NodeList'
                                                      // com todos inputs da página
    
    console.log(`Quantidade de inputs na página: ${inputs.length}`);
    let primeiroInputEl = inputs[0];

Selecionando vários elementos (2/3)

  • Para atribuir um evento a todos os elementos retornados:
    let imagens = document.querySelectorAll('img');  // retornou um 'NodeList'
    
    // INCORRETO: um NodeList não possui um método "addEventListener"
    imagens.addEventListener('click', function() { });
    
    // CORRETO: cada item do NodeList (array) é um elemento HTML, logo,
    // possui a propriedade "addEventListener"
    for (let i = 0; i < imagens.length; i++) {
      imagens[i].addEventListener('click', function() { });
    }

Selecionando vários elementos (3/3)

  • Um NodeList é "praticamente um array" - ele possui os métodos essenciais:
    let inputs = document.querySelectorAll('input');      // inputs é um 'NodeList'
  • // propriedade .length (igual um array)
    console.log(`Quantidade de elementos: ${inputs.length}`);
    // método 'forEach' (igual um array)
    inputs.forEach(function(el) {
      // ...
    });
    // pegando um elemento como se fosse um array
    let primeiroEl = inputs[0];

NodeList vs Vetor

  • Um NodeList é praticamente um array, mas não possui todos os métodos. Por exemplo:
  • umNodeList.length        
    umNodeList[5]            
    umNodeList.forEach(...)  
    
    umNodeList.indexOf(...)  
    umNodeList.sort()        
    umNodeList.reverse()     
    umNodeList.filter()      
    umNodeList.find()        
    umVetor.length          
    umVetor[5]              
    umVetor.forEach(...)    
    
    umVetor.indexOf(...)    
    umVetor.sort()          
    umVetor.reverse()       
    umVetor.filter()        
    umVetor.find()          
  • Se quiser transformar um NodeList em um vetor, use
    vetor = Array.from(umNodeList):
    let todosParagrafos = document.querySelectorAll('p');   // é um 'NodeList'
    todosParagrafos = Array.from(todosParagrafos);          // agora é um 'Array'

O objeto document

  • O objeto document dá acesso ao Document Object Model, ou DOM
  • Por exemplo, para pegar um elemento a partir de seu id e colocá-lo em uma variável:
    let botaoDeliciaEl = document.querySelector('#botao-delicia');
    • Agora é possível fazer várias coisas com o botão, como:
      1. Associar um evento de clique
      2. Pegar ou alterar seus atributos
      3. Alterar seu conteúdo
      4. Alterar seu estilo

Anatomia de uma tag

::: figure .figure-slides.tag-anatomy.clean.flex-align-center Anatomia de uma tag mostrando que ela consiste de seu nome envolto por sinais de "menor que" e "maior que"

Anatomia de uma tag mostrando que ela consiste de seu nome envolto por sinais de "menor que" e "maior que"

Anatomia de uma tag mostrando que ela consiste de seu nome envolto por sinais de "menor que" e "maior que"

Anatomia de uma tag mostrando que ela consiste de seu nome envolto por sinais de "menor que" e "maior que"

Anatomia de uma tag mostrando que ela consiste de seu nome envolto por sinais de "menor que" e "maior que" :::

  • Tags de abertura podem ter atributos:
    <img src="bob-esponja.png">
    • Em <img>, o atributo src="..." aponta para a URL do arquivo
    • Não deve haver espaço entre seu nome e seu valor:
      • <img src = "..."> 👎
      • <img src="..."> 👍

Alterando o conteúdo

  • É possível alterar o conteúdo de um elemento com elemento.innerHTML:

    <iframe width="250" height="130" src="//jsfiddle.net/fegemo/wLp3kv59/embedded/result/" allowfullscreen="allowfullscreen" frameborder="0" class="push-right" style="clear: right;"></iframe> <iframe width="250" height="153" src="//jsfiddle.net/fegemo/wLp3kv59/embedded/html/" allowfullscreen="allowfullscreen" frameborder="0" class="push-right" style="clear: right;"></iframe>
    let contador = 0;
    let contadorEl = document.querySelector('#contador');
    
    // quando clicado, (1) conta e (2) altera conteúdo
    contadorEl.addEventListener('click', () => {
      contador++;                       // (1) conta
      contadorEl.innerHTML = contador;  // (2) altera
    });

Alterando atributos

  • É possível alterar atributos dos elementos:
    <img src="imgs/pikachu.png" id="pokemon-lutando">
    let pokemonEl = document.querySelector('#pokemon-lutando');
    pokemonEl.src = 'imgs/bulbasaur.png';        // alteramos o 'src'
    • Aqui, alteramos o atributo src da img, mas poderia ser qualquer um
      • Por exemplo, em input costumamos pegar/alterar o value
        inputEl.value = 'novo valor';

Colocando/removendo classes

  • É possível colocar ou remover classes de elementos:
    botaoEl.classList.add('selecionado');   // coloca .selecionado
    imageEl.classList.remove('oculta');     // remove .oculta
    pEl.classList.toggle('expandido');      // coloca ou tira .expandido
    • <iframe width="250" height="170" src="//jsfiddle.net/fegemo/wbq109xg/embedded/result/" allowfullscreen="allowfullscreen" frameborder="0" class="push-right bring-forward"></iframe> Isso pode ser usado, por exemplo, para ↘
      "marcar" elementos
    • Ou então pra fazer um menu lateral aparecer...

Definindo "quem está selecionado"

<iframe width="340" height="200" style="width: 340px" src="//jsfiddle.net/fegemo/wbq109xg/embedded/result,js,css/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
  • Marca/desmarca elemento. Ideia:
    • No evento de 'click' de cada um:
      1. Alterna a classe .selecionado do elemento que foi "clicado"
        • el.classList.toggle('selecionado')
<iframe width="340" height="200" style="width: 340px" src="//jsfiddle.net/fegemo/8nsjhgga/embedded/result,js,css/" allowfullscreen="allowfullscreen" frameborder="0" class="bullet"></iframe>
  • Apenas 1 elemento selecionado por vez. Ideia:
    • No evento de 'click' de cada um:
      1. Tira a classe .selecionado de todos
      2. "Re"coloca a classe no elemento "clicado"

Um menu lateral aparecer

<iframe width="100%" height="400" src="//jsfiddle.net/fegemo/dj37kc7e/embedded/result,html,js,css/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
  • No HTML:
    <body>
      <nav id="menu">...</nav>
      <main>...</main>
    </body>
  • No JavaScript, alterna a classe .menu-visivel no <body>
  • No CSS, desloca tudo para a direita quando o <body> tem .menu-visivel

Exploração Espacial 👽

Conhecendo o além-atmosfera

  • Atividade de hoje
  • Que elemento foi clicado?
  • Subindo na árvore do DOM
  • Alternando uma classe


Exploração Espacial 👽

  • Crie parágrafos que expandem/retraem e uma galeria 📓
  • Há 2 atividades:
    1. Criar um código em JavaScript para fazer os botões "+" expadirem ou retrairem o texto dos parágrafos
      • Fazer no arquivo atividade1.js
    2. Criar uma galeria mostrando fotos e imagens da sonda Philae
      • Fazer no arquivo atividade2.js

Associando mesma callback para vários elementos

  • É bastante comum associarmos uma mesma função (callback) a algum evento de vários elementos HTML diferentes
    • Como no exercício: callback de 'click' em TODOS os parágrafos
      • <p>Parágrafo 1</p>
        <p>Parágrafo 2</p>
        <p>Parágrafo 3</p>
        ::: result .example-ps.bullet <style>.example-ps p {font-size: 0.8em}</style>

        Parágrafo 1

        Parágrafo 2

        Parágrafo 3

        :::
      function colore() {
        let el = ??; // <-- quem colocar aqui??
        el.style.background = 'lightblue';
      };
      
      let ps = document.querySelectorAll('p');
      for (let pEl of ps) {
        pEl.addEventListener('click', colore);
      }
  • Dentro da callback, é possível saber qual elemento foi alvo do evento!
    • Precisamos usar o argumento de evento! (Próximo slide)

Quem disparou o evento?

  • Quando o navegador executa uma callback de eventos, ele passa um parâmetro com informações sobre o evento
    • Tipicamente damos o nome de e, evt ou event:
      • let ps = document.querySelectorAll('p');  // igualzinho antes!
        for (let pEl of ps) {
          pEl.addEventListener('click', colore);
        }
      • function colore(e) {                  // repare o argumento 'e' (evento)
          let el = e.currentTarget;           // <--- o elemento "alvo" do evento
          el.style.background = 'lightblue';  // colore parágrafo alvo do evento
        }

Subindo na árvore do DOM

  • Todo elemento do DOM conhece, na árvore, quem é:
    1. seu pai (elemento.parentNode ou elemento.parentElement)
    2. seus filhos (elemento.childNodes ou elemento.children)
    3. irmão anterior e irmão posterior
  • Exemplo: clicou numa <img> , mas quero a <div></div> que é "pai" dela:
    function clicouNaImagem(e) {
      let clicadoEl = e.currentTarget;          // a <img> que foi clicada
      let divEl = clicadoEl.parentNode;         // <--- <div> é o pai da <img>
      console.log(divEl.id);                    // imprime id da div
    }
    
    let imgEl = document.querySelector('div > img');
    imgEl.addEventListener('click', clicouNaImagem);

Alternando uma classe

  • Às vezes queremos colocar/remover uma classe em um elemento alternadamente
  • Para isso, existe o elemento.classList.toggle('nome-da-classe')
  • Além de colocar/remover a classe, o método retorna:
    • true se tiver colocado a classe
    • false se tiver removido a classe
    let colocou = booEl.classList.toggle('selecionado');
    console.log(colocou);         // imprime 'true', porque adicionou .selecionado
    colocou = booEl.classList.toggle('selecionado');
    console.log(colocou);         // imprime 'false', porque tirou .selecionado

Referências