Como funciona o Intl.NumberFormat?

Neste breve post veremos como funciona o Intl.NumberFormat em partes para entendê-lo melhor e podermos gerar várias strings com valores numéricos formatados corretamente.

Sintaxe

A sintaxe básica é bem simples, instanciamos um objeto que precisa de dois parametros, locales e options. Ambos são opcionais

new Intl.NumberFormat([locales[, options]])

locales: em 99% dos casos nós usaremos as strings com representação do local/país/região representada no nosso objeto. Você provavelmente usará os valores ‘pt-BR’, ‘en’ ou alguma variação parecida. Para um guia completo, confira aqui: https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry

const valor = 1999.99;
console.log(new Intl.NumberFormat('pt-BR').format(valor));
// saida: 1.999,99
console.log(new Intl.NumberFormat('ar-EG').format(valor));
// saida: ١٬٩٩٩٫٩٩

options: O segundo parâmentro é um pouco mais complicado pois as opções tem várias opções… kkkk… mas faz parte Vejamos um modelo e depois explicarei o que cada coisa faz

const valor = 1999.99;

const options = {
    style : "currency",
    currency : "BRL",
    minimumIntegerDigits : 10,
    minimumFractionDigits : 2,
    maximumFractionDigits: 5,
}

console.log(new Intl.NumberFormat('pt-BR', options).format(valor));
// saida: R$ 0.000.001.999,99

style:

Definição: O estilo do formato a ser utilizado.

Valor Padrão: “decimal”

Valores Permitidos: “decimal" para formato de número simples, "currency" para formato monetário e "percent" para formato percentual;

currency:

Definição: A moeda para usar na formatação monetária.

Valor Padrão: Não existe. Se o style for “currency”, então o esta propriedade precisa ser informada

Valores Permitidos: Os valores permitidos são os códigos de moedas da ISO 4217, como "USD" para dólar estadunidense, "EUR" para euro, ou "CNY" para RMB chinês — veja a Lista de códigos de moedas e fundos atuais.

minimumIntegerDigits

Definição: A quantidade mínima de dígitos inteiros para utilizar.

Valor Padrão: 1

Valores Permitidos: de 1 a 21

minimumFractionDigits

Definição: A quantidade mínima de dígitos fracionados para utilizar.

Valor Padrão: o padrão para formatos monetários é a menor unidade de dígitos fornecidos pela lista de códigos de moedas ISO 4217 (2 se a lista não fornecer a informação).

Valores Permitidos: de 0 a 20.

maximumFractionDigits

Definição: O número máximo de dígitos fracionados para utilizar

Valor Padrão: o padrão para a formatação de número simples é o maior entre minimumFractionDigits e 3.

Valores Permitidos: de 0 a 20.

CONCLUSÃO

Isso pessoal, esse foi um tutorial bem simples de como usar uma classe extremamente útil. Para mais detalhes, vejam também a documentação oficial https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat

Como usar o forEach no JavaScript

forEach

Neste breve artigo, estarei mostrando como usar o forEach no JavaScript usando todas as possibilidades de passagem de valores no exemplos. Estarei presumindo que você entende como funcionam Arrays e Arrow Functions.

Descrição e uso do forEach

O forEach é um método acessado dos objetos array (vetores) que itera entre todos os itens da lista executando uma função que informamos passada por parâmetro. Sendo assim, quando você possui uma coleção que precisa ser iterada ele é um ótimo candidato por ser sucinto e fácil de entender.

Quando não usar o forEach

Se você precisa parar a iteração, o forEach não é o melhor candidato. Ele não é um loop que podemo encerrar com ‘break’ e se na função de callback colocarmos um ‘return’, ele simplesmente seguirá para o próximo item. Neste tipo de situação, de preferencia para os loops tradicionais.

Array.forEach simples

a forma mais simples é chamando o método e passando uma função de callback que possui apenas um parâmetro

// Uma lista simples
const dados = [1,2,3,4,5,6,7,8];
// uma função de callback com apenas 1 item passado de parametro
const callback = item => console.log(item)
// a chamada
dados.forEach(callback);

Poderíamos colocar a função diretamente dentro da chamada

dados.forEach(item => console.log(item));

Ou chamar todo o primeiro exemplo em apenas 1 linha

[1,2,3,4,5,6,7,8].forEach(item => console.log(item));

Mas é importante tentar manter o seu código o mais fácil de entender possível.

Array.forEach com 2 parâmetros no callback

Digamos que você precise saber o índice do item por algum motivo, neste caso, precisamos informar mais um parâmetro em nossa callback. Vamos fazer um exemplo um pouco diferente

// Uma lista com strings para não confundir com o valor do indice
const dados2 = ['caixa', 'pallet', 'caixote', 'sacola', 'avulo'];
// A callback agora precisa de um segundo parametro 
const callback2 = (item, indice) => console.log(`${indice}: ${item}`)
// mesma chamada
dados2.forEach(callback2);

Ao executar o código você verá que teremos a posição dos items e seus valores. Para comparação, o For tradicional geraria este Loop da seguinte maneira:

for(let indice; indice < dados2.length; indice++) console.log(`${indice}: ${item}`)

Array.forEach com 2 parâmetros

Para este exemplo, manteremos o nosso segundo vetor

const dados2 = ['caixa', 'pallet', 'caixote', 'sacola', 'avulo'];

e vamos criar um objeto bem simples com apenas 1 função que executa um console log no valor passado por parametro, no mundo real seria somente uma função, mas para nosso exemplo ele ele vale.

let obj = { log : (umItem) =&gt; console.log(umItem)}

Agora, se você quisesse executar o obj.log para cada item do dados2, você poderia fazer algo assim:

dados2.forEach(item =&gt; obj.log(item));

e vai funcionar. Agora digamos que você tenha uma ambiente dinamico no qual você não sabe o qual objeto está executando o método log e dentro deste método poderiam acontecer coisas diferentes ou até que você está montando uma biblioteca que receberá o objeto e executará alguma coisa. Como você faria? Com o forEach, é possível fazer o seguinte

dados2.forEach(item =&gt; this.log(item), obj);

Deu erro? Isso é porque arrow function não podem receber escopo, se não entendeu, veja novamente o link Arrow Functions. Entendeu, então a parte abaixo é simples. A solução mais simples, use a função normal.

dados2.forEach(function(item){ this.log(item)}, obj);

Era isso, espero que tenham gostado, qualquer duvida deixem nos comentários.

Extreme Go Horse – Gambiarra é para os fracos

extreme-go-horse

Conheça a metodologia Extreme Go Horse (XGH) onde você não precisa perder tempo com padrões, pensamento, documentação ou qualquer bobagem que vai te fazer produzir código. Aqui você sempre programa 8 mil linhas de código por segundo e se você teve que parar para pensar em fazer uma gambiarra, você lento e não sabe o que ta fazendo… kkkkkk… Bom, chega de enrolar, veja a baixo como funciona

1- Pensou, não é XGH.

XGH não pensa, faz a primeira coisa que vem à mente. Não existe segunda opção, a única
opção é a mais rápida.

2- Existem 3 formas de se resolver um problema, a correta, a errada e a XGH, que é igual à errada, só que mais rápida.

XGH é mais rápido que qualquer metodologia de desenvolvimento de software que você
conhece (Vide Axioma 14).

3- Quanto mais XGH você faz, mais precisará fazer.

Para cada problema resolvido usando XGH, mais uns 7 são criados. Mas todos eles serão
resolvidos da forma XGH. XGH tende ao infinito.

4- XGH é totalmente reativo.

Os erros só existem quando aparecem.

5- XGH vale tudo, só não vale dar o toba.

Resolveu o problema? Compilou? Commit e era isso.

6- Commit sempre antes de update.

Se der merda, a sua parte estará sempre correta.. e seus colegas que se fodam.

7- XGH não tem prazo.

Os prazos passados pelo seu cliente são meros detalhes. Você SEMPRE conseguirá
implementar TUDO no tempo necessário (nem que isso implique em acessar o BD por um
script malaco).

8- Esteja preparado para pular fora quando o barco começar a afundar… ou coloque a culpa em alguém ou algo.

Pra quem usa XGH, um dia o barco afunda. Quanto mais o tempo passa, mais o sistema
vira um monstro. O dia que a casa cair, é melhor seu curriculum estar cadastrado na
APInfo, ou ter algo pra colocar a culpa.

9- Seja autêntico, XGH não respeita padrões.

Escreva o código como você bem entender, se resolver o problema, commit e era isso.

10- Não existe refactoring, apenas rework.

Se der merda, refaça um XGH rápido que solucione o problema. O dia que o rework
implicar em reescrever a aplicação toda, pule fora, o barco irá afundar (Vide Axioma 8).

11- XGH é totalmente anárquico.

A figura de um gerente de projeto é totalmente descartável. Não tem dono, cada um faz o
que quiser na hora que os problemas e requisitos vão surgindo (Vide Axioma 4).

12- Se iluda sempre com promessas de melhorias.

Colocar TODO no código como uma promessa de melhoria ajuda o desenvolvedor XGH a
não sentir remorso ou culpa pela cagada que fez. É claro que o refactoring nunca será
feito (Vide Axioma 10).

13- XGH é absoluto, não se prende à coisas relativas.

Prazo e custo são absolutos, qualidade é totalmente relativa. Jamais pense na qualidade e
sim no menor tempo que a solução será implementada, aliás… não pense, faça!

14- XGH é atemporal.

Scrum, XP… tudo isso é modinha. O XGH não se prende às modinhas do momento, isso é
coisa de viado. XGH sempre foi e sempre será usado por aqueles que desprezam a
qualidade.

15- XGH nem sempre é POG.

Muitas POG’s exigem um raciocínio muito elevado, XGH não raciocina (Vide Axioma 1).

16- Não tente remar contra a maré.

Caso seus colegas de trabalho usam XGH para programar e você é um coxinha que gosta
de fazer as coisas certinhas, esqueça! Pra cada Design Pattern que você usa corretamente,
seus colegas gerarão 10 vezes mais código podre usando XGH.

17- O XGH não é perigoso até surgir um pouco de ordem.

Este axioma é muito complexo, mas sugere que o projeto utilizando XGH está em meio ao
caos. Não tente por ordem no XGH (Vide Axioma 16), é inútil e você pode jogar um tempo
precioso no lixo. Isto fará com que o projeto afunde mais rápido ainda (Vide Axioma 8).
Não tente gerenciar o XGH, ele é auto suficiente (Vide Axioma 11), assim como o caos.

18- O XGH é seu brother, mas é vingativo.

Enquanto você quiser, o XGH sempre estará do seu lado. Mas cuidado, não o abandone. Se
começar um sistema utilizando XGH e abandoná-lo para utilizar uma metodologia da
moda, você estará fudido. O XGH não permite refactoring (vide axioma 10), e seu novo
sistema cheio de frescurites entrará em colapso. E nessa hora, somente o XGH poderá
salvá-lo.

19- Se tiver funcionando, não rela a mão.

Nunca altere, e muito menos questione um código funcionando. Isso é perda de tempo,
mesmo porque refactoring não existe (Vide Axioma 10). Tempo é a engrenagem que move
o XGH e qualidade é um detalhe desprezível.

20- Teste é para os fracos.

Se você meteu a mão num sistema XGH, é melhor saber o que está fazendo. E se você
sabe o que está fazendo, vai testar pra que? Testes são desperdício de tempo, se o código
compilar, é o suficiente.

21- Acostume-se ao sentimento de fracasso iminente.

O fracasso e o sucesso andam sempre de mãos dadas, e no XGH não é diferente. As
pessoas costumam achar que as chances do projeto fracassar utilizando XGH são sempre
maiores do que ele ser bem sucedido. Mas sucesso e fracasso são uma questão de ponto
de vista. O projeto foi por água abaixo mas você aprendeu algo? Então pra você foi um
sucesso!

22- O problema só é seu quando seu nome está no Doc da classe.

Nunca ponha a mão numa classe cujo autor não é você. Caso um membro da equipe
morra ou fique doente por muito tempo, o barco irá afundar! Nesse caso, utilize o Axioma
8.

Smart Mask – Máscara de Dados

Precisando de uma máscara de CPF, CNPJ ou entre outras?

Smart Mask (https://github.com/pkunzel/smart_mask) é uma biblioteca de máscara de dados bem simples com o intuito de fornecer múltiplas mascaras que com frequencia com frequência em um sistema ou app. O Projeto é constituído por duas classes, uma que aplica as máscaras e outra que monitora elementos HTML para manter a máscara aplicada. 

Como funcionam as classes? 

ApplyMask 

A Classe apply mask possui apenas métodos estáticos que estão prontos para serem chamados mediante passagem de parâmetros conforme exemplo abaixo 

ApplyMask.toCPF('88888888888') 
// output '888.888.888-88' 

ApplyMask.toPhone('51999999998') 
// output '(51) 999999998'

ApplyMask.charactersOnly('qwerty12345') 
// output 'qwerty' 

CustomMask

Gera eventos para os elementos com o atributos data-custom-mask=”mascara”, onde máscara é o nome do tipo de máscara a ser implementada. As opções são 

• cpf: um CPF 

• cnpj: um CNPJ 

• phone: um telefone com DDD incluso 

• cep: um CEP 

• date: uma data seguindo o formato DD/MM/YYYY 

• numbers: extrai apenas os valores numéricos 

• characters: extrai apenas os caracteres 

• non-special-characters: Extrai apenas os caracteres não especiais 

Exemplo 

HTML 

<input type="text" data-custom-mask="cpf" value="11122233344" /> 

JS 

// Ao iniciar a página 

window.addEventListener('load', (e) => new CustomMask()); 

// Obs.: Pode ser feito inicializado em qualquer outro momento. 

Importante: Qualquer valore que seja maior que o tamanho da máscara terá os últimos caracteres removidos. ou seja, um CPF que venha com 15 caracteres devido a algum erro terá os últimos 4 caracteres removidos.

O método Call

Neste artigo falaremos mais sobre o método call() que nos permite reaproveitar métodos em contextos (this) diferentes. No artigo tentarei explicar as coisas com a menor complexidade possível e resumirei alguns itens, então para aquele que sabem bem JavaScript por favor calma ai… rsrsrsr

Primeiro vamos entender mais sobre a chamada em si. É importante saber que ela:

  • É nativa, não precisa chamar biblioteca, framework, etc…
  • É um método das funções. Sim, se você ainda não sabia as funções são um tipo de dado que possui métodos/funções próprias;
    • Se ficou confuso, aguarde o exemplo.
  • Recebe um parâmetro que informa o seu contexto onde estarão os dados a executar;
    • Nesse caso contexto é uma função, objeto ou até o window se você estiver procurando pelo em ovo.
  • Pode receber mais parâmetros depois do this. Estes parâmetros se referem qualquer outro valor que você queira enviar para a função;

Note que eu estou usando as palavras função e método de forma alternada. Isso é porque eles são a mesma e tem mais diferença entre function e arrow function do que eles. 🙂

Exemplo básico

// Se chamar essa função do jeito que está aqui, vai exibir undefined pois this.umLocal não tem um valor atribuido a ele.
function ola(){
    console.log(`Olá ${this.umLocal}`);
}

// Agora vamos criar um objeto mais simples possível com a variavel umLocal
const teste = {
    umLocal : "MundoJS"
}

//Lembra quando eu disse que o call é um método das funções? Olhá só…
ola.call(teste);

Se você executar o código acima verá que ele exibirá Olá MundoJS no console. Vejamos o que aconteceu então:

  1. Criamos uma função chamada ola().
  2. Essa função exibe algo no console e chama o this.umLocal
  3. Sem fazer a chamada call() a função olha dentro de seu contexto (o this dela), não acha nada e exibe a mesma coisa
  4. Criamos um objeto com uma variável.
    1. Note que não precisamos dizer que é no contexto do objeto, mas está lá
  5. Invocamos o método call() da função ola passando o “teste” como novo contexto.
  6. Ao tentar executar a função, desta vez ela olha no teste e encontra a variável para usá-la no console.log()

Vejamos então mais alguns exemplos

1 – Passando os parâmetros da função:

// Desta vez ola recebe um parâmetro chamado saudacao
function ola(saudacao){
// aviso: se colocar this.saudacao ele não vai achar no call()…
// a explicação do porque sai bastante do artigo, mas se você entender bem de “this” e functions já deve ter se ligado. Caso queira saber mais, prende um comentário pedindo um tutorial sobre this
    console.log(`${saudacao} ${this.umLocal}`);
}

const teste = {
    umLocal : "Universo"
}
// O primeirpo parâmetro do call sempre é o “this”, depois disso você pode chamar todos os parâmetros da própria função.
ola.call(teste, "Olá");

2 – Usando métodos de Arrays em objetos que são listas mas não vetores.

Com o ES6 vieram diversos métodos muito uteis como o filter, forEach,reduce, etc… dai você tenta usar ele em uma lista que não é um vetor/array [] e não da certo pois eles não possuem isso.

// Erro pois é um HTMLCollection
document.getElementsByTagName("p").forEach(x => console.log(x));

// Vamos criar um objeto parecido com um vetor
let arrayLike = {
  0: "Olá",
  1: "MundoJS",
  length: 2
};

// e uma função para ser chamada no reduce()
function juntar(acc, cur){
    acc = `${acc} ${cur}`;
}

// Erro
// Motivo: O seu objeto parece um array (possui indices e length) mas não é um vetor e por isso não tem o método reduce nele
arrayLike.reduce(juntar);

// Agora se chamarmos o reduce e passarmos forçarmos ele a aceitar nosso objeto como o contextosArray.prototype.reduce.call(arrayLike, juntar);

Isso ai então pessoal, espero que o artigo ajude a matar algumas duvidas sobre o call e qualquer coisa perguntem aqui nos cometários. Até mais.

Utilizando API JavaScript no Oracle APEX

Este será um artigo curto em uma série de postagens mostrando como utilizar a API JavaScript disponibilizada para o Oracle Application Express (APEX).

É comum que sistemas precisem de mensagens de alerta e confirmação quando certas ações ocorrem. Podemos querer avisar o usuário que a assinatura dele está para expirar ou queremos garantir que ele não está apagando um registro sem querer.

Solução com JavaScript puro

A um tempo atrás, seria usado o alert e confirm:

alert(“teste”);

confirm(“Você tem certeza que deseja excluir este item?”);

Que fazem o papel desejado, no entanto são um tanto simples e não se adaptam ao layout da página. Mas se estes itens te atendem ao seu projeto, você pode parar de ler aqui e acessá-los diretamente por ações dinâmicas no sub-item notification conforme a imagem abaixo:

Solução com Region e Ação Dinâmica:

Além da opção com JavaScript puro, no Apex você pode:

  • Criar uma Region;
  • Dar a posição Inline Dialog a ela;
  • Definir seu template como Inline Dialog ou Inline Popup;
  • Criar ou adicionar a uma ação dinâmica do tipo Open Region.

Então isso vai permitir abrir uma tela em branco que você precisa tratar:

Para telas simples e repetitivas como um alert e um confirm é muito trabalho que acaba sendo multiplicado pelo tamanho do seu sistema e necessidade. Mas novamente, se você tem uma necessidade mais sofisticada, ai acima está a solução

Solução com a API JavaScript

Uma solução muito boa que é disponibilizada para podermos chamar uma tela de aviso é através da API JavaScript para o APEX. Neste caso, podemos nos valer de diversas chamadas com efeitos visuais diferentes que ajudam a dar uma cara melhor e a padronizar a sua aplicação.

apex.message.alert(mensagem, callback)

Através desta função podemos chamar em tempo de execução um alert pronto para exibir qualquer mensagem. Caso você queria executar alguma coisa após o alert ser fechado pelo usuário, basta passar um callback como segundo parâmetro. Senão nem precisa informá-lo.

apex.message.alert(“Olá Mundo”);

apex.message.confirm(mensagem, callback)

Similar ao alert, o confirm tem a mesma estrutura e parâmetros. Como ele espera que o usuário clique em OK ou Cancelar, é mais importante termos uma função de callback para verificar o que foi clicado.

apex.message.confirm("Você concorda?\n Clique em OK para continuar.", function( okPressed ) {
    console.log(`Pressionou no OK: ${okPressed}`);
});

apex.message.showPageSuccess( mensagem )

Caso você queira algo menos intrusivo e que seja apenas uma mensagem na tela para seus usuários, vale a pena testar a função showPageSucess que precisa apenas de uma string para saber qual texto exibir. O mesmo deverá aparecer no canto superior da tela (se você não alterou o CSS dele).

apex.message.showPageSuccess("Algo aconteceu com sucesso!!");

Encerrando

Então era isso ai. Essas são algumas das formas mais simples de mostrar informações dentro do apex. Elas não são as únicas e caso você tenha duvidas ou precisa de algo mais especifico, vale a pena conferir a documentação neste link:

https://docs.oracle.com/database/apex-5.1/AEAPI/apex-message-namespace.htm

Gostou deste artigo? Comente abaixo!

Como criar eventos ao pressionar CTRL, ALT e SHIFT

Neste post rápido será visto como criar eventos para capturar quando o usuário pressiona CTRL, ALT ou SHIFT na tela do navegador. Aproveitando que isso já está sendo visto, também vamos testar algumas combinações de teclas.

A primeira parte que você precisa fazer é o evento. Você precisa dizer onde que deverá estar o foco na hora que foi apertado o botão, no nosso exemplo usaremos o document pois mais amplo que isso não tem como. Você pode usar o body ou até uma “zona” menor caso prefira.

 

JavaScript

document.addEventListener("keydown", function(event){});

 

JQuery

$(document).bind('keydown', function(event){ });

Note que estamos usando o evento “keydown”, isso é importante pois keypress e keyup não captura as teclas que queremos.


 

Agora vejamos sobre como saber o que foi clicado, você já deve ter tentado o key, keycode e which, mas nada aconteceu. Isso acontece pois precisamos acessar outras propriedades para saber se o CTRL, ALT ou SHIFT foram pressionados. Veja abaixo:

event.ctrlKey // CTRL

event.altKey // ALT

event.shiftKey // SHIFT

Simples assim? Sim, simples assim….

Então se quisermos saber quem foi pressionado, podemos fazer o seguinte:

 

JavaScript

document.addEventListener("keydown", function(event){

    if(event.ctrlKey) {
        console.log('ctrl');
    }

    if(event.altKey) {
        console.log('alt');
    }

    if(event.shiftKey) {
        console.log('shift');
    }
});

 

Para JQuery basta alterar a primeira linha por 

$(document).bind('keydown', function(event){

 

Por último, você pode estar querendo uma combinação, como por exemplo um CTRL + A. Agora que sabemos como pegar o CTRL, ficou fácil

document.addEventListener("keydown", function(event){

    if(event.ctrlKey && event.key == "a") {
        console.log('ctrl + a');
    }

});

 

É isso ai, espero que com esse post eu tenha ajudado outros que tiveram o mesmo problema para descobrir como criar estes eventos que combinam pressionar várias teclas. Até a próxima

Como quebrar um vetor grande em vários menores

Neste artigo veremos duas funções que leem um vetor e devolvem um outro dividido em pedaços menores. O exemplo será bem simples pois a aplicação é a mesma para 5 o para 5 bilhões de registros. 

A primeira função será genérica e você provavelmente poderá utilizá-la em outras linguagens com pouca ou nenhuma adaptação. Já a segunda é utilizando mais das funções do JavaScript para reduzir o código

Em resumo queremos que um vetor linear seja quebrado em vários pequenos vetores. No meu caso, eu precisava que uma lista de contatos fosse quebrada em diversas listas menores para facilitar o controle e atualização das mesmas.

Iremos de algo assim:

let vetor = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];

Para algo assim:

let vetor = [[0, 1, 2], 
             [3, 4, 5], 
             [6, 7, 8], 
             [9, 10, 11], 
             [12, 13, 14], 
             [15, 16]];

Como podemos fazer isso? Bom, a primeira forma é a seguinte:

Algoritmo Genérico

  1. Criar a função e inicializar as variáveis. Observe que novoVetor é um vetor com um vetor vazio dentro dele.
    function converterVetor(vetor, tamanho) {
        let novoVetor = [[]];
        let novoIndice = 0;
        let novoIndiceSub = 0;
    }
  2. Criar um laço FOR para adicionar os elementos no novoVetor. Observe que:
    1. Precisamos de um IF para testar a hora de avançar de um sub-vetor para outro.
    2. Dentro deste IF é necessário criar um vetor em branco para que o Javascript saiba o tipo do dado.
    3. No final, você está adicionando o valor dentro de um vetor que está dentro de outro vetor, então é preciso usar [x][y] para adicionar na posição correta.
    for(let indice = 0; indice < vetor.length; indice++){
    
        if(indice % tamanho == 0 && indice != 0){
            novoIndice++;
            novoVetor[novoIndice] = [];
            novoIndiceSub = 0;
        }
    
        novoVetor[novoIndice][novoIndiceSub] = vetor[indice];
        novoIndiceSub++;
    }
  3. Por ultimo, basta retornar o resultado. Veja abaixo o código completo.
    function converterVetor(vetor, tamanho) {
        let novoVetor = [[]];
        let novoIndice = 0;
        let novoIndiceSub = 0;
    
    
        for (let indice = 0; indice < vetor.length; indice++) {
    
            if (indice % tamanho == 0 && indice != 0) {
                novoIndice++;
                novoVetor[novoIndice] = [];
                novoIndiceSub = 0;
            }
    
            novoVetor[novoIndice][novoIndiceSub] = vetor[indice];
            novoIndiceSub++;
        }
    
        return novoVetor;
    }

Usando mais recursos JavaScript

Agora vejamos a mesma função, mas usando mais recursos JavaScript para reduzir um pouco o trabalho.

  1. Iniciaremos de forma muito parecida, mas precisaremos de uma variável a menos
    function converterVetor2(vetor, tamanho) {
        let index = 0;
        let novoVetor = [];
    }
  2. Agora faremos o loop for, mas ao invés de percorremos o loop original de 1 em 1, percorreremos o tamanho que já queremos colocar no sub-vetor.
    1. Dentro do loop, usaremos a função slice() que nos retornará um pedaço do vetor. Sendo ele o tamanho exato do sub-vetor.
    2. Após, adicionamos o subVetor ao novo com o método push() que adiciona um elemento na ultima posição.
    for (index = 0; index < vetor.length; index += tamanho) {
        let subVetor = vetor.slice(index, index + tamanho);
        novoVetor.push(subVetor);
    }
  3. Pronto!! Basta retornar o objeto com o resultado. Segue abaixo o código completo.
    function converterVetor2(vetor, tamanho) {
        let index = 0;
        let novoVetor = [];
    
        for (index = 0; index < vetor.length; index += tamanho) {
            let subVetor = vetor.slice(index, index + tamanho);
            novoVetor.push(subVetor);
        }
    
        return novoVetor;
    }

Conclusão

Como você pode ver, o segundo formato é um pouco menos detalhado, mas utilizando os recursos do JavaScript é possível escrever menos código que ainda é fácil de entender. Por isso que, quando você estuda uma linguagem, é importante conhecer as funções nativas e formas mais inteligentes de trabalhar com seus objetos.

Mapa de Calor com AmCharts

Neste tutorial simples e rápido estarei mostrando como criar um gráfico de mapa de calor (heat map) com a biblioteca AmCharts.

Então vamos começar. Primeiro você precisará criar um arquivo HTML com as seguintes tags.

<html>
<head>
  <!-- Setar para utf-8 para evitar problemas nos caracteres especiais -->
  <meta charset="utf-8"/>
</head>
<body>

  <!-- Buscando bibliotecas direto do site da AmCharts -->
  <script src="https://www.amcharts.com/lib/4/core.js"></script>
  <script src="https://www.amcharts.com/lib/4/maps.js"></script>
  <script src="https://www.amcharts.com/lib/4/geodata/brazilLow.js"></script>

  <!-- Onde nosso gráfico será criado -->
  <div id="chartdiv"></div>
</body>
</html>

A explicação já esta inclusa nos comentários, mas resumidamente precisamos do utf-8 para não dar problema com estados que possuem acento no nome. As bibliotecas são chamadas do site para não precisar baixar nada.

Agora você pode criar uma tag script no final do HTML e colocar o código inline ou apontar para um arquivo JS externo. A escolha é sua.

Feito isso, precisaremos de uma fonte de dados. Para o nosso exemplo e de referência futura, você pode usar a lista abaixo. E ja peço desculpas pelo tamanho da lista, mas não quis minificar para ser fácil de entender.

let dados = [
  {
    "id" : "BR-AC",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-AL",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-AP",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-AM",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-BA",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-CE",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-DF",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-ES",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-GO",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-MA",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-MT",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-MS",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-MG",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-PA",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-PB",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-PR",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-PE",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-PI",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-RJ",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-RN",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-RS",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-RO",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-RR",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-SC",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-SP",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-SE",
    "value" : Math.floor(Math.random()*10000)
  },
  {
    "id" : "BR-TO",
    "value" : Math.floor(Math.random()*10000)
  }
];

Como você pode ver, a lista precisa de um ID com a abreviação BR-UF. Porque não apenas o UF? Porque deus quis assim…. kkkk… Eles provavelmente fazem uma separação de paises pois esta biblioteca permite criar mapas de qualquer pais do mundo. A segunda parte pode ser um número qualquer fixo, mas para nosso exemplo eu quis fazer com que fossem valores aleatórios até 10000.

Feito isso, adicione o código abaixo. É importante ler os cometários para entender o que e por que está acontecendo.

// Define o local e tipo de gráfico
let chart = am4core.create("chartdiv", am4maps.MapChart);


// Atribui o 'brazilLow' como o mapa
// Você pode optar pelo 'brazilHigh', basta alterar aqui e src do script no html
// Também define que as partes que montam o mapa serão com base no MapPolygonSeries
chart.geodata = am4geodata_brazilLow;
let polygonSeries = chart.series.push(new am4maps.MapPolygonSeries());
polygonSeries.data = dados;
polygonSeries.useGeodata = true;


// Preenche os dados para fazer o mapa de calor
// Faremos com que os menores valores sejam verdes e maiores sejam vermelhos
polygonSeries.heatRules.push({
  property: "fill",
  target: polygonSeries.mapPolygons.template,
  min: am4core.color("green"),
  max: am4core.color("red")
});


// Define as legendas, posição e cores.
let heatLegend = chart.createChild(am4maps.HeatLegend);
heatLegend.series = polygonSeries;
heatLegend.align = "right";
heatLegend.width = am4core.percent(25);
heatLegend.marginRight = am4core.percent(4);
heatLegend.minValue = 0;
heatLegend.maxValue = 10000;
heatLegend.valign = "bottom";


// Configuras os tooltips (texto ao passar o mouse)
let polygonTemplate = polygonSeries.mapPolygons.template;
polygonTemplate.tooltipText = "{name}: {value}";
polygonTemplate.nonScalingStroke = true;
polygonTemplate.strokeWidth = 0.5;


// Muda a cor do estado ao passar o mouse
let hs = polygonTemplate.states.create("hover");
hs.properties.fill = am4core.color("green").brighten(-0.5);

Isso ai, com isso você terá um mapa mais ou menos (pois muda a cada atualização) assim:

Dicas para iniciar como Desenvolvedor

Neste artigo vou listar coisas que, na minha experiência, foram importantes para iniciar no mundo do desenvolvimento de sistemas. O que estou falando não é uma regra universal, mas apenas dicas de coisas que me aprendi nos últimos 10 anos atuando na área. 

Você vai notar que eu não vou falar muito de tecnologia, pois isso seria ensinar o padre a rezar a missa. E sei lá, enquanto você estiver lendo isso pode ser que elas mudem, então acredito que vale a pena ser mais genérico nesta parte. Muito bem, vamos lá

 

1) Gostar de programar

Esse parece ser meio óbvio, mas tem gente que quer o salário de tal desenvolvedor, quer ser o próximo Steve Jobs ou quer ser um nerd cientista. Nenhuma das razões acima é gostar de programar. Se você estiver na dúvida se gosta ou não, pense no seguinte:

  • Você monta apps por conta própria (sem alguém mandar ou pagar)?
  • Você fica feliz quando aprende ou entende um código?
  • Você perde a noção do tempo programando?
  • Você vai atrás do conhecimento porque gosta?

 

Se pelo menos um dos acima for sim é porque você provavelmente gosta de programar. Agora, se:

  • Você só programa se for obrigado ou pago.
  • Você não tem vontade de terminar qualquer projeto.
  • Rodou em algoritmos, estrutura de dados, lógica de programação por falta de interesse.
  • No tempo livre, entre programar e fazer qualquer outra coisa, você faz outra coisa.

Cara, ta na hora de pensar bem se é isso que você quer para o resto da sua vida.

2) Iniciativa

Se você se encaixou nos itens positivos acima, isso aqui pode ser repetição do que falei no item 1. Não espere os outros pedirem projetos nas áreas que você gosta, comece a fazê-los, mesmo que simples. Ninguém começa com o melhor e mais avançado projeto que fará em sua vida.

  • Quer ser um desenvolvedor front end? Faça projetos de sites e mini apps mobile.
  • Quer ser um desenvolvedor back end? Cruds, um site com login que não faz mais nada.
  • Quer ser um desenvolvedor de banco? Você é louco, mas todo mundo é um pouco. Crie bancos e monte as triggers, constraints, etc… para testar seus conhecimentos.

O que quero dizer aqui, não espere alguém sentar com você e pedir para que você faça o básico. Estude, teste, quebre, xingue que amanhã o problema parecerá tão simples.

 

3) Escolhendo a empresa 

Este item é tão importante (ou mais) que conseguir a vaga. Você já deve ter visto, ou verá, que existem empresas com vagas de estágio pedindo experiência ou conhecimentos de alguma coisa. Neste caso, existem 2 situações:

  1. O conhecimento é aquele que se aprende em 1 mês de curso online, na faculdade ou até com vídeo aulas do youtube. Essas empresas querem alguém que goste de programar e que vá atrás da informação. Se você atende ao “Gostar de programar” não deveria ser problema e sim um filtro para reduzir a sua concorrência.
  2. A empresa quer um desenvolvedor pelo salário de estagiário, pois não tem dinheiro para pagar um dev ou não quer pagar o valor correto. Essa pessoa normalmente já terá que produzir muito. Cara “ALERTA VERMELHO”
    1. Eles não valorizam o seu trabalho.
    2. Se tem dinheiro para pagar mais, não vão. Por isso a vaga de estagiário. Se não tem, como que vão te promover um dia? Pagando do bolso?

 

4) Entrevista

Nem tenha vergonha por estar começando, se esse não der certo, o outro vai. Mostre muito dos itens 1 e 2 que isso certamente fará diferença entre você e o carinha que quer receber para aprender o crud básico com alguém sentado do lado explicando.

Novamente, não estou dizendo que você não deve aprender no ambiente de trabalho e que o trabalho não deve ensinar você. Mas, se você chegar dizendo:

  •  “isso eu sei pois fiz um projeto e subi para o git, como que eu faço a próxima parte?”

é bem melhor que:

  •  “Certo, abrir a IDE, como que eu abro um projeto?”.

Você consegue ver a diferença?

 

Terminando

Então era isso, espero que alguém se beneficie lendo este post. Seja para entrar no ramo ou descobrir que outros são mais interessantes. Boa sorte.