├── 01-blocos-basicos
├── 01.js
├── 02.js
├── 03.js
└── 04.js
├── 02-dom
├── .gitignore
├── index.html
├── main.js
└── main.scss
├── 03-promises
├── .gitignore
├── get_data.js
├── index.html
├── main.js
└── main.scss
├── 04-apis
├── .gitignore
├── README.md
├── credentials.sample.js
├── get_data.js
├── index.html
├── loading.gif
├── main.js
└── main.scss
├── 05-classes
├── index.html
├── main.css
└── main.js
├── 06-npm
├── .gitignore
├── README.md
├── index.html
├── package-lock.json
├── package.json
├── src
│ ├── index.js
│ └── main.scss
└── webpack.config.js
└── 07-exercicio
├── .gitignore
├── README.md
├── index.html
├── package-lock.json
├── package.json
├── src
├── js
│ ├── .DS_Store
│ ├── index.js
│ └── resources
│ │ ├── google.js
│ │ └── musicbrainz.js
└── styles
│ └── main.scss
└── webpack.config.js
/01-blocos-basicos/01.js:
--------------------------------------------------------------------------------
1 | // Escreva uma função que recebe
2 | // um número e retorna `true` se ele
3 | // é um numero de cartao de credito
4 | // valido ou `false` se não.
5 | //
6 | // Dica: Algoritmo de Luhn.
7 |
8 | // 1. limpar o input, deixando so os digitos
9 | // 2. loopar a sequencia de digitos de tras pra frente
10 | // 1. pegar um digito sim e um nao e multiplicar por dois
11 | // 2. se for o produto for maior que nove, soma os algarismos
12 | // 3. depois disso ai em cima, somar todos
13 | // 3. pegar soma total, e verificar se modulo 10 e zero
14 |
15 | function isValidCreditCard(card) {
16 | let clean_card = card.replace(/\D/g, "").split("")
17 | // let clean_card = ""
18 | // for (const char of card) {
19 | // if (!isNaN(char * 1)) {
20 | // clean_card += char
21 | // // ou...
22 | // // clean_card = clean_card + char
23 | // }
24 | // // ou...
25 | // if (!isNaN(Number(char))) {
26 | // }
27 | // ou...
28 | // if ("0123456789".indexOf(char) !== -1) {
29 | // }
30 | // }
31 | // ou ...
32 | // for (let i = 0; i < card.length; i++) {
33 | // const char = card.charAt(i)
34 | // }
35 | for (let i = clean_card.length - 2; i >= 0; i -= 2) {
36 | let result = (clean_card[i] * 2).toString()
37 | if (result.length === 2) {
38 | result = parseInt(result[0]) + parseInt(result[1])
39 | }
40 | clean_card[i] = result
41 | }
42 | let sum = 0
43 | for (const element of clean_card) {
44 | sum += parseInt(element)
45 | }
46 | return sum > 0 && sum % 10 === 0
47 | }
48 |
49 | // ou...
50 | // function isValidCreditCard(card) {
51 | // let clean_card = card.replace(/\D/g, "").split("")
52 | // let aux = false
53 | // let sum = 0
54 | // for (let i = clean_card.length - 1; i >= 0; i--) {
55 | // let result = clean_card[i]
56 | // if (aux) {
57 | // result = (clean_card[i] * 2).toString()
58 | // if (result.length === 2) {
59 | // result = parseInt(result[0]) + parseInt(result[1])
60 | // }
61 | // }
62 | // sum += parseInt(result)
63 | // aux = !aux
64 | // }
65 | // return sum > 0 && sum % 10 === 0
66 | // }
67 |
68 | const valid_credit_cards = [
69 | "799 273 987 13",
70 | "378734493671000",
71 | "3714-4963-5398-431",
72 | "5610XXX..5910--810!18250",
73 | "30569309025904",
74 | "385 2000 0023 237",
75 | "6011111111111117",
76 | "6011000990139424",
77 | "353 0111 3333 00000",
78 | "356600 woop woop 2020360505",
79 | "5555555555554444",
80 | "5105105105105100"
81 | ]
82 |
83 | for (const valid of valid_credit_cards) {
84 | console.log(isValidCreditCard(valid))
85 | }
86 |
87 | const invalid_credit_cards = [
88 | "799 223 987 13",
89 | "3787786493671000",
90 | "3724-4963-5398-431",
91 | "5610XX3..5910--810!18250",
92 | "0305699025904",
93 | "385 2000 0011123 237",
94 | "6011111111117",
95 | "60190139424",
96 | "353 0111 3333 00100",
97 | "3566043 woop woop 2020360505",
98 | "55553555555554444",
99 | "5105205105105100"
100 | ]
101 |
102 | for (const invalid of invalid_credit_cards) {
103 | console.log(isValidCreditCard(invalid))
104 | }
--------------------------------------------------------------------------------
/01-blocos-basicos/02.js:
--------------------------------------------------------------------------------
1 | // Escreva uma função que recebe
2 | // um RG não formatado e retorna ele
3 | // formatado. Exemplo: "5 5555553" -> "5.555.555-3"
4 |
5 | function formatRG(unformatted) {
6 | let result = unformatted.replace(/\D/g,"");
7 | result.split("");
8 | if (result.length === 9){
9 | return result[0] + result[1] + "." + result[2] + result[3] + result[4] + "." + result[5] + result[6] + result[7] + "-" + result[8];
10 | } else {
11 | return result[0] + result[1] + "." + result[2] + result[3] + result[4] + "." + result[5] + result[6] + result[7] + "-" + "x";
12 | }
13 | }
14 |
15 | function formatRG(unformatted) {
16 | const clearRg = unformatted.replace(/\D/g,"");
17 | return `${clearRg.substr(0, 2)}.${clearRg.substr(2, 3)}.${clearRg.substr(5, 3)}-${clearRg.substr(8, 1)}`;
18 | }
19 |
20 | function formatRG(unformatted) {
21 | const clearRg = unformatted.replace(/\D/g,"");
22 | return clearRg.replace(/(\d{1})(\d{3})(\d{3})(\d{1})/, "$1.$2.$3-$4")
23 | }
24 |
25 | function cpfValido(cpf) {
26 | return cpf.match(/(\d{3})\.(\d{3})\.(\d{3})\-(\d{2})/)
27 | }
28 |
29 |
30 | https://regexr.com/
--------------------------------------------------------------------------------
/01-blocos-basicos/03.js:
--------------------------------------------------------------------------------
1 | // Escreva uma função que
2 | // recebe dois arrays de objetos
3 | // e retorna um terceiro array
4 | // com todos os objetos que aparecem
5 | // no segundo mas não no primeiro.
6 |
7 | function difference(arr1, arr2) {
8 |
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/01-blocos-basicos/04.js:
--------------------------------------------------------------------------------
1 | // Escreva uma função que recebe um
2 | // array de números e strings e retorna
3 | // um objeto com o seguinte formato:
4 | // { elemento: repetições }
5 | // ordenado de forma decrescente pelo
6 | // número de repetições.
7 |
8 | function repetitions(arr) {
9 |
10 | }
--------------------------------------------------------------------------------
/02-dom/.gitignore:
--------------------------------------------------------------------------------
1 | *.css.map
2 | *.css
3 | /.sass-cache
--------------------------------------------------------------------------------
/02-dom/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | CPF
10 |
11 |
12 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/02-dom/main.js:
--------------------------------------------------------------------------------
1 | const input_cpf = document.getElementById("cpf")
2 |
3 | input_cpf.addEventListener("focus" , function(event) {
4 | input_cpf.value = "___.___.___-__"
5 | setTimeout(function() {
6 | input_cpf.setSelectionRange(0, 0)
7 | }, 1)
8 | // ou...
9 | // event.target.value = "___.___.___-__"
10 | // setTimeout(function() {
11 | // event.target.setSelectionRange(0, 0)
12 | // }, 1)
13 | // ou...
14 | // this.value = "___.___.___-__"
15 | // const that = this
16 | // setTimeout(function() {
17 | // that.setSelectionRange(0, 0)
18 | // }, 1)
19 | // ou...
20 | // this.value = "___.___.___-__"
21 | // let set_cursor_position = function () {
22 | // this.setSelectionRange(0, 0)
23 | // }
24 | // set_cursor_position = set_cursor_position.bind(this)
25 | // setTimeout(set_cursor_position, 1)
26 | })
27 |
28 | input_cpf.addEventListener("blur" , function() {
29 | this.value = ""
30 | })
31 |
32 | input_cpf.addEventListener("keydown", function(event) {
33 | event.preventDefault()
34 | if("0123456789".indexOf(event.key) !== -1
35 | && this.value.indexOf("_") !== -1) {
36 | this.value = this.value.replace(/_/, event.key)
37 | const next_index = this.value.indexOf("_")
38 | this.setSelectionRange(next_index, next_index)
39 | } else if (event.key === "Backspace") {
40 | this.value = this.value.replace(/(\d$)|(\d(?=\D+$))/, "_")
41 | const next_index = this.value.indexOf("_")
42 | this.setSelectionRange(next_index, next_index)
43 | }
44 | })
45 |
--------------------------------------------------------------------------------
/02-dom/main.scss:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | margin: 0;
4 | padding: 0;
5 | font-size: 16px;
6 | font-family: 'Montserrat', sans-serif;
7 | }
8 |
9 | body {
10 | background-color: #e8f7e2;
11 | display: flex;
12 | align-items: center;
13 | height: 100vh;
14 | }
15 |
16 | form {
17 | width: 400px;
18 | margin: 0 auto;
19 | padding: 80px 40px;
20 | background-color: white;
21 | box-shadow: 0px 0px 90px 0px rgba(14, 87, 0, 0.151);
22 | border-radius: 3px;
23 |
24 | label {
25 | width: 100%;
26 | margin-bottom: 15px;
27 | display: block;
28 | }
29 |
30 | input {
31 | border-radius: 7px;
32 | width: 100%;
33 |
34 | &[type="submit"] {
35 | text-align: center;
36 | text-transform: uppercase;
37 | font-weight: 800;
38 | background-color: #54c259;
39 | padding: 15px 30px;
40 | margin: 30px 0 0;
41 | display: block;
42 | color: white;
43 | border: none;
44 | cursor: pointer;
45 |
46 | &:active {
47 | box-shadow: 3px 3px 10px 0px rgba(0,0,0,0.1);
48 | }
49 | }
50 |
51 | &[type="text"] {
52 | padding: 20px 15px;
53 | border: 1px solid #ccc;
54 |
55 | &:focus {
56 | box-shadow: inset 0px 0px 3px 0px rgba(0,0,0,0.2);
57 | }
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/03-promises/.gitignore:
--------------------------------------------------------------------------------
1 | *.css.map
2 | *.css
3 | /.sass-cache
--------------------------------------------------------------------------------
/03-promises/get_data.js:
--------------------------------------------------------------------------------
1 | // Cria uma função que retorna uma Promise.
2 | // Essa função recebe como argumento uma URL e faz uma request HTTP
3 | // para essa URL. A Promise resolve se a request tiver sido bem sucedida
4 | // e retorna os dados da resposta da request. Se a request nao for bem
5 | // sucedida a Promise sera rejeitada.
6 | function get_data(url) {
7 | return new Promise(function (resolve, reject) {
8 | // Cria uma nova request
9 | const req = new XMLHttpRequest()
10 |
11 | // Cria a request
12 | req.open('GET', url)
13 |
14 | // Captura o evento de 'onload', que é quando a
15 | // request terminou de ser executada.
16 | req.onload = function () {
17 | // Checa se o status da request é 200,
18 | // o que quer dizer que a request foi bem sucedida.
19 | if (req.status === 200) {
20 | // Resolve a Promise retornando a resposta da nossa request
21 | resolve(req.response)
22 | } else {
23 | // Rejeita a Promise retornando os status e texto da request
24 | reject(req.status + ' ' + req.statusText)
25 | }
26 | }
27 |
28 | // Captura o evento de 'onerror' caso o não tenha conseguido
29 | // fazer a request. Geralmente por não estar conectado a internet.
30 | req.onerror = function () {
31 | // Rejeita a Promise retornando a string 'Erro de conexão'
32 | reject('Erro de conexão')
33 | }
34 |
35 | // Envia a request.
36 | req.send()
37 | })
38 | }
--------------------------------------------------------------------------------
/03-promises/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | CEP
8 |
9 |
10 |
11 |
12 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/03-promises/main.js:
--------------------------------------------------------------------------------
1 | const cep_input = document.getElementById("cep")
2 | const logradouro_input = document.getElementById("logradouro")
3 | const complemento_input = document.getElementById("complemento")
4 | const bairro_input = document.getElementById("bairro")
5 | const localidade_input = document.getElementById("localidade")
6 | const uf_input = document.getElementById("uf")
7 | const cep_error = document.getElementById("cep-error")
8 |
9 | cep_input.addEventListener("focus", function () {
10 | cep_input.classList.remove("error")
11 | cep_error.style.display = "none"
12 | this.value = ""
13 | })
14 |
15 | cep_input.addEventListener("blur", function () {
16 | const cep = this.value.replace(/\D/g, "")
17 |
18 | logradouro_input.value = "..."
19 | complemento_input.value = "..."
20 | bairro_input.value = "..."
21 | localidade_input.value = "..."
22 | uf_input.value = "..."
23 |
24 | get_data(`https://viacep.com.br/ws/${cep}/json/`)
25 | .then(function(data) {
26 | data = JSON.parse(data)
27 | if (data.erro) {
28 | cep_input.classList.add("error")
29 | cep_error.style.display = "block"
30 |
31 | logradouro_input.value = ""
32 | complemento_input.value = ""
33 | bairro_input.value = ""
34 | localidade_input.value = ""
35 | uf_input.value = ""
36 | } else {
37 | logradouro_input.value = data.logradouro
38 | complemento_input.value = data.complemento
39 | bairro_input.value = data.bairro
40 | localidade_input.value = data.localidade
41 | uf_input.value = data.uf
42 | }
43 | })
44 | .catch(function(error) {
45 | cep_input.classList.add("error")
46 | cep_error.style.display = "block"
47 |
48 | logradouro_input.value = ""
49 | complemento_input.value = ""
50 | bairro_input.value = ""
51 | localidade_input.value = ""
52 | uf_input.value = ""
53 | })
54 | })
--------------------------------------------------------------------------------
/03-promises/main.scss:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | font-family: 'Open Sans', sans-serif;
4 | font-size: 16px;
5 | margin: 0;
6 | padding: 0;
7 | }
8 |
9 | body {
10 | display: flex;
11 | align-items: center;
12 | min-height: 100vh;
13 | }
14 |
15 | form {
16 | width: 100%;
17 | max-width: 400px;
18 | margin: 0 auto;
19 | padding: 50px 30px;
20 |
21 | label {
22 | color: #888;
23 | margin-top: 30px;
24 | display: block;
25 | }
26 |
27 | #cep-error {
28 | margin-top: 5px;
29 | font-size: 12px;
30 | color: red;
31 | display: none;
32 | }
33 |
34 | input {
35 | display: block;
36 | width: 100%;
37 | padding: 15px;
38 | border: none;
39 | margin: 7px 0 0;
40 | background-color: #f5f5f5;
41 | border-radius: 5px;
42 | color: green;
43 |
44 | &.error {
45 | border: 1px solid red;
46 | }
47 |
48 | &:focus {
49 | border: 1px solid #d5d5d5;
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/04-apis/.gitignore:
--------------------------------------------------------------------------------
1 | *.css.map
2 | *.css
3 | /.sass-cache
4 | credentials.js
--------------------------------------------------------------------------------
/04-apis/README.md:
--------------------------------------------------------------------------------
1 | ### Youtube
2 |
3 | Para esse projeto funcionar corretamente,
4 | voce deve duplicar o arquivo `credentials.sample.js`,
5 | mudar o nome dele para `credentials.js` e colocar
6 | a sua chave de API ([veja aqui como criar](https://developers.google.com/youtube/v3/docs/))
7 | para o Youtube API v3.
--------------------------------------------------------------------------------
/04-apis/credentials.sample.js:
--------------------------------------------------------------------------------
1 | const gkey = ""
--------------------------------------------------------------------------------
/04-apis/get_data.js:
--------------------------------------------------------------------------------
1 | // Cria uma função que retorna uma Promise.
2 | // Essa função recebe como argumento uma URL e faz uma request HTTP
3 | // para essa URL. A Promise resolve se a request tiver sido bem sucedida
4 | // e retorna os dados da resposta da request. Se a request nao for bem
5 | // sucedida a Promise sera rejeitada.
6 | function get_data(url) {
7 | return new Promise(function (resolve, reject) {
8 | // Cria uma nova request
9 | const req = new XMLHttpRequest()
10 |
11 | // Inicia a request
12 | req.open('GET', url)
13 |
14 | // Envia a request.
15 | req.send()
16 |
17 | // Captura o evento de 'onload', que é quando a
18 | // request terminou de ser executada.
19 | req.onload = function () {
20 | // Checa se o status da request é 200,
21 | // o que quer dizer que a request foi bem sucedida.
22 | if (req.status === 200) {
23 | // Resolve a Promise retornando a resposta da nossa request
24 | resolve(req.response)
25 | } else {
26 | // Rejeita a Promise retornando os status e texto da request
27 | reject(req.status + ' ' + req.statusText)
28 | }
29 | }
30 |
31 | // Captura o evento de 'onerror' caso o não tenha conseguido
32 | // fazer a request. Geralmente por não estar conectado a internet.
33 | req.onerror = function () {
34 | // Rejeita a Promise retornando a string 'Erro de conexão'
35 | reject('Erro de conexão')
36 | }
37 | })
38 | }
--------------------------------------------------------------------------------
/04-apis/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | YouTube
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
Faça sua busca...
18 |
19 |
20 |
21 |
22 |
23 |
24 | https://developers.google.com/youtube/v3/
--------------------------------------------------------------------------------
/04-apis/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reprograma/t6-javascript-iii/48d2162eb4e6d5013f94e48bd660724d19f4aece/04-apis/loading.gif
--------------------------------------------------------------------------------
/04-apis/main.js:
--------------------------------------------------------------------------------
1 | const input_search = document.querySelector("input")
2 | const results_container = document.getElementById("results")
3 |
4 | input_search.addEventListener("blur", function () {
5 | results_container.innerHTML = "
"
6 | get_data(`https://www.googleapis.com/youtube/v3/search?part=snippet&q=${this.value}&type=video&key=${gkey}`)
7 | .then(function(data) {
8 | data = JSON.parse(data)
9 | results_container.innerHTML = ""
10 | // ou...
11 | // while (results_container.firstChild) {
12 | // results_container.removeChild(results_container.firstChild)
13 | // }
14 | if (data.items.length > 0) {
15 | for (const video of data.items) {
16 | results_container.innerHTML += `
17 |
18 | ${video.snippet.title}
19 | ${video.snippet.description}
20 |
21 | `
22 | }
23 | } else {
24 | results_container.innerHTML = "Nenhum resultado encontrado
"
25 | }
26 | })
27 | .catch(function(error) {
28 | results_container.innerHTML = `${error}
`
29 | })
30 | })
--------------------------------------------------------------------------------
/04-apis/main.scss:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | font-family: 'Roboto', sans-serif;
4 | }
5 |
6 | #container {
7 | width: 500px;
8 | padding: 30px;
9 | margin: 80px auto;
10 | min-height: 80vh;
11 | box-shadow: 0px 0px 48px 0px rgba(0,0,0,0.31);
12 | }
13 |
14 | #loading {
15 | display: block;
16 | margin: 0 auto;
17 | }
18 |
19 | form {
20 | input {
21 | width: 100%;
22 | padding: 10px 15px;
23 | border: 1px solid #e0e0e0;
24 | }
25 | }
26 |
27 | #results {
28 | margin-top: 30px;
29 |
30 | & > p {
31 | text-align: center;
32 | color: grey;
33 | }
34 |
35 | a {
36 | color:black;
37 | text-decoration: none;
38 | display: block;
39 | padding: 20px;
40 | margin-bottom: 20px;
41 | border: 1px solid #e0e0e0;
42 | transition: box-shadow 200ms ease-in;
43 |
44 | &:hover {
45 | box-shadow: 0px 0px 7px 0px rgba(0,0,0,0.3);
46 | }
47 |
48 | h1 {
49 | margin-bottom: 15px;
50 | font-size: 16px;
51 | margin: 0;
52 | }
53 |
54 | p {
55 | margin-bottom: 0;
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/05-classes/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Document
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/05-classes/main.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | margin: 0;
4 | padding: 0;
5 | }
6 |
7 | body {
8 | overflow: hidden;
9 | display: flex;
10 | align-items: center;
11 | justify-content: center;
12 | height: 100vh;
13 | }
14 |
15 | main {
16 | width: 500px;
17 | height: 500px;
18 | border: 1px solid black;
19 | position: relative;
20 | }
21 |
22 | div {
23 | border-radius: 100%;
24 | position: absolute;
25 | }
--------------------------------------------------------------------------------
/05-classes/main.js:
--------------------------------------------------------------------------------
1 | class Ponto {
2 | constructor(nome, posX, posY) {
3 | this.nome = nome
4 | this.x = posX
5 | this.y = posY
6 | }
7 |
8 | mover_horizontalmente(distancia) {
9 | this.x += distancia
10 | return this.x
11 | }
12 |
13 | mover_verticalmente(distancia) {
14 | this.y += distancia
15 | return this.y
16 | }
17 |
18 | mover(distanciaX, distanciaY) {
19 | this.x += distanciaX
20 | this.y += distanciaY
21 | return [ this.x, this.y ]
22 | }
23 |
24 | distancia_entre_dois_pontos(outro_ponto) {
25 | const x1 = this.x
26 | const y1 = this.y
27 | const x2 = outro_ponto.x
28 | const y2 = outro_ponto.y
29 | return Math.sqrt( ( Math.abs( x1 - x2 ) ) ** 2 + ( Math.abs( y1 - y2 ) ) ** 2 )
30 | }
31 | }
32 |
33 | class Div extends Ponto {
34 | constructor(nome, cor, posX, posY, altura, largura) {
35 | super(nome, posX, posY)
36 |
37 | this.cor = cor
38 | this.altura = altura
39 | this.largura = largura
40 | }
41 |
42 | desenhar(container) {
43 | this.node = document.createElement("div")
44 | this.node.style.width = this.largura + "px"
45 | this.node.style.height = this.altura + "px"
46 | this.node.style.backgroundColor = this.cor
47 | this.node.style.left = this.x + "px"
48 | this.node.style.top = this.y + "px"
49 | container.appendChild(this.node)
50 | }
51 |
52 | // direcao: up, down, left, right
53 | mover_na_tela(direcao, incremento) {
54 | if (direcao === "up") {
55 | this.mover_verticalmente(-incremento)
56 | this.node.style.top = this.y + "px"
57 | } else if (direcao === "down") {
58 | this.mover_verticalmente(incremento)
59 | this.node.style.top = this.y + "px"
60 | } else if (direcao === "left") {
61 | this.mover_horizontalmente(-incremento)
62 | this.node.style.left = this.x + "px"
63 | } else if (direcao === "right") {
64 | this.mover_horizontalmente(incremento)
65 | this.node.style.left = this.x + "px"
66 | }
67 | }
68 | }
69 |
70 | const container = document.querySelector("main")
71 | const div0 = new Div("beatriz", "lime", 10, 10, 20, 20)
72 | div0.desenhar(container)
73 | const div1 = new Div("wanessa", "red", 40, 40, 20, 20)
74 | div1.desenhar(container)
75 | const divs = [div0, div1]
76 |
77 | let active
78 | for (const div of divs) {
79 | div.node.addEventListener("click", function (event) {
80 | active = div
81 | })
82 | }
83 |
84 | document.addEventListener("keydown", function(event) {
85 | if (event.key === "ArrowUp") {
86 | if (active.y > 0) {
87 | active.mover_na_tela("up", 10)
88 | }
89 | } else if (event.key === "ArrowDown") {
90 | if (active.y < (container.offsetHeight - active.altura)) {
91 | active.mover_na_tela("down", 10)
92 | }
93 | } else if (event.key === "ArrowLeft") {
94 | if (active.x > 0) {
95 | active.mover_na_tela("left", 10)
96 | }
97 | } else if (event.key === "ArrowRight") {
98 | if (active.x < (container.offsetWidth - active.largura)) {
99 | active.mover_na_tela("right", 10)
100 | }
101 | }
102 | })
--------------------------------------------------------------------------------
/06-npm/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # parcel-bundler cache (https://parceljs.org/)
61 | .cache
62 |
63 | # next.js build output
64 | .next
65 |
66 | # nuxt.js build output
67 | .nuxt
68 |
69 | # vuepress build output
70 | .vuepress/dist
71 |
72 | # Serverless directories
73 | .serverless
74 |
75 | # FuseBox cache
76 | .fusebox/
77 |
78 | # SCSS
79 | .sass-cache/
80 | *.css.map
81 | *.sass.map
82 | *.scss.map
83 |
84 | # JS
85 | dist/
--------------------------------------------------------------------------------
/06-npm/README.md:
--------------------------------------------------------------------------------
1 | # Boilerplate NPM
2 |
3 | Boilerplate simples para projetos com JS e SCSS.
4 |
5 | ### Pré-requisitos do projeto
6 |
7 | - npm (^6.4.1)
8 |
9 | #### Como montar o projeto
10 |
11 | ```bash
12 | npm install && npm run build
13 | ```
14 |
15 | #### Como assistir os arquivos JS e CSS
16 |
17 | ```bash
18 | npm run watch
19 | ```
20 |
--------------------------------------------------------------------------------
/06-npm/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/06-npm/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "06-npm",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "webpack",
9 | "watch": "webpack --watch"
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "css-loader": "^1.0.1",
15 | "node-sass": "^4.10.0",
16 | "path": "^0.12.7",
17 | "sass-loader": "^7.1.0",
18 | "style-loader": "^0.23.1",
19 | "webpack": "^4.25.1",
20 | "webpack-cli": "^3.1.2"
21 | },
22 | "dependencies": {
23 | "jquery": "^3.3.1"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/06-npm/src/index.js:
--------------------------------------------------------------------------------
1 | import './main.scss'
2 |
3 | import $ from 'jquery'
4 |
5 | console.log($)
6 |
--------------------------------------------------------------------------------
/06-npm/src/main.scss:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: cyan;
3 | }
--------------------------------------------------------------------------------
/06-npm/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | mode: 'development',
5 | entry: './src/index.js',
6 | output: {
7 | path: path.resolve(__dirname, 'dist'), // ./dist
8 | filename: 'bundle.js'
9 | },
10 | module: {
11 | rules: [{
12 | test: /\.scss$/,
13 | use: [{
14 | loader: "style-loader"
15 | }, {
16 | loader: "css-loader"
17 | }, {
18 | loader: "sass-loader"
19 | }]
20 | }]
21 | }
22 | };
23 |
--------------------------------------------------------------------------------
/07-exercicio/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # parcel-bundler cache (https://parceljs.org/)
61 | .cache
62 |
63 | # next.js build output
64 | .next
65 |
66 | # nuxt.js build output
67 | .nuxt
68 |
69 | # vuepress build output
70 | .vuepress/dist
71 |
72 | # Serverless directories
73 | .serverless
74 |
75 | # FuseBox cache
76 | .fusebox/
77 |
78 | # SCSS
79 | .sass-cache/
80 | *.css.map
81 | *.sass.map
82 | *.scss.map
83 |
84 | # JS
85 | dist/
86 |
87 | # Credentials
88 | credentials.js
--------------------------------------------------------------------------------
/07-exercicio/README.md:
--------------------------------------------------------------------------------
1 | # Exercicio API busca artistas
2 |
3 | 1. escutar pelo evento de submissao do input
4 | 1. pegar o valor dentro do input
5 | 2. usar o valor pra fazer a busca
6 | 1. musicbrainz api - https://wiki.musicbrainz.org/Development/JSON_Web_Service
7 | exemplo: http://musicbrainz.org/ws/2/artist/?query=nirvana&fmt=json
8 | 2. google imagens api
9 | 1. api key - https://developers.google.com/custom-search/v1/introduction#identify_your_application_to_google_with_api_key
10 | 2. cx - https://cse.google.com/all
11 | exemplo: https://www.googleapis.com/customsearch/v1?key=&cx=&q=nirvana&searchType=image&imgSize=huge
12 | 3. verifica se retornou algo ou nao
13 | - se retornou... tranforma em um objeto e usa os dados pra criar o html
14 | - se nao retornou... mlstra mensagem avisando que nao teve resultados encontrados
15 | - se deu erro... avisa o usuario que deu erro
16 |
17 |
--------------------------------------------------------------------------------
/07-exercicio/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Music Brainz
9 |
10 |
11 |
12 |
13 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/07-exercicio/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "06-npm",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "webpack",
9 | "watch": "webpack --watch"
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "css-loader": "^1.0.1",
15 | "node-sass": "^4.10.0",
16 | "path": "^0.12.7",
17 | "sass-loader": "^7.1.0",
18 | "style-loader": "^0.23.1",
19 | "webpack": "^4.25.1",
20 | "webpack-cli": "^3.1.2"
21 | },
22 | "dependencies": {
23 | "axios": "^0.18.0"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/07-exercicio/src/js/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reprograma/t6-javascript-iii/48d2162eb4e6d5013f94e48bd660724d19f4aece/07-exercicio/src/js/.DS_Store
--------------------------------------------------------------------------------
/07-exercicio/src/js/index.js:
--------------------------------------------------------------------------------
1 | import "../styles/main.scss"
2 |
3 | import google_image_search from "./resources/google"
4 | import musicbrainz_search from "./resources/musicbrainz"
5 |
6 | const bg = document.getElementById("bg")
7 | const form = document.querySelector("form")
8 | const input = form.querySelector("input")
9 | const main = document.querySelector("main")
10 | const content = document.getElementById("content")
11 |
12 | for (const event of ["focus", "click", "keypress"]) {
13 | input.addEventListener(event, function () {
14 | main.style.width = "60vw"
15 | })
16 | }
17 |
18 | input.addEventListener("blur", function () {
19 | if (content.innerHTML !== "" &&
20 | content.innerHTML !== "Carregando..." &&
21 | content.innerHTML !== "Erro de conexão.
" &&
22 | content.innerHTML !== "Nenhum resultado encontrado.
" &&
23 | main.style.width === "60vw") {
24 | main.style.width = input.offsetWidth + main.style.padding * 2 + "px"
25 | }
26 | })
27 |
28 | form.addEventListener("submit", function(event) {
29 | event.preventDefault()
30 |
31 | const query = input.value
32 | content.innerHTML = "Carregando..."
33 | content.style.height = "auto"
34 | bg.style.opacity = 0
35 | musicbrainz_search(query)
36 | .then(function(mb_data) {
37 | let image_index = 0;
38 | (function loadImage (index) {
39 | google_image_search(`${mb_data.name}`, index)
40 | .then(function (g_data) {
41 | bg.src = g_data
42 | bg.onload = function() {
43 | bg.style.opacity = 1
44 | main.style.width = input.offsetWidth + main.style.padding * 2 + "px"
45 |
46 | content.innerHTML = ""
47 | content.style.height = 0
48 | const h1 = document.createElement("h1")
49 | const h3 = document.createElement("h3")
50 | const p = document.createElement("p")
51 | h1.textContent = mb_data.name
52 | h3.textContent = mb_data.life_span
53 | p.textContent = mb_data.area
54 | content.appendChild(h1)
55 | content.appendChild(h3)
56 | content.appendChild(p)
57 | content.style.height = h1.clientHeight + h3.clientHeight + p.clientHeight + 80 + "px"
58 | }
59 | bg.onerror = function (error) {
60 | console.log("load image error", error)
61 | image_index++
62 | loadImage(image_index)
63 | }
64 | })
65 | .catch(function (error) {
66 | console.log("google", error)
67 | error = error !== "Nenhum resultado encontrado."
68 | ? "Erro de conexão." : error
69 | content.innerHTML = `${error}
`
70 | })
71 | })(image_index)
72 | })
73 | .catch(function (error) {
74 | console.log("mb", error)
75 | error = error !== "Nenhum resultado encontrado."
76 | ? "Erro de conexão." : error
77 | content.innerHTML = `${error}
`
78 | })
79 | })
--------------------------------------------------------------------------------
/07-exercicio/src/js/resources/google.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import credentials from '../credentials'
3 |
4 | function google_image_search(search, index) {
5 | return new Promise(function (resolve, reject) {
6 | axios.get(`https://www.googleapis.com/customsearch/v1?key=${credentials.google.key}&cx=${credentials.google.cx}&q=${search}&searchType=image&imgSize=huge`)
7 | .then(function (response) {
8 | const image_index = index ? index : 0
9 | if (response.data.items[index]) {
10 | resolve(response.data.items[image_index].link)
11 | } else {
12 | reject("Nenhum resultado encontrado.")
13 | }
14 | })
15 | .catch(function (error) {
16 | reject(error)
17 | });
18 | })
19 | }
20 |
21 | export default google_image_search
--------------------------------------------------------------------------------
/07-exercicio/src/js/resources/musicbrainz.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 |
3 | function musicbrainz_artist_search(search) {
4 | return new Promise(function (resolve, reject) {
5 | axios.get(`http://musicbrainz.org/ws/2/artist/?query=${search}&fmt=json`)
6 | .then(function (response) {
7 | const search_result = response.data.artists[0]
8 | if (search_result) {
9 | resolve({
10 | name: search_result.name,
11 | life_span: `${search_result["life-span"].begin} - ${search_result["life-span"].ended ? search_result["life-span"].end : "present"}`,
12 | area: search_result.area ? search_result.area.name : ""
13 | })
14 | } else {
15 | reject("Nenhum resultado encontrado.")
16 | }
17 | })
18 | .catch(function (error) {
19 | reject(error)
20 | });
21 | })
22 | }
23 |
24 | export default musicbrainz_artist_search
--------------------------------------------------------------------------------
/07-exercicio/src/styles/main.scss:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | margin: 0;
4 | padding: 0;
5 | font-family: "Open Sans", sans-serif;
6 | }
7 |
8 | h1,
9 | h2,
10 | h3,
11 | h4,
12 | h5,
13 | h6 {
14 | font-family: "Montserrat", sans-serif;
15 | }
16 |
17 | body {
18 | background-size: cover;
19 | background-color: #f0f0f0;
20 | overflow: hidden;
21 |
22 | #bg {
23 | position: absolute;
24 | top: 0;
25 | left: 0;
26 | width: 100vw;
27 | z-index: -1;
28 | opacity: 0;
29 | transition: opacity 1s ease-in-out;
30 | }
31 | }
32 |
33 | main {
34 | width: 60vw;
35 | max-width: 60vw;
36 | padding: 70px;
37 | background-color: rgba(255, 255, 255, 0.9);
38 | min-height: 100vh;
39 | display: flex;
40 | flex-direction: column;
41 | justify-content: center;
42 | align-items: flex-end;
43 | transition-delay: 1s;
44 | transition: width 1s ease-in-out;
45 |
46 | .group {
47 | width: 100%;
48 | max-width: 500px;
49 | }
50 |
51 | #content {
52 | margin-bottom: 80px;
53 | width: 100%;
54 | height: 0;
55 | transition: height 1s ease-in-out;
56 | overflow: hidden;
57 |
58 | h1 {
59 | font-size: 3rem;
60 | margin-bottom: 15px;
61 | }
62 |
63 | h3 {
64 | font-size: 2rem;
65 | margin-bottom: 20px;
66 | }
67 |
68 | p {
69 | font-size: 1.2rem;
70 | }
71 | }
72 |
73 | #search {
74 | width: 100%;
75 |
76 | input {
77 | padding: 15px 20px;
78 | font-size: 16px;
79 | color: #999;
80 | border-radius: 5px;
81 | border: 1px solid #e0e0e0;
82 | width: 100%;
83 |
84 | &:focus {
85 | box-shadow: inset 0px 0px 3px 0px rgba(0,0,0,0.2);
86 | }
87 | }
88 | }
89 | }
--------------------------------------------------------------------------------
/07-exercicio/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | mode: 'development',
5 | entry: './src/js/index.js',
6 | output: {
7 | path: path.resolve(__dirname, 'dist'), // ./dist
8 | filename: 'bundle.js'
9 | },
10 | module: {
11 | rules: [{
12 | test: /\.scss$/,
13 | use: [{
14 | loader: "style-loader"
15 | }, {
16 | loader: "css-loader"
17 | }, {
18 | loader: "sass-loader"
19 | }]
20 | }]
21 | }
22 | };
23 |
--------------------------------------------------------------------------------