Carga asíncrona de contenido HTML mediante Ajax

Carga asíncrona de contenido HTML en un objeto mediante una llamada AJAX a una URL.

Insertar este código en un archivo .js que esté referenciado en la cabecera de la página:

function FactoryXMLHttpRequest()
{
  if(window.XMLHttpRequest) {
    return new XMLHttpRequest();
  }
  else if (window.ActiveXObject) {
    var msxmls = new Array(
                   'Msxml2.XMLHTTP.5.0',
                   'Msxml2.XMLHTTP.4.0',
                   'Msxml2.XMLHTTP.3.0',
                   'Msxml2.XMLHTTP',
                   'Microsoft.XMLHTTP');

    for (var i = 0; i < msxmls.length; i++) {
      try {
        return new ActiveXObject(msxmls[i]);
      }
      catch (e) {}
    }
  }
  throw new Error("Could not instantiate XMLHttpRequest");
}

function Asynchronous()
{
  this._xmlhttp = new FactoryXMLHttpRequest();
}

function Asynchronous_call(url, id)
{
  var instance = this;
  this._xmlhttp.open('GET', url, true);
  this._xmlhttp.onreadystatechange = function() {
  switch(instance._xmlhttp.readyState) {
    case 1:
      instance.loading();
      break;

    case 2:
      instance.loaded();
      break;

    case 3:
      instance.interactive();
      break;

    case 4:
      instance.complete(instance._xmlhttp.responseText, id);
      break;
    }
  }
  this._xmlhttp.send(null);
}
function Asynchronous_loading() { }
function Asynchronous_loaded() { }
function Asynchronous_interactive() { }
function Asynchronous_complete(responseText, id) { }

Asynchronous.prototype.loading = Asynchronous_loading;
Asynchronous.prototype.loaded = Asynchronous_loaded;
Asynchronous.prototype.interactive = Asynchronous_interactive;
Asynchronous.prototype.complete = Asynchronous_complete;
Asynchronous.prototype.call = Asynchronous_call;

Esto son las funciones que se ocupan de la petición asíncrona al servidor utilizando el objeto AJAX XMLHttpRequest.

Notas: las principales ventajas que aporta este código son:

  • está escrito siguiendo un patrón de diseño orientado a la generación de instancias del objeto XMLHttpRequest (Factory pattern), lo que da soporte cross-browser
  • utiliza solicitudes asíncronas (asynchronous requests) para evitar el bloqueo del navegador

Después, en la página en la que vayamos a querer cargar el contenido extraído (pe. de una base de datos) de forma asíncrona habremos de colocar la función que llama a la url:

var asynchronous = new Asynchronous();
asynchronous.complete = function(responseText, id) {
  document.getElementById(id).innerHTML = responseText;
}

/* Carga el contenido HTML que devuelve la URL solicitada en el elemento con ID indicado */
function load_content(url, id)
{
  var responseItem = document.getElementById(id)
  //alert( responseItem.id + ' - ' + (responseItem.innerHTML=="") + ' - ' + responseItem.style.display) //debug

  if ((responseItem.innerHTML=="") || (responseItem.style.display=='none')) {
   responseItem.style.display='block'; //muestra el elemento, por si estuviera oculto

   if (responseItem.innerHTML=="") {
     responseItem.innerHTML = '<img src="images/ico_loading.gif" align="absmiddle"/> cargando pregunta...';
     asynchronous.call(url, id)
   }
  }
  else {
   responseItem.style.display='none';
  }
}

La URL será una página sencilla que haga todo el trabajo de consultar a la base de datos y devolver los datos en un formato HTML que la función load_content pueda insertar fácilmente y de forma asíncrona en nuestra página de destino.

Si quisieramos cargar un documento XML entero (o un nodo) tendríamos que sustituir la línea con la llamada responseItem.innerHTML = '...' por algo así como:

dom.loadXML(objXMLHTTP.responseText);
document.getElementById('id').innerText = dom.selectSingleNode('nombre_nodo').text;

Finalmente en el elemento de la página que quisieramos que disparara la carga asíncrona pondríamos la llamada a la función anterior. Uno (de entre muchas formas de responder al evento) sería:

<a href="javascript: load_content('url_peticion', 'id_elemento_destino')">texto del enlace</a>

Notas:

  • el archivo ico_loading.gif hace de imagen que muestra el progreso, se puede poner cualquier cosa
  • el parámetro url será la URL de una página que haga todo el trabajo de consultar a la base de datos y devolver los datos en un formato HTML que la función load_content pueda insertar fácilmente y de forma asíncrona en el elemento con identificador id en nuestra página de destino.
  • código probado en IE 6 y 7 y Firefox 2.0

Otros artículos de esta serie:

[seriesposts show_date=0 order=asc]

8 Comentarios

  1. 12 enero, 2009 (19:55) #

    Hola tengo algunas dudas, la primera parte del código y la segunda parte que contiene la función load_content(‘url’,'id’); van en el mismo archivo .js que se invoca en la cabecera de la página en la que se va a cargar el contenido asincronamente?

    Por que yo lo aplique así y no me jalo, ojala me puedas aclarar eso por favor.

    Gracias!!

  2. 13 enero, 2009 (4:27) #

    Échale un vistazo a http://www.opestudio.com/ayuda.asp, que es dónde está aplicado. Las funciones load_content y aquellas que se llaman desde ésta, deben ir dentro de un .js que deberá estar referenciado en la cabecera de la página dónde se ejecuta load_content.

  3. alex
    9 marzo, 2009 (17:52) #

    Buenas… podrias poner un ejemplo de lo que iria dentro de el archivo que se pasa como url? seria enb php?
    muchas gracias

    • 10 marzo, 2009 (0:26) #

      Hola, el archivo que se le pasa como URL solamente tiene que mostrar la cadena de texto o fragmento HTML que queremos “inyectar”. Después la función ya se encarga de “embeberlo” e integrarlo en el HTML de nuestra página

  4. 23 marzo, 2009 (15:28) #

    Oscar:
    Finalmente pude implementar el codigo, y funciona bien. La unica cuestion es que lo hace perfecto en Firefox y Opera. Pero presenta algunos problemas en Safari, ya que agranda y deforma la pagina…y en explorer no se ejecuta el evento (tira el tipico cuadrito blanco con la cruz roja), puede ser que sea porque estoy previsualizando la pagina desde mi disco duro?…
    Saludos y gracias por tiempo.

  5. 23 marzo, 2009 (16:40) #

    Hola Leandro,
    No entiendo muy bien a qué te refieres pero un recuadro blanco con aspa roja me suena más a que puede ser que no encuentre la imagen de progreso.
    Saludos.

  6. 23 marzo, 2009 (20:30) #

    Oscar, he resuelto los problemas. El unico problema me surge ahora cuando una vez cargado el contenido dentro del div designado, quiero pinchar un link de dicho contenido. El problema es que se abre en otra ventana del navegador, no puedo seguir haciendo que se abra en el mismo div.

  7. 24 marzo, 2009 (0:16) #

    Leandro,
    Entiendo que quieres seguir cargando asíncronamente contenido DENTRO de ese mismo div mediante enlaces renderizados en su propio contenido? eso solo se me ocurre que se podría hacer con un iframe.

Publicar un Comentario

Si es la primera vez que escribes, tu comentario será moderado por un administrador.

Con el fin de garantizar un ambiente de debate respetuoso, no se permitirán comentarios:

  • insultantes, difamatorios, racistas, sexistas, y/o discriminatorios
  • excesivamente críticos con otros participanes
  • que no aporten nada, sin sentido o repetidos
  • con enlaces considerados publicidad o spam
  • con material protegido por derechos de autor
*
*