Módulo para criação de tags e componentes

[download id=”390″]

Introdução

Nesse artigo serão mostradas funções que podem ser utilizadas para a criação de componentes HTML. O projeto será uma versão simplificada de uma biblioteca que estou montando para agilizar o desenvolvimento e gerenciamento de objetos criados dinamicamente.

Como requisito, você precisa ter conhecimentos básicos de JavaScript e HTML5, acesso a biblioteca CSS w3.css e um navegador atualizado que aceite o básico do ES6.

  • Criando as Tags básicas

    Como você deve saber, o JavaScript oferece uma função que permite a criação de qualquer tag. Basta fornecer corretamente o nome da tag como uma string por parâmetro que a função retornará o elemento para que você possa manipulá-lo. Segue abaixo um exemplo:

    document.createElement("p");

    O código acima retorna um elemento do tipo paragrafo. Ele pode ser manipulado (adicionadas, classes, estilo, texto, etc..) da mesma maneira que os elementos da função getElementById() também podem ser manipulados. Mas ele é simples e dependendo das necessidades, você acabará tendo diversos trechos de código onde cria uma tag, adiciona classes e adiciona conteúdo. Para nos ajudar com isso, teremos as duas seguintes funções:

    function CriarElementoComClasse(nomeTag, listaDeClasses) {
        let element = document.createElement(nomeTag);
        if (listaDeClasses) {
            listaDeClasses.forEach(classe => {
                element.classList.add(classe);
            });
        }
        return element;
    }
    
    function CriarElementoComClasseTexto(nomeTag, listaDeClasses, texto) {
        let element = CriarElementoComClasse(nomeTag, listaDeClasses);
        element.innerHTML = texto;
        return element;
    }

     

    A primeira função recebe uma string com o nome da tag e uma lista de strings com o nome das classes que serão adicionadas. Ela cria o elemento, confere se a lista não é nula ou indefinida e a percorre adicionando as classes uma a uma.

    A segunda função faz o mesmo que a primeira, mas também adiciona texto dentro da tag. É importante notar que esta função depende da anterior e que texto talvez seja uma definição muito ampla pois foi utilizado a propriedade innerHTML que permite que sejam adicionadas mais coisas. Por enquanto vamos com a ideia de adicionar texto, isso a torna uma boa candidata para criar <span>, <p>, <strong>, stc…

  • Criando Links e Imagens

    Como a parte simples e mais abstrata já foi feita, agora iremos implementar funções que nos auxiliaram a criar mais rapidamente tags de imagens e para links de hipertexto. Segue abaixo o código de implementação de ambas funções

    function CriarImagemCompleta(src, imgClasses, imgAlt = "imagem") {
        let element = CriarElementoComClasse("img", imgClasses);
        element.alt = imgAlt;
        element.src = src;
        return element;
    }
    
    function CriarLinkCompleto(link, linkClasses, texto) {
        let element = CriarElementoComClasseTexto("a", linkClasses, texto);
        element.href = link;
        return element;
    }

    Após analisar o código você poderá notar que ambas funções reutilizam as rotinas que criamos anteriormente, sendo que apenas implementamos o código que falta para que a criação de tag de imagem e link possam ser implementadas sem precisarmos ficar repetindo o código adicional que cada uma precisa toda vez que precisarmos cria-las.

  • Anexando diversos elementos juntos

    Até agora vimos 4 funções que nos permitem criar alguns componentes que podem ser bem úteis. No entanto, se você trabalha com códigos mais extensos, coisas parecidas ou piores que o código abaixo podem aparecer

    let umaDiv = CriarElementoComClasse("div", ["classe1","classe2","classe3"]);
    let umaDiv2 = CriarElementoComClasse("div",["classe1","classe2","classe3"]);
    let umSpan = CriarElementoComClasseTexto("span", ["classe2","classe2","classe3"],"Lorem Ipsum"); 
    let umSpan2 = CriarElementoComClasseTexto("span", ["classe2","classe2","classe3"],"Lorem Ipsum dolor"); 
    let umaImagem = CriarImagemCompleta("https://mundojs.com.br/images/logo.png", ["classe1","classe2","classe3"], "Logo MundoJS"); 
    let umLink = CriarLinkCompleto("https://mundojs.com.br", ["classe1","classe2","classe3"], "MundoJS"); 
    let umLink2 = CriarLinkCompleto("https://mundojs.com.br/artigos/index.html", ["classe1","classe2","classe3"], "MundoJS - artigos");
    
    umaDiv.appendChild(umSpan); 
    umaDiv.appendChild(umaImagem);
    umaDiv.appendChild(umLink); 
    umaDiv.appendChild(umaDiv2); 
    
    umaDiv2.appendChild(umSpan2); 
    umaDiv2.appendChild(umLink2);

    E quanto mais elementos tivermos, maior será o comprimento de código repetido. Por isso, iremos criar uma função ao qual passamos o elemento onde será feito o append e uma lista dos arquivos que serão adicionados a ele.

    function AppendElementos(pai, filhos) {
        filhos.forEach(element => {
            pai.appendChild(element);
        });
    }

    E isso nos permite transformar os diversos append anteriores em 2 linhas de código

    AppendElementos(umaDiv, [umSpan, umaImagem, umLink, umaDiv2]); 
    AppendElementos(umaDiv2, [umSpan2, umLink2]);
  • Criação de Thumbnail

    Por padrão, um thumbnail é uma área com uma imagem no topo seguida de um titulo e/ou texto descritivo. O interessante deste tipo de componente o fato que ele pode ser facilmente incorporado em páginas responsivas devido ao seu formato. Antes de continuarmos, no seu arquivo CSS será necessário adicionar as seguintes classes:

    .mundojs-media{
        overflow: hidden;
        display: block;
        text-decoration: none;
        -webkit-box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75);
        -moz-box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75);
        box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75);
    }

    Segue abaixo o código para implementarmos thumbnails utilizando nossas funções já criadas e a formatação fornecida pelo w3.css:

    function CriarThumbnail(linkArquivo, titulo, descricao, imagem) {
        let linkThumbnail = CriarLinkCompleto(linkArquivo, ["w3-third", "w3-margin-bottom", "mundojs-media"]);
        let divCard = CriarElementoComClasse("div", ["w3-card-4"]);
        linkThumbnail.appendChild(divCard);
    
        let imgThumbnail = CriarImagemCompleta(imagem, ["w3-image"]);
    
        let divConteudo = CriarElementoComClasse("div", ["w3-container", "w3-center"]);
        let h4Titulo = CriarElementoComClasseTexto("h4", null, titulo);
        let pDescricao = CriarElementoComClasseTexto("p", ["w3-small"], descricao);
    
        AppendElementos(divConteudo, [h4Titulo, pDescricao]);
        AppendElementos(linkThumbnail, [imgThumbnail, divConteudo]);
    
        return linkThumbnail;
    }

    Você poderá ver pelo código que ele sempre terá 1/3 do comprimento do container dele em telas maiores e 100% em telas de smartphones. Isso pode ser adaptado simplesmente trocando as classes fornecidas no elemento linkThumbnail.

  • Criado um Media Card

    Por último criaremos o media card, uma espécie de cartão que possui uma imagem em sua lateral. Ele é um estilo bem utilizado para a criação de objetos representando notícias, lista de notícias ou posts com o gravatar.

    function CriarMedia(linkArquivo, titulo, descricao, imagem) {
        function AreaImagem() {
            let divImagem = CriarElementoComClasse("div", ["w3-quarter"]);
            divImagem.appendChild(CriarImagemCompleta(imagem, ["w3-image"]));
    
            return divImagem;
        }
    
        function AreaConteudo() {
            let divConteudo = CriarElementoComClasse("div", ["w3-threequarter", "w3-container", "w3-margin-bottom"])
            let h2Titulo = CriarElementoComClasseTexto("h2", ["w3-xlarge"], titulo);
            let pDescricao = CriarElementoComClasseTexto("p", null, descricao);
            let linkArquivo = CriarLinkCompleto(linkArquivo, ["w3-btn", "w3-theme-l4", "w3-border", "w3-border-theme", "w3-round-large"], "Saiba Mais");
    
            AppendElementos(divConteudo, [h2Titulo, pDescricao, linkArquivo]);
    
            return divConteudo;
        }
    
        let divMedia = CriarElementoComClasse("div", ["w3-row", "w3-margin", "w3-border-bottom", "w3-border-theme-l4", "mundojs-media"]);
    
        AppendElementos(divMedia, [AreaImagem(), AreaConteudo()]);
    
        return divMedia;
    }

    Apesar de ser um pouco mais extenso que as funções anteriores, o resultado fica bem legal e pode ser utilizado facilmente para gerar uma lista de newsfeed, comentários de posts entre outras opções.

Conclusão

Como você pode ver, foi possível criar diversas ferramentas para auxiliar na montagem de itens na tela. Na minha experiência pessoal, eles não auxiliam muito se você utiliza um site estático. No entanto, caso você esteja trabalhando com dados dinâmicos ou simplesmente informações que se repetem muito, este tipo de técnica auxilia muita a reduzir o HTML e o JS comparado a criação manual sob demanda.

Gerenciando os plug-ins do Facebook em arquivos JS

[download id=”383″]

Introdução

Nesse artigo rápido, veremos como é possível centralizar o controle das tags do Facebook em um único arquivo JavaScript. O objetivo é facilitar o gerenciamento dos componentes que eles oferecem e remover todas as tags <script> com código embutido.

Para entender este artigo você precisará ter conhecimentos básicos de HTML, JS e da API de plug-ins sociais do Facebook. Apesar dos plug-ins serem um pouco mais complexos do que os iniciantes estão acostumados, a documentação é bem direta e boa parte do código é gerado automaticamente.

Passo 1

A primeira coisa que você precisa fazer é criar um arquivo JS onde colocaremos o código. Você pode nomeá-lo como quiser, mas para esse artigo o chamaremos de “codigoFB.js”. Dentro dele adicione o evento conforme abaixo e já explicaremos o que ele significa.

window.onload = function () {
    (function (d, s, id) {
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) return;
        js = d.createElement(s); js.id = id;
        js.src = "//connect.facebook.net/pt_BR/sdk.js#xfbml=1&version=v2.10&appId=9999999";
        fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));
}

O que fizemos aqui foi o seguinte, estamos dizendo que ao carregar a tela deve ser executada uma função. Por enquanto a única coisa que colocamos dentro desta função é outra função que é a fornecida pelo Facebook (ver códigos da API no link deles) para ser possível utilizar os plug-ins deles.

Importante: Se você simplesmente copiar e colar, não dará certo pois o appID não é valido, será necessário ter o seu appID e/ou copiar o mesmo código fornecido em paginas como https://developers.facebook.com/docs/plugins/like-button.

Passo 2

A segunda coisa que faremos serão os objetos de configuração. Neste artigo, para fins de simplificação, iremos configurar apenas dois plug-ins, o de curtir e o de comentários.

No botão de comentários padrão fornecido no site, você pode ver que ele tem uma classe e 2 atributos.

<div class="fb-comments" 
    data-href="http://www.linkpaginaseusite.com.br" 
    data-numposts="5"></div>

Vamos tranforma-los em um objeto com o seguinte formato

let configFbComments = {
    classes: ["fb-comments"],
    atributos: [{
        nome: "data-href",
        valor: window.location.href
    },
    {
        nome: "data-numposts",
        valor: 5
    }]
};

Como você pode ver, o objeto é composto por duas propriedades, classes e atributos, e elas contem respectivamente um vetor de strings e um vetor de objetos. Note que como o comentário precisa utiliza o link da sua página como referência, para podermos reutilizar o objeto foi colocado o window.location.href que mudará em cada página.

Para o botão de curtir (e compartilhar), faremos um exemplo um pouco mais complexo.

let configFbLike = {
    classes: ["fb-like","FloRight"],
    atributos: [{
        nome: "data-href",
        valor: window.location.href
    },
    {
        nome: "data-layout",
        valor: "button_count"
    },
    {
        nome: "data-action",
        valor: "like"
    },
    {
        nome: "data-size",
        valor: "small"
    },
    {
        nome: "data-show-faces",
        valor: "true"
    },
    {
        nome: "data-share",
        valor: "true"
    }]
};

Aqui temos duas classes, sendo que “fb-like” é obrigatória, e diversos atributos, mas a lógica ainda é a mesma, um objeto com duas propriedades que são vetores. Agora precisamos de uma forma inteligente de processar nossos a plug-ins sem precisarmos nos importar com quais ou quantos dados são fornecidos, o que importa é apenas o formato. Segue abaixo o código para processarmos eles:

function configurarPlugin(elementoHTML, config) {
    elementoHTML.classList.add(config.classes);

    config.atributos.forEach(attr => {
        elementoHTML.setAttribute(attr.nome, attr.valor);
    });
}

O que estamos fazendo aqui? Estamos passando um elemento HTML e o objeto de configuração. Utilizando os métodos do classList, adicionamos todas as classes e após, percorremos o vetor de atributos e os adicionamos um a um ao elemento.

Após isso, basta fazermos a chamada das configurações após termos carregado a função do Facebook que adicionamos la no começo da página. No meu caso, eu fiz uma função (pluginsFacebook) que as adiciona e passa 2 divs que tenho na página, mas seria possível chama-las direto também.

window.onload = function () {
    (function (d, s, id) {
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) return;
        js = d.createElement(s); js.id = id;
        js.src = "//connect.facebook.net/pt_BR/sdk.js#xfbml=1&version=v2.10&appId=999999";
        fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));

    pluginsFacebook();
}

function pluginsFacebook() {
    configurarPlugin(document.getElementById("btnCurtirFb"), configFbLike);
    configurarPlugin(document.getElementById("frameComentariosFb"), configFbComments);
}

Conclusão

Como podemos ver, é possível separar a lógica de programação fornecida pelos plug-ins sociais do Face sem afetar negativamente a experiência do usuário. Pessoalmente eu prefiro este formato pois permite que a pessoa acessando veja o conteúdo da página antes do processamento deles iniciar, o que causa a impressão de conteúdo carregado mais rápido. Existem outros jeitos de fazermos o código acima, mas acredito que está tenha sido uma das formas mais rápidas e simples de implementar a funcionalidade proposta.

Como fazer um jogo em JavaScript

[download id=”285″]

Olá Pessoal do MundoJs !

Esse é um artigo/tutorial sobre mecanismos básicos de jogos em javascript

Será apresentada uma maneira bem básica de como fazer um jogo da cobrinha em javascript. É um jogo para ser jogado no browser/navegador (chrome/firefox/explorer) mas não funciona em tablets e celulares porque precisa do teclado…

Vamos começar criando um arquivo .html em branco. E logo em seguida escrever um pouco de html:

<html>
<body>
    <div id=principal></div>
    <script>
        document.getElementById('principal').innerHTML='Daqui surge o jogo';
    </script>
</body>
</html>

Até aqui sem maiores surpresas… um simples arquivo sem muita complicação.

Logo em seguida vamos criar o tabuleiro por onde a cobra irá se movimentar:

<html>
<body>
    <div id=principal></div>
    <script>
    tabuleiro="<table align=center border=1>";
    for(x=0;x<10;x++){
        tabuleiro+="<tr>";
        for(y=0;y<10;y++)
            tabuleiro+="<td>"+x+"_"+y+"</td>";
        tabuleiro+="</tr>";
    }
    document.getElementById('principal').innerHTML=tabuleiro+"</table>";
    </script>
</body>
</html>

Vamos dar um id para cada celula do tabuleiro:

for(y=0;y<10;y++){
    tabuleiro+="<td id=td"+x+"_"+y+" style='width:30px; height:30px;'> </td>";
}

Vamos ‘pintar’ uma celula do tabuleiro:

document.getElementById('td3_3').style.background="#333333";

Vamos criar uma variavel cobra[] que armazena a coordenada (x,y) da cobra:

cobra=[5,0];
document.getElementById('td'+cobra[0]+'_'+cobra[1]).style.background="#333333";

Vamos fazer a cobra ‘andar’ com a função ‘setTimeout’:

function anda(){
    cobra[1]++;
    document.getElementById('td'+cobra[0]+'_'+cobra[1]).style.background="#333333";
    setTimeout('anda()',300);
}
anda();

Essa função setTimeout é a base do movimento em javascript. Existem alternativas mas essa é nativa e tem vantagens…

E vamos ‘apagar’ o rastro da cobrinha:

function anda(){
    document.getElementById('td'+cobra[0]+'_'+cobra[1]).style.background="#ffffff";
    cobra[1]++;
}

Vamos ‘interceptar/interpretar’ a tecla que o usuário aperta no teclado:

<body onKeyDown="pegadirecao(event.keyCode);">
function pegadirecao(tecla){
    alert(tecla);
}

Vamos criar uma variavel direcao que armazena/determina pra onde a cobra deve se mover:

direcao=2;
function pegadirecao(tecla){
    /*alert(tecla);*/
    if(tecla==37)direcao=0;
    if(tecla==38)direcao=1;
    if(tecla==39)direcao=2;
    if(tecla==40)direcao=3;
}

E dentro da função anda

if(direcao==0)cobra[1]--;
if(direcao==1)cobra[0]--;
if(direcao==2)cobra[1]++;
if(direcao==3)cobra[0]++;

vamos criar a maçã:

mx=parseInt(Math.random()*10);
my=parseInt(Math.random()*10);

E na função ‘anda()’

document.getElementById('td'+mx+'_'+my).style.background="#ff3333";

Vamos fazer a maçã ser gerada novamente:

if(mx==cobra[0]&&my==cobra[1]){
    mx=parseInt(Math.random()*10);
    my=parseInt(Math.random()*10);
    cobra[cobra.length]=[10,10];
}

Agora vem a parte mais sofisticada do jogo. Vamos transformar a variável cobra de um array para um array de arrays. Até agora a variavel cobra armazenava um ponto. A partir daqui essa variavel armazenará um array de pontos…

cobra=[[5,0]];
function anda(){
    document.getElementById('td'+cobra[cobra.length-1][0]+'_'+cobra[cobra.length-1][1]).style.background="#ffffff";
    if(mx==cobra[cobra.length-1][0]&&my==cobra[cobra.length-1][1]){
        mx=parseInt(Math.random()*10);
        my=parseInt(Math.random()*10);
        cobra[cobra.length]=[10,10];
    }
    if(direcao==0)cobra[0][1]--;
    if(direcao==1)cobra[0][0]--;
    if(direcao==2)cobra[0][1]++;
    if(direcao==3)cobra[0][0]++;
    document.getElementById('td'+cobra[0][0]+'_'+cobra[0][1]).style.background="#333333";
    document.getElementById('td'+mx+'_'+my).style.background="#ff3333";
    setTimeout('anda()',300);
}

Para fazer a cobra se movimentar devemos passar os valores de cada coordenada de cada ‘gomo’ da cobra para o ‘gomo de traz’:

for(x=cobra.length-1;x>0;x--){
    cobra[x][0]=cobra[x-1][0];
    cobra[x][1]=cobra[x-1][1];
}

Agora só falta fazer função que executará quando a cobra ‘morrer’:

vivo=true;
if(vivo)setTimeout('anda()',300);
else alert('Fim de jogo');
for(x=1;x<cobra.length;x++){
    if(cobra[0][0]==cobra[x][0]&&cobra[0][1]==cobra[x][1])vivo=false;
    if(cobra[0][0]<0||cobra[0][1]<0||cobra[0][0]>9||cobra[0][1]>9)vivo=false;
}

O código completo fica:

<html>
<body onKeyDown="pegadirecao(event.keyCode);">
<div id=principal></div>
<script>
    tabuleiro="<table align=center border=1>";
    for(x=0;x<10;x++){
        tabuleiro+="<tr>";
        for(y=0;y<10;y++)
            tabuleiro+="<td id=td"+x+"_"+y+" style='width:30px; height:30px;'> </td>";
        tabuleiro+="</tr>";
    }
    document.getElementById('principal').innerHTML=tabuleiro+"</table>";
    cobra=[[5,0]];
    direcao=2;
    mx=parseInt(Math.random()*10);
    my=parseInt(Math.random()*10);
    vivo=true;
    function anda(){
        document.getElementById('td'+cobra[cobra.length-1][0]+'_'+cobra[cobra.length-1][1]).style.background="#ffffff";
        if(mx==cobra[cobra.length-1][0]&&my==cobra[cobra.length-1][1]){
            mx=parseInt(Math.random()*10);
            my=parseInt(Math.random()*10);
            cobra[cobra.length]=[10,10];
        }
        for(x=cobra.length-1;x>0;x--){
            cobra[x][0]=cobra[x-1][0];
            cobra[x][1]=cobra[x-1][1];
        }
        if(direcao==0)cobra[0][1]--;
        if(direcao==1)cobra[0][0]--;
        if(direcao==2)cobra[0][1]++;
        if(direcao==3)cobra[0][0]++;
        for(x=1;x<cobra.length;x++)if(cobra[0][0]==cobra[x][0]&&cobra[0][1]==cobra[x][1])vivo=false;
        if(cobra[0][0]<0||cobra[0][1]<0||cobra[0][0]>9||cobra[0][1]>9)vivo=false;
        document.getElementById('td'+cobra[0][0]+'_'+cobra[0][1]).style.background="#333333";
        document.getElementById('td'+mx+'_'+my).style.background="#ff3333";
        if(vivo)setTimeout('anda()',300);
        else alert('Fim de jogo');
    }
    anda();
    function pegadirecao(tecla){
        /*alert(tecla);*/
        if(tecla==37)direcao=0;
        if(tecla==38)direcao=1;
        if(tecla==39)direcao=2;
        if(tecla==40)direcao=3;
    }
</script>
</body>
</html>

 

Construindo um slider e parallax com JavaScript

[download id=”257″]

Nesse artigo prático e rápido você verá como construir um slider utilizando apenas o JavaScript, sem precisar importar nenhuma biblioteca e ou editar o CSS fora das funções. O objetivo aqui é trabalhar os conhecimentos de manipulação do DOM e o básico de estrutura de dados.

Configurando o HTML

Então vamos começar. Primeiro é necessário preparar no HTML o local onde será definido slider. Qualquer TAG de bloco serve, mas para simplicidade e por boas práticas, vamos utilizar uma DIV com o ID igual a slider. O código JavaScript ficará separado, mas por se tratar de um exemplo rápido, vamos manter tudo dentro da mesma pasta (incluído as imagens que serão adicionadas).

<html>
<head>
</head>
<body>
  <div id="slider"><div>
  <script src="slider.js"><script>
</body>
</html>

Adicionando uma imagem de fundo

Certo, está área terá o local que utilizaremos como referência, mas neste exemplo, as imagens serão parte do plano de fundo, então além de definir qual imagem aparecerá, teremos que estabelecer um tamanho para ela. Então quando a janela estiver carregada, vamos chamar a função criarSlider() que no momento apenas colocará uma imagem de fundo com tamanho igual a 40% da altura da tela.

window.onload = function(){
  criarSlider();
}
 
function criarSlider(){
  let slider = document.getElementById("slider");
  slider.style.height = "40vh";
  slider.style.backgroundSize = "cover";
  slider.style.backgroundImage = "url(imagem1.jpg)";
}

Adicionando o efeito Parallax

Para fazermos esse efeito de forma fácil e prática, utilizaremos a propriedade “backgroundAttachment” e a definiremos como “fixed”. OBS.: Ainda existem navegadores que não dão suporte ao atributo “fixed” (confira https://caniuse.com/#search=background-att).

function criarSlider(){
  let slider = document.getElementById("slider");
  slider.style.height = "40vh";
  slider.style.backgroundSize = "cover";
  slider.style.backgroundImage = "url(imagem1.jpg)";
  /*Efeito Parallax*/
  slider.style.backgroundAttachment = "fixed";
}

Definindo uma lista de imagens

Com esse código já é possível rodar a tela inicial e você verá sua imagem ocupado todo o espaço da div e com a altura fixa e possui o efeito. No entanto, nada acontece. Para mudarmos isso, vamos utilizar a função JavaScript chamada setInterval() que fará uma ação fixa a cada intervalo de tempo.

Poderíamos definir as imagens que serão passadas de forma fixa, mas para dar mais flexibilidade, vamos coloca-las em um vetor para que uma quantidade indefinida de arquivos possa ser utilizada, reduzindo assim o retrabalho futuro (basta adicionar a nova imagem ao vetor).

Para esta sessão, serão necessárias 3 implementações

  • Adicionar o vetor no começo da função
let imagens = ["imagem1.jpg","imagem2.jpg", "imagem3.jpg"];
  • Substituir a backgroundImage pelo primeiro item do vetor
slider.style.backgroundImage = "url(" + imagens[0] + ")";
  • Adicionar uma variável de contador e a função setInterval() conforme abaixo
let i = 1;
  setInterval(function () {
    slider.style.backgroundImage = "url(" + imagens[i] + ")";
    i = i + 1;
    if (i === imagens.length) {
    i = 0;
  }
}, 3000);

Melhorando o efeito

Você deve ter notado que a troca de imagens está meio crua, apenas piscando rapidamente e alternado entre elas. Para deixar esse efeito mais suave, adicione uma transição entre elas conforme a linha abaixo (pode ser colocado abaixo do style.backgroundSize):

slider.style.transition = "all 400ms linear";

Melhorando o código

Agora temos um slider parallax com um efeito de transição de imagens melhorado. Mas nosso código permite montar apenas um slider por tela pois todas as variáveis foram montadas dentro da função. Vamos passar como parâmetros da função os valores do Id do slider, o vetor de imagens, se será parallax e o tempo de troca entre imagens. Com isso teremos uma função que permite fazer diversos sliders com configurações diferente entre eles e sem precisar alterar muito o código como você pode ver abaixo:

function criarSlider(slider, imagens, isParalalx, tempo){
  let slider = document.getElementById("slider");
  slider.style.height = "40vh";
  slider.style.backgroundSize = "cover";
  slider.style.backgroundImage = "url(" + imagens[0] + ")";
  slider.style.backgroundAttachment = "fixed";
 
  if (isParalalx) {
    slider.style.backgroundAttachment = "fixed";
  }
 
  let i = 1;
  setInterval(function () {
    slider.style.backgroundImage = "url(" + imagens[i] + ")";
    i = i + 1;
    if (i === imagens.length) {
    i = 0;
    }
  }, tempo);
}

Conclusão

O projeto apresentado já é funcional e poderia ser aplicado em qualquer website, mas caso você queira se desafiar, existem coisas que podem ser implementadas. As variáveis de configuração poderiam ser em apenas um objeto com os todos os parâmetros que possam ser configurados e valores padrões (default), poderiam haver conferencias para garantir que dados incorretos ou nulos não travem o slider entre outras possibilidades.

De toda forma, o código do projeto pode ser utilizado em qualquer website pois oferece todas as funcionalidades necessárias para a montagem de forma simples e rápida. Caso você tenha gostado deste artigo, por favor, compartilhe-o e deixe seu comentário. Se você achou um bug ou tem uma sugestão, por favor avise que atualizarei o código.

FileSaver: Salve arquivos com JavaScript

 

[download id=”245″]

Este tutorial serve para quem precisa criar pequenos arquivos de texto e salva-los em um formato que o pc do usuário final possa ler. Para isso utilizaremos a biblioteca do FileSaver.js para eftuar a lógica de criação e baixar o arquivo na máquina cliente. Então vamos começar!

Passo 1

Baixe o script do FileSaver.min.js no link (https://github.com/eligrey/FileSaver.js/) ou junto com nosso código fonte acima e copie-o para o seu local de trabalho. Caso queira conhecer melhor o código, você pode baixar a versão não minificada, em qualquer outro caso não vale a pena.

Passo 2

Vamos criar alguns inputs html para que possamos salvar nossos dados. Precisaremos de um input para o nome do arquivo, um textarea para o texto do arquivo e um botão para iniciarmos a rotina.

<html>
<head>
   <style>
   div {
     min-width: 300px;
     width: 50%;
     margin: 10px auto;
   }
   input,
   textarea {
     width: 100%;
     min-width: 250px;
   }
   </style>
</head>
<body>
   <h3>Salvar arquivo com JavaScript</h3>
   <div>
     <label for="input-fileName">Nome do Arquivo</label><br/>
     <input type="text" id="titulo" placeholder="Nome do Arquivo">
   </div>
   <div>
     <label for="textarea">Texto</label><br/>
     <textarea id="texto" placeholder="Digite um texto para salva-lo"></textarea>
   </div>
   <div>
     <button onclick="salvar()">Salvar</button>
   </div>
</body>
</html>

Passo 3

O código acima já serve como uma base simples para implementarmos nosso código. Vamos adicionar, antes da tag de fechamento do body, a biblioteca do FileSaver e logo após colocaremos a seguinte função JavaScript.

  <!-- Biblioteca que adicionara o código -->
   <script type="text/javascript" src="FileSaver.min.js"></script>
   <!-- função ao clicar em salvar -->
   <script>
   function salvar() {
      let texto = document.getElementById("texto").value;
      let titulo = document.getElementById("titulo").value;
      let blob = new Blob([texto], { type: "text/plain;charset=utf-8" });
      saveAs(blob, titulo + ".txt");
   }
   </script>
</body>
</html>

Como função do FileSaver que cria o arquivo precisa de um objeto blob para definir a formatação além do texto do arquivo, criamos o objeto utilizando o valor obtido no textarea com id texto e definimos que será codificado em utf-8 (valor padrão para formatação de texto no Brasil).

Tendo feito isso, basta chamar a função saveAs(), passando como parâmetros o blob e o título concatenado com o formato desejado. Note que você pode colocar outros formatos (ex.: XML, CSV), mas terá que garantir que o conteúdo possa ser lido pelo sistema que o abrir.

Passo 4)

O passo final é o teste. Rode o código e preencha os campos de título e texto para ver se ao salvar o arquivo para download aparecerá na sua tela. Ele apareceu? Tem conteúdo dentro? Se a respostas das perguntas anteriores for sim, então parabéns, seu código está funcionando.


Possíveis problemas

É necessário observar que nem todos s navegadores onde ele será utilizado dão suporte ao Blob e também, se o título ou o texto não existirem, talvez seja necessário informar o usuário ou colocar valores padrões para o título ou texto


Conclusão

Como é possível ver, criar um arquivo de texto utilizando apenas o JavaScript é super fácil. Caso você leve em consideração os possíveis problemas, você poderá fazer uma ferramenta mais flexível e completa que permita ao seu usuário criar e editar pequenos arquivos de forma rápida e eficiente

Como fazer Captcha com JavaScript

[download id=”227″]

O Captcha (Completely Automated Public Turing test to tell Computers and Humans Apart) é uma ferramenta utilizada para combater spam utilizando um método chamado de teste de Turing reverso. Normalmente o servidor pede ao usuário que termine um teste que não pode ser completado por um computador e por isso assume-se que quem respondeu corretamente é um humano.

Nesse artigo/tutorial veremos como fazer 2 “captchas” simples e rápidos usando apenas o JavaScript puro ao invés efetua-lo pelo servidor. A vantagem de fazê-lo assim é a de podermos manter o controle no front-end e fornecer uma proteção básica e rápida. Por outro lado, o código estará exposto para “não robôs” contorna-lo. Vale o julgamento de cada um para saber se este controle é o suficiente.

Soma de números aleatórios

Um jeito fácil de fazer um teste é fornecer 2 números aleatórios e pedir para o usuário digitar a resposta completa.

  • Primeiro precisamos do html que será usado no exemplo:
<form id="formContato">
   <p id="teste"></p>
   <input id="valida" type="text" />
   <input type="submit" value="Enviar" />
   <p id="mensagem"></p>
</form>
  • Agora criamos as variáveis para o cálculo e a reposta. Neste exemplo, criaremos 2 números aleatórios de 0 a 9 e vamos soma-los. Mas você poder fazer qualquer faixa e operação
var num1 = Math.floor(Math.random() * 10);
var num2 = Math.floor(Math.random() * 10);
var resposta = num1 + num2;
  •  Adicionamos um evento para que, ao carregar a página, seja capturado o parágrafo que fará a pergunta do teste e utilizamos as variáveis para gerar uma pergunta diferente cada vez que a página recarrega:
window.onload = function () {
   document.getElementById("teste").innerHTML = "qual a soma de " + num1 + " + " + num2 + "?";
}}
  • Dentro da função anterior, adicionaremos um evento ao ser feito o submit do formulário para conferirmos se a resposta está correta. Caso esteja, a submissão dele ocorre normalmente, senão trancamos o envio e mostramos uma mensagem na tela
document.getElementById("formContato").onsubmit = function (e) {
  if (document.getElementById("valida").value != resposta) {
    document.getElementById("mensagem").innerHTML = "A soma está errada!";
    e.preventDefault();
  }
}

Com isso temos todo o código necessário para fazer nosso captcha funcionar, execute a página e faça o teste você mesmo.

Teste x Valor

A segunda alternativa é um pouco mais complexa, mas ainda assim muito simples de implementar. Ela pode ser utilizada para mostrar uma imagem, dados complexos, etc… e um valor que corresponde a resposta correta.

  • Neste exemplo vamos tentar utilizar o máximo possível da lógica anterior para evitar complicar algo desnecessário. O form de antes será reutilizado exatamente como era e a lógica será novamente implementada dentro da função do evento window.onload
  • Vamos então adicionar as 2 variáveis que precisaremos. A Primeira será um vetor contendo objetos com 2 propriedades, teste e valor. A segunda é um gerador aleatório de índice.
window.onload = function () {
  var vetor = [
    { teste: "BBbananaAA", valor: "banana" },
    { teste: "AAabacaxiII", valor: "abacaxi" },
    { teste: "BBtomateAA", valor: "tomate" },
    { teste: "BBkiwiAA", valor: "kiwi" },
    { teste: "BBmelaoAA", valor: "melao" }
  ];
  var indice = Math.floor(Math.random() * 100) % 5;
}

Note que a propriedade teste do vetor é possível utilizar o caminho de uma imagem, uma pergunta, uma data, qualquer coisa. O importante é que o que for colocado no teste precisa ter uma reposta correspondente e a tag onde ele será inserido talvez precise ser trocada ou tratada (ex.: se for uma imagem, trocar para img com o src sendo definido pelo caminho da imagem).

  • Utilizando o gerador aleatório de índice, buscamos um item dentro do vetor e o exibimos para ser o teste. Lembrando que aqui meu vetor tem 5 itens, você provavelmente terá um vetor maior, então ajuste o gerador de acordo com a necessidade
document.getElementById("teste").innerHTML = "Qual a palavra formada pelas letras minusculas do texto " + vetor[indice].teste + "?";
  • Por último temos novamente o teste antes de efetuar o submit do formulário que irá conferir se a resposta é igual ao valor do objeto naquela mesma posição do vetor. Com isso saberemos se podemos deixar o formulário ser enviado ou se precisamos bloqueá-lo
document.getElementById("formContato").onsubmit = function (e) {
  if (document.getElementById("valida").value != vetor[indice].valor) {
    document.getElementById("mensagem").innerHTML = "Resposta Errada";
    e.preventDefault();
  }
}

Conclusão

Como você pode ver, criar um controle de captcha pode ser bem simples e ajudará a evitar e-mails spam, pessoas clicando em enviar sem parar e outros incômodos básicos. Claro que existem outros jeitos de fazer a mesma coisa usando bibliotecas prontas ou técnicas de programação diferentes, mas acredito que a forma apresentada ajude a todos, principalmente os iniciantes.

 

Diferença de className, classList e setAttribute

A linguagem JavaScript nos permite manipular elementos HTML de diversas formas e algumas vezes precisamos montar componentes “on the fly” pois eles dependem de atualizações vindas de fontes externas, ações do usuário ou que o banco de dados finalmente termine de processar algum calculo monstruoso que aquele cliente disse ser fundamental.

Quando isso acontece, precisamos trabalhar para criar elementos que além de uteis sejam bonitos e com isso vem as implementações de CSS. Agora você que a passou por isso pode ter se deparado com a possibilidade de usar os métodos

  • Classname
  • Classlist.add
  • Setattribute

A performance

Mas qual é o melhor? Vale a pena ter um método para definir classes e um para definir atributos? Tendo isso em vista, resolvi pesquisar para saber qual seria a melhor opção. Segundo o site https://measurethat.net/Benchmarks/Show/54/0/classname-vs-setattribute-vs-classlist, alguém já havia se perguntado o mesmo. Eles fizeram o seguinte teste que rodei no Chrome, Edge e Firefox:

<div id="foo"></div>

className

var element = document.getElementById("foo");
var i = 1000;
while (i--) {
    element.className = "bar";
}

setAttribute

var element = document.getElementById("foo");
var i = 1000;
while (i--) {
    element.setAttribute("class", "bar");
}
classList
var element = document.getElementById("foo");
var i = 1000;
while (i--) {
    element.classList.add("bar");
}

Resultado em operações por segundo

Chrome

Firefox

Edge

Na prática

Mesmo sendo bem claro, o teste acima não é um absoluto, devemos levar em consideração outros fatores como manipulação, funcionalidades e boas práticas.

  1. className: Permite a manipulação das classes no formato string, nesse caso tendo uma string com todas as classes escritas dentro e permitindo a manipulação dos dados neste formato. Por ser uma funcionalidade antiga, é utilizado por diversos navegadores
  2. setAttribute: O set atribute simplesmente faz isso, define o valor dentro de um atributo. Existe o getAttribute que permite visualizar este valor, mas a manipulação é limitada a isso.
  3. classList: Coloca as classes dentro de uma lista para serem manipuladas de forma ordenada através de diversos métodos específicos. A nível de funcionalidade é a mais prática, mas além de ter uma performance inferior, não foi implementada em navegadores mais antigos.

Conclusão

Acredito que o className e o classList sejam os melhores candidatos. Se você precisa de performance e está apenas definindo e apagando classes, utilize o className. Agora se você tem um sistema que precisa procurar por classes dentro da tag ou adicionar apenas se não existe, poupe o esforço de criar uma lógica para isso e utilize o classList.

Como criar a tag para uma string

Essa é uma dica rápida para ajudar você a criar a tag HTML <a> com base em um link digitado dentro de uma string. Há alguns dias atrás tive esta duvida pois precisava ajudar a criar o link para as mensagens de texto que os clientes colocavam dentro de um sistema que estamos desenvolvendo. Então precisávamos fazer com que uma frase como:


Confira o site www.mundojs.com.br para mais informações, ou acesse nossa fanpage https://www.facebook.com/mundojs/ para receber mais noticias


Exibisse em tela da com os hiperlinks da seguinte forma:


Veja o site www.mundojs.com.br para mais informações, ou acesse nossa fanpage https://www.facebook.com/mundojs/ para receber mais noticias


Depois de pesquisar bastante por um solução que fosse A) inteligente e B) Eficiente, encotrei a seguinte função regex

function urlify(text) {
    let urlRegex = /(https?:\/\/[^\s]+)/g;
    return text.replace(urlRegex, function(url) {
        return '<a href="' + url + '">' + url + '</a>';
    })
    /* ou de forma mais resumida */
    /* return text.replace(urlRegex, '<a href="$1">$1</a>') */
}

let text = "Confira o site www.mundojs.com.br para mais informações, ou acesse nossa fanpage https://www.facebook.com/mundojs/ para receber mais noticias";
let html = urlify(text);

Com ela você poderá passar qualquer strings que você receberá seus links adaptados para que em uma pagina HTMl possa exibi-los corretamente.

Criando bibliotecas com TypeScript

O objetivo desse post será a demonstração através de alguns passos de como podemos criar de uma biblioteca com TypeScript e publicarmos ela no portal NPM.

Primeiro passo: Inicialização do projeto

Nosso primeiro passo será a criação de um novo diretório, para esse artigo nós criamos um com o nome ts-library, navegue até o seu diretório via CMD e execute o comando npm init -y.

O comando a cima irá criar um arquivo chamado package.json, esse será o primeiro arquivo que nós precisamos editar. Para isso, iremos precisa de em um editor de textos, nesse artigo nós iremos utilizar o VS Code (Visual Studio Code).

Com o VS aberto, agora nós precisamos atualizar o nosso arquivo package.json:

{
    "name": "typescript-library",
    "version": "1.0.0",
    "description": "",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "main": "dist/index.js",
    "types": "dist/index.d.ts"
}
  • name: deve ser o nome da sua biblioteca;
  • version: a versão atual do seu código;
  • types: local do nosso arquivo de type definition, para quem ainda não conhece segue o link de um artigo sobre esse tema Type Definitions.

Segundo passo: Configurando TypeScript

Agora nós precisamos criar o nosso arquivo de configurações do TypeScript. Para isso, crie um novo arquivo chamado tsconfig.json na raiz do seu projeto.

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es5",
        "declaration": true,
        "outDir": "./dist"
    },
    "include": [
        "src/**/*"
    ]
}

Passando pelo nosso arquivo a cima nós temos:

  • target: a versão do ecmascript que nós estamos utilizando.
  • declaration: nós deixamos como true para que ele gere o nosso arquivo de types.
  • include: local onde ele deve varrer para achar os nossos arquivos .ts.

Terceiro passo: Criação da biblioteca

Para esse passo nós iremos criar uma biblioteca para pegar o valor de um parâmetro passado pelo URL, algo bem simples somente para que possamos ver esse fluxo.

export namespace GetUrl {
    export function params(url) {

    var queryString = url ? url.split('?')[1] : window.location.search.slice(1);


    var obj = {};

    if (queryString) {
        queryString = queryString.split('#')[0];
        var arr = queryString.split('&');

        for (var i = 0; i < arr.length; i++) {

        var a = arr[i].split('=');
        var paramNum = undefined;
        var paramName = a[0].replace(/\[\d*\]/, function (v) {
            paramNum = v.slice(1, -1);
            return '';
        });

        var paramValue = typeof (a[1]) === 'undefined' ? true : a[1];
        paramName = paramName.toLowerCase();
        paramValue = paramValue.toLowerCase();
        if (obj[paramName]) {

            if (typeof obj[paramName] === 'string') {
            obj[paramName] = [obj[paramName]];
            }

            if (typeof paramNum === 'undefined') {
            obj[paramName].push(paramValue);
            }
            else {
            obj[paramName][paramNum] = paramValue;
            }
        } else {
            obj[paramName] = paramValue;
        }
    }
}
    return obj;
}}

O trecho de código a cima foi retirado do site. A baixo tem uma explicação de como eles recomendam a sua utilização.

getAllUrlParams().product; // 'shirt' 
getAllUrlParams().color; // 'blue' 
getAllUrlParams().newuser; // true 
getAllUrlParams().nonexistent; // undefined 
getAllUrlParams('http://test.com/?a=abc').a; // 'abc'

Quarto passo: Criação do arquivo main

Para que possamos exportar a nossa biblioteca para o NPM, nós precisamos criar o arquivo que nós definimos no passo dois desse artigo na tag main. Para isso, crie na raiz do seu projeto um arquivo chamado index.ts e dentro dele importe o sua biblioteca.

import { GetUrl } from "./geturl-params";

Quinto passo: Publicando no NPM

Para essa etapa, nós iremos precisar de uma conta no portal NPM, caso ainda não tenha basta clicar no link e criar uma. Com o seu usuário e senha do em mãos, digite no seu terminal npm login e insira as suas credenciais, em seguida execute o comando npm publish, para que possamos verificar se o o nosso pacote foi publicado com sucesso, basta acessar o portal NPM no seu perfil.

Para quem tiver interesse em como ficou a versão final do código demonstrado nesse artigo, segue seu link no GitHub.

Angular: Criação de Pipes

Introdução

Para quem ainda não conhece as pipes do Angular, elas são uma maneira elegante de realizarmos transformações no nosso front-end. Com ela nos podemos criar funções ou filtros (como ela é chamado no inglês), que podem ser utilizadas em qualquer parte do template do nosso projeto. Para que você possa ter um entendimento melhor, irei criar um exemplo de uma pipe que nos auxilie com o problema “unsafe” de URL’s externas.

Criação do projeto

Para esse artigo, eu não irei abordar os passos para criação de um projeto, irei partir de um já criado com Angular cli. Caso ainda não tenha o Angular Cli instalado e queira saber mais sobre esse passo, segue link de um artigo onde eu demonstro esse tema Angular Cli Scaffold. Para quem tiver interesse, eu irei disponibilizar o link do projeto que utilizaremos no final desse artigo.

Pipes

O Angular já nos prove algumas pipes para utilização como: date, uppercase, lowercase … etc mas na maioria das vezes nós precisamos de algo mais complexo. Para que possamos criar a nossa pipe, nos iremos utilizar o command line do Angular cli. Para isso, execute o comando abaixo no seu terminal/CMD.

ng generate pipe [name]

Nesse artigo eu dei o nome de Safe. Esse comando irá gerar um novo arquivo chamado safe.pipe.ts. Vamos atualizar ele com o seguinte código:

import { Pipe, PipeTransform } from '@angular/core';
/*Carregando o pacote DomSanitizer, ele auxilia com o Cross Site Scripting Security.*/
import { DomSanitizer } from "@angular/platform-browser";

@Pipe({
    name: 'safe'
})

export class SafePipe implements PipeTransform {
    /*Injetando o DomSanitizer no nosso componente.*/
    constructor(private _sanitizer: DomSanitizer) { }

    /*Criando um método que recebe uma URL, em seguida nós retornamos ele passando pelo método bypassSecurityTrustResourceUrl, dessa forma a nossa aplicação passa a acreditar (remover o erro unsafe) da nossa console.*/
    transform(url) {
        return this._sanitizer.bypassSecurityTrustResourceUrl(url);
    }
}

Caso você queria entender melhor a classe DomSanitizer, segue um link para sua documentação oficial DomSanitizer Docs.

Testando

Para que possamos testar a nossa Pipe, iremos utilizar o Iframe de vídeos do Youtube. Para isso, iremos atualizar o nosso AppComponent com os códigos abaixo:

app.component.html

<iframe width="500" height="400" [src]="video | safe"></iframe>

app.component.html

export class AppComponent {
    title = 'app';
    video: string = "https://www.youtube.com/embed/Ckom3gf57Yw"
}

Bom, com isso nos finalizamos esse post, caso tenha interesse na versão final do projeto, segue o seu link no GitHub.