JavaScript sin dolor usando Prototype

baluart3 Marzo 2006 - 5:40pm 39 comentarios
Enviar por Email Imprimir

JavaScript sin dolor usando PrototypeYa conocemos la potencia de Prototype para crear aplicaciones de una forma muy sencilla. Si eres nuevo en esto, dale un vistazo a estas aplicaciones y comprenderás lo fácil que se ha vuelto el desarrollo de JavaScript con Prototype:

Ahora, en un artículo de “Tutoriales de Javascript & DHTML” de SitePoint, Dan Webb demuestra como usar la librería Prototype. El artículo es muy bueno. Es una completa introducción a la librería, por lo que hemos decidido traducirlo en dos partes, a continuación empecemos a familiarizarnos con ella...

Painless JavaScript Using Prototype

Prototype es una librería JavaScript Orientada a Objetos (escrita por Sam Stephenson y amigos) que hace a JavaScript divertido. Esto lo dice su sitio de todas las formas. Aquellos que estén familiarizados con el último y mayor marco de aplicaciones Open Source, Rails, pueden reconocer a Prototype como la espina dorsal del asistente JavaScript de Rails. Sin embargo, Prototype se puede utilizar independientemente de Rails para ayudar a la codificación de muchas aplicaciones de la Web 2.0.

Personalmente, yo tengo un juicio aparte en el conjunto de cosas divertidas del JavaScript, pero Protoype es una librería realmente buena que, aunque la situación ha estado mejorando últimamente, ha tenido escasa documentación. Este artículo proporciona un viaje relámpago pero completo de la librería. A lo que apuntamos con esto, es proporcionar ejemplos y recursos para poder empezar a incluir a Prototype en sus proyectos DOM Scripting.

Primero, examinaremos los componentes básicos de Prototype: Las funciones $, Las adiciones a los Strings, Números, Arrays y Funciones de objetos. En otro artículo veremos sus bondades en el manejo de formularios y las funciones de DOM, seguiremos observando a los ayudantes de Ajax. Y finalmente, terminaremos con una breve discusión de otros proyectos interesantes que están basados en Prototype.

Me gustaría notar que la versión estable de Prototype al momento de escribir este artículo es la 1.4.0. Tengo el presentimiento, que la librería se actualizará muy rápidamente, en respuesta al ciclo de desarrollo veloz de Rails, entonces las cosas cambiarán. Finalmente, lo que malogra la nota es que en estos momentos, es que Prototype sólo soporta a los navegadores más recientes. Puede visitar el sitio de Prototype, para más información sobre el soporte de navegadores.

Primeros Pasos

La anterior versión de Prototype puede ser descargada del sitio oficial de prototype. Simplemente descargue prototype.js y enlácelo en sus páginas con la etiqueta <script>.

<script type="text/JavaScript" src="path/to/prototype.js"></script>

Si esta utilizando Rails, no necesita descargar Prototype: La librería viene incluido en la distribución. Usted puede incluirlo en sus páginas poniendo dentro de las etiquetas <head>:

<%= javascript_include_tag 'prototype' %>

Ahora, vamos al fondo del tema!

Pequeñas ayudas de Prototype

Una de las cosas realmente agradables sobre la utilización de Prototype son las sencillas funciones de ayuda que proporciona para las tareas comunes de scripting. Las funciones $ ya han conseguido algo de atención. Denle uno o vario elementos ID y le devolverán referencias a ellos:

// reference to the element with the ID 'nav'
$("nav")
// an array of element references
$("img1", "img2", "img3")

Es como una superposición de document.getElementById y es asombroso cuanto conviene esta codificación cuando usted la utiliza.

Otra función increíblemente útil es document.getElementsByClassName, que hace lo que dice la lata: Toma un nombre de clase CSS y devuelve una lista de todos los elementos con dicha clase:

// todos los elementos con la clase 'navlink'
document.getElementsByClassName("navlink")
// todos los elementos con la clase navlink y detrás el elemento con ID 'nav'
document.getElementByClassName("navlink", $("nav"))

Por cierto, cuando este artículo fue escrito, la versión 1.5.0_rc0 de Prototye ganó la poderosa función $$, que permite seleccionar elementos usando una sintaxis estándar del selector CSS:

// un array de todos los elementos input detras de 'commentform'
$$("#commentform input")
// un array de todos los links con la clase 'external'
$$("a.external")

Por favor, tenga presente que, a la hora de escribir, a menos que usted descargue la versión más reciente de Prototype, esta función no estará disponible para usted.

$F toma un ID y devuelve el valor de cualquier campo de formulario, por ejemplo, un menú select como este:

<select name="country" id="country">
<option selected="selected" value="UK">United Kingdom</option>
<option value="FR">France</option>
...
</select>

$F('country') // 'UK'

Haciendo que JavaScript aspire menos

Oops, he robado la etiqueta de otra librería JavaScript. Los desarrolladores de la librería JavaScript no pueden dejar de intentar que JavaScript se parezca a otra lengua. Los individuos de Mochikit quisieran que JavaScript fuera como Python, incontables programadores han intentado hacer a JavaScript como Java y ahora, los intentos de Prototype para hacerlo a gusto de Ruby. Por tanto, Prototype extiende la base de JavaScript, que puede (si usted elige utilizarlo) tener un efecto dramático en su acercamiento a la codificación JavaScript. Dependiendo de su experiencia y de la manera en que proyecta sus trabajos, la librería puede, o no, ser de su ayuda.

OO la manera Ruby(ista): Class.create y Object.extend

El método Class.create permite definir clases de un modo muy parecido a Ruby, aunque sea puramente estético es esencial para inicializar el método que define el constructor.

var DOMTable = Class.create();
DOMTable.prototype = {
initialize : function(el) {
this.el = el;
},
...
}

Sin embargo, mucho más potente es el método simple pero eficaz de Object.extend. Todo lo que lo hace es copiar las propiedades y métodos de un objeto a otro objeto, pero sus aplicaciones son muchas. Aquí un test rápido:

// make a (shallow) copy of obj1
var obj2 = Object.extend({}, obj1);

var options = {
method : "post",
args : ""
};

// merges in the given options object to the default options object opciones implícitas
Object.extend(options, {
args : "data=454",
onComplete : function() { alert("done!"); }
});

options.method // "post"
options.args // "ata=454"
options.onComplete // function() { alert("done!"); }

Esto es lo más es usado para "mezclar" métodos de un objeto con otro. Por ejemplo, usted podría crear un juego de funciones que hacen seguros los elementos de DOM Sortable:

var Sortable = {
sortBy : function(func) {
...
},
sortByReversed : function(func) {
...
},
reset : function() {
...
}
};

Luego, si queremos hacer nuestro DOMTable desde Sortable, podríamos mezclar en estos métodos al objeto de DOMTable:

var myTable = new DOMTable("table-id");
Object.extend(myTable, Sortable);

Ahora podemos llamar estos elementos en una tabla.

// sort the table using the given function
myTable.sortBy(function (itemA, itemB) { ... });

Función Binding

Prototype también añade a la función objeto dos métodos realmente útiles: bind y bindAsEventListener. Estos son usados muchas veces para atar una función a un objeto particular de modo que la palabra clave apunte a ese objeto. Esto es increíblemente útil cuando usted está fijando funciones. Imagínese que usted intenta algo como esto:

var myObject = new Object();
myObject.message = "Hello!";
myObject.eventHandler = function() {
alert(this.message);
}

$("mydiv").onmouseover = myObject.eventHandler;

Tradicionalmente, usted conseguiría un error, porque, cuando el evento llama a la función handler, esta se refiere al elemento mydiv, no a myObject, entonces this.message es indefinido. Usted puede solucionar este problema con:

$("mydiv").onmouseover = myObject.eventHandler.bind(myObject);

Ahora todo trabaja muy bien, porque la palabra clave está limitada a myObject. Siguiendo esto, el bindAsEventListener hace lo mismo, aunque pasa el objeto del evento a través de su función de una manera compatible de cross-browser, así que usted no tiene ninguna necesidad de preocuparse del window.event en IE. Trate esto:

myObject.eventHandler = function(event) {
alert(event.srcElement.nodeName);
}

$("mydiv").onmouseover = myObject.eventHandler.bindAsEventListener(myObject);

Ahora nuestra función de eventHandler tiene el acceso al objeto del evento. Mayores detalles de estos dos métodos están disponibles en el sitio de su creador.

Nuevos Métodos de String y Números

Prototype ha añadido un enorme número de métodos útiles al construir objetos String. Aquí tiene una mirada rápida de lo mejor.

// "backgroundColor"
"background-color".camelize()

camelize devuelve strings que uno puede trabajar con propiedades CSS.

// "I am a piece of HTML"
"I am a piece of <strong>HTML</strong>".striptTags()

// {a : 10, b: "thing"}
"a=10&b=thing".toQueryParams()

También Prototype añade un gran método para Numerar. ¡Diga adiós a los loops!.

// alerts "1", "2", "3" ... "50"
50.times(function(n) {
alert(n);
}};

Aquí, el método de “times” toma una función que llamará a un número dado de veces y pasa en la corriente interacción de los números como un argumento. Este empleo de una función de interacción es común usando Enumerable, del cual hablamos a continuación.

Interacción a la manera de Ruby: Enumerable y Hash

Unas de las gemas ocultas de Prototype es Enumerable y el objeto Hash, que han sido usurpados directamente de ruby. Si usted no esta familiarizado con ruby, no se preocupe. Lo explicaré todo aquí.

Comenzaremos con Enumerable. En breve cuando sumamos Enumerable a un objeto que usa Object.extend, le da al objeto en cuestión, muchas funciones realmente útiles para trabajar con sus propiedades. Enumerable ha sido agregado Prototype Arrays, entonces cualquier array tiene estos métodos nuevos. Aquí están unos ejemplos de lo que usted puede hacer con los nuevos arrays "enumerados":

// alerts "a is at 0" then "b is at 1" then "c is at 2"
["a", "b", "c"].each(function(item, index) {
alert(item + " is at " + index);
});

// [80,50]
[1, 80, 3, 50].select(function(item) {
return (item > 20);
});

Select crea un nuevo Array que contiene sólo los elementos que hacen que la función devuelva true.

// ["A", "B", "C"]
["a", "b", "c"].invoke("toUpperCase");

Invoque llamadas al especificar el método de cada elemento del Array y devuelve el arrray resultante.

// ["cat", "rat"]
["cat", "dog", "rat", "mouse",].grep(/at/);

Grep devuelve todos los elementos que emparejan la expresión regular dada.

Enumerables ofrece un inmenso número de funciones increíblemente poderosas que pueden hacer el desarrollo, del tedioso DOM scripting, en una tris. Por ello, sugiero que usted de una buena mirada a los métodos de Enumerable en los útiles apuntes de desarrollador, de Sergio Pereira.

Hay un pequeño problema aquí, aunque en JavaScript, usted puede encontrar por casualidad muchos tipos de objetos que, a efectos prácticos, actúan como arrays, pero no son objetos de arrays. Los objetos como DOM NodeLists y argumentos de función no tendrán a Enumerable disponible automáticamente. Esto es fácil de rectificar, aunque; para agregar las funciones Enumerables a cualquier objeto parecido a un Array debe usar $A:

// add Enumerable to childNodes
var children = $A($("mydiv").childNodes);

// sets class="highlighted" for all child nodes of "mydiv"
children.each(function(child) {
child.setAttribute("class", "highlighted");
});

Para crear un Hash, llame a la función mágica $H en cualquier objeto. Esto gira todas las propiedades del objeto en un juego de pares de valor clave con Enumerable. Vamos a tomar Hash para dar una vuelta:

// create a hash by feeding an object to $H
var contact = $H({
name : "Dan Webb",
email : "dan@danwebb.net",
address : "None of your Business, London",
postcode : "a111111"
});

// ["name", "email", "address", "postcode"]
contact.keys()
// ["Dan Webb", "dan@danwebb.net","None of your Business, London", "a111111"]
contact.values()
// "name=Dan Webb&email=..."
contact.toQueryString()

Hash extiende a Enumerable, entonces todos aquellos métodos útiles están también disponibles.

// alerts "name contains Dan Webb" and so on
contact.each(function(item) {
alert(item.key + " contains " + item.value);
});

¡Al principio, si usted no es un Rubyista, Enumerable y el Hash pueden parecer un poco tediosos; pero puedo asegurarle, una vez que usted comience a usarlos, usted se preguntará por qué alguna vez se molestó en conseguir un RSI que escriba todos aquellos loops! Cuando usa a uno o varios de ellos juntos, comprenderá el poder masivo de estos nuevos métodos. Usted puede leer sobre Enumerable y el Hash más detalladamente en Encyte Media.

El objeto Event ayuda a proveer, lo que a muchos, es el Santo Grial del JavaScript: Simple, Cross-browser event handling:

function eventHandlerFunction(e) {
// the element that triggered the event
var element = Event.element(e);
// gets the mouse position
var mouseX = Event.pointerX(e),
mouseY = Event.pointerY(e);
// stop default behaviour and event propagation
Event.stop(e);
}

// register eventHandlerFunction to the onclick of myObject
Event.observe(myObject, "click", eventHandlerFunction, false);

// removes the event handler
Event.stopObserving(myObject, "click", eventHandlerFunction, false);

De un modo bastante agradable, Prototype trata de evitar aquellos escapes de memoria indeseados en IE automáticamente, quitando a cada observador cuando la página se descarga.

En mi opinión, la solución en este momento es un sub-desarrollo del manejo del evento, por lo que podría valer la pena pensar en usar algo un poco más rico como addEvent del Decano Edwards, por el momento.

Comentarios

Imagen de Kitune

Muy buen trabajo, felicidades. Estoy empezando con prototype y me va a servir de mucha ayuda estos artículos.  Como ya lo hizo el de Edicion in Situ.  Permíteme que los enlace desde mi blog :)

Imagen de sgwd
sgwd

Hola,

necesito hacerte una consulta:

utilizo este codigo:

Event.observe('imgTest', 'click', function(event) {
fxAlgo();
});

Mi pregunta es:
como hago para poder conocer que funcion tiene asignado el elemento 'imgTest' para el evento click? es decir obtener como resultado fxAlgo();

Nota:
anteriormente, utilizaba el evento onclick en la etiqueta:

image id='imgTest' src='image.png' onclick='fxAlgo();

y haciendo luego: $('imgTest').onclick

obtenia:

function onclick(event) {
fxAlgo();
}

Imagen de Anonymous
Imagen de Hectorweb

hola, estoy leyendo sobre este frameworks pero muestra unos codigos y todo bien, pero quien me yuda a dar el primer paso, osea como se usa, un ejemplo.. es que veo que colocan

// sets class="highlighted" for all child nodes of "mydiv"
children.each(function(child) {
child.setAttribute("class", "highlighted");
});

Y MI PREGUNTA ES ESO DONDE COÑO SE PONEE???? o como se llamaa, como se usa??????

HELP...

Imagen de Prezenty
Imagen de Prezent
Imagen de Juancar

Muchas gracias por tomarte el tiempo para mostrarnos nuevas formas de desarrollar.

La verdad es que cada vez más uso javascript para facilitarles la vida a los usuarios, y gracias a ti también se va a facilitar la mía.

Buen trabajo!!

Imagen de Jonathan
Jonathan

Excelente, trabajo!

Imagen de Omar
Imagen de Counter Strike

Excelente, yo trabajo freelance con perl, PHP/AJAX pero en mis aplicaciones uso mi propio JS y prototype es excelente, me ha ahorrado mucho tiempo de desarrollo, gracias por el art

Imagen de Kitune

Muy buen trabajo, felicidades. Estoy empezando con prototype y me va a servir de mucha ayuda estos artículos.  Como ya lo hizo el de Edicion in Situ.  Permíteme que los enlace desde mi blog :)

Imagen de Max

I've been thinking about this a little more.Patching IE is too slow. Especially the event model. On a Mozilla platform you have access to the underlying DOM objects. It is an easy matter to extend the interfaces of any object you like. To do the same on IE, you have to extend the interface of each individual DOM object. This is really really slow.User scripts are no different to other scripts IMO. I think you should keep GreaseMonkIE simple. The same as the original GreaseMonkey. Keep it as a mechanism for injecting user scripts.One possiblity is that you guys (Todd and Aaron) could come up with a mini API to aid in the creation of cross-browser user scripts. GM_addEventListener immediately springs to mind. :-)My real belief is that both GMs should be plain and simple. Leave the cross-browser headache to the scripters themselves.

Imagen de pepo
pepo

horrible tutorial

Imagen de Sergio

Gracias por difundir nuevas formas de programar, todos los que necesitamos crear aplicaciones nos es de gran utilidad todos estos articulos on line que dan soporte para crear nuevas aplicaciones.

Imagen de Allegro
Imagen de Omar

es posible crear un arbol con la estructura de un objeto usando $H(objeto)  ??

Imagen de tanie projektowanie www
Imagen de netsearch

Gracias por difundir nuevas formas de programar, todos los que necesitamos crear aplicaciones nos es de gran utilidad todos estos articulos on line que dan soporte para crear nuevas aplicaciones.

Imagen de Nick Mayer
Imagen de Pendrive
Imagen de luna

Gracias por difundir nuevas formas de programar..Gracias!

Imagen de migueljavier

a ver si me podeis resolver esto,estoy haciendo una web,sencilla en flash,pero tengo un grave problema,os explico,vamos a ver,parto de que va a ser visitada desde un link,entonces yo quiero saber quien me ha visitado desde ese link,ya que unos pueden entrar directos desde la url y otros a traves de ese link que esta en otra web,vale,pero ademas,tengo un carrito de la compra,y me gustaria saber si el que entro desde ese link hace algun pedido.Los archivos serian:El del link-------link1.htmlEl del pedido----pedido.htmlEs decir,me gustaria que hubiera algun javascript que cuando pinchen en el link que va ha entrar en mi web,o lo mismo deberia hacer un html que digera que va a entrar en mi web,y desde ahi cargar el javascript,y se pegara directamente en la hoja de pedido que es un html,por si llega al carro de la compra y decide comprar.Asi tener constancia que el pedido lo ha realizado un señor que entro desde un link determinado.Miguel.   

Imagen de Sortorama
Imagen de Adam

Gracias por difundir nuevas formas de programar !

Imagen de luna 95
Imagen de kredi
Imagen de Aukcje

Thanks for very interesting article. btw. I really enjoyed reading all of your posts. It’s interesting to read ideas, and observations from someone else’s point of view… makes you think more.

Imagen de mazury
Imagen de kanutouren
Imagen de Minimal

Páginas

Tutoriales

Cómo descargar videos de VK.com
En este artículo voy a explicar como descargar videos y películas...
Descargar Facebook Móvil Gratis
Por si aún no lo han hecho, es posible descargar Facebook Móvil...
Cómo generar tráfico web con las redes sociales - Paso a Paso
Muchas empresas están publicando contenidos como la forma de crear...

Artículo Recomendado

3 Tips cruciales para recuperar archivos eliminados
¿Te imaginas perder el trabajo de toda una semana en tan solo unos segundos? Todos hemos pasado por este problema. Quizás eliminamos por error un archivo importante o lo borramos sin pensar que era valioso para otro... más