Prototype

Visita este artí­culo en http://www.estadobeta.com/2006/08/04/prototype/

Por Ismael en artículos, educación, javascript

Introducción al desarrollo de aplicaciones Javascript con Prototype.js

Con este post entramos de lleno en Prototype. Prototype es una librería (la palabra correcta es “biblioteca”, pero por alguna razón suena rara) Javascript diseñada para extender las propiedades básicas del lenguaje y regularizar las diferencias de implementación entre navegadores.

Lo que sigue es una descripción de los principales aportes de Prototype. Para entenderla debes estar familiarizado con Javascript y los conceptos de función / método, variable y nociones básicas de Orientación a Objetos. También recomiendo que leas este y este artículo de EstadoBeta, si no lo has hecho ya.

Vayan nomás, yo los espero aquí.


A diferencia de librerías como Dojo o Mochikit, que son frameworks*1 y colecciones de Widgets o mini aplicaciones prehechas (sistemas de navegación, tablas ordenables, etc), Prototype aprovecha la maleabilidad de Javascript para enriquecer la funcionalidad de sus objetos base (Object, Array, Number, String), incluye nuevas clases utilitarias para trabajar con Ajax y un sencillo sistema de herencia para acercar a Javascript a las nociones OOP familiares en Java, Ruby u otros lenguajes orientados a objetos. Prototype no es en si una aplicación, sino una base para escribir aplicaciones más sólidas. De hecho, Prototype es usado para desarrollar librerías especializadas como Scriptaculous (para Ajax avanzado y efectos cinemáticos) o pequeños Widgets como LightBox 2.

Pero veamos ejemplos.

DOM

Prototype gira en torno a la manipulación del DOM, y normaliza las implementaciones dispares que los distintos browsers han hecho de la interfaz.

$()

Por ejemplo, imaginemos un elemento HTML en nuestro documento:

<a href="http://www.estadobeta.net" id="beta-link">EstadoBeta!</a>

Para obtener este elemento desde Javascript en Internet Explorer 5, haríamos esto:

var un_link = document.all["beta-link"]

En navegadores estándar donde no existe la colección all:

var un_link = document.getElementById("beta-link")

Prototype regulariza el acceso a elementos del DOM con la breve función $().

var un_link = $(“beta-link”);

$() hace todo lo necesario para retornar un objeto Javascript, sin importar la versión del navegador. Este tipo de abstracción es la base de la librería.

No sólo eso. Si pasamos varios argumentos, $() nos retorna un array de objetos.


var links = $( "link-1", "link-2", "beta-link" );
document.write( links[2].href ); // imprime "http://www.estadobeta.net"

$() puede incluso recibir objetos, o una mezcla de IDs y objetos. Si el argumento ya es un elemento del DOM simplemente lo retorna.

$$()

Esta función es interesante. A diferencia de $(), que sólo puede recibir una ID o un objeto, $$() recibe un selector CSS, retornándonos los objetos correspondientes que podemos manipular.


var todos_los_links = $$( “body a” );//un array con todos los links del documento

var beta_link = $$( “#beta-link” );// el link id=”beta-link”

var seleccionados = $$( “a.seleccionado” );//links con class=”seleccionado”

En combinación con los Iteradores que veremos más abajo, la función $$() es increíblemente útil.

Element

Ahora queremos remover el elemento del documento. La rebuscada forma de hacerlo según el estandar Javascript:


var un_link = document.getElementById("beta-link");
un_link.parentNode.removeChild(un_link);

Prototype define el objeto Element, con muchas utilidades para manipular elementos con poco código. Lo de arriba se reduce a

Element.remove("beta-link");

Todas las funciones del DOM de Prototype usan $() internamente. Por eso podemos pasar directamente la ID a Element.remove()

Para manipular dinámicamente el diseño de nuestro documento frecuentemente agregamos y removemos clases CSS a los elementos. En la forma tradicional debemos primero asegurarnos de que el elemento no contenga ya la clase a agregar.


var un_link = document.getElementById( "beta-link" );
if( un_link.className.indexOf( “seleccionado” ) > -1 ){//clase todavía no existe, agrégala
     un_link.className += “seleccionado”;
}

Prototype hace todo eso en la siguiente línea:


$("beta-link").addClassName("seleccionado");

Para remover la clase:


$("beta-link").removeClassName("seleccionado");

Si. Los métodos de Element también son agregados a Object.prototype, el objeto base del que descienden todos los objetos Javascript. Nuestro ejemplo para remover elementos se puede reescribir así: $("beta-link").remove().

Otros métodos utilitarios del objeto Element son hide(), show() y toggle() (más info en links al final de este artículo).

Arrays e Iteradores

Prototype es la librería javascript “oficial” del framework de desarrollo Ruby on Rails, y es incluído en la distribución de la aplicación. Por esto, Prototype introduce mejoras a la sintaxis de Javascript que emulan la flexibilidad de lenguajes como Ruby o Python. Esto es claro en el concepto de “iteradores” (llamados “bloques” en Ruby). Prototype extiende el prototipo de la clase Array con métodos de este tipo. Para entender esto veamos primero la forma tradicional de recorrer un array (una lista de elementos) en Javascript:


var nombres = [ “Pedro”, “Juan”, “Diego” ];
for(var i=0; i < nombres.length; i++){
    document.write(nombres[i]);
}

Prototype define el método Array.each(), que recibe una función iteradora que será aplicada a cada elemento del array. La función iteradora la definimos nosotros pero debe recibir como parámetro el elemento del array correspondiente a cada vuelta del loop. Opcionalmente recibe el índice de este elemento en el array.


[ "Pedro", "Juan", "Diego" ].each(
    function( nombre, indice ){
        document.write( nombre );
    }
);

¿cuál es la gracia, se preguntarán ustedes? En este ejemplo no mucha. ¿se acuerdan de la función $$(), que retorna objetos en base a un selector CSS? Las líneas siguientes usan $$() y Array.each() para crear un nuevo array con las direcciones de todos los links con clase “seleccionado” en el documento.


var direcciones = [];
$$( “a.seleccionado” ).each( function( elemento ){ direcciones.push(elemento.href) } );

Dense unos minutos para entender eso. En el próximo artículo de la serie exploraré en más detalle los Iteradores de Prototype (si no pueden esperar, les recomiendo este artículo, en inglés).

Ajax

El objeto Ajax de Prototype reduce las dos principales implementaciones existentes - el objeto XMLHttpRequest de Netscape/Mozilla y el objeto ActiveX Microsoft.XMLHTTP de Microsoft - en una clase muy fácil de usar para cargar y enviar datos desde el servidor. Lo siguiente carga los resultados de una búsqueda en un DIV id=”resultados”.


// En Javascript
function buscar( palabra ){
    var url = "http://tu.servidor.com/buscar.php";
    var pars = "palabra=" + palabra;

    var myAjax = new Ajax.Updater( “resultados”, url, { method: “get”, parameters: pars } );

}

// En HTML
<input type=”text” id=”palabra” />
<input type=”submit” onClick=”buscar( $(”palabra”).value )” value=”buscar” />

Y eso es lo básico de Ajax. El tercer argumento de Ajax.Updater es un objeto de parámetros opcionales. Ahí es posible definir callbacks o funciones que se ejecutarán según la petición Ajax termine con exito o fracase.

Pero todo a su debido tiempo.

Event

Otra cosa particularmente complicada entre navegadores es el manejo de eventos. El objeto Event provee una forma estandar de asignar y remover eventos a elementos HTML. Lo siguiente ejecuta la función inicio() al evento onLoad del documento (cuando el HTML termina de cargar).


var inicio = function(){
    alert("Hola Mundo!");
}

Event.observe( window, "load", inicio );

Event.observe() además mantiene una “cola” de funciones asignadas al mismo evento. Una nueva llamada a Event.observe( window,”load”,otra_funcion ) no suprimirá la ejecución de inicio().

Otro ejemplo es asignar un evento onMouseover a elementos de control; en este caso un <textarea id="mensaje“>.


Event.observe(mensaje“, “mouseover”, function(){ alert(”Hola Mundo!”) } );

Un ejemplo

Hay mucho, mucho más que ver en Prototype pero espero que esto haya servido de introducción. En los próximos episodios (y por el mismo canal) publicaré notas dedicadas a cada uno de estos elementos y a los que dejé de lado.

Para abrir el apetito por Prototype, les dejo una pequeña aplicación que agrega dinámicamente la clase “pdf” a todos los links del documento que vinculen a un archivo PDF. Esta clase CSS puede servir para agregar un icono especial a esos links. Aquí pueden bajar los archivos necesarios.


var superLinks = function(){
	$$("a").each(
		function(elemento){
			if( elemento.href.indexOf(”.pdf”) > -1 )
				Element.addClassName( elemento,”pdf” );
		}
	);

}

Event.observe( window, “load”, superLinks );

Links

Prototype Meets Ruby: A Look at Enumerable, Array and Hash
Excelente sumario de las extensiones de Prototype a las clases nativas Array y Object. Mi próximo artículo sobre Iteradores será prácticamente una traducción literal.
Developer Notes for Prototype.js
Aunque no es oficial, esta es hasta la fecha la mejor documentación de la librería. Incluye buenos ejemplos.
Sitio oficial de Prototype
Eso. En el sitio de Sam Stephenson, creador de Prototype.
Quick Guide to Prototype
Otra buena introducción a Prototype por la gente de Particletree.
*1
Una librería sólo provee utilidades o extensiones al lenguaje, mientras que en un framework es muy importante la relación entre los distintos componentes, y en general se requiere adaptar la metodología de trabajo a las convenciones dictadas por el framework.

*2
Al momento de escribir esta nota la función $$() sólo se encuentra en la última versión de Prototype, que puedes bajar desde esta dirección.

17 comentarios para “Prototype”

  1. Gravatarmeneame.net Dice:

    Introducción al desarrollo de aplicaciones Javascript con Prototype.js

    Magnifico tutorial introductorio, en español, sobre el uso de la libreria Prototype.

  2. Gravatarsosa Dice:

    Felicidades! Que buen tuto. Prototype es mi librería favorita, aunque a veces me veo tentado a switchear a jQuery…

    Hace como un mes impartí un pequeño taller sobre Ajax y cuando les mostré como se podía reducir una función de 20 líneas a sólo 3 usando Prototype todos los asistentes dijeron “woooooow”. Yo tambien lo dije en su momento. $$() rules!

  3. GravatarJosé Rodríguez Dice:

    Jonathan Snook publicó hace un tiempo atrás un completo wallpaper-resumen de prototype que resume muchos métodos y propiedades de esta maravillosa biblioteca.

    PD: $() & $$() rules!!!

  4. Gravatarstan Dice:

    he estado haciendo algunos ejemplos de prototype pero se me ha hecho algo complicado. quizas por que no estoy muy familiarizado con javascript, sin embargo seguire probando.

  5. GravatarIsmael Dice:

    Stan: Prototype es muy productivo si ya manejas lo básico de Orientación a Objetos y entiendes el concepto de Encapsulación en programación. Te recomiendo que le des una mirada a esos temas, en Javascript o cualquier otro lenguaje.

  6. GravatarMañungo Dice:

    Hola Ismael! Te acuerdas de mi comentario a propósito de tu post Links javascript accesibles ?

    Resulta que use tu tutorial de Prototype para implementar la idea de las tablas ordenables, usando javascript-triggers en los class y, obviamente, Prototype. Fue un buen ejercicio y me sorprendió que efectivamente con Prototype se ahorran muchísimas líneas de código.

    Se los dejo a tus lectores, si le quieren echar un vistazo.

  7. GravatarIsmael Dice:

    Excelente Mañungo!
    Funciona de lo mejor y con poco codigo! Le voy a echar una mirada para comentarte.

  8. GravatarJosé Rodríguez Dice:

    A propósito de las tablas ordenables, un problema recurrente al hacer ordenamientos es la comparación de textos que contienen números, por ejemplo el siguiente ordenamiento se utiliza una comparación estándar:

    rfc1.txt
    rfc2086.txt
    rfc822.txt

    Sin embargo, sabemos que 2086 es mayor a 822. Este otro ordenamiento “natural” (natsort) es sensible a los valores numéricos dentro de un string y da el siguiente resultado:

    rfc1.txt
    rfc822.txt
    rfc2086.txt

    En http://sourcefrog.net/projects/natsort
    pueden descargar esta función de comparación.

  9. GravatarEstadoBeta » Archivo » Apagando elementos “select” para IE Dice:

    […] Ahora, si estas usando la librería Javascript Prototype.js podrías usar la espectacular función $$(), que recibe un selector CSS, y hacer algo como esto: […]

  10. GravatarEstadoBeta » Archivo » Prototype: iteradores Dice:

    […] Prototype es una librería Javascript que agrega utilidades al lenguaje para escribir aplicaciones más complejas con menos código. Si no lo has hecho, te recomiendo que leas el artículo introductorio aquí en EstadoBeta antes de continuar con este artículo. […]

  11. GravatarEstadoBeta » Archivo » Cambio de contraste con Javascript y CSS Dice:

    […] Mientras preparo un próximo artículo sobre Ajax en Prototype, los dejo con un ejemplo para ejercitar el músculo de Javascript y tonificar el cutis CSS (nadie lee EstadoBeta por mi poesía, no se quejen). […]

  12. GravatarEstadoBeta » Archivo » Prototype: Ajax Dice:

    […] Hemos visto suficiente de la librería Javascript Prototype como para entrar de lleno en una de sus utilidades más… Estee… útiles: Ajax (si no sabes qué es Prototype lee este y este artículo). […]

  13. Gravatarjgrdal Dice:

    Excelente introducción. Gran artículo.

  14. GravatarAntonio De Juaan Dice:

    Excelente libreria, me ha ahorrado un monton de tiempo, antes usaba las llamadas ajax nativas y como lengueaje de trasapaso usaba xml, ahora que uso prototype lo mezclo con json y listo, simplicidad, trasapaso de datos liviano, es la mejor libreria que he visto, habiendo usado muchas.

    la recomiendo 100%.

  15. GravatarApagando “select” en IE | AplicacionesWeb Dice:

    […] si estas usando la librería Javascript Prototype.js podrías usar la espectacular función $$(), que recibe un selector CSS, y hacer algo como […]

  16. GravatarCiro Dice:

    Empeze a usar esta libreria, y me facilitaba mucho, sobre todo la serializacion, pero cuando queria cargar archivos .JPG o .DOC u otros, no podia hacerlo, tal vez alguien me sugiera que podria hacer.

  17. Gravatarwww.republicadeluque.com.py Dice:

    que buen tutorial te felicito.. me ayudo mucho