Ajax y Request transparentes al usuario

La experiencia como usuario de una aplicación hecha con la suma de las Ajax es mucho mejor que sin. En un sitio sin llamadas asincrónicas tenemos que esperar a que vuelva a cargarse todo el sitio, cuando solo cambiamos el contenido principal o peor aún cuando guardamos un formulario y lo único nuevo que aparece es un mensaje de “Guardado ok”. Pero como toda tecnología tiene sus desventajas. La idea es poder eliminar las desventajas para no perder la usabilidad dada en la asincronía de Ajax.

Desventajas de Ajax

  • Los buscadores no ejecutan JavaScript (por lo menos no todo el JavaScript, solo algunas cosas)
  • La realidad es que no todos los navegadores tienen JavaScript o lo tienen activado
  • Olvidate del boton volver o recargar o guardar la página en un marcador o enviar el link a un amigo
  • Mayor costo de desarrollo por su complejidad y para gran parte de las necesidades simples se hacen a travéz de un framework por la falta de madurez del JavaScript

También existen otras desventajas, pero estas son las principales.

Google lo hizo

Bueno vamos a resolver algunos de estos problemas de una manera parecido como lo resuelve Gmail, con las anclas en los links. Las anclas (anchor en inglés) son los links que usamos para ir a una parte específica del sitio. Numeral, almohadilla, sostenido, en concreto #. Esas son las anclas.

¿Como funciona esto? Bueno en vez de simplemente ejecutar la función, lo que hacemos es cambiar la dirección por #lo-que-sea. Por ejemplo en Gmail cuando hacemos click en alguna etiqueta (label) nos envía a #label/NombreDeLaEtiqueta. Lo mismo que cuando vamos a la bandeja de entrada (inbox) nos redirige a #inbox. Entonces si copias el link y dice mail.google.com/mail/#label/Blog sabe que tiene que cargar la vista de la etiqueta “Blog”.

Bueno simplemente eso, las anclas pueden ser pasadas a un amigo, pueden ser guardadas en marcadores/favoritos (bookmarks) e incluso pueden ser guardadas en el historial para poder hacer atrás y adelante (nada que ver con el acto sexual o algún baile), dependiendo del navegador se necesita un hack con los iframes.

Ejemplo

Para el ejemplo vamos a aprovechar el Zend Framework y en el lado JavaScript Prototype, pero no es necesario ningún framework, bueno para la llamada de Ajax da muuuucha paja fiaca hacer una propia, pero cualquier framework/librería sirve.

La idea es tener un template principal y cargar el contenido principal por Ajax o por un request HTTP “normal”. Para esto Zend tiene un componente llamado Layout, en el cual definimos una vista en común para los módulos y acciones.

/app/views/scripts/layout.phtml
<?php

$urlPath = dirname($_SERVER['SCRIPT_NAME']) . '/';

?><html>
<head>
<title>Mi Ajax-HTTP Request</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<script src="<?php echo $urlPath ?>js/prototype.js"></script>
<script src="<?php echo $urlPath ?>js/cleanhttpcall.js"></script>
<script>
CleanHttpCall.BASE_PATH = "<?php echo $urlPath ?>";
window.onload = function()
{
CleanHttpCall.init();
}
</script>
</head>
<body>
<?php if(!isset($_SESSION['jsClose'])): ?>
<noscript>
Tienes JS deshabilitado. <a href="<?php echo $_SERVER['REQUEST_URI']; ?>?js=close">cerrar este mensaje</a>
</noscript>
<?php endif; ?>

<h1>Mi Ajax-HTTP Request</h1>

<ul>
<li><a href="<?php echo $urlPath ?>" class="ajax-link">Home</a></li>
<li>
<a href="<?php echo $urlPath ?>modulo/" class="ajax-link">Módulo</a>
<ul>
<li><a href="<?php echo $urlPath ?>modulo/una-seccion/" class="ajax-link">Una Sección</a></li>
<li><a href="<?php echo $urlPath ?>modulo/otra-seccion/" class="ajax-link">Otra Sección</a></li>
</ul>
</li>
</ul>

<div id="main">
<?php echo $this->layout()->content ?>
</div>

<div id="footer">
by <a href="http://rodrigoarce.com">Albo</a>
</div>

</body>
</html>

Ahi creamos los links como si lo hariamos normalmente y le agregamos la clase “ajax-link” para poder convertirla en un link de ajax.

/public_html/js/cleanhttpcall.js
var CleanHttpCall = {

	BASE_PATH : "/",
	CONTAINER : "main",
	CLASS: "ajax-link",
	PARAM: "is-ajax",

	view: null,

	init: function()
	{
		if(!this.view && window.location.href.search("#") > 0)
		{
			this.callView(window.location.href.replace("#",""));
		}
		var linkElement;
		var CleanHttpCall = this;
		var linksElements = document.getElementsByTagName("a");
		for(var i = 0; i < linksElements.length; i++)
		{
			linkElement = linksElements[i];
			if(linkElement.className.match(this.CLASS))
			{
				linkElement.onclick = function(){ return CleanHttpCall.onclick(this); };
			}
		}
	},

	onclick: function(linkElement)
	{
		this.callView(linkElement.href);
		return false;
	},

	callView: function(link)
	{
		var path = this.BASE_PATH;
		var pathPosition = link.search(new RegExp(path));
		var anchorLink = link.substring(pathPosition + path.length);
		window.location.href = path + "#" + anchorLink;
		this.view = anchorLink;
		var params = {};
		params[this.PARAM] = true;
		new Ajax.Updater(this.CONTAINER, link, {parameters: params});
	}

};

Creamos onclick para sobreescribir el href del link y hacemos una llamada con Ajax.Updater que automaticamente nos escribe lo recibido por Ajax en el div contenedor.

/public_html/index.php
<?php

/** Bootstrap */

session_start();
error_reporting(E_ALL | E_STRICT);

$rootPath = dirname(dirname(__FILE__));
set_include_path(get_include_path() . PATH_SEPARATOR . realpath($rootPath . '/../lib') );

require_once 'Zend/Loader.php';
Zend_Loader::registerAutoload();

/**
 * Si no es una llamada por ajax activamos el Layout
 */
if(!isset($_REQUEST['is-ajax']))
{
	Zend_Layout::startMvc();
}
/**
 * Si cerror el mensaje de JS inhabilitado no lo mostramos mas
 */
if(isset($_GET['js']) && $_GET['js'] == "close")
{
	$_SESSION['jsClose'] = true;
}

$frontController = Zend_Controller_Front::getInstance();
$frontController->setControllerDirectory($rootPath . '/app/controllers')
                ->throwExceptions(true)
                ->dispatch();

En el index cargamos o no el Layout segun sea un request normal o uno del Ajax.

También le agregue un código simple para que muestre un mensaje cuando no hay JavaScript. La idea es avisarle al usuario que puede recibir un link con /#algo/dinamico y que lo tiene que cambiar a /algo/dinamico (no hay manera del lado servidor de obtener lo que hay despues del #).

Lo podes ver en http://sandbox.rodrigoarce.com/http-ajax/public_html/.

Descargar código. Necesitas el directorio de Zend dentro de la carpeta lib (agrega donde esta la carpeta lib en el set_include_path del index.php) y en la carpeta public_html/js/ poner el código de Prototype.

Tags: , ,

Comments are closed.