Contenido

DOMCached, librería para facilitar el almacenamiento DOM con jQuery y Prototype

23 feb

+ 6

Ayer vimos como Web SQL Database apunta buenas maneras para el futuro del almacenamiento de datos en el cliente. Tambien hemos visto lo interesante del almacenamiento DOM como sustituto de las odiosas cookies, Lawnchair nos ofrecía un interfaz límpio y cómodo para interactuar con estas opciones, y ahora DOMCached, nos facilita tambien la integración con jQuery y Prototype.

// Ejemplo jQuery
<script src="jquery.js"></script>
<script src="jquery-json.js"></script>
<script src="domcached.js"></script>
<script>
// Leemos el valor de "key"
var value = $.DOMCached.get("key");
if(!value){
	// Si no está disponible lo cargamos desde el servidor
 	value = load_data_from_server()
 	// Lo añadimos al DOM para futuros usos
	$.DOMCached.set("key",value);
}
</script>

Compatible con la mayoría de navegadores actuales, DOMCached está disponible como plugin para Prototype y para jQuery. Podemos ver el código fuente alojado en GitHub y probarlo en vivo mediante este ejemplo usando el plugin jQuery.

Idle Spy para MooTools, usa Ajax solo cuando sea necesario

23 ene

+ 3

Alfredo Artiles nos vuelve a deleitar con un espectacular script con el que aprovecharemos al máximo los recursos del usuarios y los de nuestro servidor haciendo peticiones Ajax solo cuando estemos en una aplicación web.

El script montado para funcionar con MooTools, se basa en que cuando cambiamos de pestaña el navegador continua ejecutando nuestros scripts de actualización mediante Ajax. Estas llamadas consumen recursos sin ser necesarios, ya que estamos en otra pestaña. Alfredo ha optado por controlar el movimiento del ratón y teclado sobre la página y en caso de pasar un tiempo sin que este actúe sobre nuestra página cancelará nuestras peticiones Ajax.

Modo de empleo

var idleSpy = new IdleSpy({
 idleTime: 300000
});
idleSpy.addEvents({
 'idle': function() { /* on user idle code here */ },
 'back': function() { /* on user back code here */ }
});
idleSpy.start();

Básicamente lo que nos ofrece el script es la posibilidad de definir un tiempo de espera antes de activar el evento idle en el que definiremos que hacer cuando llevemos X segundos sin actuar sobre nuestra página. Posteriormente, definiremos el evento back que se encargará de reestablecer todo lo que hayamos parado previamente.

¿Para jQuery?

Los que usamos jQuery tambien tenemos un plugin que nos permite realizar la misma tarea. jQuery idleTimer, nos permite definir ambos eventos.

// timeout en milliseconds; defaults 30000
$.idleTimer(10000);

$(document).bind("idle.idleTimer", function(){
// ....
});

$(document).bind("active.idleTimer", function(){
// ....
});

$.idleTimer('destroy');

Nicholas C. Zakas, implementó hace ya tiempo una versión para YUI que los desarrolladores que usen pueden tener en cuenta.

Actualizo (11:58)

Alfredo me avisa de que ha encontrado uno para funcionar con Prototype.

jQuery 1.4 por fin vió la luz

15 ene

+ 23

Hace ya tiempo que jQuery anunció la versión 1.4, primero fue en versión Alpha y posteriormente en Release Candidate, hoy oficialmente ha visto la luz la versión final, y para ello se ha creado un nuevo dominio http://www.jquery14.com destinado a mostrarnos lo que la que la nueva versión nos ofrece.

Rendimiento

4271691293_8e11e4666d_o
(Ver Imagen)

Como todas las versiones de jQuery, el rendimiento es algo que tiende a disminuirse. En esta versión, hay que destacar que las funcionalidades más comunes han mejorado sustancialmente sus tiempos de respuesta en comparación la versión 1.3.2.

4271691747_a8733f1b1f_o
(Ver Imagen)

Sobretodo las funciones que atacan al DOM han recibido una impresionante optimización. Y por fin, la generación de HTML mediante el método html() mejora hasta un 300% el tiempo de respuesta.

4271691147_ae533c2cd5_o
(Ver Imagen)

Al igual que los métodos attr() y css() (mejora un 200%) que mejoran sustancialmente frente a la versión anterior del framework.

Setters mejorados

Los setters son aquellos métodos que nos permiten modificar los atributos, estilos o valores de los elementos jQuery. En esta nueva versión se han replanteado para facilitar su funcionamiento. Para ello nos permiten pasar funciones como parámetros que contendrán el valor actual del elemento, ideal para realizar modificaciones sobre el valor actual.

// Buscamos todos los &amp; y los añadimos a un span
$('a').html(function(i,html){
 return html.replace(/&amp;/gi,'<span>&amp;</span>');
});

// Añadimos información al title de los enlaces externos
$('a[target]').attr("title", function(i,title){
 return title + " (Opens in External Window)";
});

Creación sencilla de elementos

Crear elementos mediante jQuery será tan sencillo como esto:

jQuery("<div/>", {
 id: "foo",
 css: {
 height: "50px",
 width: "50px",
 color: "blue",
 backgroundColor: "#ccc"
 },
 click: function() {
 $(this).css("backgroundColor", "red");
 }
}).appendTo("body");

Ideal para generar elemento que no necesariamente deben añadirse al DOM nada más ser creados.

eq(-N) y get(-N)

Imagina que quieres obtener los dos últimos elementos de una lista, con esta nueva funcionalidad será más sencillo todavía conseguirlo.

$("#listado").get(-2);

Eventos

Los eventos también han sido optimizados y replanteados, además de que todos los eventos para ser live() (excepto ready(), focus() y blur()) aunque usemos bind(), nos permitirá encadenar varios en la misma llamada.

$("div.test").bind({
 click: function(){
 $(this).addClass("active");
 },
 mouseenter: function(){
 $(this).addClass("inside");
 },
 mouseleave: function(){
 $(this).removeClass("inside");
 }
});

jQuery.proxy()

Esta función nos permitirá solventar el problema del contexto entre funciones, con ella será sencillo reutilizar código:

var app = {
 config: {
 clickMessage: 'Hi!'
 },
 clickHandler: function() {
 alert(this.config.clickMessage);
 }
};

// jQuery 1.3.2
jQuery('a').bind('click', app.clickHandler);  // Esto produce un error al llamar a this dentro de jQuery

// jQuery 1.4
jQuery('a').bind(
 'click',
 jQuery.proxy(app, 'clickHandler')
);

delay()

Se trata de una implementación más limpia de setTimeout() que nos permitirá pausar nuestros scripts.

$("div").fadeIn().delay(4000).fadeOut();

Descargar

corMVC, modelo MVC basado en jQuery

22 dic

+ 5

El modelo MVC nos permite separar las diferentes capas de nuestros desarrollos de una forma clara, actualmente es la arquitectura más usada por los principales lenguajes de programación para generar frameworks que nos facilitan el trabajo.

cormvc-overview
(Ver Imagen)

Esa es la idea de corMVC, un framework jQuery que nos implementa esta tecnología. Para ello nos ofrece window.application con una serie de métodos para trabajar cómodamente con las diferentes capas.

Instalación

Para instalar el framework, y al estar basado en jQuery, debemos incluirlo previamente como vemos en el código:

<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="application.js"></script>

Modo de empleo

mvc-workflow
(Ver Imagen)

Una vez instalado en nuestra página, podemos empezar a usar los métodos disponibles para difinir nuestro código.

Modelo

window.application.addModel((function( $, application ){

	function Contact( ){
		// ....
	};

	Contact.prototype.validate = function(){
		// ....
	};

	return( Contact );
})( jQuery, window.application ));

En este ejemplo, vemos como podemos definir el objeto que será usado como modelo en nuestra aplicación.

Controlador

window.application.addController((function( $, application ){

	function Controller(){
		// Rutas que dirigen nuestras acciones
		this.route( "/", this.index );
		this.route( "/contacts/", this.index );
		this.route( "/contacts/add/", this.addContact );
		this.route( "/contacts/edit/:id", this.editContact );
		this.route( "/contacts/delete/:id", this.deleteContact );
	};

	Controller.prototype = new application.Controller();
	Controller.prototype.init = function(){
		// Cargamos la vista
		this.contactFormView = application.getView( "ContactForm" );
	};
	Controller.prototype.addContact = function( event ){
		// Mostramos la vista
		this.showView( this.contactFormView, event );
	};
	Controller.prototype.editContact = function( event, id ){
		// ...
	};
	Controller.prototype.deleteContact = function( event, id ){
		// Cargamos el modelo
		application.getModel( "ContactService" ).deleteContact(
			id,
			function(){
				application.relocateTo( "contacts" );
			}
		);
	};
	ContactService.prototype.saveContact = function(){
		var self = this;
		// Ajax para grabar datos
		application.ajax({
			url: "...",
			data: {
				....
			},
			normalizeJSON: true,
			success: function( response ){
				if (response.success){
					// ...
				} else {
					// ...
				}
			}
		});
	Controller.prototype.index = function( event ){
		// ...
	};
	Controller.prototype.showView = function( view, event ){
		// ...
	};

	return( new Controller() );

})( jQuery, window.application ));

El controlador se encargará de redirigir nuestras acciones para interactuar con el modelo. Como podemos ver, indicamos las rutas asociadas a los métodos del controlador.

View

window.application.addView((function( $, application ){

	function ContactForm(){
		// Parámetros por defecto
		this.form = null;
		// ...
	};
	ContactForm.prototype.init = function(){
		var self = this;
		this.form = $( "#contact-form" );

		this.form.submit(
			function( event ){
				self.submitForm();
				return( false );
			}
		);
	};

	ContactForm.prototype.submitForm = function(){
		var self = this;

		// Obtenemos el modelo
		application.getModel( "Contact" ).saveContact(
			// ...
			function( id ){
                                // Redirigimos al controlador
				application.relocateTo( "contacts" );
			},
			function( errors ){
				self.applyErrors( errors );
			}
		);
	};
	return( new ContactForm() );
})( jQuery, window.application ));

La vista, nos permitirá dirigir los datos hacia y desde el usuario.

Templates

<script id="contact-list-item-template" type="application/template">
 <li>
   <div>
     <a>${name}</a>
   </div>
   <div>
     <a href="javascript:void( 0 )">more</a> &nbsp;|&nbsp;
     <a href="#/contacts/edit/${id}">edit</a> &nbsp;|&nbsp;
     <a href="#/contacts/delete/${id}">delete</a>
   </div>
   <dl>
     <dt>name:</dt>
     <dd>${name}</dd>
     <dt>phone:</dt>
     <dd>${phone}</dd>
     <dt>email:</dt>
     <dd>${email}</dd>
   </dl>
 </li>
</script>

Como buen framework, nos ofrece un motor de plantillas destinado para pintar la salida que la vista nos ofrece.

Aunque a simple vista parezca un poco engorroso, los que hayan usado alguna vez el modelo MVC sabrán que este código solo ofrece ventajas a la hora de trabajar con varios desarrolladores o para organizar el código de proyectos medianamente grandes.

jQuery 1.4 Alpha 2

19 dic

+ 6

El equipo de desarrollo de jQuery no para y si ojeas el código de esta versión 1.4 Alpha 2 verás que no han estado descansando este tiempo. En cuanto a velocidad en interacción con el DOM podemos ver que la evolución desde la 1.2.6 es constante y sobretodo buena para nosotros.

RightJS es entre 6-8 veces más rápido que jQuery

13 dic

+ 15

Hace unos meses vimos que jQuery era el framework JS más lento de los probados con TaskSpeed (un test masivo sobre frameworks JS). Ahora la versión 1.5 de RightJS, deja al framework desarrollado por John Resig a la altura del betún demostrando que és hasta 8 veces más rápido que jQuery.

Google Chrome

chrome
(Ver Imagen)

Además vemos como la versión 1.4 alpha 1, recien anunciada, mejora el tiempo de respuesta algo pero no lo suficiente para competir con RightJS en alguna de las prueabas realizadas.

Mozilla Firefox 3.5.5

ff
(Ver Imagen)

También es interesante ver en las imágenes que sobre Google Chrome, RightJS llega a ser hasta un 740% más rápido (jQuery 1.3.2) frente a los resultados en Firefox 3.5 en el que vemos que la diferencia solo es de 333% con la misma versión de jQuery, será por que John Resig trabaja en Mozilla :D

Actualizo:

Grabriel en uno de los comentarios nos pasa la url de donde se ha realizado el test. Con la aparición de la versión 1.5.0 de RightJS se decidió enfrentear con la aplicación TaskSpeed (que se encarga de testear los aspecto más comunes de los frameworks JS) esta nueva versión con la de los principales frameworks, obteniendo unos tiempos como vemos en las imágenes anteriores.

Despues nos muestra un par de optimizaciones para conseguir un tiempo similar al ofrecido por RightJS (343ms jQuery vs 80ms RightJS).

"make": function(){
	for(var i = 0; i<250; i++){
 	document.body.appendChild(
 		$(
 		"<ul id='setid" + i + "' class='fromcode'>"+
 		"<li>one</li>"+
 		"<li>two</li>"+
 		"<li>three</li>"+
 		"</ul>"
 		)[0]
 	);
 	}
 	return $("ul.fromcode").length;
}

Como podemos ver el código que deberíamos usar para poder acercarnos a ese tiempo, debemos prescindir de todo el jQuery posible, basando nuestro Script en Javascript puro y duro.

"make": function(){
	var elements = '<div>';
 	for(var i = 0; i<250; i++){
 		elements = elements+
 			"<ul id='setid" + i + "' class='fromcode'>"+
 			"<li>one</li>"+
 			"<li>two</li>"+
 			"<li>three</li>"+
 			"</ul>";
 		}
 		$(elements+'</div>')
 		.children()
 		.each(function() {
 			document.body.appendChild(this);
 			});
 return $("ul.fromcode").length;
}

Aclaración

Evidentemente un Framework Javascript no se evalua únicamente por la velocidad de ejecución, sinó que hay factores igual o más importantes, como la documentación, comunidad y compatibilidad con navegadores. Este estudio, únicamente debe servir para detectar este problema y conocerlo para poder encontrarle solución en caso de toparnos con este problema.

¿Como detectan el navegador los diferentes frameworks Javascript?

1 dic

+ 2

Detectar el navegador no siempre es la mejor solución para condicionar nuestros scripts, siempre que podamos deberíamos detectar si las funcionalidades que vamos a ejecutar están disponibles y en caso de no estarlo ofrecer una alternativa, sin importar el navegador. Pero, como bien sabemos, no siempre podemos hacer lo correcto.

En estos casos, saber como lo hacen los frameworks Javascript más usados nos permitirá hacernos una idea de como actuar frente a este problema.

jQuery

Aunque desde la versión 1.3 el atributo browser está desaprovado, aún está disponible en el código para que se vayan migrando los scripts. Supongo que en breve dejará de estar, dejando paso a la detección de funcionalidades.

var userAgent = navigator.userAgent.toLowerCase();
// Figure out what browser is being used
jQuery.browser = {
	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
	safari: /webkit/.test( userAgent ),
	opera: /opera/.test( userAgent ),
	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
};

En este caso, hace uso del userAgent para comprobar mediante expresiones regulares el navegador del usuario. Se trata de una comprobación muy genérica y que no nos permite detectar móviles.

MooTools

Por otro lado, MooTools, nos ofrece un objeto (Browser) que nos permite detectar el motor de renderizado sin importar el navegador.

var Browser = $merge({
  Engine: {name: 'unknown', version: 0},
  Platform: {name: (window.orientation != undefined) ? 'ipod' : (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase()},
  Features: {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)},
  Plugins: {},
  Engines: {
    presto: function(){
      return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925));
    },
    trident: function(){
      return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4);
    },
    webkit: function(){
      return (navigator.taintEnabled) ? false : ((Browser.Features.xpath) ? ((Browser.Features.query) ? 525 : 420) : 419);
    },
    gecko: function(){
      return (!document.getBoxObjectFor && window.mozInnerScreenX == null) ? false : ((document.getElementsByClassName) ? 19 : 18);
    }
  }
}, Browser || {});

Como podemos ver, se encarga de realizar una serie de comprobaciones de funcionalidades para determinar el motor de renderizado que está usando el visitante.

Prototype

Prototype, al igual que MooTools nos ofrece un objeto (Browser) que nos ofrece la versión del navegador.

Browser: (function(){
   var ua = navigator.userAgent;
   // Opera (at least) 8.x+ has "Opera" as a [[Class]] of `window.opera`
   // This is a safer inference than plain boolean type conversion of `window.opera`
   var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
   return {
     IE: !!window.attachEvent && !isOpera,
     Opera: isOpera,
     WebKit: ua.indexOf('AppleWebKit/') > -1,
     Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
     MobileSafari: /Apple.*Mobile.*Safari/.test(ua)
   }
 })(),

Al igual que jQuery comprueba el navegador mediante expresiones regulares simples que no nos permite detectar versiones móviles.

YUI

YUI nos ofrece un atributo que nos indicará el navegador que está usando el usuario.

ua = nav && nav.userAgent,
if (ua) {

  if ((/windows|win32/i).test(ua)) {
    o.os = 'windows';
  } else if ((/macintosh/i).test(ua)) {
    o.os = 'macintosh';
  }

  // Modern KHTML browsers should qualify as Safari X-Grade
  if ((/KHTML/).test(ua)) {
    o.webkit=1;
  }
  // Modern WebKit browsers are at least X-Grade
  m=ua.match(/AppleWebKit\/([^\s]*)/);
  if (m&&m[1]) {
    o.webkit=numberfy(m[1]);

    // Mobile browser check
    if (/ Mobile\//.test(ua)) {
      o.mobile = "Apple"; // iPhone or iPod Touch
    } else {
      m=ua.match(/NokiaN[^\/]*|Android \d\.\d|webOS\/\d\.\d/);
      if (m) {
        o.mobile = m[0]; // Nokia N-series, Android, webOS, ex: NokiaN95
      }
    }

    m=ua.match(/AdobeAIR\/([^\s]*)/);
    if (m) {
      o.air = m[0]; // Adobe AIR 1.0 or better
    }

  }

  if (!o.webkit) { // not webkit
    // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
    m=ua.match(/Opera[\s\/]([^\s]*)/);
    if (m&&m[1]) {
      o.opera=numberfy(m[1]);
      m=ua.match(/Opera Mini[^;]*/);
      if (m) {
        o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
      }
    } else { // not opera or webkit
      m=ua.match(/MSIE\s([^;]*)/);
      if (m&&m[1]) {
        o.ie=numberfy(m[1]);
      } else { // not opera, webkit, or IE
        m=ua.match(/Gecko\/([^\s]*)/);
        if (m) {
          o.gecko=1; // Gecko detected, look for revision
          m=ua.match(/rv:([^\s\)]*)/);
          if (m&&m[1]) {
            o.gecko=numberfy(m[1]);
          }
        }
      }
    }
  }
}

Al igual que jQuery y Prototype, recurre a las expresiones regulares para detectar el navegador, con la diferencia de que esta implementación nos permite detectar alguna versión más de las disponibles.

FireQuery, jQuery con Firebug con cualquier página

31 oct

+ 3

Jose Dueñas publica en Twitter una interesante aplicación que nos permite disponer de jQuery en cualquier página con Firebug.

jQueryfy
(Ver Imagen)

De esta forma tienes a tu disposición todas las facilidades que jQuery en cualquier página que este editando. Ideal para depurar las aplicaciones que no podemos editar directamente.

Versión sin plugin

Básicamente podemos conseguir lo mismo sin necesidad de usar ningún plugin ejecutando un pequeño script desde Firebug.

var s = document.createElement("script");
s.type = "text/javascript";
s.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js";
document.getElementsByTagName("head")[0].appendChild(s);

De esta forma, usaremos Google Ajax Libraries para cargar jQuery desde los servidores de Google.

jQuery.animate, todo lo que siempre quisiste saber

13 oct

+ 0

Si te gusta jQuery, y estás aprendiendo a usar animaciones con él, este artículo te mostrará todo lo que necesitas saber para usar el método animate(), esencial para conseguir que nuestras animaciones se realizen perfectamente.

jQuery 1.3 Visual Cheat Sheet

24 sep

+ 9

Antonio de Woork nos vuelve a sorprender, gratamente, con una nueva Cheat Sheet. En este caso se trata de jQuery 1.3 y una espectacular (y extensa) hoja recopilatoria con todas las opciones del potente framework.[Descargar][Preview]