| | | |

AJAX paso a paso: paginación de entradas para WordPress

Siguiendo con AJAX, hoy vamos a realizar un ejemplo que puede ser útil para los usuarios de WordPress. Se trata de un marco que muestra una lista con las entradas de nuestro blog, con paginación y efecto de fundido para darle más vistosidad.
ajax-paginacion.png

El método que vamos a seguir es el siguiente: la aplicación se conecta mediante AJAX a un script PHP que nos devuelve 5 entradas del blog, las cuales mostraremos en la ventana, inicialmente carga 3 páginas y cuando se avance en la paginación irá cargando otra página.

Esta es la parte AJAX, la parte HTML funciona de la siguiente manera: hay un marco que tiene clipping para solo mostrar lo que nos interesa, y donde estará la página actual que estamos viendo, el resto de las páginas estarán a la derecha o a la izquierda de esta (ocultas debido al clipping). Si se avanza en la paginación, la página actual irá a la izquierda al igual que la nueva que se va a mostrar (que se habrá cargado con AJAX y que inicialmente estará a la derecha). Si se retrocede en la paginación, la página actual irá a la derecha, al igual que la que queremos mostrar. A parte habrá un efecto de fundido para darle más espectacularidad.

La parte PHP es las más sencilla, consta de dos partes: una que obtiene los datos de la base de datos y otra que crea un XML con los datos y los devuelve.

En WordPress existe una tabla que se llama wp_posts que contiene las entradas del blog, tiene dos columnas que nos interesan: el título del post (post_title) y la url del post (guid). Estas dos columnas son las que necesitamos para crear nuestra lista de entradas.

$inc = 5;
$pos = $_GET['pos'];
// Conectamos a la BD
$bd = mysql_connect("localhost", $usuario, $password) or
die("No se puede conectar a la BD: " . mysql_error());
mysql_select_db($nombreBD);
// Obtenemos las entradas y sus enlaces
$res = mysql_query("SELECT guid, post_title FROM wp_posts w where guid is not null AND guid <> '' LIMIT ".($pos-1).", ".($pos+$inc-1));
$datos = null;
// Cargamos los datos en un array
while ($fila = mysql_fetch_array($res)) {
$datos[count($datos)] = array($fila['guid'], $fila['post_title']);
//$datos[count($datos)] = array($fila, $fila);
}
// Liberamos
mysql_free_result($res);
mysql_close($bd);

La creación del XML es simple: leemos los datos, nos creamos una cadena de texto con el XML y lo devolvemos. El XML tiene una raíz llamada datos (como en los ejemplos anteriores de AJAX que hemos publicado), y de este cuelga una elemento entrada por cada uno de los post, y este a su vez un elemento titulo y otro url:

// Devuelvo el XML con la palabra que mostramos (con los '_') y si hay éxito o no
$xml  = '<?xml version="1.0" standalone="yes"?>';
$xml .= '<datos>';
$xml .= '<total>'.count($datos).'</total>';
$xml .= '<inicio>'.$pos.'</inicio>';
$xml .= '<final>'.min($pos+$inc-1, count($datos)).'</final>';
for ($i = 0; $i<count($datos); $i++) {
$xml .= '<entrada>';
$xml .= '<titulo>'.$datos[$i][0].'</titulo>';
$xml .= '<url>'.$datos[$i][1].'</url>';
$xml .= '</entrada>';
}
$xml .= '</datos>';
header('Content-type: text/xml');
echo $xml;

La parte HTML/Javascript quizás sea un poco más compleja, pero supongo que no habrá problemas para entenderla. Dispondremos de dos capas, una que contiene el fondo y el recuadro para la paginación y otra que contendrá las distintas páginas.

<div class="contenedor">
<p id="paginacion">
<a href="javascript: anterior()"><<</a>
 <span id="inicio">_</span> al <span id="final">_</span> (<span id="total">_</span>) 
<a href="javascript: siguiente()">>></a></p>
</div>
<div id="contenido">
<div id="marco"></div>
</div>

Con sus estilos:

div.contenedor {
margin: 0 0 0 50%;
left: -100px;
position: absolute;
}
div#contenido {
margin: 0 0 0 50%;
left: -100px;
width: 200px;
height: 120px;
border: 2px solid #008585;
xoverflow: auto;
position: relative;
background: url(gr.gif) repeat-x;
}
div#marco {
width: 200px;
height: 120px;
position: absolute;
clip: rect(auto 200px auto auto);
}
div#contenido p {
width: 200px;
margin: 0px;
padding: 2px 4px 2px 4px;
}
a {
color: #008585;
font-family: Arial;
font-weight: bold;
text-decoration: none;
font-size: 9pt;
}
p#paginacion {
text-align: center;
font-weight: bold;
top: 102px;
position: relative;
border: 2px solid #008585;
background-color: #FFFFFF;
width: 110px;
left: 46px;
font-family: Arial;
font-size: 9pt;
z-index: 100;
}
div#contenido p a {
font-weight: bold;
display: block;
position: relative;
}
div#contenido p a:hover {
background-color: #008585;
color: #FFFFFF;
}

El elemento que se encarga la paginación consta de varios span que son los que modificaremos para escribir de cual a cual enseñamos y cuantos hay en total. El elemento marco es el que usaremos para añadir cada una de las páginas y es el que tiene el clipping. Cuando se carga una página se colocará a la derecha del recuadro (fuera del clipping), menos la página para la posición 1 (la primera), que se colocará dentro del recuadro.

function paginacion(pos) {
max = Math.max(pos, max);
ajax = ajaxobj();
ajax.open("GET", "paginacion.php?pos="+pos, true);
ajax.onreadystatechange=function() {
if (ajax.readyState==4) {
// Accion que ejecutamos cuando recibimos los datos
var datos = ajax.responseXML;
var entradas = datos.getElementsByTagName('entrada');
var contenido = document.getElementById("marco");
// Creamos una capa con posición
// absoluta para poder moverla
// La capa representa la página
var capa = document.createElement("DIV");
capa.id = "capa"+pos;
capa.style.position = "absolute";
// Si no es la primera página la colocamos a la derecha
if (pos != 1) {
capa.style.left = ancho+"px";
}
// Para cada entrada nos creamos mediante DOM
// un objeto P y dentro un objeto A con el enlace
// a la página
for (var i=0; i<entradas.length; i++) {
var p = document.createElement("P");
var link = document.createElement("A");
link.setAttribute("href", entradas[i].childNodes[0].firstChild.data);
var txt = entradas[i].childNodes[1].firstChild.data;
// Acortamos el texto para que no se sobrepase
var linkTxt = document.createTextNode(txt.substring(0, 25)+(txt.length <= 25? "":"..."));
link.appendChild(linkTxt);
p.appendChild(link);
capa.appendChild(p);
}
contenido.appendChild(capa);
var ini = datos.getElementsByTagName('inicio').item(0).firstChild.data;
var act = datos.getElementsByTagName('final').item(0).firstChild.data;
var tot = datos.getElementsByTagName('total').item(0).firstChild.data;
paginas[ini] = new Array(act, tot);
// Si es el primero modificamos los datos de paginacion
// si no, ya se cambiarán cuando avancemos/retrocedamos
if (pos == 1) {
document.getElementById("inicio").innerHTML = ini;
document.getElementById("final").innerHTML = act;
document.getElementById("total").innerHTML = tot;
inicio = false;
}
}
}
ajax.send(null);
}

Las funciones para avanzar o retroceder en la paginación existen las siguientes funciones:

// Avanza en la paginacion
function siguiente() {
if (paginas[posActual + inc]) {
// Muevo a la izquierda la actual
desplazar("capa"+posActual, false, 1);
posActual += inc;
visitados[posActual] = true;
// Muevo a la izquierda la nueva
desplazar("capa"+posActual, false, ancho);
document.getElementById("inicio").innerHTML = posActual;
document.getElementById("final").innerHTML = paginas[posActual][0];
document.getElementById("total").innerHTML = paginas[posActual][1];
// Cargo una nueva pagina
if (posActual < paginas[posActual][1]) {
paginacion(parseInt(max)+inc);
}
}
}
// Retroce en la paginacion
function anterior() {
if (paginas[posActual - inc]) {
// Muevo a la derecha la actual
desplazar("capa"+posActual, true, 1);
posActual -= inc;
// Muevo a la derecha la nueva
desplazar("capa"+posActual, true, -ancho);
document.getElementById("inicio").innerHTML = posActual;
document.getElementById("final").innerHTML = paginas[posActual][0];
document.getElementById("total").innerHTML = paginas[posActual][1];
}
}

Y las funciones para desplezar las capas y el efecto de fundido son las siguientes:

function desplazar(id, derecha, pos) {
var obj = document.getElementById(id);
var desp = (derecha? -1: 1)*velocidad;
obj.style.left = (pos-desp)+"px";
if (Math.abs(pos-desp) < ancho && pos-desp != 0) {
setTimeout("desplazar('"+id+"', "+derecha+", "+(pos-desp)+")", 30);
}
transparencia(obj, 100 - (Math.abs(pos-desp)*100/ancho));
}
function transparencia(obj, porc) {
if (typeof obj.style.filter != 'undefined') { // Es IE
obj.style.filter = "alpha(opacity="+porc+")";
} else {
obj.style.opacity = porc/100;
}
}

Podéis bajaros el código aquí

Similar Posts