Ver Mensaje Individual
  #6  
Antiguo 05-03-2009
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Reputación: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Siempre he pensado que esto de Ajax se ha manejado como algo oscuro y complicado y hasta se escriben libros dedicados a ello, cuando en verdad no es más que:

1. Crear un objeto de tipo XHTTPRequest
2. Usarlo para enviar una petición HTTP
3. Asignar su evento OnReadyStateChange

La parte más "difícil" es la 1 porque se debe crear el objeto según qué navegador y qué versión, pero una búsqueda en Google nos dará múltiples versiones.

En la parte 2 simplemente hay que especificar el método de la petición (GET, POST o HEAD) y si el envío es síncrono o asíncrono. No hay mucho que pensarle, debe ser asíncrono a no ser que -en las condiciones actuales- queramos fastidiar al usuario congelando su navegador.

Lo interesante está en la parte 3, en dónde esencialmente sólo nos interesa esperar a recibir el readyState = 4 indicando que ya se competó la respuesta y determinar el status de la misma: =200 ok, !=200 not ok (básicamente).

Y ya, no hay nada más. De verdad.

Es más, la X de ajax no sé ni quién la use, porque normalmente veo que se usa la respuesta de tipo texto en lugar de xml, y si se quiere algo más estructurado, mejor usar json, que puede manejarse directamente con javascript.

Lo que sí hay extra son las facilidades para recibir esta respuesta, como es la de ponerla en automático en un <div> y traducir el onreadystatechange en eventos cómodos para el programador. Es lo que ha hecho David.


Ahora, como yo no soy dado a las licencias gpl, mit, lgpl y cosas así, pues les pongo aquí lo que alguna vez hice, lo pongo al dominio público, osea para que cada cual haga con el lo que desee. Lo único interesante -posiblemente- es la clase HTTPParams y la función parseForm para leer los campos de un formulario ya hecho y traducirlo en los pares key=value que se envían con la petición HTTP. Pero la verdad es que la he usado muy poco porque no estoy convencido (todavía) de enviar formularios vía ajax.

Código:
/******************************************************************************

    Función createRequest

    Crear un objeto HttpRequest según los distintos navegadores

    Desde luego, esta función puede refinarse tanto como sea necesario.

******************************************************************************/

function createRequest()
{
    if (window.XMLHttpRequest)
    {
        return new XMLHttpRequest();
    }
    else if (window.ActiveXObject)
    {
        return new ActiveXObject('Microsoft.XMLHTTP');
    }

    return null;
}

/******************************************************************************

    Clase HttpParams

    Almacena pares [key, value] para ser enviados en una petición HTTP

*******************************************************************************/

function HttpParams()
{
    this.items = new Array();
}

// Agrega un par a la lista
//
HttpParams.prototype.add = function(key, value)
{
    this.items[this.items.length] = [key, value];
}

// Construye la cadena a ser enviada
//
HttpParams.prototype.getQueryString = function()
{
    var result = '';

    for (var i = 0; i < this.items.length; i++)
    {
        var item = this.items[i];

        if (result)
        {
            result += '&';
        }

        result += item[0] + '=' + item[1];
    }

    return encodeURI(result);
}

/******************************************************************************

    Función parseForm

    Extrae la información de un formulario y la coloca en un objeto HttpParams

******************************************************************************/

function parseForm(form)
{
    var elements = form.elements;
    var params = new HttpParams();
    var element;

    for (var i = 0; i < elements.length; i++)
    {
        element = elements.item(i);

        if (!element.name)
        {
            continue;
        }

        switch (element.type.toLowerCase())
        {
            case 'text': case 'password': case 'hidden': case 'textarea':
                params.add(element.name, element.value);
                break;

            case 'select-one':
                if (element.value)
                {
                    params.add(element.name, element.value);
                }
                break;

            case 'select-multiple':
                options = element.options;

                for (j = 0; j < options.length; j++)
                {
                    option = options.item(j);

                    if (option.selected)
                    {
                        params.add(element.name, option.value);
                    }
                }
                break;

            case 'radio':   case 'checkbox':
                if (element.checked)
                {
                    params.add(element.name, element.value);
                }
                break;
        }
    }

    return params;
}

/******************************************************************************

    Clase Ajax

    Interfaz para el envio de peticiones HTTP através de un objeto HTTPRequest

******************************************************************************/

function Ajax(url)
{
    this.url = url;
    this.params = new HttpParams();
    this.async = true;
    this.request = null;
    this.handler = null;
}

Ajax.prototype.send = function(method)
{
    // Crear un objeto HttpRequest
    //
    // Estos objetos no parecen ser reusables por lo que hay que crearlos cada
    // vez que enviemos una petición HTTP
    //
    this.request = createRequest();

    // Si la llamada es asíncrona, establecer el procesador de eventos
    //
    if (this.request && this.async)
    {
        var self = this; // extraño ¿no?

        this.request.onreadystatechange = function()
        {
            // cuando se llame a este evento, this es una copia del objeto
            // por ello es que debemos usar self
            //
            if (self.request.readyState == 4 && self.request.status == 200 && self.handler != null)
            {
                // llamar al manejador del usuario
                self.handler();
            }
        }
    }

    if (method.toLowerCase() == 'post')
    {
        this.request.open(method, this.url, this.async);
        this.request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        this.request.send(this.params.getQueryString());
    }
    else
    {
        this.request.open(method, this.url + '?' + this.params.getQueryString(), this.async);
        this.request.send(null);
    }

    // Si la llamada fue síncrona, llamar al manejador ahora
    //
    if (!this.async && this.handler != null)
    {
        this.handler();
    }
}

Ajax.prototype.getText = function()
{
    return this.request.responseText;
}

Ajax.prototype.getXml = function()
{
    return this.request.responseXml;
}

Ajax.prototype.parseForm = function(form)
{
    this.params = parseForm(form);
}
// Saludos
Responder Con Cita