Archive for the ‘JavaScript’ Category
Quando uma deficiência pode se tornar uma feature numa linguagem de programação
Estava lendo um antigo post do Obie Fernandez onde ele lista várias razões do porquê Java é uma porcaria (em tom de brincadeira, claro =). Numa das razões citadas por ele, há o seguinte trecho:
8 ) Java has good debugging support
Java has great and powerful debugging (which is very necessary since most Java code sucks so much ass). Ruby has ridiculously pitiful debugging support, which means our code actually needs to be well-tested and readable.
Traduzindo:
8 ) Java possui um bom suporte a debugging
Java possui um excelente e poderoso debugging (o que é necessário, já que boa parte de códigos em Java são muito ruins). Ruby tem um suporte a debugging lamentavelmente ridículo, o que significa que nosso código realmente precisa ser bem testado e legível.
Vendo por este lado, Ruby é uma excelente linguagem para quem sabe fazer direito e uma droga pra quem está acostumado com IDEs com Intellisense e checagem de erros pelo compilador.
Outras linguagens possuem problemas que são resolvidos facilmente com o uso de testes unitários. Um problema clássico que acontece com o PHP, o White Screen of Death (um erro que acontece com o script que nenhuma informação ou mensagem de erro é apresentada), pode ser resolvido com o uso de testes.
Alguns “problemas” advindos com linguagens dinâmicas é com a mudança de tipo de uma determinada variável, por exemplo:
x = 1
y = 3
def soma(self):
return self.x + self.y
op = Op()
op.y = "aha!"
op.soma() #Ooopss... TypeError
Este é um tipo de problema que vem com a checagem de tipo em tempo de execução, ao invés de ser feito em tempo de compilação. Muitas pessoas que não possuem a mesma visão do Obie, encaram isto como um problema.
Opinionated Software
Um trecho muito conhecido do Getting Real é o trecho que fala sobre opinionated software:
Your app should take sides
Some people argue software should be agnostic. They say it’s arrogant for developers to limit features or ignore feature requests. They say software should always be as flexible as possible.
We think that’s bullshit. The best software has a vision. The best software takes sides. When someone uses software, they’re not just looking for features, they’re looking for an approach. They’re looking for a vision. Decide what your vision is and run with it.
Traduzindo:
Seu aplicativo deve tomar partido
Algumas pessoas defendem que o software deve ser agnóstico. Dizem que é arrogante da parte dos desenvolvedores limitar a funcionalidade ou ignorar pedidos de novos recursos. Dizem que o software deve ser sempre o mais flexível possível.
Para nós isso é papo-furado. O melhor software traz consigo uma visão. O melhor software toma partido. Quando alguém usa um software, não está procurando apenas recursos, está procurando uma abordagem. Está procurando uma visão. Decida qual é sua visão e atenha-se a ela.
Esta mesma idéia permeia linguagens de programação. Você não achará um linguagem que sirva bem para todos os tipos de casos. Python, por exemplo, não é uma boa linguagem se você quiser usar threads pesadamente. Erlang, apesar de ser uma excelente escolha para programação distribuída e paralela, enfrenta um certo preconceito por ser funcional e não ter suporte à orientação a objetos. C#.NET é uma boa linguagem para criação de aplicativos comerciais, mas não é totalmente portável para todas as plataformas (o Mono mal suporta o .NET 3.5 e o framework já está na versão 4).
Conclusão: antes de reclamar de uma linguagem de programação, saiba que toda linguagem tem um approach, um foco e veja se esta “falha” pode ser algo útil… muitas vezes o é ![]()
[jQuery para apressados] Modularizando sua aplicação com Module Pattern e jQuery
O module pattern é um padrão de projetos para JavaScript que permite que você use closures autoexecutáveis para criação de “classes” com “atributos privados”.
Calma que eu explico :0)
O JavaScript não possui meios de declarar uma variável como “protected” ou “private”, como você costuma ver em linguagens como Java, C# e C++. Como uma forma de “proteger” alguns objetos de acesso externo, desenvolveu-se uma técnica chamada “module pattern”, que tem o poder de encapsular e restringir o acesso a tais objetos.
Antes de irmos para o module pattern, de uma olhada numa função autoexecutável:
alert('olá, mundo!');
}) ();
Interessante, não? Eu estou criando uma função e executando-a ao mesmo tempo. Note que eu posso passar um parâmetro pra ela se for necessário:
alert('Olá, '+nome+'!'); // Olá, Herberth
}) ('Herberth');
O module pattern funciona do mesmo jeito:
var itens = []; // variável "privada". Não pode ser acessada externamente
function hasItem(item)
{
return jQuery.inArray(item,itens)!=-1;
}
function addItem(item)
{
if(!hasItem(item))
{
itens.push(item);
}
else
{
alert('Opa! O item '+item+' já está selecionado');
}
}
function removeItem(item)
{
var position = jQuery.inArray(item,itens);
if(hasItem(item))
{
delete itens[position];
}
else
alert('Opa, não temos o item '+item+' no carrinho de compras')
}
// retorna um objeto com o que será visível pro mundo
// note que o array itens não está incluído
return {removeItem:removeItem,addItem:addItem};
})();
//poderíamos utilizar o código acima da seguinte forma:
CarrinhoDeCompras.addItem('Livro');
CarrinhoDeCompras.addItem('Caneca');
CarrinhoDeCompras.addItem('Livro'); //Opa, o item Livro já está adicionado
CarrinhoDeCompras.removeItem('Livro'); // remove ok
CarrinhoDeCompras.removeItem('Livro'); // Opa, não temos o item Livro no carrinho de compras
// mas não poderiámos fazer algo assim:
CarrinhoDeCompras.itens.push('Camiseta');
Neste caso, eu estou retornando um objeto contendo a referências das funções que eu declarei dentro da minha função autoexecutável. Perceba que, em hipótese alguma, eu conseguiria acessar diretamente o conteúdo/valor do array itens, pois eu não tenho uma referência dele externamente.
Isto é algo importante, por dois motivos:
- Se você estiver num time de desenvolvimento e desenvolver um módulo utilizando o module pattern, o desenvolvedor que pegar o seu módulo para utilizar saberá o que ele pode e o que não pode acessar.
- Você previne que aquele engraçadinho que sabe usar o Firebug mexa nos seus objetos em tempo de execução.
Onde o jQuery entra nesta história?
O jQuery entra principalmente na parte em que começamos a trabalhar com eventos customizados. Estes eventos customizados podem funcionar como um meio de comunicação entre os módulos da aplicação, sem que um conheça necessariamente o outro. O que é necessário que cada módulo saiba é como utilizar os eventos.
Continuando o exemplo anterior:
var itens = []; // variável "privada". Não pode ser acessada externamente
function hasItem(item)
{
return jQuery.inArray(item,itens)!=-1;
}
function addItem(item)
{
if(!hasItem(item))
{
itens.push(item);
}
else
{
alert('Opa! O item '+item+' já está selecionado');
}
}
function removeItem(item)
{
var position = jQuery.inArray(item,itens);
if(hasItem(item))
{
delete itens[position];
}
else
alert('Opa, não temos o item '+item+' no carrinho de compras')
}
function finalizarCompras()
{
// dispara o evento "finalizaCompras"
// quem estiver "ouvindo" este evento, receberá os itens como argumento
$(document).trigger("finalizaCompras",itens);
}
function init() { } // algum código de inicialização
// retorna um objeto com o que será visível pro mundo
// note que o array itens não está incluído
return {removeItem:removeItem,addItem:addItem,init:init};
})();
var Services = (function(){
function finalizarCompras(event,itens) // função "privada". Não pode ser acessada externamente
{
// envia os itens por AJAX e faz algum tratamento.
}
function init()
{
// "escuta" pelo evento finalizaCompras
// quando o mesmo for disparado, a função finalizarCompras será executada
// com os parâmetros do evento
$(document).bind("finalizaCompras",finalizarCompras);
}
return {init:init};
})();
$(document).ready(function(){
//inicializamos os módulos e colocamos os manipuladores de eventos.
CarrinhoDeCompras.init();
Services.init();
});
Whoa! Conseguimos desacoplar nossa aplicação utilizando eventos customizados.
Um módulo não conhece o outro, mas os mesmos se comunicam através de eventos. Note que a única coisa comum entre os módulos é o nome do evento utilizado para finalizar a compra.
Fazendo um paralelo com Programação Orientada a Objetos, os eventos seriam nossa Interface, neste caso.
Seria possível ainda, o módulo Service disparar um evento para avisar o CarrinhoDeCompras quando a transação for completada.
Interessante, não? ![]()
[jQuery para apressados] Efeitos e animações avançadas
Encadeando efeitos
Os métodos de efeitos do jQuery permitem que você passe uma função de callback como argumento para serem executados assim que os efeito termine. Esta funcionalidade nos permite encadear efeitos:Animações customizadas com o $.animate
O jQuery faz as animações customizadas através das propriedades que você quer que ele anime, de uma duração (opcional), de uma função de animação (já pré-definida no jquery - opcional) e de um callback (também opcional) para ser executado quando a animação acabar. Um exemplo bem básico do .animate:[jQuery para apressados] Efeitos e animações básicas
Métodos básicos
Os métodos básicos escondem e mostram elementos utilizando alguns efeitos. Dê uma olhada no método hide e no show:Nota: estes métodos são "sobrecarregados". Se você não passar nenhum valor como argumento, o elemento será mostrado/escondido sem animações.
slideDown e slideUp
Esconde e mostra (respectivamente) elementos utilizando o efeito slide. O uso é simples:
fadeOut e fadeIn
Esconde e mostra (respectivamente) elementos ajustando a sua transparência até desaparecerem/aparecerem por completo. O uso é bem simples também:
Os métodos toggle
O toggle é um utilitário do jQuery que lhe permite mostrar/esconder elementos sem consultar se o mesmo está visível ou não. Ou seja, ao invés de fazer algo assim:<script type="text/javascript">
$(document).ready(function(){
$('h1').hover(function(){
if( $('p:visible').length == 0) //nenhum p visível
$('p').show()
else
$('p').hide()
});
});
</script>
[jQuery para apressados] – Trabalhando com eventos customizados
Let's pull the $.trigger
O método trigger serve para lançar eventos e toma como parâmetro o nome do evento. Por exemplo:<script type="text/javascript">
$(document).ready(function(){
$('button[name=executeEvent]').bind('custom', function(event, param1, param2) {
alert(param1 + "\n" + param2);
});
$('button[name=executeEvent]').trigger('custom', ['Evento', 'Customizado']);
});
</script>
Nota: No exemplo do botão acima, eu tive que colocar um bind para o evento click e dentro do evento click eu disparo o evento 'custom'. Isso não afeta o comportamento do evento customizado, apenas fiz assim para poder demonstrar melhor.
No próximo post farei uma introdução ao module pattern e mostrarei como você pode desacoplar sua aplicação JavaScript usando custom events. Até mais![inline][/inline][jQuery para apressados] Tratamento avançado de eventos
$.live and let $.die
Os métodos 'live' e 'die' funcionam exatamente da mesma forma dos métodos bind e unbind exceto por uma característica: eles podem trabalhar com elementos inseridos dinamicamente na página. Exemplo:<script type="text/javascript">
$(document).ready(function(){
$('h1').bind('click',function(){ alert('fui clicado') }); // só funciona para os atuais elementos da página
$('h1').live('click',function(){ alert('fui clicado -- live') }); // funciona para os elementos atuais
//vai exibir o alert "fui clicado -- live" quando
// for clicado
$('body').append('<h1>Elemento inserido dinamicamente</h1>');
});
</script>
<script type="text/javascript">
clickHandler = function()
{
alert('Fui clicado e não serei clicado novamente');
$(this).die('click',clickHandler);
}
$(document).ready(function(){
$('h1').bind('click',function(){ alert('fui clicado') }); // só funciona para os atuais elementos da página
$('h1').live('click',clickHandler); // funciona para os elementos atuais
$('body').append('<h1>Elemento inserido dinamicamente</h1>');
});
</script>
$.delegate e $.undelegate
Os métodos delegate e undelegate são métodos auxiliares dos métodos live e die. Eles trabalham com elementos atuais e do futuro (quando os mesmos forem inseridos) e permitem adicionar manipuladores de eventos em elementos DOM específicos. Exemplo:<script type="text/javascript">
// retirado da documentação do jQuery
$(document).ready(function(){
$("table").delegate("td", "hover", function(){
$(this).toggleClass("hover");
});
// o código acima seria equivalente a este:
$("table").each(function(){
$("td", this).live("hover", function(){
$(this).toggleClass("hover");
});
});
});
</script>
O objeto event
No post anterior, eu mostrei um pequeno exemplo (sem dar muitos comentários) sobre o objeto event:<script type="text/javascript">
enviarDados = function(event)
{
var dados = event.data;
alert('Enviando dados. Dados enviados:'+dados);
}
$(document).ready(function()
{
$('#enviarDados').bind('click','Dado que vai para a função que trata o evento',enviarDados);
});
</script>
