Tag Archives: DOM

Função Dollar do Prototype para capturar elementos HTML

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:

  1. Cria-se uma função privada no contexto referenciada por _$;
  2. 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.