Monday, November 20, 2006

Ajax for Starters

After thinking it for enough time, I have decided to start by writing an initiation on AJAX, with something which i would have liked to find when i began on AJAX world. As descriptions of AJAX can be found by the net and there is enough articles with the theory, i will focus this article in a more practical way, with some theory but at more low level, to facilitate a general vision.

In first place, it is necessary to understand the AJAX's principal atraction, which is to be able to use a Client-server structure in Web. This is possible executing code in the client by means of javascript and code in the server by means of php, asp, etc. The HttpRequest object , which it is usually called ajax object , is created and executed on client side, therefore in javascript, and allows to ask for a web's content by an asynchronous way. What wants to say? So that we prune to ask, for example, for the result of a form whereas the user continues doing changes in it. But how we write the response on the web? For it we need a container, usually using the "div" etiquette of HTML. This container is an element in javascript that contains the property innerHTML, where it is possible to write the response of the server (normally a HTML page ). It is important to see that when we ask for a page and we write the response, we are not updating the current page, but we are changing its content, therefore, all the objects that are created in javascript are kept, and therefore we prune to support variables in client side memory during the page navigation. We will see it more clearly with an example.

First, we need a page on client side, which will be the one that the users will open and where they will do the requests to one or several pages (does not have why ask only a server for a page). For example it might be like that:

<html>
<title>Example</title>
<body>
<div id="container_ajax"></div>
</body>
</html>

We see that the page is not very complicated , hehe. We prune to see the container with the "div" etiquettes where we will write the page content for that we will ask. It needs to have an "id" to be able to use it from javascript. We prune to call this page "example.htm" for example. Now we prune to include the necessary code of javascript to create the AJAX object and to do the request. We need to add therefore the tag "script" to the page. We will add also a button in order that should be the client who does the request. If we do it on having opened the page, it can be so instantaneous that we do not see difference between ajax and to ask for the page directly:

<html>
<title>Example</title>
<script language="javascript" src="example.js"></script>
<body>
<input type="button" onclick="request()">
<div id="container_ajax"></div>
</body>
</html>

With the tag "script" we say that should include the code of the file "example.js" that is in javascript. In this file we will include the whole necessary code to do the request and to write it in the container. We prune to create a variable that counts the number of made requests, which we should prune initialize to zero and will be increased in every request. We will have to implement the function "request" that we call on having done click in the button. First we need to create the object AJAX or HttpRequest. It is a widespread enough function that is not very difficult to find in the net, anyway I put the version that I use:

function newAjax()
{
var objetoAjax=false;
try
{ /*Para navegadores distintos a internet explorer*/
objetoAjax = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try
{ /*Para explorer*/
objetoAjax = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (E)
{
objetoAjax = false;
}
} if (!objetoAjax && typeof XMLHttpRequest!='undefined')
{
objetoAjax = new XMLHttpRequest();
}
return objetoAjax;
}

As you see, the ajax object is created of different forms, in function of the browser that we have. This function is the one that we will use in the following code, the implementation of the function "request" that will do the request and will write the response in the container. This code, as in the function of above, will go in "example.js", just under "newAjax" function. But first we will define "counter" variable which will count the number of made requests. As it must to be global, must go out of the function "request":

var counter = 0;

Already inside the "request" function, first we increase the counter and we will create the object ajax:

function request()
{
counter = counter + 1;
var ajax = newAjax();

After we open the object, specifying the method used for the request ('POST or 'GET'), the url, and the last parameter to true (it says that the request is asynchronous, principal advantage of ajax):

ajax.open ('GET', 'hello.htm', true);

We request a page, which is in the same server, and it's named 'hello.htm'. Its content can be for example a html with the words " hello world! " or simple flat text. Later we need to define the function that will receive the response and will write the content. With the content we add also the value of the counter:

ajax.onreadystatechange = function() {
if (ajax.readyState==1) {
document.getElementById('container_ajax').innerHTML="Loading.......";
}
else if (ajax.readyState==4){
if(ajax.status==200){
document.getElementById('container_ajax').innerHTML= "Request :"+counter+"<br>"+ajax.responseText;
}
else
{
document.getElementById('container_ajax').innerHTML= "Request :"+counter+"<br>"+ajax.responseText;
}
}
}

Finally we change the header, send the request and close the function "request". The send parameters are the variables that you want to send by post, a string with all the variables separated with "&" (for example "variable1=valor1&variable2=valor2") in the case that the method was "POST", if it is "GET" they must go in the url. For the present we do not complicate ourselves any more.

ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
ajax.send(null);
}

As result, when we open the page of the client and press the button, the "hello.htm" page content will be shown just below, inside the container, with the number of requests done up to the moment. As we will see, the variable only is initialized on enter to to the "example.htm" page , therefore we prune to see that the variable is kept in client while we do the requests. As it was said before, the page is not updated, its content is changed, concretly that of the container. If we push on update, it will reinitiate the variable, because we are opening "example.htm". And if we push on the "Back" button, we will go back to the page in that we was before opening "example.htm", not to the previous state of the same page (for example to see the result of the request 3 after the request to 4). If instead of asking "example.htm", we ask for a php page that is executed on server side and consults a database, for example, we will be able to see the result of this in the page of the client. We prune to make enclosed that the response is different depending on the information that it finds in the database, and to do that the page to be different every time, or even to update different containers ( we will see like later on).

Here ends this article.

Thanks!


p.d.: Any question may be writen in comments, please.

----------------------------------------------------------------------------------

Después de pensarlo durante bastante tiempo, he decidido empezar escribiendo una iniciación en AJAX, con aquello con lo que a mi me hubiese gustado encontrarme cuando empecé en el mundo de AJAX. Como descripciones sobre AJAX sobran y hay artículos de sobra sobre la teoría, enfocaré este artículo de una forma más práctica, con algo de teoría pero a más bajo nivel, para facilitar la visión general.

En primer lugar, hay que entender el principal atractivo de AJAX, que es poder usar una estructura Cliente-Servidor vía web. Esto se consigue ejecutando código en el cliente por medio de javascript y código en el servidor por medio de php, asp, etc. El objeto HttpRequest, al cual se le suele llamar objeto ajax, se crea y ejecuta de lado del cliente, por lo tanto en javascript, y nos permite pedir el contenido de la web de forma asíncrona. ¿Que quiere decir esto? Pues que podemos pedir, por ejemplo, el resultado de un formulario mientras que el usuario sigue haciendo cambios en el. ¿Pero como volcamos la respuesta? Para ello necesitamos un contenedor, se suele usar la etiqueta "div" de HTML. Este contenedor es un elemento en javascript que contiene la propiedad innerHTML, donde se puede volcar la respuesta del servidor (normalmente una página HTML). Es importante ver que cuando pedimos una página y volcamos la respuesta, no estamos actualizando la página actual, sino que estamos cambiando su contenido, por lo tanto, todos los objetos que hallamos creado en javascript se mantienen , y por lo tanto podemos mantener variables en memoria del lado del cliente durante la navegación de una página. Lo veremos mas cláramente con un ejemplo.

En primer lugar, necesitamos una página del lado del cliente, que será la que abrirá y donde se harán las peticiones a una o varias páginas (no tiene porqué pedirse solo una página a un solo servidor). Por ejemplo podría ser así:

<html>
<title>Ejemplo</title>
<body>
<div id="container_ajax"></div>
</body>
</html>

Vemos que la página muy complicada no es, jeje. Podemos ver el contenedor con las etiquetas "div" donde volcaremos el contenido de la página que pediremos. Necesita tener un id para poder usarlo desde javascript. Esta página la podemos llamar "ejemplo.htm" por ejemplo. Ahora podemos incluir el código necesario de javascript para crear el objeto AJAX y hacer la petición. Necesitamos por lo tanto añadir el tag "script" a la página. Añadiremos también un botón para que sea el cliente quien haga la petición. Si lo hacemos al abrir la página, puede ser tan instantáneo que no veamos diferencia entre ajax y pedir la página diréctamente:

<html>
<title>Ejemplo</title>
<script language="javascript" src="ejemplo.js"></script>
<body>
<input type="button" onclick="peticion()">
<div id="container_ajax"></div>
</body>
</html>

Con el tag "script" le decimos que incluya el código del fichero "ejemplo.js" que está en javascript. En este fichero incluiremos todo el código necesario para hacer la petición y volcarla en el contenedor. Podemos crear una variable que cuente el número de peticiones hechas, que podemos inicializar a cero y se irá incrementando en cada petición. Tendremos que implementar la función "peticion" que llamamos al hacer click en el botón. En primer lugar necesitamos crear el objeto AJAX o HttpRequest. Es una función bastante extendida que no nos costará encontrar en la red, de todas formas pongo la versión que uso yo:

function newAjax()
{
var objetoAjax=false;
try
{ /*Para navegadores distintos a internet explorer*/
objetoAjax = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try
{ /*Para explorer*/
objetoAjax = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (E)
{
objetoAjax = false;
}
}
if (!objetoAjax && typeof XMLHttpRequest!='undefined')
{
objetoAjax = new XMLHttpRequest();
}
return objetoAjax;
}

Como veis, el objeto ajax se crea de distintas formas, en función del navegador que tengamos. Esta función es la que usaremos en el siguiente código, la implementación de la función "peticion" que hará la petición y volcará la respuesta en el contenedor. Este código, al igual que en la función de arriba, irá en "ejemplo.js", justo debajo de la función "newAjax". Pero primero definiremos la variable "contador" que contará el numero de peticiones hechas. Como debe ser global, debe ir fuera de la función "petición":

var contador = 0;

Ya dentro de la función "peticion", en primer lugar incrementamos el contador y crearemos el objeto ajax:

function peticion()
{
contador = contador + 1;
var ajax = newAjax();

Después abrimos el objeto, especificando el método utilizado para la peticion ('POST' o 'GET'), la url, y el ultimo parametro a true (le dice que la petición es asíncrona, principal ventaja de ajax):

ajax.open ('GET', 'hola.htm', true);

Como vemos pedimos una página, que está en el mismo servidor que se llama 'hola.htm'. Su contenido puede ser por ejemplo un html con las palabras "hola mundo!" o simple texto plano. A continuación necesitamos definir la función que recibirá la respuesta y volcará el contenido. Con el contenido agregamos también el valor del contador:

ajax.onreadystatechange = function() {
if (ajax.readyState==1) {
document.getElementById('container_ajax').innerHTML="Cargando.......";
}
else if (ajax.readyState==4){
if(ajax.status==200){
document.getElementById('container_ajax').innerHTML= "Peticion :"+contador+"<br>"+ajax.responseText;
}
else
{
document.getElementById('container_ajax').innerHTML= "Peticion :"+contador+"<br>"+ajax.responseText;
}
}
}

Finalmente cambiamos el header , enviamos la petición y cerramos la función "peticion". El parametro del send, son las variables que queramos pasar por post, un string con todas las variables separadas con "&" (por ejemplo "variable1=valor1&variable2=valor2") en el caso que el método fuera "POST", si es "GET" deben ir en la url. Por ahora no nos compliquemos más.

ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
ajax.send(null);
}

Como resultado, cuando abramos la página del cliente y apretemos el botón, nos saldrá el contenido de la página "hola.htm" justo debajo, dentro del contenedor, junto al número de peticiones hechas hasta el momento. Como veremos, la variable solo se inicializa al entrar en la página "ejemplo.htm", por lo tanto podemos ver que la variable se mantiene hagamos las peticiones que hagamos. Com se dijo antes, la página no se actualiza, se cambia su contenido, concrétamente el del contenedor. Si le damos a actualizar, sí que se reiniciaria la variable, porque estamos volviendo a abrir "ejemplo.htm". Y si le damos al botón "atras", iremos a la página en la que estabamos antes de abrir "ejemplo.htm", no al estado anterior de la misma página (por ejemplo ver el resultado de la petición 3 después de hacer la petición 4). Si en lugar de pedir "ejemplo.htm", pedimos una pagina php que se ejecuta del lado del servidor y consulta una base de datos, por ejemplo, podremos ver el resultado de esta en la página del cliente. Podemos hacer incluso que la respuesta sea diferente en función de los datos que halla en la base de datos, y hacer que la pagina sea distinta cada vez, o incluso actualizar contenedores diferentes (ya veremos más adelante como).

Hasta aquí este artículo.
Grácias!


p.d.: Cualquier pregunta que tengais la podeis poner en "Comentarios".