Bien ahora veremos la parte del código y pequeña explicación por cada fragmento de código. Empezemos con nuestra tabla la cual llamaremos chat y tendra solo 3 campos: fecha, usuario, mensaje:

CREATE TABLE `chat` (
 `fecha` datetime NOT NULL default '0000-00-00 00:00:00',
 `usuario` varchar(15) NOT NULL default '',
 `mensaje` text NOT NULL
) type=MyISAM;

Para los datos de la conexión al servidor MySQL usamos el archivo conexion.php.

<?php
   //Configuracion de la conexion a base de datos
   $bd_host = "localhost";
   $bd_usuario = "root";
   $bd_password = "123456";
   $bd_base = "ribosomatic";
   $con = mysql_connect($bd_host, $bd_usuario, $bd_password);
   mysql_select_db($bd_base, $con);
?> 

El archivo consulta.php se encargará de mostrar los últimos registros agregados a la tabla chat. La variable $UltFecha contiene la fecha del último registros que se le mostró al usuario. Si no esta definido es por que el usuario inicia por primera vez la aplicación, por lo que mostrará todos los registros de la tabla. Además usaremos XML para el envio de los datos obtenidos de la consulta. Las primeras 4 cabeceras (header) son para que el navegador vuelva a cargar los resultados y no los tome de la cáche. La última cabecera es para especificar que se trata de un documento XML.

<?php
 require("conexion.php");
 $UltFecha=$_GET['ultfec'];
 if($UltFecha=='undefined'){
  $query = "SELECT * FROM chat ORDER BY fecha ASC";
 }else{
  $query = "SELECT * FROM chat WHERE fecha>'$UltFecha' ORDER BY fecha ASC";
 }
 $lista = mysql_query($query,$con);
 $i=1;
 // no cargar de la cache del navegador.
 header( "Expires: Mon, 26 Jul 1997 05:00:00 GMT" );
 header( "Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . "GMT" );
 header( "Cache-Control: no-cache, must-revalidate" );
 header( "Pragma: no-cache" );
 header('Content-type: text/xml; charset=UTF-8', true);
 echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
 echo "<xml>";
 while($row = mysql_fetch_array($lista)){
  echo "<elemento> \n";
  echo "	<fecha>".$row['fecha']."</fecha> \n";
  echo "	<usuario>".$row['usuario']."</usuario> \n";
  echo "	<mensaje>".$row['mensaje']."</mensaje> \n";
  echo "</elemento> \n";
  $i++;
 }
 echo "</xml>";
?>

Para registrar los mensaje usamos el archivo registro.php. Obtenemos las variables usuario y mensaje las cuales han sido enviadas mediante JavaScript (mas adelante veremos esto) y hacemos un INSERT INTO para guardar los datos en la tabla. Luego eliminamos los registros de la tabla si esto superan los 10.

<?php
 require('conexion.php');
 $usuario=$_POST['usuario'];
 $mensaje=$_POST['mensaje'];
 if($usuario=='') $usuario='anonimo';
 if($mensaje=='') $mensaje='ningun mensaje';
 $query = "INSERT INTO chat ( fecha, usuario, mensaje) VALUES (NOW(),'$usuario','$mensaje')";
 mysql_query($query);
 //eliminando registros si estos superarn los 10
 $max=10;
 $NroRegistros=mysql_num_rows(mysql_query("SELECT * FROM chat",$con));
 if($NroRegistros>$max){
  $NroAEliminar=$NroRegistros-$max;
  mysql_query("DELETE FROM chat ORDER BY fecha ASC LIMIT $NroAEliminar");
 }
?>

Hasta aquí hemos visto todo el proceso que realiza el servidor. Veamos ahora las funciones en JavaScript que enviarán los valores a los archivos PHP antes mencionados.

El archivo ajax.js contien las funciones para declarar y usar el objeto XMLHttpRequest y, el envio y recepción de los mensaje; además de una variable global UltFec no definida.

 var UltFec;
 function objetoAjax(){
  var xmlhttp=false;
  try{
   xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
  }catch(e){
   try{
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
   }catch(E){
    xmlhttp = false;
   }
  }
  if(!xmlhttp && typeof XMLHttpRequest!='undefined'){
   xmlhttp = new XMLHttpRequest();
  }
  return xmlhttp;
 }
 function enviarMensaje(){
  usu=document.nuevo_empleado.usuario.value;
  men=document.nuevo_empleado.mensaje.value;
  ajax=objetoAjax();
  ajax.open("POST", "registro.php",true);
  ajax.onreadystatechange=function() {
   if (ajax.readyState==4) {
    consultaMensajes();
    document.nuevo_empleado.mensaje.value="";
    document.nuevo_empleado.mensaje.focus();
   }
  }
  ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
  ajax.send("usuario="+usu+"&mensaje="+men)
 }
 function consultaMensajes(){
  divResultado = document.getElementById('pagina');
  ajax=objetoAjax();
  ajax.open("GET", "consulta.php?ultfec="+UltFec,true);
  ajax.onreadystatechange=function() {
   if (ajax.readyState==4) {
    //obtenemos los resultados XML;
    var datos=ajax.responseXML.documentElement;
    //mediante manejo de DOM accedemos a los elementos del XML
    for (i = 0; i < datos.getElementsByTagName('elemento').length; i++){
     var item = datos.getElementsByTagName('elemento')[i];
     var fec = item.getElementsByTagName('fecha')[0].firstChild.data;
     var usu = item.getElementsByTagName('usuario')[0].firstChild.data;
     var men = item.getElementsByTagName('mensaje')[0].firstChild.data;
     var linea='<div class="c_fecha">'+fec+'</div><div class="c_usuario">'+usu+'</div><div class="c_mensaje">'+men+'</div>';
     CrearCaja(linea);
    }
    //si ultima fecha esta definida se usará
    //caso contrario se dejara con su valor anterior
    if(typeof fec!='undefined'){
     UltFec=fec;
    }
   }
  }
  ajax.send(null)
  //consultar mensaje nuevos cada 3 seg.
  setTimeout('consultaMensajes();',3000);
 }
//cuando se carga la pagina principal consultamos los mensajes
 window.onload = function (){
  consultaMensajes();
 }

El archivo dom.js nos permite crear la estructura del documento HTML. En la página index.html (mas abajo) vamos a especificar un elemento div con su atributo id=’pagina’. La función CrearCaja(texto) crea un elemento div dentro del div pagina. Estos elementos tiene atributos como class llamada ‘caja’ (para IE se usa el atributo className). En su propiedad innerHTML asignamos el contenido a este div. Luego lo agregamos al inicio de los demás elementos. Por último removemos los div caja si estos superaran los 10.

 function CrearCaja(texto){
  //contenedor principal
  var pagina=document.getElementById('pagina');
  //creando nuevo div
  var cajaNueva=document.createElement('div');
  //asignandoles atributos
  cajaNueva.setAttribute('className','caja'); //para IE
  cajaNueva.setAttribute("class", "caja");
  //llenando la caja nueva
  cajaNueva.innerHTML=texto;
  //insertar antes del primer elemento de pagina
  pagina.insertBefore(cajaNueva,pagina.firstChild);
  //elimiar el ultimo elemento
  EliminarCaja();
 }
 //remueve el ultimo elementos si estos superan los 10
 function EliminarCaja(){
  var pagina=document.getElementById('pagina');
  elementos=pagina.childNodes;
  if(elementos.length>10){
   pagina.removeChild(pagina.lastChild);
  }
 }

Finalmente el archivo index.html contendrá un formulario con dos campos: uno para el nombre del usuario y otro para el mensaje, y un botón Enviar. En el evento onsubmit del formulario especificamos la función enviarMensaje().

<html>
<head>
<title>Chat con Ajax</title>
<script src="ajax.js" type="text/javascript"></script>
<script src="dom.js" type="text/javascript"></script>
<link href="estilos.css" rel="stylesheet" type="text/css">
</head>
<body>
 <form name="nuevo_empleado" action="" onSubmit="enviarMensaje(); return false">
 <h2>Chat con Ajax - Intranet </h2>
 <p>Usuario
  <input name="usuario" type="text" id="usuario">
 </p>
 <p>Mensaje</p>
 <p><strong>
  <textarea name="mensaje" cols="50" rows="5" id="mensaje"></textarea>
 </strong></p>
 <p>
  <label>
  <input type="submit" name="Submit" value="Enviar" />
  </label>
 </p>
 </form>
 <div id="barra">
  <div class="c_fecha">
  Fecha / Hora
  </div>
  <div class="c_usuario">
  Usuario
  </div>
  <div class="c_mensaje">
  Mensaje
  </div>
</div>
<div id="pagina">
//aqui apareceran los contenedores con los mensajes
</div>
</body>
</html>

Y así acabamos con este ejemplo de chat con Ajax, sin embargo si alguien sabe la forma de mejorarlo pues avisen. Pero sobre todo si alguien por allí conoce la forma de implementarlo mejor con Comet sería excelente. Puedes descargar los archivos de este ejemplo ó ver un ejemplo avanzado basado en este código en el nuevo Tablero dinámico de RibosoMatic.