Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[Unifal SACIC 2016] Front-end: Construindo uma ...

[Unifal SACIC 2016] Front-end: Construindo uma aplicação com workflow e ferramentas modernas

Talysson de Oliveira Cassiano

September 20, 2016
Tweet

More Decks by Talysson de Oliveira Cassiano

Other Decks in Programming

Transcript

  1. Um front-end trabalha com o quê? HTML JavaScript CSS Gerenciamento

    de dependência GIT Comunicação com o back-end Testes Usabilidade Frameworks Responsividade Linguagens de template
  2. O que aprenderemos hoje? HTML JavaScript CSS Gerenciamento de dependência

    GIT Comunicação com o back-end Testes Usabilidade Frameworks Responsividade Linguagens de template
  3. HTML: doctype + tags <!doctype html> <html> <head> <title> Minha

    página :) </title> </head> <body> <div id="my-element" class="main-section container"> <img src="http://fakeurl.com/img.jpg" /> </div> </body> </html>
  4. HTML: doctype + tags <!doctype html> <html> <head> <title> Minha

    página :) </title> </head> <body> <div id="my-element" class="main-section container" data-main> <img src="http://fakeurl.com/img.jpg" /> </div> </body> </html> tipo do documento abertura de tag atributos self-closing tag fechamento de tag } <head> = configuração da página } <body> = conteúdo da página
  5. CSS: seletores + regras de estilo .hello { color: #424242;

    font-size: 15px; } #world { border: 1px solid yellow; } .parent .child { height: 30px; }
  6. CSS: seletores + regras de estilo .hello { color: #424242;

    font-size: 15px; } #world { border: 1px solid yellow; } .parent .child { height: 30px; } seletor valor atributo } estiliza o elemento com .class: <div class="hello">...</div> } estiliza o elemento com #id: <div id="world">...</div> } estiliza o elemento aninhado: <div class="parent"> <div class="child">...</div> </div>
  7. JavaScript: a linguagem de programação function showNumber(number) { console.log(number); }

    var numbers = [1, 2, 3, 4]; numbers.forEach((currentNumber) => { showNumber(currentNumber * 2); }); var obj = { name: 'Unifal', year: 2016 }; console.log(obj.name);
  8. JavaScript: a linguagem de programação function showNumber(number) { console.log(number); }

    var numbers = [1, 2, 3, 4]; numbers.forEach((currentNumber) => { showNumber(currentNumber * 2); }); var obj = { name: 'Unifal', year: 2016 }; console.log(obj.name); função vetor / array objeto printa o valor do atributo com a chave name for(var i = 0; i < numbers.length; i++) { showNumber(numbers[i] * 2); }
  9. Iniciando o projeto ▣ Criar a estrutura de pastas ▢

    Editar arquivo index.html <!doctype html> <html> <head> <meta charset="UTF-8"> <title>Pokédex</title> </head> <body> <script src="./js/index.js"></script> </body> </html> index.html
  10. Iniciando o projeto ▣ Criar a estrutura de pastas ▣

    Editar arquivo index.html ▢ Editar arquivo js/index.js var pokemons = [ { name: 'pikachu' }, { name: 'blaziken' }, { name: 'lucario' } ]; pokemons.forEach(function(pokemon) { console.log(pokemon.name); }); js/index.js
  11. # Abra o arquivo index.html no navegador # Abra o

    console do navegador na aba Console # Atualize a página # Verifique o nome dos pokémons printados Iniciando o projeto ▣ Criar a estrutura de pastas ▣ Editar arquivo index.html ▣ Editar arquivo js/index.js ▢ Verificar no navegador
  12. Modularização JavaScript ▣ Criar arquivo js/pokemons.js ▢ Mover pokémons js/index.js

    > js/pokemons.js var pokemons = [ { name: 'pikachu' }, { name: 'blaziken' }, { name: 'lucario' } ]; js/pokemons.js
  13. Modularização JavaScript ▣ Criar arquivo js/pokemons.js ▣ Mover pokémons js/index.js

    > js/pokemons.js ▢ Importar js/pokemons.js no index.html? <!doctype html> <html> <head> <meta charset="UTF-8"> <title>Pokédex</title> </head> <body> <script src="./js/pokemons.js"></script> <script src="./js/index.js"></script> </body> </html> ??? index.html
  14. Modularização JavaScript ▣ Criar arquivo js/pokemons.js ▣ Mover pokémons js/index.js

    > js/pokemons.js ▢ Importar js/pokemons.js no index.html? ▢ Gerar build/bundle.js <!doctype html> <html> <head> <meta charset="UTF-8"> <title>Pokédex</title> </head> <body> <script src="./build/bundle.js"></script> </body> </html> arquivo com o conteúdo de js/index.js e js/pokemons.js na ordem correta index.html
  15. > npm init # verificar arquivo package.json criado > npm

    install --save-dev browserify # verificar que browserify foi adicionado ao package.json Modularização JavaScript ▣ Criar arquivo js/pokemons.js ▣ Mover pokémons js/index.js > js/pokemons.js ▢ Importar js/pokemons.js no index.html? ▢ Gerar build/bundle.js ▢ Instalar ferramenta de bundling: Browserify
  16. Modularização JavaScript ▣ Criar arquivo js/pokemons.js ▣ Mover pokémons js/index.js

    > js/pokemons.js ▢ Importar js/pokemons.js no index.html? ▢ Gerar build/bundle.js ▣ Instalar ferramenta de bundling: Browserify ▢ Configurar script que gera o build/bundle.js { "name": "front-unifal", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build:js": "browserify js/index.js -o build/bundle.js" }, "author": "", "license": "ISC", "devDependencies": { "browserify": "^13.1.0" } } gera o arquivo build/bundle.js a partir da árvore de dependências de js/index.js package.json
  17. Modularização JavaScript ▣ Criar arquivo js/pokemons.js ▣ Mover pokémons js/index.js

    > js/pokemons.js ▢ Importar js/pokemons.js no index.html? ▢ Gerar build/bundle.js ▣ Instalar ferramenta de bundling: Browserify ▣ Configurar script que gera o build/bundle.js ▢ Transformar js/index.js e js/pokemons.js em módulos var pokemons = [ { name: 'pikachu' }, { name: 'blaziken' }, { name: 'lucario' } ]; module.exports = pokemons; js/pokemons.js exporta o array de pokémons
  18. Modularização JavaScript ▣ Criar arquivo js/pokemons.js ▣ Mover pokémons js/index.js

    > js/pokemons.js ▢ Importar js/pokemons.js no index.html? ▢ Gerar build/bundle.js ▣ Instalar ferramenta de bundling: Browserify ▣ Configurar script que gera o build/bundle.js ▢ Transformar js/index.js e js/pokemons.js em módulos var pokemons = require('./pokemons'); pokemons.forEach(function(pokemon) { console.log(pokemon.name); }); js/index.js import o array de pokémons de js/pokemons.js agora js/pokemons.js está na árvore de dependências
  19. Modularização JavaScript ▣ Criar arquivo js/pokemons.js ▣ Mover pokémons js/index.js

    > js/pokemons.js ▢ Importar js/pokemons.js no index.html? ▢ Gerar build/bundle.js ▣ Instalar ferramenta de bundling: Browserify ▣ Configurar script que gera o build/bundle.js ▣ Transformar js/index.js e js/pokemons.js em módulos ▢ Criar pasta build front-unifal js index.html index.js pokemons.js build
  20. Modularização JavaScript ▣ Criar arquivo js/pokemons.js ▣ Mover pokémons js/index.js

    > js/pokemons.js ▢ Importar js/pokemons.js no index.html? ▢ Gerar build/bundle.js ▣ Instalar ferramenta de bundling: Browserify ▣ Configurar script que gera o build/bundle.js ▣ Transformar js/index.js e js/pokemons.js em módulos ▣ Criar pasta build ▢ Gerar build/bundle.js > npm run build:js # verificar aquivo build/bundle.js criado # executar index.html novamente no browser # verificar console do browser
  21. Planejando nossos módulos Pokedex Dados → Models Representações → Views

    Pokemon PokemonList { name: "Torchic" } [ { name: "Abra" }, ... ]
  22. Planejando nossos módulos Pokedex Dados → Models Representações → Views

    Pokemon PokemonList PokemonView Abra Chikorita Onix PokemonListView { name: "Torchic" } [ { name: "Abra" }, ... ]
  23. Models ▣ Criar pasta js/models ▢ Criar arquivo js/models/Pokemon.js class

    Pokemon { constructor(info) { this.name = info.name; } } module.exports = Pokemon; js/models/Pokemon.js
  24. Models ▣ Criar pasta js/models ▢ Criar arquivo js/models/Pokemon.js class

    Pokemon { constructor(info) { this.name = info.name; } } module.exports = Pokemon; js/models/Pokemon.js cria classe chamada Pokemon quando um objeto da classe for criado, salva o nome do Pokémon exporta a classe Pokemon
  25. Models ▣ Criar pasta js/models ▣ Criar arquivo js/models/Pokemon.js ▢

    Criar arquivo js/models/PokemonList.js var Pokemon = require('./Pokemon'); class PokemonList { constructor(infoArray) { this.items = []; for(var i = 0; i < infoArray.length; i++) { var pokemon = new Pokemon(infoArray[i]); this.items.push(pokemon); } } } module.exports = PokemonList; js/models/PokemonList.js
  26. Models ▣ Criar pasta js/models ▣ Criar arquivo js/models/Pokemon.js ▢

    Criar arquivo js/models/PokemonList.js var Pokemon = require('./Pokemon'); class PokemonList { constructor(infoArray) { this.items = []; for(var i = 0; i < infoArray.length; i++) { var pokemon = new Pokemon(infoArray[i]); this.items.push(pokemon); } } } module.exports = PokemonList; js/models/PokemonList.js importa classe Pokemon recebe array de informações de pokemons para cada item do array de informações, cria uma instância de Pokemon e salva na lista
  27. Models ▣ Criar pasta js/models ▣ Criar arquivo js/models/Pokemon.js ▣

    Criar arquivo js/models/PokemonList.js ▢ Usar classe PokemonList em js/pokemons.js var PokemonList = require('./models/PokemonList'); var pokemonsInfo = [ { name: 'pikachu' }, { name: 'blaziken' }, { name: 'lucario' } ]; var pokemons = new PokemonList(pokemonsInfo); module.exports = pokemons; js/pokemons.js
  28. Models ▣ Criar pasta js/models ▣ Criar arquivo js/models/Pokemon.js ▣

    Criar arquivo js/models/PokemonList.js ▢ Usar classe PokemonList em js/pokemons.js var PokemonList = require('./models/PokemonList'); var pokemonsInfo = [ { name: 'pikachu' }, { name: 'blaziken' }, { name: 'lucario' } ]; var pokemons = new PokemonList(pokemonsInfo); module.exports = pokemons; js/pokemons.js cada um destes items será usado para criar um objeto da classe Pokemon
  29. Models ▣ Criar pasta js/models ▣ Criar arquivo js/models/Pokemon.js ▣

    Criar arquivo js/models/PokemonList.js ▣ Usar classe PokemonList em js/pokemons.js ▢ Usar nossa nova lista em js/index.js var pokemons = require('./pokemons'); pokemons.items.forEach(function(pokemon) { console.log(pokemon.name); }); js/index.js usa campo items da lista de pokémons
  30. Models ▣ Criar pasta js/models ▣ Criar arquivo js/models/Pokemon.js ▣

    Criar arquivo js/models/PokemonList.js ▣ Usar classe PokemonList em js/pokemons.js ▣ Usar nossa nova lista em js/index.js ▢ Verificar no navegador > npm run build:js # verificar aquivo build/bundle.js criado # executar index.html novamente no browser # verificar console do browser
  31. Models ▣ Criar pasta js/models ▣ Criar arquivo js/models/Pokemon.js ▣

    Criar arquivo js/models/PokemonList.js ▣ Usar classe PokemonList em js/pokemons.js ▣ Usar nossa nova lista em js/index.js ▣ Verificar no navegador ▢ Erro de sintaxe?! ?
  32. Compilação JavaScript ▣ Porque? ▣ Como? ▢ Com que ferramenta?

    > npm install --save-dev babelify > npm install --save-dev babel-preset-es2015 plugin do Babel para o Browserify plugin de ES2015 para o Babel
  33. Compilação JavaScript ▣ Porque? ▣ Como? ▣ Com que ferramenta?

    ▢ Configurando Browserify para usar o babelify { "name": "front-unifal", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build:js": "browserify js/index.js -o build/bundle.js" }, "author": "", "license": "ISC", "devDependencies": { "babel-preset-es2015": "^6.13.2", "babelify": "^7.3.0", "browserify": "^13.1.0" }, "browserify": { "transform": ["babelify"] } } package.json avisa ao Browserify para usar o babelify }
  34. Compilação JavaScript ▣ Porque? ▣ Como? ▣ Com que ferramenta?

    ▣ Configurando Browserify para usar o babelify ▢ Configurando Babel para usar plugin ES2015 ▢ Criar arquivo .babelrc front-unifal js index.js build models .babelrc
  35. Compilação JavaScript ▣ Porque? ▣ Como? ▣ Com que ferramenta?

    ▣ Configurando Browserify para usar o babelify ▢ Configurando Babel para usar plugin ES2015 ▣ Criar arquivo .babelrc ▢ Configurar .babelrc { "presets": ["es2015"] } .babelrc
  36. Compilação JavaScript ▣ Porque? ▣ Como? ▣ Com que ferramenta?

    ▣ Configurando Browserify para usar o babelify ▣ Configurando Babel para usar plugin ES2015 ▣ Criar arquivo .babelrc ▣ Configurar .babelrc ▢ Verificar no navegador > npm run build:js # verificar aquivo build/bundle.js criado # executar index.html novamente no browser # verificar console do browser
  37. Testes automatizados ▣ O que são? ▢ Porque? ▣ Durabilidade

    do código ▣ Documentação ▢ Melhor design e confiança no código Código ruim Poucos testes Medo de refatorar Baixa testabilidade Código novo Testes Refatoração Código bom
  38. Testes automatizados ▣ O que são? ▣ Porque? ▣ Durabilidade

    do código ▣ Documentação ▣ Melhor design e confiança no código ▢ Como? ▢ Metodologia Test-first
  39. Testes automatizados ▣ O que são? ▣ Porque? ▣ Durabilidade

    do código ▣ Documentação ▣ Melhor design e confiança no código ▢ Como? ▣ Metodologia ▢ Ferramentas > npm install --save-dev mocha > npm install --save-dev chai
  40. Testes automatizados ▣ O que são? ▣ Porque? ▣ Durabilidade

    do código ▣ Documentação ▣ Melhor design e confiança no código ▢ Como? ▣ Metodologia ▣ Ferramentas ▢ NPM script { "name": "front-unifal", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "mocha", "build:js": "browserify js/index.js -o build/bundle.js" }, "author": "", "license": "ISC", "devDependencies": { "babel-preset-es2015": "^6.13.2", "babelify": "^7.3.0", "browserify": "^13.1.0", "chai": "^3.5.0", "mocha": "^3.0.2" }, "browserify": { "transform": ["babelify"] } } package.json executará todos os arquivos na pasta test
  41. Testes automatizados ▣ O que são? ▣ Porque? ▣ Durabilidade

    do código ▣ Documentação ▣ Melhor design e confiança no código ▣ Como? ▣ Metodologia ▣ Ferramentas ▣ NPM script ▢ Escrevendo o primeiro teste ▢ Criar pasta test front-unifal js build test
  42. Testes automatizados ▣ O que são? ▣ Porque? ▣ Durabilidade

    do código ▣ Documentação ▣ Melhor design e confiança no código ▣ Como? ▣ Metodologia ▣ Ferramentas ▣ NPM script ▢ Escrevendo o primeiro teste ▣ Criar pasta test ▢ Criar arquivo test/Pokemon.test.js var chai = require('chai'); var expect = chai.expect; var Pokemon = require(../js/models/Pokemon'); describe('Pokemon', function() { }); test/Pokemon.test.js o nome da classe que vamos testar classe que vamos testar nossos testes para a classe Pokemon ficarão aqui
  43. Testes automatizados ▣ O que são? ▣ Porque? ▣ Durabilidade

    do código ▣ Documentação ▣ Melhor design e confiança no código ▣ Como? ▣ Metodologia ▣ Ferramentas ▣ NPM script ▢ Escrevendo o primeiro teste ▣ Criar pasta test ▢ Criar arquivo test/Pokemon.test.js var chai = require('chai'); var expect = chai.expect; var Pokemon = require(../js/models/Pokemon'); describe('Pokemon', function() { it('should save the pokemon name', function() { }); }); test/Pokemon.test.js descrição do nosso teste o corpo do nosso teste ficará aqui
  44. Testes automatizados ▣ O que são? ▣ Porque? ▣ Durabilidade

    do código ▣ Documentação ▣ Melhor design e confiança no código ▣ Como? ▣ Metodologia ▣ Ferramentas ▣ NPM script ▢ Escrevendo o primeiro teste ▣ Criar pasta test ▢ Criar arquivo test/Pokemon.test.js var chai = require('chai'); var expect = chai.expect; var Pokemon = require(../js/models/Pokemon'); describe('Pokemon', function() { it('should save the pokemon name', function() { var pokemon = new Pokemon({ name: 'growlithe' }); }); }); test/Pokemon.test.js testaremos se a variável pokemon salvará o nome growlighte dentro dela
  45. Testes automatizados ▣ O que são? ▣ Porque? ▣ Durabilidade

    do código ▣ Documentação ▣ Melhor design e confiança no código ▣ Como? ▣ Metodologia ▣ Ferramentas ▣ NPM script ▢ Escrevendo o primeiro teste ▣ Criar pasta test ▢ Criar arquivo test/Pokemon.test.js var chai = require('chai'); var expect = chai.expect; var Pokemon = require(../js/models/Pokemon'); describe('Pokemon', function() { it('should save the pokemon name', function() { var pokemon = new Pokemon({ name: 'growlithe' }); expect(pokemon.name).to.equal('growlithe'); }); }); test/Pokemon.test.js leia “espera-se que pokemon.name seja igual a growlithe”
  46. Testes automatizados ▣ O que são? ▣ Porque? ▣ Durabilidade

    do código ▣ Documentação ▣ Melhor design e confiança no código ▣ Como? ▣ Metodologia ▣ Ferramentas ▣ NPM script ▢ Escrevendo o primeiro teste ▣ Criar pasta test ▣ Criar arquivo test/Pokemon.test.js ▢ Executar teste > npm run test # verificar saída do teste no terminal test/Pokemon.test.js
  47. Testes automatizados ▣ O que são? ▣ Porque? ▣ Durabilidade

    do código ▣ Documentação ▣ Melhor design e confiança no código ▣ Como? ▣ Metodologia ▣ Ferramentas ▣ NPM script ▢ Escrevendo o primeiro teste ▣ Criar pasta test ▣ Criar arquivo test/Pokemon.test.js ▣ Executar teste ▢ Forçar falha de teste # modifique o código do teste para que ele falhe > npm run test # verificar saída do teste no terminal test/Pokemon.test.js
  48. ▣ Criar pasta js/views ▢ Criar arquivo js/views/PokemonListView.js class PokemonListView

    { constructor(attrs) { this.pokemonList = attrs.pokemons; } render() { // ? } } module.exports = PokemonListView; js/views/PokemonListViews.js Views
  49. ▣ Criar pasta js/views ▢ Criar arquivo js/views/PokemonListView.js class PokemonListView

    { constructor(attrs) { this.pokemonList = attrs.pokemons; } render() { // ? } } module.exports = PokemonListView; js/views/PokemonListViews.js como a view renderizará os pokémons? Views
  50. ▣ Criar pasta js/views ▢ Criar arquivo js/views/PokemonListView.js class PokemonListView

    { constructor(attrs) { this.pokemonList = attrs.pokemons; } render() { // ? } } module.exports = PokemonListView; js/views/PokemonListViews.js hoje usaremos jQuery :) Views
  51. ▣ Criar pasta js/views ▣ Criar arquivo js/views/PokemonListView.js ▢ Instalar

    jQuery > npm install --save jquery # verificar que jquery foi adicionado ao package.json Views
  52. ▣ Criar pasta js/views ▣ Criar arquivo js/views/PokemonListView.js ▣ Instalar

    jQuery ▢ Usar jQuery em js/views/PokemonListView.js var $ = require('jquery'); class PokemonListView { constructor(attrs) { this.pokemonList = attrs.pokemons; this.$element = $('<div/>'); this.$element.addClass('pokemon-list'); } render() { // ? } } module.exports = PokemonListView; js/views/PokemonListViews.js importa o jQuery e salva na variável $ cria elemento div vazio e adiciona classe pokemon-list } Views
  53. ▣ Criar pasta js/views ▣ Criar arquivo js/views/PokemonListView.js ▣ Instalar

    jQuery ▢ Usar jQuery em js/views/PokemonListView.js var $ = require('jquery'); class PokemonListView { constructor(attrs) { this.pokemonList = attrs.pokemons; this.$element = $('<div/>'); this.$element.addClass('pokemon-list'); } render() { this.pokemonList.items.forEach((pokemon) => { this.$element.append(`<div>${pokemon.name}</div>`); }); } } module.exports = PokemonListView; js/views/PokemonListViews.js adiciona o nome de cada pokémon no HTML no elemento função que usa this internamente (não aprofundaremos aqui no porque de usar => e não function) Views
  54. ▣ Criar pasta js/views ▣ Criar arquivo js/views/PokemonListView.js ▣ Instalar

    jQuery ▣ Usar jQuery em js/views/PokemonListView.js ▢ Adicionar elemento da aplicação em index.html index.html <!doctype html> <html> <head> <meta charset="UTF-8"> <title>Pokédex</title> </head> <body> <div class="pokedex"></div> <script src="./build/bundle.js"></script> </body> </html> elemento onde renderizaremos nossa pokédex Views
  55. ▣ Criar pasta js/views ▣ Criar arquivo js/views/PokemonListView.js ▣ Instalar

    jQuery ▣ Usar jQuery em js/views/PokemonListView.js ▣ Adicionar elemento da aplicação em index.html ▢ Usar nova view em js/index.js var $ = require('jquery'); var pokemons = require('./pokemons'); var PokemonListView = require('./views/PokemonListView'); var $pokedex = $('.pokedex'); var pokemonListView = new PokemonListView({ pokemons: pokemons }); pokemonListView.render(); $pokedex.append(pokemonListView.$element); js/index.js pega o elemento que criamos em index.html. O jQuery usa seletores igual o CSS :) renderiza a lista de pokémons adiciona elemento da lista no HTML da página Views
  56. ▣ Criar pasta js/views ▣ Criar arquivo js/views/PokemonListView.js ▣ Instalar

    jQuery ▣ Usar jQuery em js/views/PokemonListView.js ▣ Adicionar elemento da aplicação em index.html ▣ Usar nova view em js/index.js ▢ Conferir no navegador pega o elemento que criamos em index.html. O jQuery usa seletores igual o CSS :) renderiza a lista de pokémons adiciona elemento da lista no HTML da página > npm run build:js # executar index.html no browser Views
  57. ▣ Criar pasta js/views ▣ Criar arquivo js/views/PokemonListView.js ▣ Instalar

    jQuery ▣ Usar jQuery em js/views/PokemonListView.js ▣ Adicionar elemento da aplicação em index.html ▣ Usar nova view em js/index.js ▣ Conferir no navegador ▢ Mover pokemon para uma view ▢ Criar arquivo js/views/PokemonView.js var $ = require('jquery'); class PokemonView { constructor(attrs) { this.pokemon = attrs.pokemon; this.$element = $('<div/>'); this.$element.addClass('pokemon'); } render() { this.$element.append(this.pokemon.name); } } module.exports = PokemonView; js/views/PokemonViews.js lógica extraída do método render de PokemonListView Views
  58. ▣ Criar pasta js/views ▣ Criar arquivo js/views/PokemonListView.js ▣ Instalar

    jQuery ▣ Usar jQuery em js/views/PokemonListView.js ▣ Adicionar elemento da aplicação em index.html ▣ Usar nova view em js/index.js ▣ Conferir no navegador ▢ Mover pokemon para uma view ▣ Criar arquivo js/views/PokemonView.js ▢ Usar view em PokemonListView var $ = require('jquery'); var PokemonView = require('./PokemonView'); class PokemonListView { constructor(attrs) { this.pokemonList = attrs.pokemons; this.$element = $('<div/>'); this.$element.addClass('pokemon-list'); } render() { this.pokemonList.items.forEach((pokemon) => { var pokemonView = new PokemonView({ pokemon: pokemon }); pokemonView.render(); this.$element.append(pokemonView.$element); }); } } module.exports = PokemonListView; js/views/PokemonListViews.js Views
  59. ▣ Criar pasta js/views ▣ Criar arquivo js/views/PokemonListView.js ▣ Instalar

    jQuery ▣ Usar jQuery em js/views/PokemonListView.js ▣ Adicionar elemento da aplicação em index.html ▣ Usar nova view em js/index.js ▣ Conferir no navegador ▢ Mover pokemon para uma view ▣ Criar arquivo js/views/PokemonView.js ▣ Usar view em PokemonListView ▢ Conferir no navegador > npm run build:js # executar index.html no browser Views
  60. Estilização & CSS ▣ Criar pasta css ▢ Criar arquivo

    css/style.css * { box-sizing: border-box; } .pokedex { height: 400px; width: 350px; background-color: #FF0000; color: #FFFFFF; } css/style.css
  61. Estilização & CSS ▣ Criar pasta css ▢ Criar arquivo

    css/style.css * { box-sizing: border-box; } .pokedex { height: 400px; width: 350px; background-color: #FF0000; color: #FFFFFF; } css/style.css ativa o modo border-box para todos os elementos = espessura da borda é subtraíra da largura/altura seletor para todos os elementos altura de 400px e largura de 350px fundo vermelho seletor para elemento com classe pokedex fonte branca
  62. Estilização & CSS ▣ Criar pasta css ▣ Criar arquivo

    css/style.css ▢ Adicionar css/style.css em index.html e verificar no navegador index.html <!doctype html> <html> <head> <meta charset="UTF-8"> <title>Pokédex</title> <link rel="stylesheet" href="./css/style.css"> </head> <body> <div class="pokedex"></div> <script src="./build/bundle.js"></script> </body> </html> importar a folha de estilo
  63. Estilização & CSS ▣ Criar pasta css ▣ Criar arquivo

    css/style.css ▣ Adicionar css/style.css em index.html e verificar no navegador ▢ Se decepcione
  64. Estilização & CSS ▣ Criar pasta css ▣ Criar arquivo

    css/style.css ▣ Adicionar css/style.css em index.html e verificar no navegador ▣ Se decepcione ▢ Estilizar lista de pokémons importar a folha de estilo * { box-sizing: border-box; } .pokedex { height: 400px; width: 350px; background-color: #FF0000; padding: 15px; } .pokemon-list { height: 100%; width: 100%; background-color: #61C93E; border: 1px solid #bb2929; color: #FFFFFF; padding: 10px; } css/style.css
  65. Estilização & CSS ▣ Criar pasta css ▣ Criar arquivo

    css/style.css ▣ Adicionar css/style.css em index.html e verificar no navegador ▣ Se decepcione ▢ Estilizar lista de pokémons importar a folha de estilo * { box-sizing: border-box; } .pokedex { height: 400px; width: 350px; background-color: #FF0000; padding: 15px; } .pokemon-list { height: 100%; width: 100%; background-color: #61C93E; border: 1px solid #bb2929; color: #FFFFFF; padding: 10px; } css/style.css espaçamento interno de 15px cor de fundo verde borda vermelha de 1px movido do seletor de cima por especificidade espaçamento interno de 10px seletor para lista de pokémons
  66. Modularização CSS ▢ Estilos para elementos diferentes no mesmo arquivo

    importar a folha de estilo * { box-sizing: border-box; } .pokedex { height: 400px; width: 350px; background-color: #FF0000; padding: 15px; } .pokemon-list { height: 100%; width: 100%; background-color: #61C93E; border: 1px solid #bb2929; color: #FFFFFF; padding: 10px; } css/style.css elementos diferentes na mesma folha de estilo
  67. Modularização CSS ▣ Estilos para elementos diferentes no mesmo arquivo

    ▢ Criar arquivos css/pokedex.css e css/pokemonList.css front-unifal js build css style.css pokedex.css pokemonList.css
  68. Modularização CSS ▣ Estilos para elementos diferentes no mesmo arquivo

    ▣ Criar arquivos css/pokedex.css e css/pokemonList.css ▢ Mover cada estilo para seu arquivo * { box-sizing: border-box; } css/style.css .pokedex { height: 400px; width: 350px; background-color: #FF0000; padding: 15px; } css/pokedex.css .pokemon-list { height: 100%; width: 100%; background-color: #61C93E; border: 1px solid #bb2929; color: #FFFFFF; padding: 10px; } css/pokemonList.css
  69. Modularização CSS ▣ Estilos para elementos diferentes no mesmo arquivo

    ▣ Criar arquivos css/pokedex.css e css/pokemonList.css ▣ Mover cada estilo para seu arquivo ▢ Adicionar folhas de estilo ao index.html? index.html <!doctype html> <html> <head> <meta charset="UTF-8"> <title>Pokédex</title> <link rel="stylesheet" href="./css/style.css"> <link rel="stylesheet" href="./css/pokedex.css"> <link rel="stylesheet" href="./css/pokemonList.css"> </head> <body> <div class="pokedex"></div> <script src="./build/bundle.js"></script> </body> </html> ???
  70. Modularização CSS ▣ Estilos para elementos diferentes no mesmo arquivo

    ▣ Criar arquivos css/pokedex.css e css/pokemonList.css ▣ Mover cada estilo para seu arquivo ▢ Adicionar folhas de estilo ao index.html? ▢ Gerar build/style.css index.html <!doctype html> <html> <head> <meta charset="UTF-8"> <title>Pokédex</title> <link rel="stylesheet" href="./build/style.css"> </head> <body> <div class="pokedex"></div> <script src="./build/bundle.js"></script> </body> </html> arquivo com o conteúdo de css/style.css, css/pokedex.css e css/pokemonList.css
  71. Modularização CSS ▣ Estilos para elementos diferentes no mesmo arquivo

    ▣ Criar arquivos css/pokedex.css e css/pokemonList.css ▣ Mover cada estilo para seu arquivo ▢ Adicionar folhas de estilo ao index.html? ▢ Gerar build/style.css ▢ Instalar pré-compilador de CSS: SASS > npm install --save-dev node-sass # verificar que node-sass foi adicionado ao package.json
  72. Modularização CSS ▣ Estilos para elementos diferentes no mesmo arquivo

    ▣ Criar arquivos css/pokedex.css e css/pokemonList.css ▣ Mover cada estilo para seu arquivo ▢ Adicionar folhas de estilo ao index.html? ▢ Gerar build/style.css ▣ Instalar pré-compilador de CSS: SASS ▢ Renomear arquivos de .css para .scss front-unifal js build css style.scss _pokedex.scss _pokemonList.scss Começam com _ porque serão importados por style.scss
  73. Modularização CSS @import 'pokedex'; @import 'pokemonList'; * { box-sizing: border-box;

    } ▣ Estilos para elementos diferentes no mesmo arquivo ▣ Criar arquivos css/pokedex.css e css/pokemonList.css ▣ Mover cada estilo para seu arquivo ▢ Adicionar folhas de estilo ao index.html? ▢ Gerar build/style.css ▣ Instalar pré-compilador de CSS: SASS ▣ Renomear arquivos de .css para .scss ▢ Importar arquivos css/style.scss caminho dos arquivos sem o _ no começo do nome
  74. Modularização CSS { "name": "front-unifal", "version": "1.0.0", "description": "", "main":

    "index.js", "scripts": { "test": "mocha", "build:js": "browserify js/index.js -o build/bundle.js", "build:css": "node-sass css -o build" }, "author": "", "license": "ISC", "devDependencies": { "babel-preset-es2015": "^6.13.2", "babelify": "^7.3.0", "browserify": "^13.1.0", "chai": "^3.5.0", "mocha": "^3.0.2", "node-sass": "^3.8.0" }, "browserify": { "transform": ["babelify"] } } ▣ Estilos para elementos diferentes no mesmo arquivo ▣ Criar arquivos css/pokedex.css e css/pokemonList.css ▣ Mover cada estilo para seu arquivo ▢ Adicionar folhas de estilo ao index.html? ▢ Gerar build/style.css ▣ Instalar pré-compilador de CSS: SASS ▣ Renomear arquivos de .css para .scss ▣ Importar arquivos ▢ Configurar npm script package.json pega todos arquivos sem _ da pasta css, compila e coloca resultado na pasta build
  75. Modularização CSS > npm run build:css # verificar conteúdo de

    build/style.css # executar no navegador e verificar que continua funcionando ▣ Estilos para elementos diferentes no mesmo arquivo ▣ Criar arquivos css/pokedex.css e css/pokemonList.css ▣ Mover cada estilo para seu arquivo ▢ Adicionar folhas de estilo ao index.html? ▢ Gerar build/style.css ▣ Instalar pré-compilador de CSS: SASS ▣ Renomear arquivos de .css para .scss ▣ Importar arquivos ▣ Configurar npm script ▢ Executar npm script e verificar no navegador
  76. Usando o poder do SASS ▢ O SASS não é

    apenar um concatenador de CSS
  77. Usando o poder do SASS ▣ O SASS não é

    apenar um concatenador de CSS ▢ Variáveis ▢ Criar arquivo css/_variables.scss front-unifal css style.scss _pokedex.scss _pokemonList.scss _variables.scss
  78. Usando o poder do SASS ▣ O SASS não é

    apenar um concatenador de CSS ▢ Variáveis ▣ Criar arquivo css/_variables.scss ▢ Extrair cores para o novo arquivo em variáveis $pokedex-color: #FF0000; $pokedex-shadow-color: #bb2929; $white-color: #FFFFFF; $screen-color: #61C93E; css/_variables.scss
  79. Usando o poder do SASS ▣ O SASS não é

    apenar um concatenador de CSS ▢ Variáveis ▣ Criar arquivo css/_variables.scss ▢ Extrair cores para o novo arquivo em variáveis $pokedex-color: #FF0000; $pokedex-shadow-color: #bb2929; $white-color: #FFFFFF; $screen-color: #61C93E; css/_variables.scss nome da variável padrão de notação: hífen atribuição com dois-pontos em vez de símbolo de igual valor pode ser qualquer valor de propriedade CSS
  80. Usando o poder do SASS ▣ O SASS não é

    apenar um concatenador de CSS ▢ Variáveis ▣ Criar arquivo css/_variables.scss ▣ Extrair cores para o novo arquivo em variáveis ▢ Importar arquivo em css/style.scss @import 'variables'; @import 'pokedex'; @import 'pokemonList'; * { box-sizing: border-box; } css/style.scss primeiro arquivo a ser importado
  81. Usando o poder do SASS ▣ O SASS não é

    apenar um concatenador de CSS ▢ Variáveis ▣ Criar arquivo css/_variables.scss ▣ Extrair cores para o novo arquivo em variáveis ▣ Importar arquivo em css/style.scss ▢ Usar variáveis .pokedex { height: 400px; width: 350px; background-color: $pokedex-color; padding: 15px; } css/pokedex.scss .pokemon-list { height: 100%; width: 100%; background-color: $screen-color; border: 1px solid $pokedex-shadow-color; color: $white-color; padding: 10px; } css/pokemonList.scss
  82. Usando o poder do SASS ▣ O SASS não é

    apenar um concatenador de CSS ▣ Variáveis ▣ Criar arquivo css/_variables.scss ▣ Extrair cores para o novo arquivo em variáveis ▣ Importar arquivo em css/style.scss ▣ Usar variáveis ▢ Parent operator ▢ Criar arquivo css/_pokemon.scss @import 'variables'; @import 'pokedex'; @import 'pokemonList'; @import 'pokemon'; * { box-sizing: border-box; } css/style.scss .pokemon { background-color: $screen-color; } .pokemon:hover { background-color: lighten($screen-color, 5%); } css/_pokemon.scss importar arquivo novo
  83. Usando o poder do SASS ▣ O SASS não é

    apenar um concatenador de CSS ▣ Variáveis ▣ Criar arquivo css/_variables.scss ▣ Extrair cores para o novo arquivo em variáveis ▣ Importar arquivo em css/style.scss ▣ Usar variáveis ▢ Parent operator ▢ Criar arquivo css/_pokemon.scss @import 'variables'; @import 'pokedex'; @import 'pokemonList'; @import 'pokemon'; * { box-sizing: border-box; } css/style.scss .pokemon { background-color: $screen-color; } .pokemon:hover { background-color: lighten($screen-color, 5%); } css/_pokemon.scss função para clarear a cor
  84. Usando o poder do SASS ▣ O SASS não é

    apenar um concatenador de CSS ▣ Variáveis ▣ Criar arquivo css/_variables.scss ▣ Extrair cores para o novo arquivo em variáveis ▣ Importar arquivo em css/style.scss ▣ Usar variáveis ▢ Parent operator ▢ Criar arquivo css/_pokemon.scss @import 'variables'; @import 'pokedex'; @import 'pokemonList'; @import 'pokemon'; * { box-sizing: border-box; } css/style.scss .pokemon { background-color: $screen-color; } .pokemon:hover { background-color: lighten($screen-color, 5%); } css/_pokemon.scss escrevemos .pokemon duas vezes :(
  85. Usando o poder do SASS ▣ O SASS não é

    apenar um concatenador de CSS ▣ Variáveis ▣ Criar arquivo css/_variables.scss ▣ Extrair cores para o novo arquivo em variáveis ▣ Importar arquivo em css/style.scss ▣ Usar variáveis ▢ Parent operator ▣ Criar arquivo css/_pokemon.scss ▢ Usar parent operator & @import 'variables'; @import 'pokedex'; @import 'pokemonList'; @import 'pokemon'; * { box-sizing: border-box; } css/style.scss .pokemon { background-color: $screen-color; &:hover { background-color: lighten($screen-color, 5%); } } css/_pokemon.scss
  86. Usando o poder do SASS ▣ O SASS não é

    apenar um concatenador de CSS ▣ Variáveis ▣ Criar arquivo css/_variables.scss ▣ Extrair cores para o novo arquivo em variáveis ▣ Importar arquivo em css/style.scss ▣ Usar variáveis ▢ Parent operator ▣ Criar arquivo css/_pokemon.scss ▢ Usar parent operator & @import 'variables'; @import 'pokedex'; @import 'pokemonList'; @import 'pokemon'; * { box-sizing: border-box; } css/style.scss .pokemon { background-color: $screen-color; &:hover { background-color: lighten($screen-color, 5%); } } css/_pokemon.scss operador & indica seletor pai no caso, o .pokemon deve ficar aninhado ao elemento pai
  87. Usando o poder do SASS ▣ O SASS não é

    apenar um concatenador de CSS ▣ Variáveis ▣ Criar arquivo css/_variables.scss ▣ Extrair cores para o novo arquivo em variáveis ▣ Importar arquivo em css/style.scss ▣ Usar variáveis ▢ Parent operator ▣ Criar arquivo css/_pokemon.scss ▣ Usar parent operator & ▢ Verificar resultado > npm run build:css # verificar conteúdo de build/style.css # executar no navegador e verificar que continua funcionando
  88. Responsividade ▣ Responsivo vs adaptativo ▣ Abrir modo celular no

    browser ▣ Se decepcionar novamente ▢ Adicionar metatag de viewport index.html <!doctype html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"> <title>Pokédex</title> <link rel="stylesheet" href="./build/style.css"> </head> <body> <div class="pokedex"></div> <script src="./build/bundle.js"></script> </body> </html>
  89. Responsividade ▣ Responsivo vs adaptativo ▣ Abrir modo celular no

    browser ▣ Se decepcionar novamente ▢ Adicionar metatag de viewport index.html <!doctype html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"> <title>Pokédex</title> <link rel="stylesheet" href="./build/style.css"> </head> <body> <div class="pokedex"></div> <script src="./build/bundle.js"></script> </body> </html> informa ao navegador a largura da tela do celular, a escala inicial a a máxima
  90. Responsividade ▣ Responsivo vs adaptativo ▣ Abrir modo celular no

    browser ▣ Se decepcionar novamente ▣ Adicionar metatag de viewport ▢ Tornar CSS responsivo ▢ Criar variável para largura tela de celular css/_variables.scss $pokedex-color: #FF0000; $pokedex-shadow-color: #bb2929; $white-color: #FFFFFF; $screen-color: #61C93E; $mobile-screen: 480px; consideraremos que toda tela de 480px de largura, ou menos, é um celular
  91. Responsividade ▣ Responsivo vs adaptativo ▣ Abrir modo celular no

    browser ▣ Se decepcionar novamente ▣ Adicionar metatag de viewport ▢ Tornar CSS responsivo ▣ Criar variável para largura tela de celular ▢ Utilizar variável em css/_pokedex.scss css/_pokedex.scss .pokedex { height: 100%; width: 100%; background-color: $pokedex-color; padding: 15px; @media(min-width: $mobile-screen + 1) { height: 400px; width: 350px; } }
  92. Responsividade ▣ Responsivo vs adaptativo ▣ Abrir modo celular no

    browser ▣ Se decepcionar novamente ▣ Adicionar metatag de viewport ▢ Tornar CSS responsivo ▣ Criar variável para largura tela de celular ▢ Utilizar variável em css/_pokedex.scss css/_pokedex.scss .pokedex { height: 100%; width: 100%; background-color: $pokedex-color; padding: 15px; @media(min-width: $mobile-screen + 1) { height: 400px; width: 350px; } } estilos para todo tamanho de tela } estilo para telas maiores que uma tela de celular } diretiva para aplicar estilos para um determinado tamanho de tela
  93. Responsividade ▣ Responsivo vs adaptativo ▣ Abrir modo celular no

    browser ▣ Se decepcionar novamente ▣ Adicionar metatag de viewport ▢ Tornar CSS responsivo ▣ Criar variável para largura tela de celular ▣ Utilizar variável em css/_pokedex.scss ▢ Removendo espaço extra css/_pokedex.scss @import 'variables'; @import 'pokedex'; @import 'pokemonList'; @import 'pokemon'; * { box-sizing: border-box; } body { margin: 0; }
  94. Melhorando o design ▣ Planejando o design ▢ Bordas arredondadas

    apenas em desktop css/_pokedex.scss .pokedex { height: 100%; width: 100%; background-color: $pokedex-color; padding: 15px; @media(min-width: $mobile-screen + 1) { height: 400px; width: 350px; border-radius: 5px; } } borda com raio de 5px
  95. Melhorando o design ▣ Planejando o design ▣ Bordas arredondadas

    apenas em desktop ▢ Estilo 3D apenas em desktop ▢ Adicionar profundidade css/_pokedex.scss .pokedex { height: 100%; width: 100%; background-color: $pokedex-color; padding: 15px; @media(min-width: $mobile-screen + 1) { height: 400px; width: 350px; border-radius: 5px; box-shadow: 0 10px 0 darken($pokedex-color, 10%); } }
  96. Melhorando o design ▣ Planejando o design ▣ Bordas arredondadas

    apenas em desktop ▢ Estilo 3D apenas em desktop ▢ Adicionar profundidade css/_pokedex.scss .pokedex { height: 100%; width: 100%; background-color: $pokedex-color; padding: 15px; @media(min-width: $mobile-screen + 1) { height: 400px; width: 350px; border-radius: 5px; box-shadow: 0 10px 0 darken($pokedex-color, 10%); } } deslocamento no eixo X deslocamento no eixo Y desfoque 10% mais escuro que a pokédex
  97. Melhorando o design ▣ Planejando o design ▣ Bordas arredondadas

    apenas em desktop ▢ Estilo 3D apenas em desktop ▣ Adicionar profundidade ▢ Tornar profundidade mais perceptível css/_pokedex.scss .pokedex { height: 100%; width: 100%; background-color: $pokedex-color; padding: 15px; @media(min-width: $mobile-screen + 1) { height: 400px; width: 350px; border-radius: 5px; box-shadow: 0 10px 0 darken($pokedex-color, 10%); border: 3px solid lighten($pokedex-color, 10%); } } borda de 3px, contínua, 10% mais clara que a cor da pokédex
  98. Melhorando o design ▣ Planejando o design ▣ Bordas arredondadas

    apenas em desktop ▢ Estilo 3D apenas em desktop ▣ Adicionar profundidade ▣ Tornar profundidade mais perceptível ▢ Finalizar efeito 3D css/_pokedex.scss .pokedex { height: 100%; width: 100%; background-color: $pokedex-color; padding: 15px; @media(min-width: $mobile-screen + 1) { height: 400px; width: 350px; border-radius: 5px; box-shadow: 0 10px 0 darken($pokedex-color, 10%); border: 3px solid lighten($pokedex-color, 10%); border-top: none; } } remove a borda superior
  99. Melhorando o design ▣ Planejando o design ▣ Bordas arredondadas

    apenas em desktop ▣ Estilo 3D apenas em desktop ▣ Adicionar profundidade ▣ Tornar profundidade mais perceptível ▣ Finalizar efeito 3D ▢ Fonte com visual 8-bit
  100. Melhorando o design ▣ Planejando o design ▣ Bordas arredondadas

    apenas em desktop ▣ Estilo 3D apenas em desktop ▣ Adicionar profundidade ▣ Tornar profundidade mais perceptível ▣ Finalizar efeito 3D ▢ Fonte com visual 8-bit ▢ Google Fonts fonts.google.com
  101. Melhorando o design ▣ Planejando o design ▣ Bordas arredondadas

    apenas em desktop ▣ Estilo 3D apenas em desktop ▣ Adicionar profundidade ▣ Tornar profundidade mais perceptível ▣ Finalizar efeito 3D ▢ Fonte com visual 8-bit ▢ Google Fonts
  102. Melhorando o design ▣ Planejando o design ▣ Bordas arredondadas

    apenas em desktop ▣ Estilo 3D apenas em desktop ▣ Adicionar profundidade ▣ Tornar profundidade mais perceptível ▣ Finalizar efeito 3D ▢ Fonte com visual 8-bit ▣ Google Fonts ▢ Importar fonte Copiar
  103. Melhorando o design ▣ Planejando o design ▣ Bordas arredondadas

    apenas em desktop ▣ Estilo 3D apenas em desktop ▣ Adicionar profundidade ▣ Tornar profundidade mais perceptível ▣ Finalizar efeito 3D ▢ Fonte com visual 8-bit ▣ Google Fonts ▢ Importar fonte index.html <!doctype html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"> <title>Pokédex</title> <link href="https://fonts.googleapis.com/css?family=Press+Start+2P" rel="stylesheet"> <link rel="stylesheet" href="./build/style.css"> </head> <body> <div class="pokedex"></div> <script src="./build/bundle.js"></script> </body> </html> Colar
  104. Melhorando o design ▣ Planejando o design ▣ Bordas arredondadas

    apenas em desktop ▣ Estilo 3D apenas em desktop ▣ Adicionar profundidade ▣ Tornar profundidade mais perceptível ▣ Finalizar efeito 3D ▢ Fonte com visual 8-bit ▣ Google Fonts ▣ Importar fonte ▢ Usar fonte no CSS Copiar
  105. Melhorando o design ▣ Planejando o design ▣ Bordas arredondadas

    apenas em desktop ▣ Estilo 3D apenas em desktop ▣ Adicionar profundidade ▣ Tornar profundidade mais perceptível ▣ Finalizar efeito 3D ▢ Fonte com visual 8-bit ▣ Google Fonts ▣ Importar fonte ▢ Usar fonte no CSS css/_pokemon.scss .pokemon { background-color: $screen-color; font-family: 'Press Start 2P', cursive; &:hover { background-color: lighten($screen-color, 5%); } } Colar
  106. Melhorando o design ▣ Planejando o design ▣ Bordas arredondadas

    apenas em desktop ▣ Estilo 3D apenas em desktop ▣ Adicionar profundidade ▣ Tornar profundidade mais perceptível ▣ Finalizar efeito 3D ▢ Fonte com visual 8-bit ▣ Google Fonts ▣ Importar fonte ▣ Usar fonte no CSS ▢ Ajustar tamanho css/_pokemon.scss .pokemon { background-color: $screen-color; font-family: 'Press Start 2P', cursive; font-size: 14px; &:hover { background-color: lighten($screen-color, 5%); } }
  107. Melhorando o design ▣ Planejando o design ▣ Bordas arredondadas

    apenas em desktop ▣ Estilo 3D apenas em desktop ▣ Adicionar profundidade ▣ Tornar profundidade mais perceptível ▣ Finalizar efeito 3D ▢ Fonte com visual 8-bit ▣ Google Fonts ▣ Importar fonte ▣ Usar fonte no CSS ▣ Ajustar tamanho ▢ Ajustar espaçamento css/_pokemon.scss .pokemon { background-color: $screen-color; font-family: 'Press Start 2P', cursive; font-size: 14px; padding: 5px; &:hover { background-color: lighten($screen-color, 5%); } } espaçamento interno de 5px
  108. Adicionando imagens ▢ Adicionar uma imagem qualquer var $ =

    require('jquery'); class PokemonView { constructor(attrs) { this.pokemon = attrs.pokemon; this.$element = $('<div/>'); this.$element.addClass('pokemon'); } render() { var url = 'https://img.pokemondb.net/sprites/black-white/normal/blaziken.png'; var $pokemonImage = $('<img/>'); $pokemonImage.addClass('pokemon-image'); $pokemonImage.attr('src', url); var $pokemonName = $('<div/>'); $pokemonName.addClass('pokemon-name'); $pokemonName.append(this.pokemon.name); this.$element.append($pokemonImage); this.$element.append($pokemonName); } } module.exports = PokemonView; js/views/PokemonViews.js cria uma tag de imagem mostrando a imagem da URL } cria uma tag div com o nome do Pokémon dentro } adiciona a imagem e o nome ao elemento da view }
  109. Adicionando imagens ▣ Adicionar uma imagem qualquer ▢ Corrigir problema

    de rolagem .pokemon-list { height: 100%; width: 100%; background-color: $screen-color; border: 1px solid $pokedex-shadow-color; color: $white-color; overflow: auto; padding: 10px; } css/_pokemonList.scss adiciona barra de rolagem caso ouver overflow/vazamento
  110. Adicionando imagens ▣ Adicionar uma imagem qualquer ▣ Corrigir problema

    de rolagem ▢ Regular tamanho da imagem adiciona barra de rolagem caso ouver overflow/vazamento css/_pokemon.scss .pokemon { background-color: $screen-color; font-family: 'Press Start 2P', cursive; font-size: 14px; height: 80px; padding: 5px; &:hover { background-color: lighten($screen-color, 5%); } .pokemon-image { height: 100%; } } deixa a altura de cada linha fixa em 80px deixa a altura da imagem igual a do elemento pai. No caso, a linha seletor de elemento com class pokemon-image dentro de pokemon
  111. Adicionando imagens ▣ Adicionar uma imagem qualquer ▣ Corrigir problema

    de rolagem ▣ Regular tamanho da imagem ▢ Deixar imagem e nome do Pokémon lado a lado adiciona barra de rolagem caso ouver overflow/vazamento css/_pokemon.scss .pokemon { background-color: $screen-color; font-family: 'Press Start 2P', cursive; font-size: 14px; height: 80px; padding: 5px; &:hover { background-color: lighten($screen-color, 5%); } .pokemon-image { float: left; height: 100%; } .pokemon-name { float: left; } } a imagem flutua para a esquerda para que caiba o nome ao lado nome flutua para o lado da imagem
  112. Adicionando imagens ▣ Adicionar uma imagem qualquer ▣ Corrigir problema

    de rolagem ▣ Regular tamanho da imagem ▣ Deixar imagem e nome do Pokémon lado a lado ▢ Ajustar posicionamento do nome do Pokémon adiciona barra de rolagem caso ouver overflow/vazamento css/_pokemon.scss .pokemon { background-color: $screen-color; font-family: 'Press Start 2P', cursive; font-size: 14px; height: 80px; padding: 5px; &:hover { background-color: lighten($screen-color, 5%); } .pokemon-image { float: left; height: 100%; } .pokemon-name { float: left; margin-left: 10px; margin-top: 25px; } } cria um espaço de 10px do lado esquerdo e de 25px acima, empurrando para direita e para baixo }
  113. Adicionando imagens ▣ Adicionar uma imagem qualquer ▣ Corrigir problema

    de rolagem ▣ Regular tamanho da imagem ▣ Deixar imagem e nome do Pokémon lado a lado ▣ Ajustar posicionamento do nome do Pokémon ▢ Usar a imagem correta para cada Pokémon var $ = require('jquery'); class PokemonView { constructor(attrs) { this.pokemon = attrs.pokemon; this.$element = $('<div/>'); this.$element.addClass('pokemon'); } render() { var url = 'https://img.pokemondb.net/sprites/black-white/normal/blaziken.png'; var $pokemonImage = $('<img/>'); $pokemonImage.addClass('pokemon-image'); $pokemonImage.attr('src', url); var $pokemonName = $('<div/>'); $pokemonName.addClass('pokemon-name'); $pokemonName.append(this.pokemon.name); this.$element.append($pokemonImage); this.$element.append($pokemonName); } } module.exports = PokemonView; js/views/PokemonViews.js repare que esta imagem tem o nome do Pokémon na URL :)
  114. Adicionando imagens ▣ Adicionar uma imagem qualquer ▣ Corrigir problema

    de rolagem ▣ Regular tamanho da imagem ▣ Deixar imagem e nome do Pokémon lado a lado ▣ Ajustar posicionamento do nome do Pokémon ▢ Usar a imagem correta para cada Pokémon class Pokemon { constructor(info) { this.name = info.name; } getImage() { return `https://img.pokemondb.net/sprites/black-white/normal/${this.name}.png`; } } module.exports = Pokemon; js/models/Pokemon.js retorna a URL da imagem usando o nome do Pokémon
  115. Adicionando imagens ▣ Adicionar uma imagem qualquer ▣ Corrigir problema

    de rolagem ▣ Regular tamanho da imagem ▣ Deixar imagem e nome do Pokémon lado a lado ▣ Ajustar posicionamento do nome do Pokémon ▢ Usar a imagem correta para cada Pokémon retorna a URL da imagem usando o nome do Pokémon var $ = require('jquery'); class PokemonView { constructor(attrs) { this.pokemon = attrs.pokemon; this.$element = $('<div/>'); this.$element.addClass('pokemon'); } render() { var url = this.pokemon.getImage(); var $pokemonImage = $('<img/>'); $pokemonImage.addClass('pokemon-image'); $pokemonImage.attr('src', url); var $pokemonName = $('<div/>'); $pokemonName.addClass('pokemon-name'); $pokemonName.append(this.pokemon.name); this.$element.append($pokemonImage); this.$element.append($pokemonName); } } module.exports = PokemonView; js/views/PokemonViews.js usamos nosso novo método, com a imagem correta!
  116. Adicionando imagens ▣ Adicionar uma imagem qualquer ▣ Corrigir problema

    de rolagem ▣ Regular tamanho da imagem ▣ Deixar imagem e nome do Pokémon lado a lado ▣ Ajustar posicionamento do nome do Pokémon ▣ Usar a imagem correta para cada Pokémon ▢ Testar o novo método
  117. Consumindo uma API de Pokémons ▣ O que é uma

    API web? ▢ O que é uma API REST? www API REST
  118. Consumindo uma API de Pokémons ▣ O que é uma

    API web? ▢ O que é uma API REST? www API REST /evolutions /pokemons /items /games
  119. Consumindo uma API de Pokémons ▣ O que é uma

    API web? ▢ O que é uma API REST? www API REST /evolutions /pokemons /items /games /pokemons/<nome> /pokemons /pokemons /pokemons/<nome> /pokemons/<nome> GET GET POST PUT DELETE lista de todos pokémons dados de um único pokémon cria um novo pokémon atualiza um pokémon deleta um pokémon
  120. Consumindo uma API de Pokémons ▣ O que é uma

    API web? ▣ O que é uma API REST? ▢ Pokéapi http://pokeapi.co/
  121. { "count": 811, "previous": null, "results": [ { "url": "http://pokeapi.co/api/v2/pokemon/1/",

    "name": "bulbasaur" }, { "url": "http://pokeapi.co/api/v2/pokemon/2/", "name": "ivysaur" }, { "url": "http://pokeapi.co/api/v2/pokemon/3/", "name": "venusaur" } // outros 17 pokémons ocultados ], "next": "http://pokeapi.co/api/v2/pokemon/?offset=20" } Consumindo uma API de Pokémons ▣ O que é uma API web? ▣ O que é uma API REST? ▢ Pokéapi ▢ Recurso /pokemon http://pokeapi.co/api/v2/pokemon/
  122. { "count": 811, "previous": null, "results": [ { "url": "http://pokeapi.co/api/v2/pokemon/1/",

    "name": "bulbasaur" }, { "url": "http://pokeapi.co/api/v2/pokemon/2/", "name": "ivysaur" }, { "url": "http://pokeapi.co/api/v2/pokemon/3/", "name": "venusaur" } // outros 17 pokémons ocultados ], "next": "http://pokeapi.co/api/v2/pokemon/?offset=20" } Consumindo uma API de Pokémons ▣ O que é uma API web? ▣ O que é uma API REST? ▢ Pokéapi ▢ Recurso /pokemon http://pokeapi.co/api/v2/pokemon/ array com os dados de cada pokémon parecido com a nossa PokemonList :) dados de um pokémon } URL para os dados apenas do pokémon URL para mais 20 pokémons (API paginada)
  123. Consumindo uma API de Pokémons ▣ O que é uma

    API web? ▣ O que é uma API REST? ▢ Pokéapi ▣ Recurso /pokemon ▢ Como consumiremos?
  124. Consumindo uma API de Pokémons ▣ O que é uma

    API web? ▣ O que é uma API REST? ▣ Pokéapi ▣ Recurso /pokemon ▣ Como consumiremos? ▢ Consumindo a API ▢ Lendo pokémons da API var Pokemon = require('./Pokemon'); class PokemonList { constructor(infoArray, options) { this.items = []; this.nextUrl = options.nextUrl; for(var i = 0; i < infoArray.length; i++) { var pokemon = new Pokemon(infoArray[i]); this.items.push(pokemon); } } } module.exports = PokemonList; js/models/PokemonList.js recebemos a URL da página atual da API por parâmetro
  125. Consumindo uma API de Pokémons ▣ O que é uma

    API web? ▣ O que é uma API REST? ▣ Pokéapi ▣ Recurso /pokemon ▣ Como consumiremos? ▢ Consumindo a API ▢ Lendo pokémons da API var PokemonList = require('./models/PokemonList'); var pokemonsInfo = [ { name: 'pikachu' }, { name: 'blaziken' }, { name: 'lucario' } ]; var pokemons = new PokemonList(pokemonsInfo, { nextUrl: 'http://pokeapi.co/api/v2/pokemon/' }); module.exports = pokemons; js/pokemons.js passamos o objeto com o campo nextURL para o PokemonList
  126. Consumindo uma API de Pokémons ▣ O que é uma

    API web? ▣ O que é uma API REST? ▣ Pokéapi ▣ Recurso /pokemon ▣ Como consumiremos? ▢ Consumindo a API ▢ Lendo pokémons da API var $ = require('jquery'); var Pokemon = require('./Pokemon'); class PokemonList { constructor(infoArray, options) { this.items = []; this.nextUrl = options.nextUrl; for(var i = 0; i < infoArray.length; i++) { var pokemon = new Pokemon(infoArray[i]); this.items.push(pokemon); } this.fetchNext(); } fetchNext() { return $.get(this.nextUrl).then((data) => { console.log(data); }); } } module.exports = PokemonList; js/models/PokemonList.js importamos o jQuery para usar a função de AJAX dele envia requisição AJAX para a URL e chama a função passando a resposta como parâmetro data chamamos aqui nosso novo método, só para teste :)
  127. Consumindo uma API de Pokémons ▣ O que é uma

    API web? ▣ O que é uma API REST? ▣ Pokéapi ▣ Recurso /pokemon ▣ Como consumiremos? ▢ Consumindo a API ▢ Lendo pokémons da API > npm run build:js # abrir index.html no navegador # abrir console do navegador # esperar a requisição AJAX terminar e verificar o console
  128. Consumindo uma API de Pokémons ▣ O que é uma

    API web? ▣ O que é uma API REST? ▣ Pokéapi ▣ Recurso /pokemon ▣ Como consumiremos? ▢ Consumindo a API ▣ Lendo pokémons da API ▢ Substituindo pokémons hardcoded pela API var PokemonList = require('./models/PokemonList'); var pokemonsInfo = [ { name: 'pikachu' }, { name: 'blaziken' }, { name: 'lucario' } ]; var pokemons = new PokemonList([], { nextUrl: 'http://pokeapi.co/api/v2/pokemon/' }); module.exports = pokemons; js/pokemons.js podemos remover esta lista daqui passamos um array vazio como lista inicial
  129. Consumindo uma API de Pokémons ▣ O que é uma

    API web? ▣ O que é uma API REST? ▣ Pokéapi ▣ Recurso /pokemon ▣ Como consumiremos? ▢ Consumindo a API ▣ Lendo pokémons da API ▢ Substituindo pokémons hardcoded pela API var $ = require('jquery'); var Pokemon = require('./Pokemon'); class PokemonList { constructor(infoArray, options) { this.items = []; this.nextUrl = options.nextUrl; for(var i = 0; i < infoArray.length; i++) { var pokemon = new Pokemon(infoArray[i]); this.items.push(pokemon); } this.fetchNext(); } fetchNext() { return $.get(this.nextUrl).then((data) => { console.log(data); }); } } module.exports = PokemonList; js/models/PokemonList.js remover esta chamada de teste moveremos este bloco para cá
  130. Consumindo uma API de Pokémons ▣ O que é uma

    API web? ▣ O que é uma API REST? ▣ Pokéapi ▣ Recurso /pokemon ▣ Como consumiremos? ▢ Consumindo a API ▣ Lendo pokémons da API ▢ Substituindo pokémons hardcoded pela API var $ = require('jquery'); var Pokemon = require('./Pokemon'); class PokemonList { constructor(infoArray, options) { this.items = []; this.nextUrl = options.nextUrl; } fetchNext() { return $.get(this.nextUrl).then((data) => { for(var i = 0; i < infoArray.length; i++) { var pokemon = new Pokemon(infoArray[i]); this.items.push(pokemon); } }); } } module.exports = PokemonList; js/models/PokemonList.js substituiremos a variável infoArray por data.results
  131. Consumindo uma API de Pokémons ▣ O que é uma

    API web? ▣ O que é uma API REST? ▣ Pokéapi ▣ Recurso /pokemon ▣ Como consumiremos? ▢ Consumindo a API ▣ Lendo pokémons da API ▢ Substituindo pokémons hardcoded pela API var $ = require('jquery'); var Pokemon = require('./Pokemon'); class PokemonList { constructor(infoArray, options) { this.items = []; this.nextUrl = options.nextUrl; } fetchNext() { return $.get(this.nextUrl).then((data) => { for(var i = 0; i < data.results.length; i++) { var pokemon = new Pokemon(data.results[i]); this.items.push(pokemon); } }); } } module.exports = PokemonList; js/models/PokemonList.js nossa função retorna uma promise
  132. Consumindo uma API de Pokémons ▣ O que é uma

    API web? ▣ O que é uma API REST? ▣ Pokéapi ▣ Recurso /pokemon ▣ Como consumiremos? ▢ Consumindo a API ▣ Lendo pokémons da API ▣ Substituindo pokémons hardcoded pela API ▢ Renderizar só depois de recebermos os dados var $ = require('jquery'); var pokemons = require('./pokemons'); var PokemonListView = require('./views/PokemonListView'); var $pokedex = $('.pokedex'); var pokemonListView = new PokemonListView({ pokemons: pokemons }); pokemons.fetchNext().then(() => { pokemonListView.render(); $pokedex.append(pokemonListView.$element); }); js/index.js chama nossa função que carrega os pokémons por AJAX e renderiza só depois de receber a resposta
  133. Consumindo uma API de Pokémons ▣ O que é uma

    API web? ▣ O que é uma API REST? ▣ Pokéapi ▣ Recurso /pokemon ▣ Como consumiremos? ▢ Consumindo a API ▣ Lendo pokémons da API ▣ Substituindo pokémons hardcoded pela API ▣ Renderizar só depois de recebermos os dados ▢ Verificar no navegador > npm run build:js # abrir index.html no navegador # esperar a API carregar
  134. Carregando mais Pokémons ▢ Adicionando botão de carregar var $

    = require('jquery'); var pokemons = require('./pokemons'); var PokemonListView = require('./views/PokemonListView'); var $pokedex = $('.pokedex'); var pokemonListView = new PokemonListView({ pokemons: pokemons }); var $loadMore = $('<button/>'); $loadMore.text('Load more'); pokemons.fetchNext().then(() => { pokemonListView.render(); $pokedex.append(pokemonListView.$element); $pokedex.append($loadMore); }); js/index.js cria botão escrito “Load more” } adicionamos botão após a lista de pokémons
  135. Carregando mais Pokémons ▢ Adicionando botão de carregar > npm

    run build:js # abrir index.html no navegador # o botão parece fora de lugar, mas vamos estilizá-lo depois!
  136. Carregando mais Pokémons ▣ Adicionando botão de carregar ▢ Requisitar

    novos pokémons pela API var $ = require('jquery'); var Pokemon = require('./Pokemon'); class PokemonList { constructor(infoArray, options) { this.items = []; this.nextUrl = options.nextUrl; } fetchNext() { return $.get(this.nextUrl).then((data) => { for(var i = 0; i < data.results.length; i++) { var pokemon = new Pokemon(data.results[i]); this.items.push(pokemon); } this.nextUrl = data.next; }); } } module.exports = PokemonList; js/models/PokemonList.js atualiza a URL da próxima página da API
  137. Carregando mais Pokémons ▣ Adicionando botão de carregar ▢ Requisitar

    novos pokémons pela API var $ = require('jquery'); var PokemonView = require('./PokemonView'); class PokemonListView { constructor(attrs) { ... } loadNextPage() { return this.pokemonList.fetchNext().then((newPokemons) => { newPokemons.forEach((pokemon) => { var pokemonView = new PokemonView({ pokemon: pokemon }); pokemonView.render(); this.$element.append(pokemonView.$element); }); }); } render() { this.pokemonList.items.forEach((pokemon) => { var pokemonView = new PokemonView({ pokemon: pokemon }); pokemonView.render(); this.$element.append(pokemonView.$element); }); } } module.exports = PokemonListView; js/views/PokemonListViews.js ocultei o construtor para caber tudo na tela :) percorre cada novo pokémon carregado da API e adiciona na tela
  138. Carregando mais Pokémons ▣ Adicionando botão de carregar ▢ Requisitar

    novos pokémons pela API var $ = require('jquery'); var PokemonView = require('./PokemonView'); class PokemonListView { constructor(attrs) { ... } loadNextPage() { return this.pokemonList.fetchNext().then((newPokemons) => { newPokemons.forEach((pokemon) => { var pokemonView = new PokemonView({ pokemon: pokemon }); pokemonView.render(); this.$element.append(pokemonView.$element); }); }); } render() { this.pokemonList.items.forEach((pokemon) => { var pokemonView = new PokemonView({ pokemon: pokemon }); pokemonView.render(); this.$element.append(pokemonView.$element); }); } } module.exports = PokemonListView; js/views/PokemonListViews.js oops, temos código duplicado!
  139. Carregando mais Pokémons ▣ Adicionando botão de carregar ▢ Requisitar

    novos pokémons pela API var $ = require('jquery'); var PokemonView = require('./PokemonView'); class PokemonListView { constructor(attrs) { ... } loadNextPage() { return this.pokemonList.fetchNext().then((newPokemons) => { newPokemons.forEach((pokemon) => { var pokemonView = new PokemonView({ pokemon: pokemon }); pokemonView.render(); this.$element.append(pokemonView.$element); }); }); } render() { this.pokemonList.items.forEach((pokemon) => { var pokemonView = new PokemonView({ pokemon: pokemon }); pokemonView.render(); this.$element.append(pokemonView.$element); }); } } module.exports = PokemonListView; js/views/PokemonListViews.js vamos extrair este código para um novo método
  140. Carregando mais Pokémons ▣ Adicionando botão de carregar ▢ Requisitar

    novos pokémons pela API var $ = require('jquery'); var PokemonView = require('./PokemonView'); class PokemonListView { constructor(attrs) { ... } loadNextPage() { return this.pokemonList.fetchNext().then((newPokemons) => { this.appendPokemons(newPokemons); }); } appendPokemons(pokemons) { pokemons.forEach((pokemon) => { var pokemonView = new PokemonView({ pokemon: pokemon }); pokemonView.render(); this.$element.append(pokemonView.$element); }); } render() { this.appendPokemons(this.pokemonList.items); } } module.exports = PokemonListView; js/views/PokemonListViews.js método que recebe uma lista de pokémons e adiciona ela na view
  141. Carregando mais Pokémons ▣ Adicionando botão de carregar ▢ Requisitar

    novos pokémons pela API var $ = require('jquery'); var PokemonView = require('./PokemonView'); class PokemonListView { constructor(attrs) { ... } loadNextPage() { return this.pokemonList.fetchNext().then((newPokemons) => { this.appendPokemons(newPokemons); }); } appendPokemons(pokemons) { pokemons.forEach((pokemon) => { var pokemonView = new PokemonView({ pokemon: pokemon }); pokemonView.render(); this.$element.append(pokemonView.$element); }); } render() { this.appendPokemons(this.pokemonList.items); } } module.exports = PokemonListView; js/views/PokemonListViews.js agora os dois métodos fazem a mesma coisa :)
  142. Carregando mais Pokémons ▣ Adicionando botão de carregar ▢ Requisitar

    novos pokémons pela API var $ = require('jquery'); var PokemonView = require('./PokemonView'); class PokemonListView { constructor(attrs) { ... } loadNextPage() { return this.pokemonList.fetchNext().then((newPokemons) => { this.appendPokemons(newPokemons); }); } appendPokemons(pokemons) { pokemons.forEach((pokemon) => { var pokemonView = new PokemonView({ pokemon: pokemon }); pokemonView.render(); this.$element.append(pokemonView.$element); }); } render() { this.appendPokemons(this.pokemonList.items); } } module.exports = PokemonListView; js/views/PokemonListViews.js vamos fazer com que o fetchNext() retorne apenas os novos pokémons carregados
  143. Carregando mais Pokémons ▣ Adicionando botão de carregar ▢ Requisitar

    novos pokémons pela API var $ = require('jquery'); var Pokemon = require('./Pokemon'); class PokemonList { constructor(infoArray, options) { this.items = []; this.nextUrl = options.nextUrl; } fetchNext() { return $.get(this.nextUrl).then((data) => { var newPokemons = []; for(var i = 0; i < data.results.length; i++) { var pokemon = new Pokemon(data.results[i]); newPokemons.push(pokemon); } this.items = this.items.concat(newPokemons); this.nextUrl = data.next; return newPokemons; }); } } module.exports = PokemonList; js/models/PokemonList.js cria novo array de pokémons
  144. Carregando mais Pokémons ▣ Adicionando botão de carregar ▢ Requisitar

    novos pokémons pela API var $ = require('jquery'); var Pokemon = require('./Pokemon'); class PokemonList { constructor(infoArray, options) { this.items = []; this.nextUrl = options.nextUrl; } fetchNext() { return $.get(this.nextUrl).then((data) => { var newPokemons = []; for(var i = 0; i < data.results.length; i++) { var pokemon = new Pokemon(data.results[i]); newPokemons.push(pokemon); } this.items = this.items.concat(newPokemons); this.nextUrl = data.next; return newPokemons; }); } } module.exports = PokemonList; js/models/PokemonList.js adiciona cada novo pokémon da API no novo array
  145. Carregando mais Pokémons ▣ Adicionando botão de carregar ▢ Requisitar

    novos pokémons pela API var $ = require('jquery'); var Pokemon = require('./Pokemon'); class PokemonList { constructor(infoArray, options) { this.items = []; this.nextUrl = options.nextUrl; } fetchNext() { return $.get(this.nextUrl).then((data) => { var newPokemons = []; for(var i = 0; i < data.results.length; i++) { var pokemon = new Pokemon(data.results[i]); newPokemons.push(pokemon); } this.items = this.items.concat(newPokemons); this.nextUrl = data.next; return newPokemons; }); } } module.exports = PokemonList; js/models/PokemonList.js retorna apenas os novos pokémons adicionados
  146. Carregando mais Pokémons ▣ Adicionando botão de carregar ▢ Requisitar

    novos pokémons pela API # agora temos uma função que, quando chamada carrega novos pokémons da API e adiciona eles à tela # o que fazer? :)
  147. Carregando mais Pokémons ▣ Adicionando botão de carregar ▣ Requisitar

    novos pokémons pela API ▢ Adicionando comportamento do botão var $ = require('jquery'); var pokemons = require('./pokemons'); var PokemonListView = require('./views/PokemonListView'); var $pokedex = $('.pokedex'); var pokemonListView = new PokemonListView({ pokemons: pokemons }); var $loadMore = $('<button/>'); $loadMore.text('Load more'); $loadMore.on('click', () => { pokemonListView.loadNextPage(); }); pokemons.fetchNext().then(() => { pokemonListView.render(); $pokedex.append(pokemonListView.$element); $pokedex.append($loadMore); }); js/index.js quando o botão é clicado, chama nossa função que carrega mais pokémons
  148. Carregando mais Pokémons ▣ Adicionando botão de carregar ▣ Requisitar

    novos pokémons pela API ▣ Adicionando comportamento do botão ▢ Bloqueando o botão enquanto carrega os dados var $ = require('jquery'); var pokemons = require('./pokemons'); var PokemonListView = require('./views/PokemonListView'); var $pokedex = $('.pokedex'); var pokemonListView = new PokemonListView({ pokemons: pokemons }); var $loadMore = $('<button/>'); $loadMore.text('Load more'); $loadMore.on('click', () => { $loadMore.attr('disabled', true); pokemonListView.loadNextPage().then(() => { $loadMore.attr('disabled', false); }); }); pokemons.fetchNext().then(() => { pokemonListView.render(); $pokedex.append(pokemonListView.$element); $pokedex.append($loadMore); }); js/index.js desabilita o botão quando ele é clicado habilita o botão novamente depois de carregado
  149. Carregando mais Pokémons ▣ Adicionando botão de carregar ▣ Requisitar

    novos pokémons pela API ▣ Adicionando comportamento do botão ▣ Bloqueando o botão enquanto carrega os dados ▢ Estilizando o botão ▢ Adicionar classe CSS ao botão var $ = require('jquery'); var pokemons = require('./pokemons'); var PokemonListView = require('./views/PokemonListView'); var $pokedex = $('.pokedex'); var pokemonListView = new PokemonListView({ pokemons: pokemons }); var $loadMore = $('<button/>'); $loadMore.text('Load more'); $loadMore.addClass('load-more'); $loadMore.on('click', () => { $loadMore.attr('disabled', true); pokemonListView.loadNextPage().then(() => { $loadMore.attr('disabled', false); }); }); pokemons.fetchNext().then(() => { pokemonListView.render(); $pokedex.append(pokemonListView.$element); $pokedex.append($loadMore); }); js/index.js adicionamos classe load-more ao botão
  150. Carregando mais Pokémons ▣ Adicionando botão de carregar ▣ Requisitar

    novos pokémons pela API ▣ Adicionando comportamento do botão ▣ Bloqueando o botão enquanto carrega os dados ▢ Estilizando o botão ▣ Adicionar classe CSS ao botão ▢ Criar css/_loadMore.scss e importar em style.scss @import 'variables'; @import 'pokedex'; @import 'pokemonList'; @import 'pokemon'; @import 'loadMore'; * { box-sizing: border-box; } css/style.scss
  151. Carregando mais Pokémons ▣ Adicionando botão de carregar ▣ Requisitar

    novos pokémons pela API ▣ Adicionando comportamento do botão ▣ Bloqueando o botão enquanto carrega os dados ▢ Estilizando o botão ▣ Adicionar classe CSS ao botão ▣ Criar css/_loadMore.scss e importar em style.scss ▢ Criar estilo do botão .load-more { width: 100%; border-radius: 5px; } css/_loadMore.scss largura de 100% e borda arredondada de raio 5px }
  152. Carregando mais Pokémons ▣ Adicionando botão de carregar ▣ Requisitar

    novos pokémons pela API ▣ Adicionando comportamento do botão ▣ Bloqueando o botão enquanto carrega os dados ▢ Estilizando o botão ▣ Adicionar classe CSS ao botão ▣ Criar css/_loadMore.scss e importar em style.scss ▣ Criar estilo do botão ▢ Ajustar posicionamento do botão .load-more { width: 100%; border-radius: 5px; margin-top: 10px; } css/_loadMore.scss css/_pokedex.scss .pokedex { height: 100%; width: 100%; background-color: $pokedex-color; padding: 15px; padding-bottom: 40px; # resto do arquivo ocultado para caber tudo aumentamos o espaçamento inferir para 40px adicionamos margem de 10px ao botão, que move ele 10px para baixo
  153. Carregando mais Pokémons ▣ Adicionando botão de carregar ▣ Requisitar

    novos pokémons pela API ▣ Adicionando comportamento do botão ▣ Bloqueando o botão enquanto carrega os dados ▣ Estilizando o botão ▣ Adicionar classe CSS ao botão ▣ Criar css/_loadMore.scss e importar em style.scss ▣ Criar estilo do botão ▣ Ajustar posicionamento do botão > npm run build:js > npm run build:css # abrir index.html no navegador
  154. Onde aprender • Evite o W3Schools. Ele não é a

    W3C. • MDN: https://developer.mozilla.org/pt-BR/ • JavaScript Path: https://github.com/javascript-society/javascript-path • Marksheet: http://marksheet.io/