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<els.length;>
      var element = els[i];
      if (typeof element == 'string') {
        element = document.getElementById(element);
      };
      this.elements.push(element);
    };
    return this;
  };
</els.length;>

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<els.length; i++) {
      var element = els[i];
      if (typeof element == 'string') {
        element = document.getElementById(element);
      };
      this.elements.push(element);
    };
    return this;
  };
 
  _$.prototype = {
    each: function(fn) {
      for ( var i = 0, len = this.elements.length; i<len; ++i ) {
        fn.call(this, this.elements[i]);
      };
      return this;
    },
    setStyle: function(prop, val) {
      this.each(function(el) {
        el.style[prop] = val;
      });
      return this;
    },
    addClass: function(className) {
      this.each(function(el) {
        el.className += ' '+className;
      });
      return this;
    },
    css: function(o) {
      var that = this;
      this.each(function(el) {
        for (var prop in o) {
          that.setStyle(prop, o[prop]);
        };
      });
      return this;
    }
  };
  $ = function() {
    return new _$(arguments);
  };
}());

Observe que hoje ficou bem mais rebuscado no código das últimas versões, mas o conceito é o mesmo.

Typically chemist’s shop can sale to you with discreet treatments for various health problems. There are numerous of safe online pharmacies that will deliver medications to your address. There are divers medicines for each afflictions. Learn more about “viagra manufacturer coupon“. Maybe “viagra discount coupons” is a very complicated matter. Matters, like “coupons for viagra“, are united numerous types of health problems. If you need to take prescription medications, ask your pharmacist to check your testosterone levels before. Sometimes the treatment options may include erectile malfunction remedies or a suction device that helps get an erection. Keep in mind web-site which is ready to sell erectile dysfunction drugs like Viagra without a prescription is fraudulent. When you purchase from an unknown web-site, you run the risk of getting counterfeit remedies.

8 thoughts on “Função Dollar do Prototype para capturar elementos HTML

  1. Pingback: Resumo javascript - Jan 2008 - CMilfont Tech

  2. cmilfont Post author

    Edu, a função dollar “$” está disponível ao acrescentar o script do prototype sem a necessidade de instanciação de qualquer novo objeto. Como você fez que não funcionou?

  3. Edu

    Oi Christiano, eu tentei simplificar ao máximo para eu entender o conceito.

    function $(id){
    var obj=document.getElementById(id)
    return this
    }

    Tentei adicionar um método por prototype:
    $.prototype.color=function(cor){obj.style.color=cor}

    Na hora de chamar a função: $(“caixa”).color(“blue”), dava erro:
    “objeto não dá suporte ao método”. Ou seja, não existe o método.

    Quando eu colocava o método “color” dentro do corpo da função funcionava . Mesmo quando eu testei na base do copy & paste seu código não funcionou, dava o mesmo erro.

    Eu queria saber como não conheci seu blog antes…Seu blog é daqueles que eu considero “chato” porque tem tanta coisa interessante que a gente se perde…rsrsrs

    Ganhou um leitor assíduo rsrs

    Abraço

  4. cmilfont Post author

    Ah, agora entendi! Pensei que você estava se referindo ao Framework Prototype.
    Se voce acrescentar o script dele na sua página diretamente, verá que funciona -> http://www.prototypejs.org/assets/2008/1/25/prototype-1.6.0.2.js

    Qual o segredo aqui, antigamente eles faziam assim:
    1 – definiam uma função privada ao escopo do script chamada de function _$() {…}
    2 – retornava uma instância dessa função referenciada à variável $.

    Observe o update que fiz no post.

  5. Edu

    Agora simmm!!! Entendi!!!!

    Muito interessante isso. Olha se vc for mesmo destrinchar os frameworks vai ser muito bom!! Vai ser muito interessante e didático.

    Uma referência assim seria até agora inédito, acho, já que não vi ninguém fazer.

    Abraços

  6. Paulinholiveira

    Tentei aqui $(‘Loading’).css(‘display’, ‘block’) e nao deu certo estou chamando errado? vc poderia fazer uma pagina de exemplo?

  7. José A M Pacheco

    I made a page with only the following:

    before the

    console.log (cpf.value); // “Anything”

    tested in chrome 36; IE8 and IE11 and latest version firefox and it worked in all of them.
    Because this work? This makes obsolete document.getElementById?

Comments are closed.