Construyendo una nube de ntiquetas con jQuery
Spanish (Español) translation by Luis Chiabrera (you can also view the original English article)
Una nube de etiquetas es una excelente manera de mostrar a los visitantes de tu blog los principales temas de interés disponibles. También hay información adicional contenida en una nube de etiquetas. Además de los enlaces en sí, que dan a las personas una idea de los temas que cubre tu sitio, también pueden mostrar cuán populares son los diferentes temas. Otra gran cosa acerca de las nubes de etiquetas es que pueden usarse para describir la frecuencia de cualquier cosa; puede vincular a artículos, publicaciones de blog, imágenes, videos o cualquier otra cosa que tenga en abundancia en tu sitio.
Las nubes de etiquetas son fáciles de hacer mal; ya sea desde una perspectiva de diseño o desde una perspectiva de código. Gracias a jQuery, también es fácil hacerlo bien. Utilizaremos la nueva versión 1.3 de jQuery para este ejemplo y trabajaremos con PHP y MySql para proporcionar una fuente JSON de nuestras etiquetas. En primer lugar, ingresar las etiquetas en una base de datos está más allá del alcance de este tutorial, pero es bastante simple recuperarlas y pasarlas a una página de espera a través de AJAX.
Empezando
Comencemos en la página en la que se mostrará la nube de etiquetas; en un nuevo archivo en tu editor de texto, crea la siguiente página:
1 |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
|
2 |
<html>
|
3 |
<head>
|
4 |
<link rel="stylesheet" type="text/css" href="tagcloud.css"> |
5 |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
6 |
<title>jQuery Tag Cloud</title> |
7 |
</head>
|
8 |
<body>
|
9 |
<div id="tagCloud"> |
10 |
<h2>Tag Cloud</h2> |
11 |
</div>
|
12 |
<script type="text/javascript" src="jquery-1.3.min.js"></script> |
13 |
<script type="text/javascript"> |
14 |
$(function() { |
15 |
//get tag feed
|
16 |
$.getJSON("http://localhost/jquery/tagcloud.php?callback=?", function(data) { |
17 |
//process JSON object
|
18 |
});
|
19 |
});
|
20 |
</script>
|
21 |
</body>
|
22 |
</html>
|
Guarda esto como tagcloud.html. En esta etapa, no tenemos casi nada en la página, solo un contenedor simple para la nube de etiquetas y un encabezado de segundo nivel dentro del contenedor. Cualquier otro elemento que necesitemos puede crearse cuando sea necesario. Vinculamos a una hoja de estilo en la cabeza para un estilo que agregaremos más adelante, y al final del cuerpo vinculamos a jQuery. Hacemos la solicitud de la respuesta JSON en un bloque de script personalizado después de la referencia a jQuery.
getJSON
Usamos el alias $ para llamar al método getJSON jQuery, que es una abstracción de nivel superior del método ajax; normalmente, los métodos jQuery se invocan en objetos que son referencias a elementos, pero como no estamos haciendo referencia a ningún elemento, podemos utilizar el alias jQuery. Esto también significa que el método no devolverá el objeto jQuery. En cambio, xmlHTTPRequest se devuelve. El método getJSON acepta dos argumentos en este ejemplo (aunque se pueden usar más si es necesario); la primera es la URL a la que hacemos la solicitud. Como recibiremos un objeto JSON, tiene sentido usar getJSON. Podríamos usar el método ajax, pero luego necesitaríamos configurar más propiedades de la solicitud (como el dataType), por lo que usar esto nos ahorra un poco de tiempo y codificación. Al final de la URL, especificamos una JSONP callback - ?callback=? - lo que permitirá al navegador manipular directamente el objeto JSON, incluso si proviene de otro dominio, sin ningún procesamiento adicional del lado del servidor.
La función de devolución de llamada
El segundo argumento es la función de devolución de llamada que queremos ejecutar una vez que el objeto se devuelve a la página. Todavía no hemos puesto ningún código en esta función, porque no tenemos el objeto JSON con el que trabajar. Podemos volver a esta página en un momento una vez que hayamos escrito el PHP. Dije hace un momento que no se necesita procesamiento del lado del servidor cuando se trabaja con devoluciones de llamada JSONP, y sin embargo ahora vamos a salir y escribir algo de PHP. Esto se debe solo a que nadie proporciona los datos que queremos, por lo que debemos crearlos nosotros mismos. Si alguien proporcionara un feed JSON de etiquetas populares, aún podríamos usar el mismo código jQuery para solicitarlo y procesarlo.
Algo de PHP
Deberás tener acceso a un servidor web para ejecutar el archivo que estamos a punto de crear, pero este podría ser tu propio servidor web local que utilices para el desarrollo, o podría ser el servidor donde tu sitio o blog está alojado. En una nueva página en tu editor de texto, agrega el siguiente código:
1 |
<?php
|
2 |
|
3 |
//connection information
|
4 |
$host = "localhost"; |
5 |
$user = "root"; |
6 |
$password = "your_password_here"; |
7 |
$database = "tagcloud"; |
8 |
|
9 |
//make connection
|
10 |
$server = mysql_connect($host, $user, $password); |
11 |
$connection = mysql_select_db($database, $server); |
12 |
|
13 |
//query the database
|
14 |
$query = mysql_query("SELECT * FROM tags"); |
15 |
|
16 |
//start json object
|
17 |
$json = "({ tags:["; |
18 |
|
19 |
//loop through and return results
|
20 |
for ($x = 0; $x < mysql_num_rows($query); $x++) { |
21 |
$row = mysql_fetch_assoc($query); |
22 |
|
23 |
//continue json object
|
24 |
$json .= "{tag:'" . $row["tag"] . "',freq:'" . $row["frequency"] . "'}"; |
25 |
|
26 |
//add comma if not last row, closing brackets if is
|
27 |
if ($x < mysql_num_rows($query) -1) |
28 |
$json .= ","; |
29 |
else
|
30 |
$json .= "]})"; |
31 |
}
|
32 |
|
33 |
//return JSON with GET for JSONP callback
|
34 |
$response = $_GET["callback"] . $json; |
35 |
echo $response; |
36 |
|
37 |
//close connection
|
38 |
mysql_close($server); |
39 |
?>
|
Guarda esto como tagcloud.php. Para este ejemplo, supongo que tienes MySql instalado y configurado, y has configurado una base de datos llamada tagcloud. Dentro de esta base de datos, también supongo que hay una tabla llamada etiquetas. Esta tabla tendrá filas de las etiquetas y la frecuencia de las ocurrencias de estas etiquetas. Quiero enfatizar que este no es un código de nivel de producción porque la seguridad no ha sido un factor en su diseño; necesitamos un lugar para obtener nuestra respuesta AJAX en este ejemplo y este código nos dará eso en algún lugar.
Veamos brevemente lo que hemos hecho.
1 |
//connection information
|
2 |
$host = "localhost"; |
3 |
$user = "root"; |
4 |
$password = "your_password_here"; |
5 |
$database = "tagcloud"; |
Primero configuramos la información de conexión que necesitaremos para conectarnos a la base de datos. Asegúrate de reemplazar your_password_here con la contraseña real que configuraste para acceder a MySql. Luego nos conectamos a la base de datos y establecemos la consulta que usaremos para acceder a los datos desde la tabla de etiquetas.
1 |
//start json object
|
2 |
$json = "({ tags:["; |
3 |
|
4 |
//loop through and return results
|
5 |
for ($x = 0; $x < mysql_num_rows($query); $x++) { |
6 |
$row = mysql_fetch_assoc($query); |
7 |
|
8 |
//continue json object
|
9 |
$json .= "{tag:'" . $row["tag"] . "',freq:'" . $row["frequency"] . "'}"; |
A continuación, creamos la cadena que iniciará el objeto JSON, antes de recorrer cada fila de la tabla y realizar la consulta. Continuamos construyendo la cadena JSON dentro del bucle for, agregando los datos de ambos campos de la fila actual como propiedades y valores.
1 |
//add comma if not last row, closing brackets if is
|
2 |
if ($x < mysql_num_rows($query) -1) |
3 |
$json .= ","; |
4 |
else
|
5 |
$json .= "]})"; |
6 |
}
|
Realizamos una verificación simple en cada iteración del bucle usando el condicional for para ver si estamos leyendo la última fila de la tabla; si no lo estamos, usamos una coma para separar cada objeto, si lo estamos cerramos el objeto. El formato del objeto JSON serán objetos de registro individuales dentro de una matriz de contenedor único, dentro de un objeto externo.
1 |
//return JSON with GET for JSONP callback
|
2 |
$response = $_GET["callback"] . $json; |
3 |
echo $response; |
4 |
|
5 |
//close connection
|
6 |
mysql_close($server); |
Luego hacemos eco de la respuesta al cliente utilizando una solicitud GET; esto es necesario para hacer uso de la devolución de llamada jsonp en nuestra página principal. Necesitamos especificar el nombre del parámetro de URL que sigue a la URL de en el JavaScript, que en este ejemplo es simplemente devolución de llamada. Sin embargo, no podemos decirle el nombre de la función a la que queremos pasarla, porque la función es anónima. jQuery se encargará de esto por nosotros y se asegurará de que los datos se pasen a la función correcta.
Una vez que hayamos terminado, cerramos la conexión. En esta etapa, todavía no podemos ver nada en la página, pero si corres la ejecución desde un directorio de contenido de tu servidor web y usa la pestaña NET de Firebug, puedes ver los datos que se devuelven a la página:


Procesando el json
Ahora que tenemos algunos JSON con los que trabajar, volvamos a la página HTML y hagamos algo con ella. Nuestra primera tarea es procesarla para extraer los datos; en tagcloud.html, elimina el comentario que dejamos en la devolución de llamada y agrega el siguiente código:
1 |
//create list for tag links |
2 |
$("<ul>").attr("id", "tagList").appendTo("#tagCloud");
|
3 |
|
4 |
//create tags |
5 |
$.each(data.tags, function(i, val) {
|
6 |
|
7 |
//create item |
8 |
var li = $("<li>");
|
9 |
|
10 |
//create link |
11 |
$("<a>").text(val.tag).attr({title:"See all pages tagged with " + val.tag, href:"http://localhost/tags/" + val.tag + ".html"}).appendTo(li);
|
12 |
|
13 |
//add to list |
14 |
li.appendTo("#tagList");
|
15 |
}); |
Primero creamos un nuevo elemento de lista, establecemos su atributo de identificación y lo agregamos a nuestro contenedor en la página. Como los datos en el objeto JSON no están en ningún orden en particular, una lista desordenada cumple con nuestros requisitos. Luego usamos el método each () jQuery para iterar sobre todos los elementos de la matriz anidados dentro de nuestro objeto JSON. Para cada iteración, creamos un nuevo elemento de lista y un nuevo enlace.
Establecemos el texto de cada enlace al valor de la propiedad de etiqueta del objeto actual de nuestro objeto JSON, así como establecemos el título y un href. El href utilizado dependerá en gran medida de cómo se generarán las páginas que muestran las etiquetas, podríamos generar una página de estilo de resultados de búsqueda que enumere todas las páginas que coinciden con la etiqueta en la que se hizo clic usando PHP o .NET con bastante facilidad (la página de resultados es también más allá del alcance de este tutorial). El enlace se agrega al elemento de la lista, y ambos se agregan a la <ul>.
En esta etapa, nuestra página debería aparecer como la siguiente:
Ciertamente es una lista de enlaces, pero no es una nube de etiquetas. Podemos ajustar fácilmente la apariencia del widget con un poco de CSS. Hagamos esto a continuación. En un nuevo archivo en tu editor de texto, agrega el siguiente código:
1 |
#tagCloud { |
2 |
width:290px; background-color:#575454; text-align:center; padding:5px; |
3 |
overflow:auto; font-size:70%; font-family:arial; |
4 |
}
|
5 |
#tagCloud h2 { |
6 |
color:#ffffff; font-size:2.5em; margin:0 0 10px 0; |
7 |
background:url(images/cloud.gif) no-repeat 0; padding:15px 0 15px 80px; |
8 |
}
|
9 |
#tagList { margin:0; padding:0; } |
10 |
#tagList li { |
11 |
list-style-type:none; float:left; margin:0 10px; height:35px; |
12 |
}
|
13 |
#tagList li a { text-decoration:none; color:#ffffff; } |
14 |
#tagList li a:hover ( text-decoration:underline; } |
Guarda esto como tagcloud.css. Los estilos utilizados son una mezcla de reglas funcionales y estéticas, como flotar los elementos de la lista y establecer sus dimensiones para controlar cómo funciona el widget. He mantenido los estilos lo más mínimo posible, ya que sin duda tendrás que cambiar la mayoría de los estilos puramente visuales para que encajen con el tema de tu sitio existente.
Un punto importante a tener en cuenta es el tamaño de fuente que hemos usado; se establece un tamaño de fuente del 70% en el elemento contenedor externo; esto representa el texto más pequeño que aparecerá en la nube de etiquetas. Vamos a ajustar el tamaño de fuente de algunas etiquetas usando unidades em en la parte final del script. Por lo tanto, establecer un tamaño de fuente de referencia es importante para la coherencia.
Ahora, cuando ejecutas la página, debería aparecer de la siguiente manera:
Terminando el script
Uno de los atributos distintivos de las etiquetas en una nube de etiquetas es que las etiquetas individuales se dimensionan de acuerdo con su frecuencia de aparición; cuanto más popular es una etiqueta, más grande se muestra. Podemos utilizar fácilmente la propiedad freq dentro de nuestro objeto JSON para cambiar el tamaño de cada enlace de acuerdo con su popularidad. Entre crear el nuevo enlace y agregarlo a la lista desordenada en nuestro script, agrega el siguiente código:
1 |
//set tag size |
2 |
li.children().css("fontSize", (val.freq / 10 < 1) ? val.freq / 10 + 1 + "em": (val.freq / 10 > 2) ? "2em" : val.freq / 10 + "em");
|
En verdad, el método css podría encadenarse fácilmente al objeto jQuery directamente después de establecer el atributo de título del enlace, pero se separan aquí para una mejor legibilidad. Dentro del método css, especificamos el atributo de estilo fontSize y utilizamos el condicional ternario estándar de JavaScript para verificar si el valor actual de la propiedad freq dividido entre 10 es menor que 1. Si es así, agregamos 1 a la figura y luego concatenamos la cadena em al final. Esto asegurará que ninguna de las etiquetas tenga un tamaño de fuente de menos de 1em, que es igual a nuestra regla de estilo del 70% establecida en el elemento contenedor.
Sin embargo, si el valor de la propiedad freq dividido entre 10 no es menor que 1, entonces verificamos (usando otro ternario, el equivalente de anidar para bucles) si es mayor que 2; si es así, simplemente usamos 2em como el valor de la propiedad de tamaño de fuente. Cualquier elemento con un tamaño de fuente de 2em tendrá el doble del tamaño de nuestra línea base original del 70%, que probablemente sea tan grande como cualquier etiqueta que este tipo de widget debería tener. Cualquier valor mayor que 1 pero menor que 2 se usa en su forma fraccional para establecer un peso de fuente entre 1 y 2 ems. La página final ahora debería aparecer como la siguiente captura de pantalla cuando se ve en un navegador:
Resumen
En este tutorial, hemos visto lo "fácil" que es crear una nube de etiquetas básica que recupere las etiquetas para mostrarlas como parte de una solicitud de AJAX directamente después de cargar la página. Es fácil cambiar el tamaño de cada etiqueta en función de su frecuencia utilizando un rango sensible de tamaños de texto. Aunque la apariencia general del widget se ha dejado con un estilo bastante mínimo, debería ser fácil construir sobre esta base para crear algo que sea hermoso y funcional.




