JavaScript

JavaScript?

Navegadores

Terminais

PhamtomJS

Aplicativos móveis

PhoneGap

Servidores Web

node.js

Aplicativos desktop

appjs

Editores de texto

Brackets

O Projeto

Save the Princess

Save the Princess

https://github.com/marcoafilho/save-the-princess

Prêmios


1º Lugar

  • 2 camisas do GitHub
  • JavaScript the definitive guide e JavaScript & jQuery
  • 40 adesivos do GitHub

Prêmios


2º Lugar

  • 2 camisas do GitHub
  • 30 adesivos do GitHub

Prêmios


3º Lugar

  • 20 adesivos do GitHub

Instalação

JavaScript é embutido na maioria dos navegadores modernos.

Inline JavaScript


<a href="javascript:void(0)"></a>
                        

Internal JavaScript


<script>
    console.log(1 + 1);
</script>
                        

External JavaScript


<script src="assets/js/filename.js"></script>
                        

Ferramentas

REPL

Read Eval Print Loop

Chrome Developer Tools

Ctrl + Shift + J
Developer tools

Brackets

Brackets

Exercício

3 min

  • Configurar Git;
  • Criar projeto no GitHub;
  • Criar um arquivo README, html, css e js;
  • Git push!

Solução


Configuração Git

$ git config --global user.name "Marco Almeida"
$ git config --global user.email "marcoantonio@infojr.com.br"
                        

$ ssh-keygen -t rsa -C "marcoantonio@infojr.com.br"
                        
Lembre-se de registrar as chaves no GitHub

Valores, tipos e operadores

Number

Representação em formato numérico

// Integer
13;
// Float
9.81;
// Exponent
2.998e8;
// Arithmetic
100 + 4 * 11;
// Infinity
Infinity - 1;
// Not a Number
NaN;
0/0;

typeof(4);
// number
                        

String

Representação em formato de texto

"Patch my boat with chewing gum";
'Monkeys wave goodbye';
// Concatenate
"con" + "cat" + "e" + "nate";

typeof('This is the first line\nAnd this is the second');
//string
                        

Boolean

Representação de verdadeiro e falso

3 > 2;
// true

3 < 2;
// false

"Aardvark" < "Zoroaster";
// true

"Itchy" !== "Scratchy";
// false

NaN === NaN;
// false

true && false;
// false

true || false;
// true

true ? 1 : 2;
// 1

typeof(true);
// boolean
                        

Undefined

Representação da falta de um valor

var a;
null;
undefined;

typeof(undefined);
// undefined
                        

Function

Representação de um conjunto de operações

var dieRoll = function () {
    return Math.ceil(Math.random() * 6);
};

var age = parseInt(window.prompt('What\'s your age?'));

console.log(dieRoll());

typeof(dieRoll);
// function
                        

Object

Representação de uma estrutura de dados complexa

var array = [0, 'Marc', {}, 1, 'James', {}];
var object = { name: 'Marc', strength: 3 };
var date = new Date();

typeof(array);
// object
                        

Exercício

3 min

Simulador de batalhas


Entrada

  • Entrada #1: Força do primeiro herói;
  • Entrada #2: Armadura do segundo herói;
  • Os atributos devem ser inteiros.

Saída

  • Retornar 'First' se força for maior que armadura;
  • Retornar 'Second' caso contrário.

Solução



(parseInt(prompt()) > parseInt(prompt())) ? 'First' : 'Second';
                        

Estrutura de um programa

Variáveis

Armazenando valores na memória

var strength = 5,
    firePower;

firePower = '3';
firePower = 10;

console.log(firePower);
                        

Funções

Encapsulando pedaços de um programa

alert('Welcome to Save the Princess!');
var name = prompt('What is your name?');
console.log(name);
var humanize = function (name) {
    return name[0].toUpperCase() + name.slice(1);
};
confirm('Is your name ' + humanize(name) + '?');
                        

Condicionais

Controlando o fluxo através de condições

var strength = prompt('What\'s your strength?');
if (strength > 3) {
    console.log('Very strong!');
} else if (strength > 1) {
    console.log('Human.');
} else {
    console.log('Weak...');
}

switch (parseInt(strength)) {
case 4:
case 5:
    console.log('Very strong!');
    break;
case 2:
case 3:
    console.log('Human.');
    break;
case 1:
    console.log('Weak...');
}
                        

Loops

Repetindo um conjunto de operações

var strength = 3, counter = 0, totalDamage = 0;
while (counter < strength) {
    totalDamage += Math.ceil(Math.random() * 6);
    counter++;
}
console.log(totalDamage);

counter = 0;
totalDamage = 0;
do {
    totalDamage += Math.ceil(Math.random() * 6);
    counter++;
} while (counter <= strength)
console.log(totalDamage);

totalDamage = 0;
for (counter = 0; counter < strength; counter += 1) {
    totalDamage += Math.ceil(Math.random() * 6);
}
console.log(totalDamage);
                        

Exercício

Primeiro, um pouco de 3D&T


  • Um personagem é composto por Força, Armadura e Resistência.
  • Esses atributos devem ter no máximo 5 pontos.
  • Pontos de vida são então derivados da Resistência.
  • Para cada ponto de Resistência, um personagem terá 5 pontos de vida.
  • O cálculo de um turno é feito da seguinte forma:
    
    totalDamage = strengthOne * random(1, 6) - armorTwo * random(1, 6);
                                

Exercício

25 min

Simulador de Batalha 2


Entrada

  • Atributos devem ser gerados aleatoriamente.


Saída

  • Atributos dos personagens;
  • Marcar com asterisco o nome do personagem vencendor.

Solução



var strength1 = Math.ceil(Math.random() * 5),
    armor1 = Math.ceil(Math.random() * 5),
    resistance1 = Math.ceil(Math.random() * 5),
    hP1 = resistance1 * 5,
    currentHP1 = hP1,
    strength2 = Math.ceil(Math.random() * 5),
    armor2 = Math.ceil(Math.random() * 5),
    resistance2 = Math.ceil(Math.random() * 5),
    hP2 = resistance2 * 5,
    currentHP2 = hP2,
    damage = 0;

while (currentHP1 > 0 && currentHP2 > 0) {
    currentHP2 -=
        Math.max(0, strength1 * (Math.ceil(Math.random() * 6) + 1)
        - armor2 * (Math.ceil(Math.random() * 6)));
    if (currentHP2 > 0) {
        currentHP1 -=
            Math.max(0, strength2 * (Math.ceil(Math.random() * 6) + 1)
            - armor1 * (Math.ceil(Math.random() * 6)));
    }
}

if (currentHP1 > 0) {
    console.log('* First\nStrength: ', strength1, '\nArmor: ', armor1, '\nResistance: ', resistance1, '\nHP: ', currentHP1, '/', hP1);
    console.log('\n\nSecond\nStrength: ', strength2, '\nArmor: ', armor2, '\nResistance: ', resistance2, '\nHP: ', currentHP2, '/', hP2);
} else {
    console.log('\n\nFirst\nStrength: ', strength1, '\nArmor: ', armor1, '\nResistance: ', resistance1, '\nHP: ', currentHP1, '/', hP1);
    console.log('* Second\nStrength: ', strength2, '\nArmor: ', armor2, '\nResistance: ', resistance2, '\nHP: ', currentHP2, '/', hP2);
}
                        

Funções

Declarando funções

Maneiras de definir uma função em JavaScript

var rollDie = function (sides) {
    return Math.ceil(Math.random() * sides);
};

function rollDie(sides) {
    return Math.ceil(Math.random() * sides);
}

rollDie();
                        

Modo estrito

Optando por uma variação mais estrita do JavaScript

var rollDie = function (sides) {
    'use strict';
    return Math.ceil(Math.random() * (sides || 6));
};
                        

Parâmetros e Escopo

Representação em formato de texto

var strength = 3,
    armor = 5,
    attack = function (strength, armor) {
        'use strict';
        return (strength * rollDie(6)) - (armor * rollDie(6));
    };

attack(strength, armor, 5, 6);

var strength = 1,
    newStrength = function () {
    'use strict';
    var strength = 4;
};
newStrength();
console.log(strength);
// => 1

var strength = 1,
    newStrength = function () {
    'use strict';
    strength = 4;
};
newStrength();
console.log(strength);
// => 4
                        

Aninhamento de funções

Definição de funções dentro de funções

var strength1 = 1,
    armor1 = 2,
    hp1 = 5,
    strength2 = 2,
    armor2 = 1,
    hp2 = 5,
    battle = function (strength1, armor1, hp1, strength2, armor2, hp2) {
        'use strict';
        var attack = function (strength) {
            return strength * dieRoll();
        },
            defend = function () {
                return armor * dieRoll();
        },
            dieRoll = function () {
                return Math.ceil(Math.random() * 6) ;
        };

        while (hp1 > 0 && hp2 > 0) {
            hp2 -= Math.max(attack(strength1) - defend(armor2), 0);
            if (hp2 > 0) {
                hp1 -= Math.max(attack(strength2) - defend(armor1), 0);
            }
        }

        return (hp1 <= 0) ? [strength2, armor2, hp2] : [strength1, armor1, hp1];
    };

battle(strength1, armor1, hp1, strength2, armor2, hp2);
                        

Parâmetros opcionais

Representação da falta de um valor

var dieRoll = function (sides) {
    'use strict';
    if (sides === undefined) {
        sides = 6;
    }
    return Math.ceil(Math.random() * sides);
};

var dieRoll = function (sides) {
    'use strict';
    return Math.ceil(Math.random() * (sides || 6));
};
                        

Exercício

20 min

Função geradora de personagens


Entrada

  • Nome do personagem;
  • Quantidade máxima de pontos


Saída

  • Array com nome e o valor dos atributos do 3D&T;
  • Atributos não podem ter mais de 5 pontos;
  • A soma dos atributos não pode passar o número dado.

Solução



var randomCharacter = function (name, limit) {
    'use strict';
    var strength = 0,
        skill = 0,
        resistance = 0,
        armor = 0,
        firePower = 0,
        randomStatus = function () {
            return Math.floor(Math.random() * 6);
        };

    if (limit >= 0) {
        strength = Math.min(generateStatus(), limit);
        limit -= strength;
    }
    if (limit >= 0) {
        skill = Math.min(generateStatus(), limit);
        limit -= skill;
    }
    if (limit >= 0) {
        resistance = Math.min(generateStatus(), limit);
        limit -= resistance;
    }
    if (limit >= 0) {
        armor = Math.min(generateStatus(), limit);
        limit -= armor;
    }
    if (limit >= 0) {
        firePower = Math.min(generateStatus(), limit);
        limit -= firePower;
    }

    return [name, strength, skill, resistance, armor, firePower];
}
                        

Estrutura de dados

Arrays

Representação de um conjunto de valores


var character = ['Marc', 1, 4, 2, 3, 0],
    monster = ['Bat', 1, 2, 2, 1, 0];

character[0];
// => 'Marc'
                        

Propriedades


var character = ['Marc', 1, 4, 2, 3, 0];

character.length;
character['length'];
                        

Métodos


var character = ['Marc', 1, 4, 2, 3, 0];

character.push(character[4] * 5);
// => 7
character.pop();
// => 15
                        

Objetos


var character = {
    name: 'Marc',
    strength: 1,
    skill: 4,
    armor: 2,
    resistance: 3,
    firePower: 0
};

character.name;
// => "Marc"
character['strength'];
// => 1
character.healthPoints = character.resistance * 5;
// => 15
                        

Mutabilidade


var character = {
    name: 'Marc',
    strength: 1,
    skill: 4,
    armor: 2,
    resistance: 3,
    firePower: 0
};

character.name;
// => "Marc"
character['strength'];
// => 1
character.healthPoints = character.resistance * 5;
// => 15
                        

Conjunto de dados


var characters = [
    { name: 'Marc', strength: 1, skill: 4, armor: 2, resistance: 3, firePower: 0 },
    { name: 'James', strength: 1, skill: 3, armor: 1, resistance: 1, firePower: 4 },
    { name: 'Leon', strength: 2, skill: 3, armor: 2, resistance: 1, firePower: 2 }],
    strongestCharacter = function (characters) {
        var strongest = characters[0],
            index;

        for (index = 0; index < characters.length; index += 1) {
            if (strongest.strength < characters[index].strength) {
                strongest = characters[index];
            }
        }

        return strongest;
    };

strongestCharacter(characters);
                        

Métodos em objetos


var Die = {
        roll: function () {
            return Math.ceil(Math.random() * 6);
        }
    };

Die.roll();
// => 5
                        

this


var Die = {
        roll: function () {
            return Math.ceil(Math.random() * 6);
        }
    },
    attack = function () {
        return this.strength * Die.roll();
    },
    defend = function () {
        return this.armor * Die.roll();
    },
    marc = { name: 'Marc', strength: 1, skill: 4, armor: 2, resistance: 3, firePower: 0, attack: attack, defend: defend },
    james = { name: 'James', strength: 1, skill: 3, armor: 1, resistance: 1, firePower: 4 };

window.attack();
// => NaN

james.attack = attack;
james.defend = defend;

james.currentHealthPoints = james.resistance * 5;
james.currentHealthPoints -= Math.max(marc.attack() - james.defend(), 0);
                        

Exercício

25 min

Simulador de batalha 3


Entrada

  • Dois personagens gerados aleatoriamente;


Saída

  • Retorne o personagem que ganhou a batalha

Solução



var Die = {
        roll: function () {
            'use strict';
            return Math.ceil(Math.random() * 6);
        }
    },

    randomCharacter = function (name, limit) {
        'use strict';
        var character = {
                name: name,
                attack: function () {
                    return Die.roll() * Math.max(this.strength, this.firePower);
                },
                defend: function () {
                    return Die.roll() * this.armor;
                }
            },
            randomStatus = function () {
                return Math.floor(Math.random() * 6);
            };

        if (limit >= 0) {
            character.strength = Math.min(randomStatus(), limit);
            limit -= character.strength;
        }
        if (limit >= 0) {
            character.skill = Math.min(randomStatus(), limit);
            limit -= character.skill;
        }
        if (limit >= 0) {
            character.resistance = Math.min(randomStatus(), limit);
            limit -= character.resistance;
        }
        if (limit >= 0) {
            character.armor = Math.min(randomStatus(), limit);
            limit -= character.armor;
        }
        if (limit >= 0) {
            character.firePower = Math.min(Math.min(randomStatus(), limit), 5);
            limit -= character.firePower;
        }
        character.healthPoints = character.resistance * 5;

        return character;
    },

    battle = function (character, opponent) {
        var winner;

        while (character.healthPoints > 0 && opponent.healthPoints > 0) {
            opponent.healthPoints -= character.attack() - opponent.defend();
            if (opponent.healthPoints > 0) {
                character.healthPoints -= opponent.attack() - character.defend();
            }
        }
        winner = (character.healthPoints > 0) ? character : opponent

        return winner;
    };

    marc = randomCharacter('Marc', 10);
    james = randomCharacter('James', 10);
    battle(marc, james);
                        

A vida secreta dos objetos

Construtores

Maneira mais conveniente de se instanciar um objeto

var Character = function (attrs) {
    this.strength = attrs.strength;
    this.skill = attrs.skill;
    // ...
};

var marc = new Character({ strength: 2, skill: 4 });
                        

Prototypes


Character.prototype.attack = function () {
    // ...
};
var marc = new Character({ strength: 2, skill: 4 });
marc.attack();
                        

var Character = function (attrs) {
    this.strength = attrs.strength;
    this.armor = attrs.armor;
    this.firePower = attrs.firePower;
};

Character.prototype.attack = function () {
    // ...
};

Character.prototype.defend = function () {
    // ...
};
                        

O DOM

Árvores

DOM Tree

Navegando na árvore


Character profile
Marc
3
<script> var character = document.querySelector('div'), divs = document.querySelectorAll('div'); console.log(character.querySelector('.name').innerText); console.log(character.querySelector('.character > img').src); console.log(character.getElementById('strongest')); </script>

Alterando a estrutura


<div class="character">
    <img src="link-to-img" alt="Character profile">
    <div class="name">Marc</div>
    <div class="strength" id="strongest">3</div>
</div>
<script>
    var character = document.querySelector('div'),
        divs = document.querySelectorAll('div'),
        name = character.querySelector('.name');
        strength = character.querySelector('.strength');

    character.insertBefore(strength, name);
    name.innerHTML = 'Marc';
</script>
                        

Criando nós


<div class="character"></div>

<script>
    var character = document.querySelector('.character'),
        node = document.createElement('div');
        text = document.createTextNode('Marc');

        character.appendChild(node);
        node.appendChild(text);
</script>
                    

Atributos


<div class="character"></div>

<script>
    var character = document.querySelector('.character');
    character.setAttribute('id', 'character_1');
    character.getAttribute('id');
    character.style.color = '#333';
</script>
                    

Exercício

30 min

Lista de personagens


Entrada

  • Função createCharacter que recebe um objeto personagem.


Saída

  • Apresente uma seção com os atributos do personagem;
  • Cada chamada de método o novo personagem deve ser listado abaixo do anterior.

Exercício

15 min

HUD de batalha


Saída

  • Liste o personagem e o inimigo.

Eventos

Lidando com eventos

Eventos globais

addEventListener('click', function () {
    alert('You clicked!);
});
                        

Eventos com elementos


var button = document.querySelector('button');
button.addEventListener('click', function () {
    console.log('Character 1 attacks Character 2');
});
                        

Exercício

20 min

Batalha


Entrada

  • Cliques no botão atacar.


Saída

  • Usuário ataca e adversário ataca;
  • Apresentar quem foi o usuário vencedor.

Exercício

20 min

Sondar


Entrada

  • Mouse sobre o nome do inimigo.


Saída

  • Usuário ataca e adversário ataca;
  • Nome do usuário vencedor deve ser marcado com uma cor diferente.

Objetos de eventos


var link = document.querySelector('a');
link.addEventListener('click', function (event) {
    event.preventDefault();
    console.log('Character 1 attacks Character 2');
});
                        

Propragação

Eventos invocados em nós filhos

<div style="padding: 20px;">
    <button>Click me!</button>
<div>

<script>
    var div = document.querySelector('div'), button = document.querySelector('button');
    button.addEventListener('click', function (event) {
        alert('I was clicked!');
    });
    div.addEventListener('click', function (event) {
        alert('I was clicked!!');
    });
</script>
                        

Eventos de teclado


var keyboardComponent = function (event) {
    swtich(event.which) {
    case 13: // Enter
        select();
        break;
    case 38: // Up
        selectUp();
        break;
    case 40: // Down
        selectDown();
        break;
    }
};

window.addEventListener('keyup', keyboardComponent);
                        

window.addEventListener('load', function () {
    alert('Page is loaded');
});
                        

Cronômetro


document.body.style.background = 'blue';
setTimeout(function () {
    document.body.style.background = 'yellow';
}, 2000);
                        

Exercício

50 min

Personagem contra vários inimigos


Entrada

  • Usuário pode clicar em atacar ou apertar enter;
  • Usuário pode clicar no inimigo ou selecionar com os direcionais;


Saída

  • Todos os inimigos atacam o personagem;
  • Inimigos vencidos devem desaparecer.

Formulários

Forms


<form action="new.html" method="GET" id="new_character">
    <input type="text" name="name" value="" placeholder="">
    <input type="submit" value="Criar">
</form>
<script>
var form = document.querySelector('#new_character');
form.addEventListener('submit', function (event) {
    event.preventDefault();
    console.log(this.firstElementChild.name);
    console.log(this.firstElementChild.value);
});
</script>
                        

Exercício

25 min

Criação de personagens


Entrada

  • Formulário com atributos do jogador.


Saída

  • Seção com atributos do jogador e inimigo;
  • Formulário deve ser removido após envio.

HTTP

Requisição x Resposta

Requisição

GET /index.html HTTP/1.1
Host: save-the-princess.com
User-Agent: Google Chrome
                        
Resposta

HTTP/1.1 200 OK
Content-Length: 3122
Content-Type: text/html
Last-Modified: Wed, 19 Dez 2014 10:48:09 GMT


... the rest of the document”
                    

GET x POST

Requisição GET

GET /index.html?name=Marco&strength=3 HTTP/1.1
Host: save-the-princess.com
User-Agent: Google Chrome
                        
Requisição POST

POST /index.html HTTP/1.1
Host: save-the-princess.com
User-Agent: Google Chrome

name=Marc&strength=3
                        

XMLHttpRequest

Chamada síncrona

var request = new XMLHttpRequest();
request.open('GET', 'new.html', false);
request.send();
console.log(request.status);
console.log(request.statusText);
console.log(request.responseText);
                        

Exercício

25 min

Criação de personagens


Formulário deve ser enviado ao servidor e retornar um template para ser preenchido com os valores preenchidos.

Requisições assíncronas


var request = new XMLHttpRequest();
request.open('GET', 'new.html', true);
request.addEventListener('load', function () {
    // Code here...
});
request.send();
                        

JSON

JavaScript Object Notation

// enemies.json
[{ "name": "Skeleton", "strength": 2 }, { "name": "Bat", "strength": 1 }, { "name": "Pikachu", "strength": 5 }]

// app.js
var request = new XMLHttpRequest();
request.open('GET', 'enemies.json', true);
request.addEventListener('load', function () {
    console.log(JSON.parse(this.responseText));
});
request.send();
                        

Exercício

25 min

Banco de dados de inimigos


Saída

  • Inimigos são selecionados aleatoriamente para batalhar;
  • Caso vença a batalha, um novo inimigo é selecionado para batalhar.

Referências

HAVERBEKE Martin. Eloquent JavaScript: A modern introduction to JavaScript.

Eloquent JavaScript by Marijn Haverbeke

Five Minutes of JavaScript


Podcast semanal de JavaScript

Five JS

Codeschool - JavaScript


Screencasts sobre JavaScript e suas bibliotecas

Code School

Obrigado!