Função Dollar do Prototype para capturar elementos HTML

{ October 13th, 2007 }


cmilfont

Autor: cmilfont

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.

Categories: Frameworks, JavaScript, Prototype, Web Development ~ ~ Trackback


Assine os comentários deste artigo.


9 Responses to “Função Dollar do Prototype para capturar elementos HTML”

  1. 1
    Resumo javascript - Jan 2008 - CMilfont Tech

    […] http://www.milfont.org/tech/2007/10/13/funcao-dollar-do-prototype-para-capturar-elementos-html/ […]

  2. 2
    Edu

    Hum…eu tentei fazer isso…mas o prototype só funciona se vc instanciar com o “new”.

  3. 3
    cmilfont

    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?

  4. 4
    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

  5. 5
    cmilfont

    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.

  6. 6
    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

  7. 7
    Paulinholiveira

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

  8. 8
    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?

  9. 9
    imgur

    Enterprises having a large website with a lot
    of traffic influx will require the reseller hosting package.
    Figure out what it is you need and want and from there shop around to see
    what web hosts matches these expectations. Elements such as text, graphics,
    images, font sizes and colors are used in designing and
    producing pages for a web site.

Leave a Reply