Contenido

5 formas de usar Ajax con jQuery

18 ago

+ 14

La gente de Nettuts publica un interesante artículo de como usar Ajax con jQuery. Concretamente las 5 formas con las que jQuery nos permite enviar peticiones asíncronas.

  1. $.load()
  2. $.get()
  3. $.post()
  4. $.getJSON()
  5. $.getScript()

$.load()

Se trata de la función que más me gusta de jQuery ya que hace que una de las tareas más comunes de desarrollar con Ajax sea tan sencillo y claro como veremos en el ejemplo:

$("#links").load("/Main_Page #jq-p-Getting-Started li");

Este ejemplo, traído de la página de documentación de jQuery, se encarga de lanzar una petición a la URL /Main_Page (usa URL Rewrite) y del HTML de respuesta cogemos los elementos  #jq-p-Getting-Started li y lo insertamos dentro de #links.

Simplemente genial, cómodo y rápido.

$.get()

Se trata del función sencilla con la que podemos lanzar peticiones GET al servidor mediante Ajax.

$.get("test.cgi", { name: "John", time: "2pm" },
  function(data){
    alert("Data Loaded: " + data);
  });

Mediante el paso de 3 opciones, de las cuales 2 son opciones ( condicionales mejor dicho) puedes lanzar la petición al fichero (1º) con los parámetros (2º) y tratar la respuesta mediante un callback (3º).

$.post()

Al igual que la anterior, esta función permite enviar peticiones POST mediante ajax.

$.post("test.php", { name: "John", time: "2pm" },
  function(data){
    alert("Data Loaded: " + data);
  });

Igual de fácil que en el caso anterior.

$.getJSON()

Aunque los anteriores tienen la posibilidad de especificar el tipo de retorno, la opción más cómoda es la de usar este método que permite obtener la respuesta JSON evaludada en la función callback.

$.getJSON("test.js", { name: "John", time: "2pm" }, function(json){
  alert("JSON Data: " + json.users[3].name);
});

Teniendo en cuenta el navegador, se usará el objeto JSON nativo o se usará el sistema basado en eval().

$.getScript()

Aunque técnicamente no es una petición Ajax, se trata de una petición al servidor y por eso tiene cabida en el post.

$.getScript("test.js", function(){
  alert("Script loaded and executed.");
});

Con este método podemos cargar asíncronamente un fichero Javascript y mediante el parámetro (2) callback podemos ejecutar código Javascript usando el que está en el fichero js que queremos cargar (1).

Carga asíncrona de grandes cantidades de dátos con Ajax

22 mar

+ 31

Ajax es una técnica para cargar asíncronamiente datos que podremos usar en nuestras páginas web. Esta técnica ha permitido a las aplicaciones web que evolucionen hasta el nivel actual y darán lugar a nuevas aplicaciones más potentes y complejas.

Esta técnica se basa en el uso de xmlhttprequest() para lanzar llamadas de forma asíncrona al servidor, pudiendo así devolver datos cargados posteriormente a la carga de la página. De esta forma la carga inicial de la página puede ser menor y dejar a elección del usuario cargar los datos a medida que los vayan necesitando.

El problema no lo encontramos con la cantidad de datos. Si el número de datos devueltos por el servidor es muy alto esto suele convertirse en una larga espera, con el fichero .gif de loading reglamentario.

Para intentar mitigar este problema he estado haciendo una serie de pruebas, con fín de dejar los ficheros XML que hasta ahora he estado usando en algunos proyectos.

XML

Durante mucho tiempo ha sido el sistema usado en muchas implementaciones para obtener datos de forma asíncrona. De ahí el propio nombre de AjaX (Asynchronous JavaScript And XML). Estos ficheros, generalmente ofrecen mayor interconexión con multiples herramientas.

En un uso para carga asíncrona, nos encontramos como príncipal problema el peso del fichero y tiempo invertido en recorrer el fichero XML para obtener los datos.

....
<hotel>
	<code>0000</code>
	<name>Hotel0</name>
	<direction>Calle0</direction>
	<telef>Telf0</telef>
	<geo>
		<lat>00</lat>
		<lng>00</lng>
	</geo>
</hotel>
....
// Javascript
var hotelDescription = data, hotelList = [];
var data = data.getElementsByTagName("hotel");
for (var x in data) {
	var hotel = data[x];
	if (!hotel.getElementsByTagName) continue;
	hotelList.push(hotel.getElementsByTagName("name")[0].firstChild.data);

		hotelDescription[hotel.getElementsByTagName("name")[0].firstChild.data] = {
			code: hotel.getElementsByTagName("code")[0].firstChild.data,
			name: hotel.getElementsByTagName("name")[0].firstChild.data,
			direction: hotel.getElementsByTagName("direction")[0].firstChild.data,
			telf: hotel.getElementsByTagName("telef")[0].firstChild.data,
			geo: {
				lat: hotel.getElementsByTagName("lat")[0].firstChild.data,
				lng: hotel.getElementsByTagName("lng")[0].firstChild.data
			}
		};

}

JSON

La primera alternativa, fué JSON, una implementación muy clara y natural de mostrar datos. Al tratarse de un fichero TXT podemos hacer que ocupe menos espacio y al evitar la estructura XML conseguimos que el tiempo invertido en recorrer el XML para obtener los datos.

Pero por contra, para poder usar los datos obtenidos hemos de usar la función eval() lo que nos penaliza la carga del fichero. Una vez evaluado el código el tiempo empleado en preparar los datos para poder usarlos es mínimo y sin duda, el más rápido de los sistemas exáminados.

....
{
	code: 0000,
	name: 'Hotel0',
	direction: 'Calle0',
	telef: 'Telf0',
	geo: {
		lat: 00,
		lng: 00
	}
}
....
// Javascript
var hotelDescription = data, hotelList = [];
for (var x in data) hotelList.push(data[x].name);

TXT

La gente de Flickr comentaba hace poco como hicieron para devolver más de 10.000 resultados en menos de 200ms. Y obviamente me ví obligado a contemplar esta técnica.

Se basa en usar una estructura preestablecida en un fichero de texto plano. Usando un separador por registro y otro por campos dentro de cada registro. De esta forma a la hora de cargar el fichero simplemente tendremos que hacer una serie de split() para cortar la cadena y convertirla en una variable que podamos usar.

Como mayor ventaja, esta técnica ofrece un tamaño de fichero mucho más pequeño que los comentados anteriormente. Por contra el tiempo de proceso sobre los datos para obtener una variable que pdamos usar es mucho mayor que la necesaria para procesar el fichero JSON, pero bastante menor que el empleado para un fichero XML.

0000:Hotel0:Calle0:Telf0:00:00|...
// Javascript
var tmp = data.split("|");
var hotelList = [];
var hotelDescription = [];
for (var x = 0, len = tmp.length; x<len; x++) {
	var hotel = tmp[x].split(":");

	hotelList.push(hotel[1]);

	hotelDescription[hotel[1]] = {
		code: hotel[0],
		name: hotel[1],
		direction: hotel[2],
		telf: hotel[3],
		geo: {
			lat: hotel[4],
			lng: hotel[5]
		}
	};
}

Comparativas

Para las pruebas, he realizado una pequeña aplicacion que nos permite cargar 500, 1000, 2000, 5000 o 10000 registros en los formatos anteriores (XML, JSON o TXT). Para los gráficos he usado los resultados obtenidos en Firefox 3.0.7 en Mac Os X.

Si queréis podéis probar por vosotros mismos los resultados que obtendríais en diferentes navegadores directamente aqui.

500 registros

500_registros

1000 registros

10000_registros

2000 registros

2000_registros2

5000 registros

5000_registros

10000 registros

10000_registros

Parece que los gráficos hablan por si solos, y podemos sacar una información interesante.

Conclusiones

bigajax

De los resultados obtenemos las siguientes premisas:

XML

  • Son los ficheros más pesados
  • El tiempo de procesamiento es mayor que los demás.

JSON

  • Son los ficheros que más tiempo tardan en cargar completamente.
  • El tiempo de procesamiento es el más rápido de los testeados.

TXT

  • Son los ficheros menos pesados.
  • El tiempo de proceso y carga son bajos aunque no destacan frente a los demás.
  • El tiempo total es el menor de los testeados.

Descargar el proyecto

He subido el proyecto a Github para que los descargueis y usais si quereis.

Preloaders.net, imagenes de loading en 3D

2 feb

+ 3

Jesus Moreno me muestra Preloaders.net, un sitio al estilo ajaxload.info que nos permite generar imagenes de “Cargando” para nuestras aplicaciones, pero en esta podemos generar imagenes con animaciones en 3D.

Pseudo-ajax para leer ficheros locales

12 ene

+ 7

CSSGalery.info nos muestra una solución para leer fichero cuando ejecutamos HTML desde nuestro local. Detectando si la página está siendo ejecutado en un entorno local mediante el protocolo file: de la URL decide como actuar ante una llamada a la función get_content().

function get_content(url,update) {
	if ( document.location.protocol == "file:" ) {
		// console.log("local");
		var ifr = new IFrame({
		src:url,
		events:{
		load: function() {
				$(update).set("html", this.contentWindow.document.body.innerHTML );
			}
		}
		}).inject(document.body);
	}else {
		// console.log("server");
		var myHTMLRequest = new Request.HTML({
		update:update,
		}).get(url);
	}
}

La función get_content(), a la que le pasamos la ruta y donde queremos descargar el cotenido se encarga de hacer todo el trabajo por nosotros. Para los que no usamos MooTools he montado una versión en JS sin necesidad de trabajar con ningún framework.

function get_content(url,update) {
  if ( document.location.protocol == "file:" ) {
    var ifr = document.createElement("iframe");
    ifr.src = url;
    ifr.onload = function() {
	document.getElementById(update).innerHTML = this.contentWindow.document.body.innerHTML;
    }
    document.getElementsByTagName("body")[0].appendChild(ifr);
  }else {
    var ajax = (XMLHttpRequest)?new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP');
    ajax.open('GET', URL); 
    ajax.onreadystatechange = function(){
		document.getElementById(update).innerHTML = ajax.responseText;
    }; 
    ajax.send(null); 
  }
}

Desde CSSGallery.info podemos testear la versión online y/o descargar un zip para probarlo en nuestro local.

CSSHttpRequest, ajax cross-domain con CSS

24 oct

+ 6

El Ajax entre diferentes dominios es algo que veremos dentro de unos meses en las nuevas versiones de los navegadores actuales. Mientras tanto los desarrolladores están dando soluciones a esta necesidad y ahora, usando la manipulación del CSS desde Javascript solventan el problema

CSSHttpRequest.get(
        "http://www.nb.io/hacks/csshttprequest/hello-world/",
        function(response) { alert(response); }
    );

Si revisamos el código, vemos la magia de esta técnica:

var s = chr.getStyleSheet();

    // IE
    if(s.addImport) {
        index = s.addImport(url);
        item = s.imports(index);
    }

    // W3C
    else if(s.insertRule) {
        index = s.insertRule("@import url(" + url + ");", 0);
        item = s.cssRules[index];
    }

Me encanta ver como la necesidad despierta estas maravillas entre los desarrolladores.

16 formularios de contacto con Ajax

22 oct

+ 1

Interesante recopilatorio de formularios de contacto que usan la tecnología Ajax para complementar funcionalidades y ofrecer al usuario una página atractiva y cómoda de usar.

Firefox3 integra opción nativa para gestionar la subida de ficheros

8 jul

+ 3

Una de las nuevas funcionalidades de Firefox3 es la extensión de los elementos <input type="file" /> que nos permite utilizarlos previamente antes de subirlos a nuestro servidor mediante Javascript.

firefox3_files

Como podemos ver en Firebug, vemos que los elementos <input /> incorporan una propiedad DOM extra llamada files, que se compone de un array de elementos ordenados que hacen referencia a los ficheros subidos mediante ese elemento.

Esta propiedad, dispone de 3 métodos con las que podremos hacer uso de los elementos que subamos:

  • Atributos : fileSize y fileName
  • Métodos: getAsDataURL, getAsBinary y getAsText

Ejemplo de uso

function writeText() {
    var data = $('text').files.item(0).getAsBinary();
    $('result').update(data);
    $('textsize').update($('text').files.item(0).fileSize);
}
function writeImage() {
  var data = $('image').files.item(0).getAsDataURL();
  $('imageresult').src = 'data:' + data;
  $('imagesize').update($('image').files.item(0).fileSize);
}

Web Development Helper monitoriza ajax en tu Internet Explorer

25 may

+ 4

Gracias a edusanver descubro Web Development Helper es un plugin para Internet Explorer que nos permite, entre otras cosas, monitorizar las peticiones Ajax como si de Firebug en Firefox se tratara.

web_development_helper

Características

Entre las características más interesantes de este plugin se encuetran:

  • Inspector DOM de todos los elementos.
  • Capturas de imagenes de la página en la que estás.
  • Log de las peticiones HTTP (o HTTPS) solicitadas por el navegador o peticiones Ajax.
  • Ver las peticiones y respuestas en detalle.
  • Habilidad de filtrar por tipos de URL’s en los logs.
  • Traza de errores en detalle de las peticiones Javascript.
  • Consola con posibilidad de interacción Javascript usando (window.debugService).

Requerimientos

Descargar

Descargar

XDomainRequest() y como Microsoft hace lo que le da la gana

9 mar

+ 2

Uno de los problemas con los que nos encontramos al usar Ajax en nuestras aplicaciones es que nos es imposible acceder, mediante javascript, a contenidos de otro servidor usando el el objeto XMLHTTPRequest(), debiendo recurrir a alternativas algo “sucias”, por ello la W3C decidió dotar a este objeto la posibilidad de trabajar en cross-domain, osea entre diferentes dominios. Esto facilitaría, por ejemplo la lectura de feeds, o cualquier tipo de contenido servido por páginas externas a nuestro dominio.

La aparición del primer borrador por parte de la W3C, hizo que los principales navegadores centraran su atención en esta nueva funcionalidad y se pusieran manos a la obra para dotar a sus navegadores de tan esperada y necesaria funcionalidad.

Con la aparición de un navegador que dije que no volvería a nombrar proximamente, apareció otra vez el dilema. XDomainRequest() ha sido el desencadenante, al alejarse del estandar ofrecido por la W3C.

Según la página del propio Microsoft, el uso de este nuevo objeto sería así:

// 1. Creamos el objeto XDR
xdr = new XDomainRequest();

// 2. Abrimos la conexión con el servidor usando el método POST
xdr.open("POST", "http://www.contoso.com/xdr.txt");

// 3. Enviamos información al servidor
xdr.send("data to be processed");

Como podemos ver, esto se parece a la actual forma de usar el objeto XMLHttpRequest() con la diferencia del nombre del objeto y de que la url a la que solicitamos la información se trata de una URL absoluta en lugar de una relativa.

Algo similar a lo propuesto por la W3C, que era extender al objeto XMLHttpRequest() con la capacidad de acceder a servidores remotos sin necesidad de modificar el código existente.

var xhr = new XMLHttpRequest();
xhr.open("GET", "http://www.anieto2k.com/.../datos.php", true);
xhr.onreadystatechange = function(){
  if ( xhr.readyState == 4 ) {
    if ( xhr.status == 200 ) {
      document.body.innerHTML = "Respuesta: " + xhr.responseText;
    } else {
      document.body.innerHTML = "ERROR";
    }
  }
};
xhr.send(null);


Como podemos ver la diferencia nos hace recordar el odiado ActiveX() y las condiciones tan feas que hemos de hacer para hacer compatibles nuestros navegadores. ¿Ahora con la nueva versión tendremos que añadir una línea más?

var ajax =  function() {
  if (windows.XDomainRequest) { //IE8
	return new XDomainRequest();
  } else if (window.XMLHttpRequest) { //FF, Opera, IE7
    	return new XMLHttpRequest();
  } else if (window.ActiveXObject) { //IE6
  	return new ActiveXObject('Microsoft.XMLHTTP')
  } else { //No Ajax Compatibles
    	alert("No hay ajax");
   	return null;
  }
}

¿Nos encontramos con un nuevo ActiveX() (versión exclusiva para Internet Explorer 6.0) o será el nuevo innerHTML (Aceptado como parte del estandar tras ser una invención de Microsoft)?

XMLHttpRequest entre servidores con Firefox 3

10 ene

+ 6

Hace un mes vimos Ajax Cross Domain Script, un script que nos permite realizar una conexión entre servidores mediante Ajax, resolviendo una limitación del objeto XMLHttpRequest().

Hoy John Resig, anuncia que Firefox 3 integrará siguiente versión evolutiva del objeto XMLHttpRequest(), permitiendo realizar peticiones entre servidores de forma directa y nativa

Modo de uso

Para asegurar una cierta seguridad, intervendrán varios factores que harán posible que podamos personalizar nuestra propia lista de sitios permitidos o denegados.

Para ello deberemos hacer uso de la cabecera Access-Control, que forma parte del borrador Access Control for Cross-Site. Permitiendo o denegando el acceso al servidor.

Cabeceras Acces-Control 

 Las cabeceras Acces-Control, podrán ser usadas desde cualquier lenguaje de programación capaz de modificar las cabeceras salientes del servidor. Veamos unos ejemplos:

Ejemplo

//PHP
<?php header('Access-Control: allow <*>'); ?> //Permitimos todos
<?php header('Access-Control: deny <*>');?>  //Denegamos todos
<?php header('Access-Control: allow <mozilla.org>');?> //Permitimos solo mozilla.org
<?php header('Access-Control: allow <mozilla.org> exclude <developer.mozilla.org>');?> //Permitimos mozilla.org y denegamos developer.mozilla.org
<?php header('Access-Control: allow <developer.mozilla.org:80> method GET, POST');?> //Permitimos developer.mozilla.org para el puerto 80 en los métodos GET y POST

//XML
<?access-control allow="*"?> //Permitimos todos
<?access-control deny="*"?> //Denegamos todos
<?access-control allow="mozilla.org"?> //Permitimos solo mozilla.org
<?access-control allow="mozilla.org" exclude="developer.mozilla.org"?> //Permitimos mozilla.org y denegamos developer.mozilla.org
<?access-control allow="developer.mozilla.org" method="GET POST"?> //Permitimos developer.mozilla.org para el puerto 80 en los métodos GET y POST

Pese a que el borrador informa que no es posible usar variables GET entre servidores, Firefox 3 parece que si lo hará.  

Javascript

Gracias a una implementación limpia, las aplicaciones Ajax no necesitarán ser modificadas ya que el uso será exactamente igual del que estamos haciendo uso ahora. Simplemente que la URL de nuestras peticiones pueden comenzar por HTTP :D