Javascript

O que todo desenvolvedor Javascript precisa saber

js

O título é quase um spoiler, mas saber de tudo é um tanto quanto convexo, já que o Javascript, embora padronizado no ECMAScrpit, ele segue vários caminhos e vários players, se fosse colocar em comparação à algo que você conheça não existe nada melhor que dizer: “É caneta para todo papel”.

Brincadeiras à parte, Javascript muda da água para o vinho dependendo onde ele é executado, no Chrome é de uma forma, no Firefox é de outra, No IE ele é uma hidra, no servidor ele é um bom moço, fora novas implementações como o DART, Coffescript e por ai vai.

De Janeiro para cá o que deu para lembrar eu fui juntando e guardando em minha lista de snipets, e resolvi publicar aqui para vocês guardarem e sempre consultarem quando for possível.

Me baseei em algumas coisas interessantes que eu achei sobre a linguagem, a melhor forma de aprender é tentar criar seu próprio framework.

Tipos

O Javascript é um PHP da vida, começa como String e terminar como Boolean, ele possui 9 tipos de variáveis possíveis de serem adotadas.

null – Nulo ou vazio. Semelhante ao Actionscript 3.0

undefined – Indefinido no Actionscript 3.0 seria NaN

string – String é isso em todo lugar, diferente do Java, aqui tanto faz você declarar com aspas simples ou dupla.

number – Igual no Actionscript, tudo aqui é tratado como Float e a grande vantagem é que a biblioteca Math do JS é semelhante ao AS3.0

boolean – Semelhante em qualquer linguagem de programação ( True ou False)

Array – Pode ser declarado como new Array() ou simplesmente [], semelhante ao AS3.0. Tem suporte à Multi-dimencional e várias APIs que implementam o Array Tipado. Ainda estão tentando implementar e definir isso de uma vez por todas.

Object– Igual no AS3.0,C#, Java, pode ser declarado como new Object(); ou pode ser criado de forma literal

     // new
     obj = new Object();
     // ou semelhante
     obj.title="Hello World";
     obj = {title:"Hello"};

E na hora que for verificar o tipo, por exemplo você recebe uma mensagem do servidor 1 // Numero e quer saber se é Boolean, geralmente você faria.

 
var resposta = true;
    resposta == typeof Boolean;
    // false
 
var itens = [1,2];
itens == typeof Array;
// false

O certo mesmo seria você usar o construtor

 
  resposta.constructor == Boolean;
// true

É bizarro isso, o que seria para ajudar, acaba é estragando tudo, mais bizarro é quando você pede por exemplo para definir o tipo.

 
typeof [1,2]; // Object ao invés de Array;
typeof typeof; // Saiba como destruir o firefox de alguém com isso, o Chrome dá erro de sintaxe
typeof null; // Object Essa ai é de matar

Function – Igual em toda linguagem de programação, função é função no mundo de pandora ou nas terras do senhor dos anéis, no JS ela pode ser sua maior amiga e pior amiga, é ai onde entra o problema e faz muita gente odiar o Javascript, a Mayara amiga minha detesta o JS justamente por desconhecer essas particularidades dele, espero que ela esteja lendo esse post.

Por que Functions é tudo isso?

Por que por padrão retornará sempre undefined se você não especificar o retorno, e a palavra [highlight bg=”#ff999d” color=”#ffffff”]this[/highlight] que você tanto se refere ao escopo da função pode ser considerada tanto Global (window) ou local do objeto que ela foi chamada e nunca pertencente ao escopo da função em sí.

Ex: O paraíso

 
function imprima (){
return "Hello World";
}
imprima();
 
// lazy 
var echo = function(){ return echo};
echo() === echo // retorna true;
 
// Como objeto
var somar = new Function("a","b","return a + b");
somar(15,15); // 30
 
// Pegar argumentos da forma tradicional
 
var multiplica = function(){return arguments[0]*arguments[1]};
multiplica(5,5);
// 25

Continuando com Functions, ela possui dois métodos um tanto intrigantes que tem o mesmo funcionamento, [highlight bg=”#ff999d” color=”#ffffff”]call()[/highlight] e [highlight bg=”#ff999d” color=”#ffffff”]apply()[/highlight]

var operacao = function(){ switch(arguments[0]){ case 'somar': return arguments[1]+arguments[2];break}};
 
operacao.call(this,'somar',1,3);
// 4
operacao.apply(this,['somar',1,3]);
// 4

A única diferença é que um você precisa colocar em array no caso do Apply e o outro é literal, é meio louco isso, embora você não viu nem a metade.

Passagem de parametros com valor padrão definido

Imagine você congelado no tempo sem saber por que raios ele não funciona com parametros pre-definidos.

 
var nasceu = function (resposta){ return resposta !== undefined ? resposta + ', finalmente decidiu' : "Decide ai"};
nasceu(); // "Decide ai"
nasceu('SIM'); // SIM, finalmente decidiu;
 
<pre>
 
<h3>Operadores</h3>
 
Ah, É cilada bino! Nesse ponto, aquele primeiro argumento de comparação faz você xingar a mãe <a href="http://en.wikipedia.org/wiki/Brendan_Eich" target="_blank">do cara</a> que fez o Javascript, por quê?
 
<pre lang="javascript">
true == 1// true
true == '1'//true
'1' == 1 // true
undefined == null // true
false == 0 // true
false == '' // true
'' == 0 // true

Especialmente quando você usa esse tipo de comparação em uma resposta de uma chamada Ajax, Deus! Como eu já perdi tempo fazendo isso. Embora a W3C insiste em ensinar errado, eu prefiro que você use as opções:

true === 1 // false
true === 0 // false
 
// usem o equivalente !== para não igual e %== para módulo

Verificando a qualidade do seu Javascript

Só existe um de respeito, e esse é o JSLint, não adianta você querer me convencer que existam outros para medir sua qualidade de código, o JSLint é fenômeno e faz o que promete de uma maneira direta e simples, te ajuda a corrigir erros bizarros que você não nota no dia-a-dia.

Testando o código de forma unitária

Nesse quesito, Jasmine é a resposta, se você espera que seu código retorne 5 e ele retorna 10, então ele vai te mostrar um erro, e a essência do Jasmine é bem simples para implementar.

Cada um em seu quadrado

O Javascript sofre a cada mudança do ECMAScript e atualmente na versão 1.8.6 faz com que a linguagem ganhe inimigos, por achar que é complexo, o fato é que a cada nova release essa quebra de padrão de uma versão anterior ou nova maneira de fazer alguma coisa que era mais simples na anterior, tira o sono de muita gente. Só que eu acho o seguinte, toda linguagem precisa de evolução, vai dizer que tu sabia o que era Tchu Tcha em 1999?

Essa fragmentação da linguagem é de lascar, da 1.5 até a 1.8.x fez muita gente adotar o JQuery como ponto de partida ou o Javascript.NET, justamente para não ter que lhe dar com tanta diferença de um navegador para outro, e essa é uma briga que nunca acabará, por que todos querem uma fatia dos usuários conectados, Browsers ainda são a janela da Internet.

Conheça os recursos

Fonte de material MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript)
Fonte de material de primeira (http://stackoverflow.com/questions/tagged/javascript)
Refresh no Javascript (http://typedarray.org/javascript-refresh/)
Melhor overview já feito, na minha opinião (http://en.wikipedia.org/wiki/JavaScript)

Javascript

Classes e heranças com Javascript sem usar framework

js

Usar coisas prontas adianta a vida, não investigar suas entranhas é um erro fácil de cometer. Eu tenho andado bem ocupado com EmberJS, AngularJS, BackboneJS e KnockoutJS.

E sabe o que eu descobri? Todos compartilham o mesmo comportamento de MVC, dessa semelhança o que eu mais gostei foi que ambos implementam um certo tipo de extensão de classes, é como se você registrasse ela no root do documento DOM (window).

O que garante o trunfo de um para outro são técnicas especificas como templates, data-biding, componentes UI; Ao mesmo tempo que aprendo com cada um deles de dentro para fora, eu vou escrevendo o meu, a vida fica bem mais fácil melhorar o que já foi criado, lá na frente quem sabe alguém não chegue a usar o meu!?

Certo, como é então que se usa classes e heranças no Js sem framework? Simples, implemente um você mesmo com poucos passos. Me lembra muito da época que o Actionscript 1.0 ainda estava sendo especificado, JS dos dias de hoje é o actionscript de 10 anos atrás. No dia que essa linguagem ganhar tipação das coisas, provavelmente as coisas virarão coisas, sacou?!

Boilerplate necessário

 
;(function(){
 
	var Classe = window.Classe = {};
 
	var fator = function () {};
 
 
    var inherits = function (parent, protoProps, staticProps) {
        var child;
        if (protoProps && protoProps.hasOwnProperty('constructor')) {
            child = protoProps.constructor;
        } else {
            child = function () { return parent.apply(this, arguments); };
        }
        // vindo do underscoreJS
        _.extend(child, parent);
 
        //Prototype é quem vai fazer valer a pena
        fator.prototype = parent.prototype;
        child.prototype = new fator();
 
        if (protoProps) _.extend(child.prototype, protoProps);
        if (staticProps) _.extend(child, staticProps);
 
        child.prototype.constructor = child;
        child.__super__ = parent.prototype;
 
        return child;
    };
    function ExtendsEls(protoProps, staticProps) {
        var child = inherits(this, protoProps, staticProps);
        child.extend = ExtendsEls;
        return child;
    }
    Classe.Base = function () {};
    Classe.Base.extends = ExtendsEls;
})();

Digamos que eu até poderia mudar no final e chamar direto ().call(this,name). Só que ai eu quebro a idéia de fazer simples sem precisar chamar o construtor e fazer a evaluação da classe em tempo de execução.

Ao invés disso você pode criar o construtor e inicar o que precisa dentro dele.

No final das contas eu criei outro arquivo MeuApp.js e escrevi o seguinte código.

// Classe extendida da classe pai Classe
var Carro = Classe.Base.extends({
	aceleracao : 0,
	buzinar: function (){
		console.log('bit bit, sai do meio!');
	}
});
 
// Carro de corrida extende Carro
 
var CarroCorrida = Carro.extends({
	constructor : function (name){
		CarroCorrida.__super__.constructor.call(this,name);
	},
	acelerar: function (){
		var acc = this.aceleracao > 300 ? this.aceleracao=Math.round(300 - Math.random()*300) : this.aceleracao+=10;
		$('body').html('<p>'+ acc +' km/h</p>');
		console.log(this.aceleracao + ' km/h');
	}
 
});
 
 
// Ferrari é um objeto 
var ferrari = new CarroCorrida();
ferrari.buzinar();
 
// Testar a aceleracao
window.setInterval(function(){ferrari.acelerar()},100);

Fácil, não? Ai agora é só implementar Views e Controllers, só depende do que você quiser fazer. A boa notícia é que mesmo sem tipação você pode simular tal opção sem se preocupar com decadência do objeto.

Ah! o código está no Github também.

AngularJS/ HTML5 / CSS3/ Javascript/ JQuery

Criando um scroll Infinito com o AngularJS e JQuery

scrollinfinito-jquery

Esse post é o início de uma série de posts relacionados ao AngularJS, se você não conhece, é bom conhecer, muito de seu comportamento é semelhante ao que tinhamos no Flex, por exemplo Databind e a idéia de componentizar. E o mais legal de tudo é que ele é compatível com qualquer biblioteca que manipule o DOM, por exemplo Zepto e JQuery, ou até mesmo o Twitter Bootstrap.

O AngularJS facilita e muito certas tarefas e mantem o DRY bem vivo. Por exemplo, esse post eu quero falar sobre o scroll infinito, igual o comportamento que o Twitter possui ou o LinkedIn possui quando você vai rolando a página e dados vão pipocando em sua frente. Pois bem, como eu faria isso em puro Javascript e usando o seletor do DOM jQuery?

O scroll é um mal necessário, é o que a Microsoft tenta adotar na nova interface do Windows 8 e o que o Flex tentou quando lançou a versão 4.0. Porém é necessário trazer informações à medida que elas vão acontecendo ou carregar só o necessário e à medida que o usuário for investigando elas forem brotando.

scrollinfinito-jquery

Scroll Infinito com Javascript e JQuery.

O HTML é bem simples:

	<div id="conteudo">
    <ul id="lista"></ul>
</div
var contador = 1;
 
$(document).ready(function () {
    carregar();
    $(this).on('scroll', function () {
        if ($(window).scrollTop() + $(window).height() >= $(this).height()) {
            carregar();
        }
    });
});
 
function carregar() {
    for (var i = 0; i < 10; i++) {
        $("#lista").append('<li><img src="http://placehold.it/100x100"/><div><h4>' + contador + ' Item</h4><p>Descrição do item '+contador+'</p></div></li>');
        contador++;
    }
}

A medida que a soma da posição da barra mais a altura da janela superar o tamanho da altura do documento, ele executa a função carregar, jogando mais itens na lista.

O truque também está na maneira como você declara o CSS, margin faz um estrago danado quando não aplicada de forma correta, nesse exemplo eu coloquei uma aparência de uma lista de smartphone, igual no Android.

body, ul,li,img,h4,p{
    margin:auto;
    font-family:'Droid Sans';
}
ul {
	margin-left: -40px;
	list-style:none;
}
li {
    color:#111;
    height: 100px;
    border-bottom:1px solid #fff;
    padding:10px;
}
li h4 {
    font-weight:400;
    font-size:20px;
    padding:0;
}
li img {
    padding-right:10px;
    float:left;
    display:block;
    vertical-align:text-top;
}
li div {
    display:inline;
}
li p {
    font-weight:300;
    font-size:12px;
}
#conteudo {
    width:100%;
    background:rgba(0,0,0,0.1);
    overflow:auto;
}

E aqui está o exemplo rodando, eu usei o jsFiddle para demonstrar melhor.

Você pode ver sendo executado diretamente no jsFiddle

Criando agora uma lista infinita com o AngularJS

O AngularJS possui vários truques na manga para deixar sua vida mais fácil, módulos, tags personalizados, data-bind, repetidores, diretivas, controllers, esses são alguns de seus recursos. A melhor parte dele como mencionei acima é que é compatível com outras bibliotecas.

Para fazer esse exemplo você vai fazer uma pequena alteração no html e substituir o Javascript, os estilos que é o visual continuam o mesmo.

Logo de cara para identificar como um App, você precisa alterar o html e fazer da seguinte forma:

<!doctype html>
<html ng-app="Rolagem">
<head>

Isso define que o módulo Rolagem será seu App nesse arquivo de html, então na parte de repetir os itens você faz da seguinte forma.

<body ng-controller="Main">
	<div id="conteudo" fazer-rolagem="carregar()">
    <ul id="lista">
         <li ng-repeat="i in items">
            <img src="http://placehold.it/100x100"/>
            <div><h4>{{i.id}} Item</h4>
            </div>
        </li>
    </ul>
</div
</body>

Como o AngularJS abstrai bastante o escopo do javascript para com o HTML, é notável algumas propriedades como o ng-controller, fazer-rolagem que são primariamente customizáveis, a presença do ng-repeat indica que o arquivo vai ser repetido N vezes, conforme vamos adicionando novos itens à lista.

E a parte fundamental desse processo é o Javascript:

function Main($scope) {
    $scope.items = [];
 
    var counter = 1;
    $scope.carregar = function() {
        for (var i = 0; i < 10; i++) {
            $scope.items.push({id: counter});
            counter += 1;
        }
    };
 
    $scope.carregar();
}
 
angular.module('Rolagem', []).directive('fazerRolagem', function() {
         return function(scope, elm, attr) {
        elm = $(document);
 
        elm.bind('scroll', function() {
             if ($(window).scrollTop() + $(window).height() >= $(this).height()) {
                 scope.$apply(attr.fazerRolagem);
             }
        });
    };
});

Agora você já sabe como criar uma diretiva, fazer um módulo e carregar os itens conforme forem feitos os scrolls, no JQuery quando você quer escutar um evento você geralmente usa o $on(), no AngularJS é necessário usar o bind, ele que vai escutar pelo evento.

Maneiras diferentes de aplicar a mesma técnica, para um resultado igual, Eu gostei mais do AngularJS, escrevi menos código e atingir o mesmo resultado.

Ah! lembrando que esses códigos estão disponíveis no Github.