Enquanto não preparo um material exclusivo sobre manpulação DOM da especificação W3C, gostaria de falar sobre o encapsulamento dessas operações que os Frameworks Javascript fazem.
A funcionalidade principal de todos os Frameworks, é abstrair a complexidade da manipulação DOM, que não é tão complexa assim mas é chata para muitos. Como o DOM é o acesso aos elementos, e dependemos deles para montar a UI (User Interface) das aplicações, todos (Frameworks) tentam minimizar ou associar essa manipulação com a facilidade de linguagens UI que temos costume no desktop.
O Extjs por exemplo, tem o objeto Ext.Element que representa um elemento DOM e possui métodos amigáveis como: Ext.get(id), para capturar um elemento, Ext.get(“my-div”).setWidth(100) para setar uma largura de 100 pixels a um elemento capturado, entre outros métodos.
O Bruno Torres em seu projeto, O Básico da web, escreveu um artigo básico sobre captura de elementos HTML. Esse artigo me inspirou a falar sobre a função $ (Dollar) famosa no Framework Prototype pela simplicidade. Quem quiser aprender como se seleciona um elemento DOM, dê uma olhada no artigo, lá está bem explicado e com uma didática legal.
A função $ (Dollar), símbolo do uso do Prototype, representa um mecanismo “conveniente” de captura de um elemento, presenteado com métodos auxiliares para a manipulação do DOM em um lote de elementos.
Para capturar o elemento DOM, você precisa usar a sintaxe:
var el = document.getElementById("id_elemento");
A partir daí podemos selecionar ou alterar suas propriedades como:
alert(el.innerHTML); // exibe o conteúdo
Enquanto no Prototype, a função $ providencia um acesso mais limpo:
var el = $("id_elemento");
Essa função é amada por todos os desenvolvedores javascript, a construção dela é absolutamente simples:
function $(els) {
this.elements = [];
for (var i=0; i < els.length; i++) {
var element = els[i];
if (typeof element == 'string') {
element = document.getElementById(element);
};
this.elements.push(element);
};
return this;
};
O código da função acrescenta os elementos passados como parâmetros (caso queira capturar vários, apenas separe por vírgula) em uma propriedade array na função. Caso o parâmetro seja uma String, um elemento é capturado pela forma tradicional usando essa String (que deve ser referência a um ID) e acrescentado no array, a cláusula return devolve o escopo da própria função.
A função $ é enriquecida com funçõse que manpulam esse conjunto de elementos. A lógica é que ao retornar esse elemento(s), uma função seja acionada e manipule esse elemento (ou conjunto deles). Essas funções podem ser adicionadas via prototype (propriedade herdada da Global que representa o escopo interno de todos os objetos):
$.prototype = {
each: function(fn) {
for ( var i=0,len=this.elements.length;i++)
{
fn.call(this, this.elements[i]);
};
return this;
}
}
Assim, ao selecionar vários elementos, podemos aplicar essas funções diretamente. Outras funções podem ser adicionadas usando o prototype, criando um ecosistema elementar para manipulação desses elementos.
Veja como a aplicação dessa função reduz o código necessário para acionarmos um elemento diretamente e aplicarmos uma instrução que se feita por DOM, levaria várias linhas:
$('botao').on('click',
function() {
$('teste').each(
function(el){
alert(el.value);
});
alert($('teste').value);
});
}
Nos próximos posts, destilaremos vários frameworks e como cada um faz sua manipulação.
[UPDATE 10-02-2008]
Para exemplificar melhor como trabalha o Framework Prototype, Devido aos comentários do Edu, ficou faltando código para compreender como a função "$" está disponível no código.
Nas versões antigas do framework, eles faziam assim:
- Cria-se uma função privada no contexto referenciada por _$;
- Retorna uma instãncia dessa função _$ referenciada a $;
Como fica isso em código:
// função privada com o código que vimos nesse post
function _$(els) {
this.elements = [];
for (var i=0; i
var element = els[i];
if (typeof element == 'string') {
element = document.getElementById(element);
};
this.elements.push(element);
};
return this;
};
Cria a função global "$" com referência a uma instância da função privada "_$"
$ = function() {
return new _$(arguments);
};
O código completo ficaria assim:
(function() {
function _$(els) {
this.elements = [];
for (var i=0; i
Observe que hoje ficou bem mais rebuscado no código das últimas versões, mas o conceito é o mesmo.