Todos hemos visto los videos (y algunos incluso han tenido acceso a la previsualización de desarrolladores) del nuevo producto de Google: Google Wave.
Esta herramienta que posee una gran IU es realmente inspiradora. Es por eso que en esta nota te enseñaremos cómo crear un sistema de comentarios estilo Google Wave.
Paso 1 - XHTML
Las tecnologÃas que estamos utilizando incluyen PHP como un back-end, MySQL como un almacenador de datos, jQuery, CSS y  XHTML para el front-end con AJAX en el medio. El deslizador es un componente creado con jQuery UI.
Primero echémosle un vistazo a la sección del cuerpo de demo.php
demo.php
-
<div id="main">
-
-
<p id="orig">View the <a href="http://tutorialzine.com/2009/10/google-wave-history-slider-jquery/" target="_blank">original tutorial »</a></p>
-
<h1>Google Wave-like</h1>
-
<h2>History Slider</h2>
-
-
<div id="wave">
-
<div id="topBar">Your Demo Wave</div>
-
<div id="subBar">
-
<img src="img/tutorialzine.png" alt="Tutorialzine" /><img src="img/demo.png" alt="Demo" /><img src="img/curious.png" alt="Curious" />
-
</div>
-
-
<div id="sliderContainer">
-
<div id="slider"></div>
-
<div class="clear"></div>
-
</div>
-
-
<div id="commentArea">
-
-
<?php
-
foreach($comments as $c)
-
{
-
showComment($c);
-
// Showing each comment
-
}
-
?>
-
-
</div>
-
<input type="button" class="waveButtonMain" value="Add a comment" onclick="addComment()" />
-
-
<div id="bottomBar">
-
</div>
-
-
</div>
-
</div>
Esto es básicamente todo el diseño que usaremos. La razón principal por la cual el código es tan corto es que estamos usando CSS para darle estilo, y la salida de comentarios está manejada por una función PHP especial, que explicaremos pronto.

Paso 2 - CSS
Lo genial de jQuery es que, gracias a CDN de Google, se puede añadir directamente en tu sitio, sin tener que descargarlo y almacenarlo en tu servidor. Esto también ayuda al tiempo de carga de tu página.
Lo miso sucede con la UI de jQuery, que contiene nuestro deslizador. No sólo eso, sino que el CDN también contiene el estilo y las imágenes necesarias para mostrarlo de forma apropiada.
Sin embargo, todavÃa tenemos que incluir nuestros propios estilos personales. Los archivos de ejemplo se pueden encontrar en demo.css. Aquà sólo se muestran las partes más interesantes:
demo.css
-
#orig{
-
/* The link that float to the right of the title */
-
float:right;
-
font-family:"MyRiad Pro",Arial;
-
font-size:10px;
-
letter-spacing:1px;
-
text-transform:uppercase;
-
padding-top:10px;
-
}
-
-
.clear{
-
/* Clearfix, needed by IE6 */
-
clear:both;
-
}
-
-
#main{
-
/* The main container */
-
width:600px;
-
margin:30px auto;
-
}
-
-
#wave{
-
/* CSS rounded corners */
-
-moz-border-radius:6px;
-
-khtml-border-radius: 6px;
-
-webkit-border-radius: 6px;
-
border-radius:6px;
-
-
background:white;
-
width:100%;
-
overflow:hidden;
-
}
-
-
#topBar{
-
background:url(img/bg.jpg) repeat-x;
-
font-size:12px;
-
color:white;
-
-
height:20px;
-
overflow:hidden;
-
padding:5px 0 0 10px;
-
-
border-bottom:1px solid #e4f1ff;
-
-moz-border-radius:6px 6px 0 0;
-
/* A Firefox fix, for once */
-
}
-
-
#bottomBar{
-
height:40px;
-
background-color:#c9e2fc;
-
-moz-border-radius:0 0 6px 6px;
-
border-top:1px solid #CCCCCC;
-
}
-
-
#subBar{
-
background-color:#c9e2fc;
-
padding-left:10px;
-
}
-
-
#subBar img{
-
/* The avatars at the top of the page */
-
margin:8px 8px 8px 0;
-
border:1px solid #cccccc;
-
}
-
-
.waveButton,.waveButtonMain{
-
/* The submit buttons */
-
background:url(img/button_bg.jpg) repeat-x 50% 50%;
-
border:1px solid #DDDDDD;
-
padding:4px;
-
-
cursor:pointer;
-
}
-
-
.waveButtonMain{
-
display:block;
-
margin:10px 20px;
-
}
-
-
.textArea{
-
padding:4px;
-
font-family:Arial,Helvetica,Sans-serif;
-
font-size:12px;
-
color:#666666;
-
border:1px solid #66aff9;
-
margin-bottom:10px;
-
}
-
-
.replyLink{
-
float:right;
-
}
-
-
#commentArea{
-
padding:10px;
-
color:#444444;
-
}
-
-
.commentText{
-
margin-left:40px;
-
}
-
-
.waveComment .waveComment{
-
padding-left:30px;
-
}
-
-
.waveComment .waveComment .replyLink{
-
/* Hiding the reply link on the comment replies -
-
only 2 levels of ancestry are allowed */
-
-
display:none;
-
}
-
-
.waveTime{
-
color:#999999;
-
float:right;
-
font-size:10px;
-
}
-
-
#slider{
-
width:400px;
-
font-size:10px;
-
float:right;
-
margin-right:10px;
-
}
-
-
#sliderContainer{
-
background:url(img/dark_bg.jpg) repeat-x #f5f5f5 50% 50%;
-
padding:9px 10px;
-
border:1px solid #bbbbbb;
-
border-left:0;
-
border-right:0;
-
-
height:10px;
-
padding:9px 10px;
-
}
-
-
div.ui-widget-content{
-
/* Styling the slider */
-
background:#FFFFFF;
-
border:1px solid #CCCCCC;
-
}
-
-
.comment{
-
margin:5px 10px;
-
padding:8px 10px;
-
border:2px solid #cccccc;
-
-
/* Rounding the comment */
-
-moz-border-radius:6px;
-
-khtml-border-radius: 6px;
-
-webkit-border-radius: 6px;
-
border-radius:6px;
-
-
overflow:hidden;
-
}
-
-
span.name{
-
font-weight:bold;
-
color:#999999;
-
}
-
-
.commentAvatar{
-
width:30px;
-
height:30px;
-
float:left;
-
margin-right:10px;
-
}

Paso 3 - PHP
Hay 4 archivos PHP principales que manejan el back-end:
1. demo.php - da salida a los comentarios;
2. ajax/saveComment.php - añade nuevos comentarios, se llega a él por medio de peticiones AJAX;
3. functions.php - retiene algunas funciones utilizadas por demo.php;
4. connect.php - maneja la conexión de base de datos.
Aquà sólo miraremos los tres primeros archivos:
demo.php
-
require 'connect.php';
-
require 'functions.php';
-
// Including the files for the DB connection and our custom functions
-
// Removing comments that are older than an hour.
-
-
-
// Selecting all the comments ordered by id in ascending order
-
-
$js_history='';
-
-
{
-
if($row['parent']==0)
-
// If the comment is not a reply to a previous comment, put it into $comments directly
-
$comments[$row['id']] = $row;
-
else
-
{
-
if(!$comments[$row['parent']]) continue;
-
-
$comments[$row['parent']]['replies'][] = $row;
-
// If it is a reply, put it in the 'replies' property of its parent
-
}
-
-
$js_history.='addHistory({id:"'.$row['id'].'"});'.PHP_EOL;
-
// Adds JS history for each comment
-
}
-
-
$js_history='<script type="text/javascript">
-
'.$js_history.'
-
</script>';
-
-
// This is later put into the head and executed on page load
Los comentarios son o parents (se anadem directamente al thread) o children (añadidos como una rélica a un parent). Sólo se permiten dos niveles de ancestrÃa (lo que quiere decir que las réplicas para los children están deshabilitadas).
Los comentarios son mostrados por la función showComment (se puede ver en el paso XHTML de arriba).
ajax / saveComment.php
-
require'../connect.php';
-
-
// If there isn't a comment text, exit
-
-
$user='Demo';
-
// This would be a nice place to start customizing - the default user
-
// You can integrate it to any site and show a different username.
-
-
$addon='';
-
if($_POST['parent']) $addon=',parent='.(int)$_POST['parent'];
-
-
mysql_query("INSERT INTO wave_comments SET usr='".$user."', comment='".$comment."', dt=NOW()".$addon);
-
-
// If the insert was successful, echo the newly assigned ID
-
else
-
echo '0';
Y por ultimo, está functions.php
functions.php
-
-
function showComment($arr)
-
{
-
echo '
-
<div class="waveComment com-'.$arr['id'].'">
-
<div class="comment">
-
<div class="waveTime">'.waveTime($arr['dt']).'</div>
-
<div class="commentAvatar">
-
</div>
-
<div class="commentText">
-
<span class="name">'.$arr['usr'].':</span> '.$arr['comment'].'
-
</div>
-
<div class="replyLink">
-
<a href="" onclick="addComment(this,'.$arr['id'].');return false;">add a reply »</a>
-
</div>
-
<div class="clear"></div>
-
</div>';
-
-
// Output the comment, and its replies, if any
-
if($arr['replies'])
-
{
-
foreach($arr['replies'] as $r)
-
showComment($r);
-
}
-
echo '</div>';
-
}
-
-
function waveTime($t)
-
{
-
-
// If the comment was written today, output only the hour and minute
-
// if it was not, output a full date/time
-
}
El último paso es el más complicado, en este caso es el código jQuery.
Paso 4 - jQuery
Todo el código JS está localizado en script.js. Lo dividiremos en dos partes:
script.js - parte 1
-
$(document).ready(function(){
-
// Executed once all the page elements are loaded
-
-
lastVal = totHistory;
-
-
// Create the slider:
-
$("#slider").slider({
-
value:totHistory,
-
min: 1,
-
max: totHistory,
-
animate: true,
-
slide: function(event, ui) {
-
-
if(lastVal>ui.value)
-
$(buildQ(lastVal,ui.value)).hide('fast').find('.addComment').remove();
-
// Using buildQ to build the jQuery selector
-
// If we are moving the slider backward, hide the previous comment
-
-
else if(lastVal<ui.value)
-
$(buildQ(lastVal,ui.value)).show('fast');
-
// Otherwise show it
-
-
lastVal = ui.value;
-
}
-
});
-
});
-
-
var totHistory=0;
-
// Holds the number of comments
-
-
var lastVal;
-
-
function addHistory(obj)
-
{
-
/* Gets called on page load for each comment, and on comment submit */
-
totHistory++;
-
positions.push(obj.id);
-
}
-
-
function buildQ(from,to)
-
{
-
/* Building a jQuery selector from the begin
-
and end point of the slide */
-
-
if(from>to)
-
{
-
var tmp=to;
-
to=from;
-
from=tmp;
-
}
-
-
from++;
-
to++;
-
-
var query='';
-
for(var i=from;i<to;i++)
-
{
-
if(i!=from) query+=',';
-
query+='.com-'+positions[i-1];
-
}
-
-
/* Each comment has an unique com-(Comment ID) class
-
that we are using to address it */
-
-
return query;
-
}
Como recordarán, hemos generado una string PHP especial, que contiene las llamadas a la función addHistory. Cada vez que se ejecuta, incrementa el contador totHistory. Luego de que todos los comentarios se cargan el $(document).ready se ejecuta y el slider se inicia con totHistory como el máximo valor del deslizador. El valor mÃnimo es 1, porque deseamos tener por lo menos un comentario visible.
Ahora, miremos la segunda parte del archivo:
script.js - parte 2
-
function addComment(where,parent)
-
{
-
/* This functions gets called from both the "Add a comment" button
-
on the bottom of the page, and the add a reply link.
-
It shows the comment submition form */
-
-
var $el;
-
if($('.waveButton').length) return false;
-
// If there already is a comment submition form
-
// shown on the page, return and exit
-
-
if(!where)
-
$el = $('#commentArea');
-
else
-
$el = $(where).closest('.waveComment');
-
-
if(!parent) parent=0;
-
-
// If we are adding a comment, but there are hidden comments by the slider:
-
$('.waveComment').show('slow');
-
lastVal = totHistory;
-
-
$('#slider').slider('option','value',totHistory);
-
// Move the slider to the end point and show all comments
-
var comment = '<div class="waveComment addComment">\
-
\
-
<div class="comment">\
-
<div class="commentAvatar">\
-
<img src="img/demo.png" width="30" height="30" />\
-
</div>\
-
\
-
<div class="commentText">\
-
\
-
<textarea class="textArea" rows="2" cols="70" name="" />\
-
<div><input type="button" class="waveButton" value="Add comment" onclick="addSubmit(this,'+parent+')" /> or <a href="" onclick="cancelAdd(this);return false">cancel</a></div>\
-
\
-
</div>\
-
</div>\
-
\
-
</div>';
-
-
$el.append(comment);
-
// Append the form
-
}
-
-
function cancelAdd(el)
-
{
-
$(el).closest('.waveComment').remove();
-
}
-
-
function addSubmit(el,parent)
-
{
-
/* Executed when clicking the submit button */
-
var cText = $(el).closest('.commentText');
-
var text = cText.find('textarea').val();
-
var wC = $(el).closest('.waveComment');
-
if(text.length<4)
-
{
-
alert("Your comment is too short!");
-
return false;
-
}
-
-
$(el).parent().html('<img src="img/ajax_load.gif" width="16" height="16" />');
-
// Showing the loading gif animation
-
// Send an AJAX request:
-
-
$.ajax({
-
type: "POST",
-
url: "ajax/saveComment.php",
-
data: "comment="+encodeURIComponent(text)+"&parent="+parent,
-
/* Sending both the text and the parent of the comment */
-
success: function(msg){
-
-
/* PHP returns the automatically assigned ID of the new comment */
-
var ins_id = parseInt(msg);
-
if(ins_id)
-
{
-
wC.addClass('com-'+ins_id);
-
addHistory({id:ins_id});
-
$('#slider').slider('option', 'max', totHistory).slider('option','value',totHistory);
-
lastVal=totHistory;
-
}
-
-
transForm(text,cText);
-
// Hiding the form and showing the newly-added comment in its place
-
}
-
});
-
}
-
-
function transForm(text,cText)
-
{
-
var tmpStr ='<span class="name">Demo:</span> '+text;
-
cText.html(tmpStr);
-
}
Las funciones de esta parte del código manejan la entrega de comentarios via AJAX al back-end PHP.
Como saben, se llama cuando hemos ejecutado de forma exitosa la petición AJAX (en este caso se llama si el comentario fue escrito a la base de datos MySQL).
Dentro de está función verificamos si se devuelve una ID apropiada, que corresponde a la id MySQL interna que se dió al campo auto-incrementado (miren abajo para la parte MySQL part o miren table.sql en los archivos de ejemplo).
Si todo está bien, llamamos la función addHistory con la nueva información y actualizamos el valor máximo del deslizador. Esto asegura que el nuevo comentario añadido sea históricamente scrollable con el resto de ellos.
Step 5 - MySQL
Este paso sólo se necesita si deseas hacer andar un demo en tu propio servidor.
Para poder hacer funcionar el demo, deberás crear la table MySQL wave_comments  con el siguiente código (también disponible en los archivos de ejemplo table.sql):
-
CREATE TABLE `wave_comments` (
-
`id` int(11) NOT NULL auto_increment,
-
`parent` int(11) NOT NULL default '0',
-
`usr` varchar(16) collate utf8_unicode_ci NOT NULL default '',
-
`comment` text collate utf8_unicode_ci NOT NULL,
-
`dt` datetime NOT NULL default '0000-00-00 00:00:00',
-
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Con esto, ¡Nuestro deslizador histórico tipo Google Wave está completo!
Conclusión
Siéntanse libres de modificar el código de este ejemplo y utilizarlo en sus propios sitios. También serÃa genial que compartan lo que realicen con la comunidad. ¡Esperamos ver sus logros!
Fuente: Tutorialzine








Lunes, 2 de Noviembre de 2009 a las 19.20
Es realmente interesante y muchas gracias por los archivos me ayudaron bastante sigan asi
Lunes, 2 de Noviembre de 2009 a las 23.08
Quiero que me llegue la invitación!!! quiero probar google wave!!!
Miércoles, 4 de Noviembre de 2009 a las 22.28
Muy interesenate , sigan asi por favor y no se detengan en inculcar mas acerca de los tips , para beneficio y prosperidad de las paginas web. Gracias
Viernes, 6 de Noviembre de 2009 a las 00.04
Me parece estupendo la mejora de las paginas WEB ya que ayuda aprovechando al maximo la funcionalidad
de las paginas WEB
Sábado, 7 de Noviembre de 2009 a las 15.59
Muy buen ejemplo. Gracias
Lunes, 9 de Noviembre de 2009 a las 02.20
muy buen tutorial y muy interezante lastima que no cuento con las herramientas para ponerlo en practica pero gracias por ayudarnos.
Miércoles, 11 de Noviembre de 2009 a las 00.15
Estaria bueno un tuto para implementarlo a algun sistema de foros o sistema de blogging
Martes, 20 de Abril de 2010 a las 19.15
Hola, muy bueno el tutorial, soy muy novato en esto del php, asà que quiero preguntar cómo serÃas posible incluir esto en cada articulo de una página web para que la gente comente, pero solo los que esten registrados. Gracias.
Lunes, 26 de Abril de 2010 a las 15.19
Hola, intente implementarlo en mi pagina, tal cual ya que soy nuevo y primero queria verlo en funcionamiento para despues hacerle algunas modificaciones (Si es que puedo) pero no he podido echarlo a andar, la direccion es esta, y marca el error, me podrÃan ayudar?
http://www.harteforjada.com/06productos/demo/demo.php
Jueves, 6 de Mayo de 2010 a las 00.55
hola me permito felicitar este blog en general me ah ayudado bastante
tengo una duda acerca de este tema
como le podre hacer para agregar
un nuevo campo de entrada por ejemplo
agregar un campo para el nombre de quien comenta
se podra hacer? bueno espero y respondan
zaludos!
Sábado, 15 de Mayo de 2010 a las 02.40
Muy bueno pero lo malo que no se como ponerlo en wordpress