Criando a classe pilha com JavaScript

Neste post estarei fazendo uma implementação simples da estrutura de dados conhecida como Pilha utilizando o JavaScript. Apesar da lista JavaScript ser totalmente capaz de simular a pilha, fila, lista, etc… a ideia é focar na teoria e criar do zero uma pilha de nós (nodes) como se a funcionalidade não estivesse disponível.

Como funciona a pilha?

A pilha é um tipo de estrutura de dados que funciona no formato que o último item que foi inserido será o primeiro a ser removido da estrutura (Lifo – Last in, First out). Então quando você adicionar 3 números e quiser remove-los, eles serão removidos na ordem inversa que foram adicionados (terceiro – segundo – primeiro).

Considerações

Algumas considerações na nossa implementação para que não ocorra confusão:

  • A classe do JavaScript ainda não permite declarar propriedades como privadas, por isso usarei _ na frente do nome das propriedades ao qual NÂO deveríamos estar acessando externamente.
  •  Esta é uma implementação para uso acadêmico. Por favor utilize a lista do JavaScript para trabalhar com a pilha em produção (new Array ou []).
  • Alguns trechos de código poderiam ser resumidos em uma única linha, mas foram mantidos quebrados para auxiliar aqueles que estão aprendendo.

Implementação:

Classe e Construtor

Beleza, então vamos começar. A primeira coisa que precisamos é criar a classe e o construtor dela conforme o código abaixo. Para o nome da classe usaremos o termo em português, mas para o resto iremos utilizar os termos em Inglês pois parece ser o padrão mais utilizado por livros e cursos.

class Pilha {
  constructor() {
    this._top = null;
    this._count = 0;
  }

  //Continuação do código

Como você pode ver, teremos apenas duas variáveis de controle, _top que fará referencia para o topo da pilha e _count que controlará quantos itens a pilha possuí.

 

GetCount()

O método GetCount é o mais simples de todos. Ele apenas irá retornar a quantidade de itens na pilha.

GetCount = function () {
  return this._count;
};

 

Peek()

Exibe o item no topo da pilha ou null caso ela esteja vazia.

Peek = function () {
  if (this._top) {
    return this._top.data;
  }
  return null;
};

 

Push(item)

O método Push (empurrar) é a forma como adicionaremos itens a pilha. Pelo fato de ser uma linguagem não tipada, poderemos adicionar qualquer valor a pilha que ela o aceitará.

Push = function (data) {
  let node = {
    data: data,
    next: null
  };
  node.next = this._top;
  this._top = node;
  this._count++;
};

Como você pode ver, o método cria um objeto chamado node (nó) que é um objeto JS e terá 2 propriedades, o data (dados em inglês) para o valor e next (próximo) para referência o item anterior. Após isso definimos este novo valor como sendo o do topo e referenciamos o antigo topo no next.

Isto é feito desta forma pois para a pilha, é importante termos um controle de quem está no topo. Os outros itens serão manipulados apenas quando chegar a vez deles.

 

Pop()

O Método Pop (tirar) funciona da forma oposta ao Push, ele remove o item que está no topo da fila.

Pop = function () {
  if (this._top) {
    let out = this._top;
    this._top = this._top.next;
    if (this._count > 0) {
      this._count--;
    }
    return out.data;
  }
  return null;
};

Como você pode ver o código acima faz o seguinte: Confere se existe algum item no topo da fila para poder remove-lo, transforma o next em topo, reduz a contagem em 1 e retorna o item removido ou null caso esteja vazio.

 

DisplayAll()

Este método exibe todos os itens da pilha, do topo ao fundo, no formato de um vetor JavaScript. Caso a pilha esteja vazia, retorna null

DisplayAll = function () {
  if (this._top) {
    let arr = new Array();
    let current = this._top;
    for (let i = 0; i < this._count; i++) {
      arr[i] = current.data;
      current = current.next;
    }
    return arr;
  }

  return null;
};

Apesar deste código ter um pouco mais de lógica que os métodos anteriores, ele ainda é fácil de entender. Ele testa se o _top não está vazio e se verdadeiro, percorrerá a pilha copiando o valor armazenado dentro de cada nó para dentro do vetor.


Executando o código

Após criar a classe, um teste simples ajudará a verificar que todos os métodos estão fazendo o que deveriam

let pilha = new Pilha();

console.log(`Contagem: ${pilha.GetCount()}`);

pilha.Push(4);
console.log(`Peek: ${pilha.Peek()}`);
console.log(`Contagem: ${pilha.GetCount()}`);

pilha.Push(22);

console.log(`Contagem: ${pilha.GetCount()}`);

console.log(`Pop: ${pilha.Pop()}`);
console.log(`Pop: ${pilha.Pop()}`);
console.log(`Pop: ${pilha.Pop()}`);

console.log(`Contagem: ${pilha.GetCount()}`);

pilha.Push(1);
pilha.Push(-2);
pilha.Push(100);
pilha.Push(350);

console.log(`Todos: ${pilha.DisplayAll()}`);

Cursos completos de JavaScript

Seguindo a linha da postagem feita ano passado sobre Cursos completos que você não conhecia, estou postando uma nova lista atualizada para de cursos de empresas menos conhecidas, mas que nem por isso sejam ruins. Já cursei alguns dos listados abaixo e posso dizer que são muito bons.

Para ficar mais fácil de se organizar, os cursos estão agrupados pelas pessoas ou empresas que os criaram.


Alfamidia

Programação JavaScript Completo

Descrição: Um curso do básico ao avançado sobre JavaScript e JQuery. Ele permite que um pessoa que não saiba muito de programação possa aprender a usar o JS e conceitos mais avançados de programação a medida que o aluno avança nas aulas

Nível: Básico – Avançado

Duração: Você define e o curso possuí acesso vitálicio

Curso recebe atualizações: Não

Investimento: Sob consulta

 

Desenvolvimento Web e Mobile

Descrição: O curso online de desenvolvimento web e mobile percorre todos os campos da programação (do front-end ao back-end). O intuito é ensinar o estudante a ser um desenvolvedor com capacitação em todas as áreas do desenvolvimento de apps.

Nível: Básico – Avançado

Duração: Você define e o curso possuí acesso vitálicio

Curso recebe atualizações: Não

Investimento: Sob consulta

 


A´gora

JavaScript Completo

Descrição: Completo e passo a passo tem por objetivo principal ensinar todos os passos necessários que um iniciante na linguagem javascript precisa para dominar esta linguagem de programação que está crescendo bastante neste últimos tempos. Nela você terá todos os conhecimentos exigidos pelo mercado, do mais elementar ao mais avançados.

Nível: Básico

Duração: Você define e o curso possuí acesso vitálicio

Curso recebe atualizações: Não

Investimento: R$197,00, podendo parcelar em 2x sem juros

 

Formação Jquery Completo

Descrição: Este curso tem por objetivo ensinar do básico ao avançado do Jquery. Então você não tem muito conhecimento ou gostaria de aprimorar o que sabe para o nível profissional, esse é o curso ára você.

Nível: Básico

Duração: Você define e o curso possuí acesso vitálicio

Curso recebe atualizações: Não

Investimento: R$157,00, podendo parcelar em 2x sem juros


Udacity

Fundamentos Web Front-End

Descrição: Curso criado nos Estados Unidos com o foco em ensinar os fundamentos da programação Front-end. Ele lida com diversos detalhes da programação JavaScript não encontramos em qualquer lugar e aponta você para outros cursos gratuitos dentro do site deles.

Nível: Básico

Duração: 2 meses de curso e acesso irrestrito somente se você completar tudo

Curso recebe atualizações: Não

Investimento: 5 x R$106,00 – Com desconto à vista

 

Web Front-end Avançado

Descrição: Continuação do curso anterior. Aprofunda-se no entendimento do JavaScript de forma a ensinar a diferença entre as novas técnicas e as antigas. Você também descobrirá mais sobre o ganho de performance e aumento de produtividade do ES6.

Nível: Avançado

Duração: 3 meses meses de curso e acesso irrestrito somente se você completar tudo

Curso recebe atualizações: Não

Investimento: 9 x R$119,00 – Com desconto à vista

 


Danki Code

Curso Webmaster Front-end Completo

Descrição: Um curso de front-end bem completo que tem por objetivo ensinar do zero sobre como lidar com todos aspectos da tela, tanto visuais quanto lógicas. Diferente de um curso de web design que foca mais na questão visual e manipulação de imagens

Nível: Do básico ao avançado

Duração: Você define seu ritmo e com acesso vitalício.

Curso recebe atualizações: Sim

Investimento: 12 x R$19,00 – Com desconto à vista

 

Pacote Fullstack

Descrição: Inclui o curso Webmaster Front-end completo mencionado acima e fornece ainda mais material para ensina-lo sobre o funcionamento do back-end. É bem indicado para aqueles que querem se tornar desenvolvedores responsaveis (ou com o conhecimento) de ambas pontas da criação de uma aplicação web.

Nível: Do básico ao avançado

Duração: Você define

Tempo de acesso: Irrestrito

Curso recebe atualizações: Sim

Investimento: 12 x R$27,00 – Com desconto à vista

 

Desenvolvimento Web Completo

Descrição: Pronto para além de estudar os conceitos de HTML, CSS e JavaScript, também estudar muito PHP? Se sim, esse curso tavez seja para você. No curso de desenvolvimento Web Completo você estará se tornando um desenvolvedor Full Stacke aprendendo a conectar todas as pontas de uma aplicação web.

Nível: Do básico ao avançado

Duração: Você define

Tempo de acesso: Irrestrito

Curso recebe atualizações: Sim

Investimento: 12 x R$22,12 – Com desconto à vista


 

Conclusão

Isso ai, espero que algum destes cursos possam ajudar alguém. Caso você tenha uma duvida, pegunta ou sugestão, deixe seu comentário aqui abaixo para que possamos melhorar essa postagem.

Loop for com espera entre iterações

Recentemente tive uma duvida, como fazer para que um for tivesse esperasse alguns segundos entre cada iteração? Supodo que eu queira exibir um alerta em 10 vezes a de 5 em cindo segundos, como posso fazer com que o JavaScript espere estes 5 segundos?

Existem timers em JavaScript, como setInterval e setTimeout. SetInterval é um método de execução de código baseado em intervalo de tempo que tem a capacidade nativa de executar repetidamente um script especificado quando o intervalo é atingido. setTimeout é um método de execução de código baseado em tempo que executará um script apenas uma vez quando o intervalo for atingido.

Tendo isto em mente, a primeira coisa que tentei foi colocar o setTimeout dentro do for para tentar obter essa espera

function timeoutFunction()
{
  console.log("Iniciando Teste");
  for(i = 0; i < 10; i++) {
    setTimeout(function () {
      console.log("Teste "+i);
    }, 5000);
  }
}
timeoutFunction();

Após o primeiro log, há um atraso de 5s, mas quando os logs dentro do setTmeout ocorrem em grupo

Por que isso acontece?

A função setTimeout() é uma função que roda em outra thread e por isso ela não bloqueia a execução do for, ou seja a função é invocada e o código segue executando sem precisar esperar que ela termine. Com isso ele executará as 10 execuções em questão de milisegundos e todos os tempos de espera ocorreram praticamente juntos.

Como adicionar o delay no loop for?

A Expressão de Função de Chamada Imediata (IIFE – Immediate Invoking Function Expression) pode ser usada para obter o que queremos. Sua sintaxe funciona da seguinte forma:

(function () {

})();

O IIFE chama imediatamente uma função. Isso significa simplesmente que a função é executada imediatamente após a conclusão da definição. Se utilizarmos essa função, obteremos a saída desejada

console.log("Iniciando Teste");
for (var i = 0; i < 10; i++) {
  (function (i) {
    setTimeout(function () {
      console.log("Teste" + i);
    }, 5000*i);
  })(i);
};

O código acima, mesmo que você nunca tenha usado uma IIFE é simples, nó passamos a varável “i” como parametro da função (pois se tentarmos acessa-lo direto do loop o settimeout conseguirá obter apenas a iteração final com i = 9) e fazemos uma matemática simples para que as funções executem de forma a serem 5 segundos X nº iteração.

Expressões de Função Imediatamente Invocadas – IIFE

Mesmo se você for um programador novo, não irá demorar muito quando você trabalhar com JavaScript antes de se deparar com esse padrão:

(function () {
    // código
})();

Ao primeiro encontro provavelmente parecerá bastante confuso, no entanto, o conceito em si é simples.

O padrão é chamado de expressão de função imediatamente invocada (Inglês: Immediate Invoking Function Expression) ou IIFE (pronunciado “iffy”).

Em JavaScript funções podem ser criadas através de uma declaração de função ou uma expressão de função. Uma declaração de função é a maneira “normal” de criar uma função nomeada.

function myFunction () { 
    /* código */ 
}

Por outro lado, se você está atribuindo uma função a uma variável ou propriedade, você está lidando com uma expressão de função.

var umaFunc= function () { /* código */ };

var objeto = {
    myFunction: function () { /* código */ }
};

Uma função criada no contexto de uma expressão também é uma expressão de função. Por exemplo:

(function () { /* código */ });

A principal coisa sobre expressões JavaScript é que elas retornam valores. Em ambos os casos, acima do valor de retorno da expressão é a função.

Isso significa que, se quisermos invocar a expressão de função imediatamente, precisamos apenas colocar alguns parênteses no final. O que nos traz de volta ao primeiro trecho de código que vimos.

(function () {
    // código
})();

Agora sabemos o que o código está fazendo, mas a pergunta “Por quê?” ainda resta.

A principal razão para usar um IIFE é obter privacidade de dados. Como var variáveis do escopo do JavaScript para sua função de contenção, quaisquer variáveis declaradas no IIFE não podem ser acessadas pelo mundo externo.

(function () {
    var foo = "bar";

    // exibe: "bar"
    console.log(foo);
})();

// Se tentar acessar a variavel, ocorrerá um erro
// ReferenceError: foo is not defined
console.log(foo);

É claro que, você poderia explicitamente nomear e depois invocar uma função para alcançar os mesmos fins.

function myImmediateFunction () {
    var foo = "bar";

    // exibe: "bar"
    console.log(foo);
}

myImmediateFunction();

// Igual ao exemplo anterior, se tentar acessar a variavel, ocorrerá um erro 
// ReferenceError: foo is not defined
console.log(foo);

No entanto, esta abordagem tem algumas desvantagens. Primeiro, ele ocupa desnecessariamente um nome no namespace global, aumentando a possibilidade de colisões de nomes. Em segundo lugar, as intenções deste código não são tão auto-documentadas quanto um IIFE. E terceiro, porque é nomeado e não é auto-documentado, pode acidentalmente ser invocado mais de uma vez.

Vale a pena ressaltar que você também pode facilmente passar argumentos para o IIFE.

var foo = "foo";

(function (innerFoo) {
    // exibe: "foo"
    console.log(innerFoo);
})(foo);

E essa é a história por trás dos IIFEs. Em breve, estaremos desenvolvendo isso analisando o padrão de módulo em JavaScript.

Tradução:

http://adripofjavascript.com/blog/drips/an-introduction-to-iffes-immediately-invoked-function-expressions.html

Conheça o Typed.js

O Typed.js é uma biblioteca JavaScript muito boa para simular um efeito de texto sendo escrito na tela, similar ao ato de digitar no console ou no Notepad.

Para acessar as funcionalidades do Typed.js, você precisa baixa-lo do site ou inserir uma tag script apontando para o link do CDN que eles disponibilizam conforme o exemplo abaixo.

<script src="https://cdn.jsdelivr.net/npm/typed.js@2.0.9"></script>

Como Funciona?

É simples e irei mostrar em alguns exemplos que cobrirão a maioria das funcionalidades que você precisará da biblioteca. Mas primeiro, caso você já não tenha algo parecido, copie o código HTML abaixo

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    <span id="texto"></span>
    <script src="https://cdn.jsdelivr.net/npm/typed.js@2.0.9"></script>
</body>
</html>

Para evitar a necessidade de fazer um download, vou deixar com o link do CDN, mas sinta-se a vontade para altera-lo. Abaixo do script do Typed.js ou em um arquivo separado, adicione o seguinte código:

// A configuração que será passada ao instanciarmos o objeto Typed
let configuracao = {
    // A lista de frases que aparecerão
    // está string podem conter tags html
    strings: ["<i>Primeira</i> frase com Typed.js.", "Olá MundoJS!"],
    // A velocidade que é digitado
    typeSpeed: 40
}

// O Objeto precisará recebe 2 parametros,
// 1º: Uma string começando com # para id ou . para classe html
// 2º: o objeto de configuração
let typed = new Typed("#texto", configuracao);

Com isso você já verá um efeito simples, mas que mostra como funciona e como pode ser executado. Agora vamos ver alguns itens um pouco menos óbvios.


Configurando o Typed.js

Parando no meio da frase

Se na string você usar o acento circunflexo seguido de um valor numérico, quando chegar naquele ponto o Typed.js irá esperar aquele número em milissegundos antes de continuar.

let configuracao = {
            strings: ["<i>Primeira</i> frase ^1000 com Typed.js.", "Olá MundoJS!"],
        }

Retorno inteligente

Se o objeto de configuração tiver uma propriedade chamada “smartBackspace” igual com o valor true, então o texto irá voltar somente até a parte onde o texto diferente.

let configuracao = {
            // A parte "Olá" não será removida quando o texto for reescrever.
            strings: ["Olá MundoJS!", "Olá JavaScript!"],
            smartBackspace: true
        }

Tempo para iniciar e retornar

Através das propriedades startDelay e backDelay é possível definir (em milissegundos ) o tempo que levará para começar a escrever e retornar o texto.

let configuracao = {
            strings: ["Olá MundoJS!", "Olá JavaScript!"],
            startDelay: 2000,
            backDelay: 500,
        }

Customizar o cursor

É possível customizar o cursor ou remove-lo completamente através de duas propriedades conforme o exemplo abaixo. Lembrando que se você colocar showCursor como false, não conseguirá ver qualquer char que definir no cursorChar.

let configuracao = {
            strings: ["Olá MundoJS!", "Olá JavaScript!"],
            showCursor: true,
            cursorChar: '#'
        }

Conclusão

Como e possível ver, a biblioteca do Type.js é simples e fácil de usar. Caso você precise customizar mais coisas va-le a pena dar uma olhada no https://github.com/mattboldt/typed.js/#user-content-customization para ver se o que você precisa já está lá.

Iniciando com amCharts

Neste artigo iremos falar sobre o amCharts, uma biblioteca JavaScript utilizada para criar diversos tipos de gráficos responsivos e interativos. Se você não se importar de ter o logo deles no canto esquerdo inferior (imagem abaixo) poderá usa-lo sem custo. Do contrário, existem valores para diferentes usos da biblioteca.

O que você precisa

Como a ideia é fornecer um tutorial básico, iremos começar com o mínimo necessário para montar os gráficos. Para isso precisamos possuir ou linkar algumas bibliotecas do deles na nossa página HTML conforme abaixo.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>amCharts</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Um css básico para que o gráfico apareça melhor bem na tela -->
    <style>
        .chart{
            width: 700px;
            max-width: 90vw;
            margin: 0 auto;
            height: 400px;
            max-height: 80vh;
        }
    </style>
</head>
<body>
    <!-- Está div montará nosso gráfico -->
    <div id="chartdiv" class="chart"></div>

    <!-- Estas são as bibliotecas necessárias. -->
    <script src="https://www.amcharts.com/lib/4/core.js"></script>
    <script src="https://www.amcharts.com/lib/4/charts.js"></script>
    
    <!-- Aqui irá nosso código JavaScript -->
    <script src="main.js"></script>
</body>
</html>

 


Montando um gráfico de pizza (Pie Chart)

Para montar um gráfico de pizza, você precisará:

  1. Capturar a DIV que exibirá o gráfico
    let grafico = am4core.create("chartdiv", am4charts.PieChart);
  2. Fornecer uma lista JavaScript de objetos (ou Json) que possuem as propriedades que serão agrupadas com o mesmo nome em todos objetos. É possível apontar para um arquivo externo, mas vamos fazer a versão simples primeiro
    grafico.data = [
            {
                tipo: "imposto",
                valor: 5000
            },
            {
                tipo: "mão de obra",
                valor: 4000
            },
            {
                tipo: "matéria prima",
                valor: 8000
            },
            {
                tipo: "escritório",
                valor: 3000
            },
            {
                tipo: "transporte",
                valor: 1500
            },
            {
                tipo: "outros",
                valor: 1000
            }
        ];
  3. Preencher os dados de configuração conforme os comentários no código abaixo.
    // Cria uma variavel de gráfico de pizza e vincula ela a div do gráfico
    let pieSeries = grafico.series.push(new am4charts.PieSeries());
    
    // Informa o gráfico que a propriedade valor será 
    pieSeries.dataFields.value = "valor";
    pieSeries.dataFields.category = "tipo";

Resultado

Como você pode ver, obtivemos o resultado abaixo utilizando o mínimo de configuração e código JavaScript. Ao mergulhar na documentação, você verá que é possível fazer alterações em praticamente todas as faces do gráfico.


Montando um gráfico de Barras (Bar Chart)

Agora que já possuímos uma noção básica do amCharts, iremos adaptar as coisas utilizadas no gráfico de pizza e adicionar mais algumas coisas

  • Para capturamos e criarmos o gráfico, o código é bem parecido, mas ao invés de utilizarmos a propriedade PieChart, usaremos a XYChart.
    let grafico = am4core.create("chartdiv", am4charts.XYChart);
    // Comparado com o anterior
    // let grafico = am4core.create("chartdiv", am4charts.PieChart);
  • Para nossos dados, iremos utilizar exatamente o mesmo objeto utilizado anteriormente.
    grafico.data = [
            //Mesmo objeto que anteriormente
        ];
  • Desta vez, iremos adicionar legendas aos eixos X e Y para ficarem mais claras as informações passadas.
    let eixoX = grafico.xAxes.push(new am4charts.CategoryAxis());
    eixoX.title.text = "Tipo de Custos";
    
    let eixoY = grafico.yAxes.push(new am4charts.ValueAxis());
    eixoY.title.text = "Custo (R$)";

  • No gráfico de barras precisamos informar explicitamente o local de onde eixoX obterá sua lista de dados.
    eixoX.dataFields.category = "tipo";
  • Por último iremos criar uma serie, que no amCharts significa uma coleção de pontos de dados similares e logicamente agrupados. A série conterá os dados que serão visualizados na relação dos eixos X e Y, nesse caso sendo as barras, mas no gráfico de linhas seria a os pontos ao qual a linha passa

Resultado

Como você pode ver pela imagem abaixo, o amcharts cuida da criação do gráficos de barras de uma forma simples e bonita


Conclusão

A biblioteca do amCharts é simples de utilizar e produz ótimos resultados com pouco código. Para saber como alterar cores, efeitos e outras coisas, acesse o site da documentação ou também o site dos demos.

Para obter o código fonte desta postagem, clique no link de download

[download id=”1684″]

Estimando a velocidade de download com Imagens

Neste post será mostrado uma forma de estimar a velocidade de download utilizando uma imagem e algumas linhas de código JavaScript. A ideia do algoritmo é a de:

  • Fornecer uma imagem de tamanho grande para calcular de forma mais confiável.
  • Iniciar um contador um passo antes de baixar a imagem.
  • Baixar a imagem.
  • Encerrar o contador no momento que a imagem termina.
  • Calcular o resultado em MBps e Mbps.

O Código HTML

Abaixo o segue o código HTML. Como você pode ver, para manter tudo simples, serão utilizadas apenas algumas linhas de código e a exibição de resultados será de apenas um texto com os dados

<!DOCTYPE html>
<html>
<head>
    <title>Teste de Velocidade</title>
    <meta charset="utf-8" />
</head>
<body>
    <!-- O botão que irá iniciar o teste -->
    <button onclick="iniciarTeste()">Iniciar</button>

    <!-- Tag de paragrafo que exibirá os resultados -->
    <p id="progresso"></p>
    
    <script src="main.js"></script>
</body>
</html>

 

O Código JavaScript

A explicação do código JavaScript abaixo está dentro dos comentários de cada trecho.

// Variaveis para controlar o inicio e o fim do download
let inicioDownload;
let fimDownload;

// Variavel que guarda os dados da imagem que serão utilizados
const imagem = {
    // Caminho da imagem. Utilize o caminho da sua imagem
    caminho: "coffe-cup.jpg",

    // O tamanho da imagem em megabytes
    tamanho: 6.877555
};

// Inica o teste de Download
// Se outros recursos estiverem sendo baixados
function iniciarTeste() {
    mostrarMensagem("Efetuando teste de Download...");
    window.setTimeout(medirConexao(), 1);
}


// Função auxiliar que exibe mensagens na tela
function mostrarMensagem(messagem) {
    // Se a variavel mensagem for uma string, exibirá ela como veio,
    // Se a variavel for um vetor, exibirá cada linha quebrado por <br/>
    let mensagemHTML = (typeof messagem == "string") ? messagem : messagem.join("<br />");
    document.getElementById("progresso").innerHTML = mensagemHTML;
}

// Função que efetivamente mede a conexao de velocidade
function medirConexao() {
    // Cria o objeto de imagem que iremos calcular o tempo de download
    let imagemTeste = new Image();

    // No envento de carregamento da emnsagem,
    // para o contador e exibe o os resultados
    imagemTeste.onload = function () {
        endTime = new Date().getTime();
        exibirResultados();
    }

    // Inicia o contador 
    startTime = new Date().getTime();
    // cria uma controlador apra evitar carregar um caminho de imagem que ja está em cache
    let cacheBuster = "?nnn=" + startTime;
    // inicia a imagem
    imagemTeste.src = imagem.caminho + cacheBuster;
}

// Exibe os resultados caculados em Megabytes por segundo
// e em Megabits por segundo
function exibirResultados() {
    // converte o tempo de milisegundos para segundis
    let duracao = (endTime - startTime) / 1000;
    // calcula o tempo que levou para baixar a imagem,
    // arredondando para duas casas decimais
    let velocidadeMbps = (imagem.tamanho / duracao).toFixed(2);
    
    mostrarMensagem([
        "A Velocidade da conexão é de:",
        velocidadeMbps + " MBps",
        (velocidadeMbps * 8) + " Mbps"
    ]);
}

Conclusão

Após rodar os testes algumas vezes, foi possível observar as seguintes coisas.

  1. O resultado sempre se apresentou abaixo do que seria a capacidade da internet na minha casa.
  2. Caso outras páginas estivessem sendo acessadas, o resultado era muito inferior ao esperado.

Apesar dos itens acima terem sido esperados, foi interessante compara-los com sites que exibem a velocidade da internet para ver o preciso é o teste em relação a eles.

API Network Information: Obtenha dados de conexão do usúario

É comum usar a largura da tela ou indicadores semelhantes para decidir quantos dados mostrar ao usuário. Mas, às vezes, um usuário com uma tela maior ou dispositivo de maior resolução tem uma conexão de rede ruim, e enviá-las para imagens maiores torna as coisas muito mais lentas para eles no carregamento do site. Seria ótimo se pudéssemos explicar as condições de rede de um usuário específico para determinar o que devemos enviá-las.

A API de informações da rede faz exatamente isso. É uma API que fornece informações sobre a conexão do sistema em termos ou tipo de conexão (por exemplo, “wifi”, “celular” etc.) que podemos usar para otimizar a experiência deles.

Acessar dados do objeto Navegador

Navigator.connection é a propriedade principal que analisaremos. É somente leitura e contém algumas informações potencialmente valiosas sobre a conexão do usuário.

let connectionInfo = navigator.connection;

Isso retorna um objeto que possui as seguintes propriedades.

Propriedades da API Network Information

  • Downlink: Retorna a estimativa de largura de banda efetiva em megabits por segundo.
  • DownlinkMax: Retorna a velocidade máxima de downlink para a tecnologia de conexão subjacente.
  • EffectiveType: retorna o tipo de conexão efetivo que significa uma das opções “slow-2g”, “2g”, “3g” ou “4g”.
  • Rtt: Retorna o tempo de ida e volta estimado estimado da conexão atual.
  • Type: retorna o tipo de conexão que um dispositivo está usando para se comunicar com a rede.
    • Inclui: “bluetooth, celular, ethernet, nenhum, wifi, wimax, outro, desconhecido”.

Nota: Atualmente, os navegadores de desktop não retornam as propriedades downlinkMax e type.

Eventos

Também podemos adicionar listeners para o evento “onchange”, que dispara quando as informações de conexão são alteradas.

Exemplos

O benefício óbvio de ter essas informações é que podemos personalizar a experiência do usuário não apenas com base no tamanho da tela, mas também em como o usuário está se conectando ao nosso site. É sobre wi-fi ou celular? É um 3g ou 4g, etc?

let preloadVideo = true;
let connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;

if (connection) {
    if (connection.type === 'cellular') {
        preloadVideo = false;
    }
}

Por exemplo, poderíamos determinar se pré-carregaremos os ativos com uso intensivo de recursos, como vídeo, com base na conexão de rede, decidindo não pré-carregar os recursos se eles estiverem em excesso no celular.

Suporte

Infelizmente, o suporte para essa API é mínimo no momento, com o Chrome e o Opera sendo os principais navegadores para suporte a dispositivos móveis e o Chrome para computador.

A boa notícia, porém, é que, embora não possamos usar isso para todos, ainda podemos usá-lo para melhorar progressivamente nossos sites para alguns de nossos usuários. E com os benefícios potenciais que poderia oferecer quando estiver amplamente disponível, é definitivamente uma API para ficar de olho em seguir em frente.

Fonte:

MDN Docs: NetworkInformation
MDN Docs: Navigator.connection
Tradução principal: https://www.afasterweb.com/2018/01/26/network-api/

Projeto Diablo.JS

Após navegar no mundo do código fonte para jogos, encontrei um projeto já abandonado a alguns anos chamado Diablo.js. Ele é um projeto simples que utiliza 1 arquivo HTML, 1 arquivo JS (não que isso seja bom) e diversasimagens para simular o jogo Diablo 2.

Como esse jogo consumiu muitas horas da minha vida, pensei em usa-lo como uma ferramenta para praticar programação e reviver o passado.Então fiz um fork dele e comecei a trabalhar em diversas alterações.

O objetivo do projeto é o seguinte:

  • “Atualizar” o código JavaScript para ES6.
  • Manter o projeto em um formato fácil de executar para outros que estão aprendendo a programar ou queira brincar com o código.
  • Melhorar o posicionamento e quantidade monstros e itens aleatórios.
  • Aumentar o mapa.
  • Permitir que o personagem morra.
  • Corrigir bug de colisão e barreiras físicas (paredes e objetos).
  • Permitir escolher outros personagens.
  • Adicionar ao menos 1 habilidade com o botão direito.

Não sei se tudo será possível, mas um objetivo fica difícil chegar a algum lugar.

Tendo dito isso, aqui vão algumas observações sobre o jogo para que você que está interessado em contribuir possa começar a fazer. Se você quiser fazer alterações, comentar cada classe e função trabalhada é muito importante!

Converter funções em classes

Já fiz isso para praticamente todas as classes, mas algumas ainda precisam ser ajustadas, as propriedades precisam ter nomes mais uteis que x, y e z.

Separar arquivos

Não é opção mais performática, mas para manter o código mais fácil de ler, seria interessante separar as classes e funcionalidades em arquivos diferentes.

Imortal

Esse aqui é o Diablo Imortal, o bárbaro não morre mesmo chegando a zero de vida.

Paredes

Além de ser possível “pisar” nas paredes, é possível atacar e ser atacado através delas

Piso e Limite do Mapa

Consegui adicionar paredes, objetos e piso indo para a diagonal esquerda, mas para o outro lado não tem força que renderize o chão.

Talvez seja possível resolver esse problema com paredes, mas tanto o jogador quanto os inimigos podem sair do limite do mapa. Dependendo, os inimigos começaram de fora do mapa.

Contador de ouro

Não que ele tenha utilidade na versão atual, mas seria legal saber quanto de ouro o personagem já coletou

Aprendendo ReactJS: Parte 2

Este artigo é uma continuação da série Aprendendo ReactJS.

Para acessar o artigo anterior, acesse: Aprendendo ReactJS: Introdução



Utilizando atributos com JSX

É possível fornecer valores de atributos usando strings

let elemento = <button className="btnRemover">Remover</button>

Obs.: devido ao fato que “class” é uma palavra reservado do JavaScript, quando você estiver definindo a propriedade classe de uma tag html, utilize a palavra propriedade JavaScript className.

Você também pode fornecer atributos utilizando expressões JavaScript cercadas por chaves:

let elemento = <img src={produto.urlImagem}/>

 

Obs.: Não coloque a expressão dentro de uma string pois isso fará ela ser tratada como uma string pura.

//Não faça isso.    
let elemento = <img src="{produto.urlImagem}"/>

 

Nota: Atributos JSX tem sua nomenclatura definida pela convenção “camelCase”. Por isso atributos HTML como fontsize se tornam fontSize no JSX.

 

Utilizando um objeto style no JSX

O atributo “style” das tags html podem ser populados com um objeto style no lugar de uma string. Veja o exemplo abaixo:

let styleObject = {

    backgroundColor: 'red',

    color: 'blue',

    fontSize: 25,

    width: 100

}

let elemento = <input style={styleObject} />

 

No exemplo abaixo, usaremos o primeiro grupo de chaves para a expressão JavaScript e o segundo para definir o objeto anônimo que definirá o style.

let element = <input style = {{width:200,height:100}}/>

 

 

Utilizando o JSX com elemento aninhados.

Elemento React podem ser aninhados/agrupados dentro de outros elementos React desde que na raiz do elemento exista uma única tag que contem todos.

// Neste exemplo, possuímos 3 elemento e apenas a div externa está na raiz
let elemento = (

    <div>
        <div>Olá MundoJS</div>
        <div>Olá MundoJS</div>
    </div>

)

// Já neste exemplo temos 2 elementos na raiz do objeto. Isso fará com que o React de erro.
var elemento2 = (

    <div>Olá MundoJS</div> 
    <div>Olá MundoJS</div>
)

 

Utilizando objetos JSX

Objetos criados com JSX podem ser manipulados como objetos JavaScript. Eles podem ser inseridos em vetores, utilizados em condicionais, utilizados em loops, passados como argumentos e retornados por funções.

// Exemplo de um objeto JSX utilizado em um IF

let produto = { nome: "banana", quantidade: 0 }

if (produto.quantidade === 0) {

    let elemento = <h1>O produto {produto.nome} não possuí estoque</h1>

}

else {

    let elemento = <h1>O produto {produto.nome} possuí {produto.quantidade} unidades em estoque</h1>

}

ReactDOM.render(

    elemento,
    document.getElementById("root")

)

Componentes React

Um componente React é um componente independente e reutilizável que exibe Elementos React baseados em suas propriedades e estados. Existem 2 tipos de componentes:

  • Componentes Funcionais
  • Componentes de Classe

Os componentes de classe têm um estado, métodos de ciclo de vida e propriedades. Enquanto componentes funcionais tem apenas propriedades. Primeiro veremos como funcionam os componentes funcionais e mais tarde falaremos de como os componentes de classe.

 

Componentes Funcionais

Este tipo de componente é apenas uma função que retorna elementos React. A convenção padrão do ReactJS pede que ao criar uma função, que o nome dela comece com letra maiúscula. Veja o exemplo abaixo:

function OlaMundoJS() {
    return <h1>Olá MundoJS!</h1>
}

 

Para utilizar o componente React que você criou dentro do JSX, basta criar uma tag HTML com o mesmo nome que o componente React.

let elemento = <OlaMundoJS/>

 

Outro exemplo

ReactDOM.render(

    <OlaMundoJS />,

    document.getElementById("root")
)

Em ambos casos, o elemento React exibido será aquele retornado pelo componente funcional HelloWorld.

 

Adicionando propriedades aos componentes funcionais

O primeiro parâmetro passado para um componente funcional é um objeto que contem as propriedades do componente.

function OlaMundo(props) {

    return <h1>mensagem: {props.mensagem}</h1>

}

 

Você pode dar valores as propriedades da mesma forma que são dados valores a atributos HTML.

ReactDOM.render(

    <HelloWorld message="Olá Mundo!" />,

    document.getElementById("root")

)

 

Propriedades podem ser strings, vetores ou qualquer outro tipo de objeto JavaScript. Você também pode utilizar elementos React como propriedades:

function OlaMundo(props) {
    return <h1>Valor: {props.listanumeros[props.index]} </h1>
}

ReactDOM.render(
    <OlaMundo index="3" listaNumeros={[1, 2, 3, 4, 5]} />,
    document.getElementById("root")
)

Criando Componentes

Componentes funcionais podem incluir outros componentes funcionais na sua exibição. Isto nos permite deixar nossos componentes organizados e fáceis de entender. Por exemplo, veja o exemplo abaixo de uma lista de supermercado.

function TituloCompras(props) {
    return (
        <div>
            <h1>{props.titulo}</h1>
            <h2>Total de Itens: {props.numItens}</h2>
        </div>
    )
}


function ItemLista(props) {
    return <li>{props.item}</li>
}


function ListaCompras(props) {
    return (
        <div>
            <h3>{props.cabecalho}</h3>
            <ol>
                <ItemLista item={props.itens[0]} />
                <ItemLista item={props.itens[1]} />
                <ItemLista item={props.itens[2]} />
            </ol>
        </div>
    )
}


function AppDeCompras(props) {
    return (
        <div>
            <TituloCompras titulo="Minha Lista de Compras" numItens="9" />
            <ListaCompras cabecalho="Comida" itens={["Maça", "Pão", "Banana"]} />
            <ListaCompras cabecalho="Roupa" itens={["Camiseta", "Tenis"]} />
            <ListaCompras cabecalho="Outros" itens={["Papel", "Copos", "Potes"]} />
        </div>
    )
}

ReactDOM.render(
    <AppDeCompras />,
    document.getElementById("root")
)

 

E compare isso com apenas definir todos os componentes de IU em um único componente funcional.

function AppDeCompras(props) {
    return (
        <div>
            <div>
                <h1>Minha lista de Compras</h1>
                <h2>Total Number of Items: 9</h2>
            </div>
            <div>
                <h3>Comida</h3>
                <ol>
                    <li>Maça</li>
                    <li>Pão</li>
                    <li>Banana</li>
                </ol>
            </div>
            <div>
                <h3>Roupa</h3>
                <ol>
                    <li>Camiseta</li>
                    <li>Tenis</li>
                </ol>
            </div>
            <div>
                <h3>Outros</h3>
                <ol>
                    <li>Papel</li>
                    <li>Copos</li>
                    <li>Potes</li>
                </ol>
            </div>
        </div>
    )
}



ReactDOM.render(
    <AppDeCompras />,
    document.getElementById("root")
)

É isso ai, esse artigo apresentou diversas coisas que valem serem testadas e praticadas para você se sentir confiante em usar o JSX e criar componentes.

Fique de olho que assim que possível estarei postando a terceira parte.

Você pode fornecer quantas propriedades você quiser. Todas elas serão acessíveis pelo parâmetro “props”.