Construye un lector de RSS con jQuery y jGFeed
Spanish (Español) translation by Elías Nicolás (you can also view the original English article)
Este tutorial muestra cómo utilizar jQuery y el complemento jGFeed para obtener fuentes de noticias de forma remota y escribir los resultados en el marcado existente. jGFeed es un complemento de jQuery que te permite obtener "cualquier" canal RSS de "cualquier" host y devuelve un objeto JSON para un uso fácil.
Este tutorial incluye un screencast disponible para los miembros de Tuts+ Premium.
Es posible que el código de ejemplo en este tutorial no funcione en Internet Explorer 7 o anterior, pero se ha probado con éxito en Firefox, Safari, Chrome e IE8.
Paso 1: Organizar los archivos para el Tutorial
Antes de comenzar a escribir cualquier código, vamos a crear un directorio donde colocar los archivos del lector de noticias. He creado un directorio en mi escritorio llamado 'feedreader'. Dentro de este directorio creamos otro llamado assets.
También necesitaremos descargar una copia de la fuente jGFeed. Puedes hacerlo aquí. Para este ejemplo, descargué la versión comprimida del archivo y la coloqué en el directorio 'assets'.
Finalmente, vamos a crear algunos archivos de texto vacíos para contener el marcado, javascript y estilos. He creado la siguiente estructura de archivos:
1 |
|
2 |
|-- assets | |
3 |
|-- feedreader.js | |
4 |
|-- jquery.jgfeed-min.js | |
5 |
`-- styles.css |
6 |
`-- index.html |
La estructura de archivos debe verse algo como:



Tenga en cuenta que index.html, feedreader.js y styles.css deben estar vacíos en esta etapa.
Paso 2: El marcado
Nuestro marcado para este tutorial será muy simple, y estamos asumiendo que usted ya sabe algo de HTML, así que lo presentaremos todo de una vez.
En nuestro archivo index.html enlazaremos con la hoja de estilo que usaremos más adelante para diseñar el lector de fuentes, luego agregaremos una lista de enlaces a las fuentes que queremos obtener y finalmente agregaremos los archivos javascript necesarios para el ejemplo.
Tenga en cuenta que agregamos los archivos de Javascript al final del cuerpo. Esto es para mejorar la velocidad de carga percibida de sus páginas, ya que el navegador puede comenzar a mostrar resultados sin tener que esperar a que se carguen los scripts.
Agregue el siguiente marcado a index.html:
1 |
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
2 |
|
3 |
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>jQuery + jGFeed AJAX Feed Reader Example</title> <link rel="stylesheet" href="assets/styles.css" |
4 |
type="text/css" /> </head> <body> |
5 |
|
6 |
<h1>jQuery + jGFeed AJAX Feed Reader Example</h1> |
7 |
|
8 |
<ul class="menu"> <li> <a class="ajax-feed-trigger" href="http://www.lupomontero.com/feed"> .lupomontero </a> </li> <li> <a class="ajax-feed-trigger" |
9 |
href="http://feeds.feedburner.com/nettuts"> Nettuts+ </a> </li> <li> <a class="ajax-feed-trigger" href="http://feeds.feedburner.com/jquery"> jQuery </a> </li> <li> <a class="ajax-feed-trigger" |
10 |
href="http://feeds2.feedburner.com/LearningJquery"> Learning jQuery </a> </li> </ul> |
11 |
|
12 |
<div id="ajax-feed-wrapper"> <div id="ajax-feed-container"> Click links above to fetch feeds </div> </div> |
13 |
|
14 |
<!-- Load jQuery, jGFeed and feedreader scripts --> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"> </script> <script type="text/javascript" src="assets/jquery.jgfeed-min.js"></script> <script type="text/javascript" src="assets/feedreader.js"></script> |
15 |
|
16 |
</body> </html> |
Ahora, cuando abrimos este archivo en el navegador web, deberíamos ver la siguiente página que contiene los elementos iniciales de nuestro lector de feeds.



Tenga en cuenta que esta marca sería perfectamente funcional para los navegadores que no ejecutan Javascript, en el sentido de que la página aún ofrecería enlaces válidos a las fuentes, pero obviamente llevarán el navegador a una nueva ubicación en lugar de mostrar las fuentes en nuestro lector.
Screencast completo
Paso 3: Anular el evento de enlace predeterminado de enlaces
Hasta ahora, cuando hacemos clic en un enlace, nuestro navegador está siendo dirigido a una nueva ubicación, la ubicación especificada en el atributo 'href' del enlace. Este es el comportamiento normal de los enlaces, pero en este caso queremos evitar que el navegador se dirija a cualquier lugar y, en cambio, obtenga la URL de forma asíncrona, procese la respuesta e imprima los datos dentro del marcado existente, lo que significa que no tenemos que abandonar el sitio. Y las noticias se presentan de la manera que queremos.
Abra el archivo vacío que guardamos como activo / feedreader.js (aquí es donde escribiremos nuestro script) y agregue el siguiente javascript:
1 |
$(document).ready(function() { // Hook to click event for ajax-feed-trigger links $('a.ajax-feed-trigger').click(function(e) { // Prevent default click action e.preventDefault(); |
2 |
|
3 |
// Store reference to container object in local var var container = $('#ajax-feed-container');
|
4 |
|
5 |
// Empty container div and temporarily add "loading" style container.empty().addClass('loading');
|
6 |
|
7 |
// Get links href attribute var href = $(this).attr('href'); alert(href);
|
8 |
|
9 |
// Get feed using jGFeed
|
10 |
|
11 |
}); // End a.ajax-feed-trigger click event }); |
El código anterior anula el comportamiento predeterminado de los enlaces en el evento de clics utilizando el método de clic de jQuery en todas las 'a' etiquetas de la clase 'ajax-feed trigger'. Dentro del método de clic, lo primero que hacemos es prevenir el comportamiento predeterminado usando preventDefault() de javascript, luego vaciamos el contenedor div, agregamos la clase de carga que nos permitirá diseñar el "state" de carga y por ahora solo mostramos el valor del atributo href del enlace pulsado. Usaremos una llamada para alert() para verificar que nuestro código funciona hasta ahora.
De vuelta en el navegador, cuando hacemos clic en los enlaces, deberíamos ver un diálogo de alerta con la URL del enlace en el que se hizo clic.



Paso 4: Obtener el feed de noticias como un objeto JSON usando jGFeed
El siguiente paso será enviar la solicitud HTTP real con jGFeed y comprobar que obtuvimos la respuesta que esperábamos.
El plugin jGFeed toma los siguientes argumentos:
- url - URL de la fuente que desea cargar
- callback: función de devolución de llamada para llamar después de cargar la fuente RSS
- num (opcional): número de entradas de blog para cargar (el valor predeterminado es 3)
- key (opcional): clave de la API de Google para usar al cargar fuentes RSS.
Más información sobre jGFeed:
http://jquery-howto.blogspot.com/2009/05/google-feeds-api-jquery-plugin.html
En este ejemplo, pasaremos el valor del atributo href del enlace como la url, una función de devolución de llamada anónima y especificaremos que queremos limitar los resultados a 5.
En assets/feedreader.js, agregue la llamada a jGFeed para que el script se vea como el listado a continuación:
1 |
$(document).ready(function() { // Hook to click event for ajax-feed-trigger links $('a.ajax-feed-trigger').click(function(e) { // Prevent |
2 |
default click action e.preventDefault(); |
3 |
|
4 |
// Store reference to container object in local var var container = $('#ajax-feed-container');
|
5 |
|
6 |
// Empty container div and temporarily add "loading" style container.empty().addClass('loading');
|
7 |
|
8 |
// Get links href attribute var href = $(this).attr('href');
|
9 |
|
10 |
// Get feed using jGFeed $.jGFeed( href, function(feeds) { // Check for errors if (!feeds) { // there was an error container.append('Error fetching feed.'); return false; } }, 5 ); // End jGFeed }); // End a.ajax-feed-trigger click event });
|
Ahora podemos usar Firebug para ver qué está haciendo jGFeed. Haga clic en cualquiera de los enlaces, abra la pestaña 'Red' en Firebug y localice la solicitud JSON. Debería decir algo como 'GET load? V1.0 & callback = jsonp12'. Si expande la vista, debería poder ver el objeto JSON y los datos que contiene.



Paso 5: Crear el marcado para cada entrada de feed dinámicamente
Ahora que sabemos que estamos obteniendo los datos, podemos proceder a hacer algo con ellos. En este caso, queremos iterar a través de las entradas en el feed y agregar una cadena con marca HTML al contenedor existente que creamos en nuestro archivo index.html.
Sin embargo, antes de iterar a través de las entradas necesitamos preparar el contenedor. Ocultamos el div para asegurarnos de que no veamos nada hasta que hayamos terminado de manipular el contenido de la etiqueta contenedora. También eliminamos la clase de carga ya que el div está oculto y agregamos el título del feed en una etiqueta de encabezado.
Usamos un bucle for para iterar sobre la propiedad de entradas del objeto de feeds que devuelve jGFeed a nuestra función de devolución de llamada. Dentro del bucle, simplemente construimos una cadena con un marcado HTML para mostrar las propiedades de cada entrada. Al final de cada iteración, agregamos esta cadena HTML al contenedor.
Una vez que hemos terminado de llenar el div contenedor con todas las entradas, llamamos al método show() de JQuery para desvanecerse en el div y, finalmente, hacerlo visible de nuevo.
1 |
$(document).ready(function() { // Hook to click event for ajax-feed-trigger links $('a.ajax-feed-trigger').click(function(e) { // Prevent default click action e.preventDefault(); |
2 |
|
3 |
// Store reference to container object in local var var container = $('#ajax-feed-container');
|
4 |
|
5 |
// Empty container div and temporarily add "loading" style container.empty().addClass('loading');
|
6 |
|
7 |
// Get links href attribute var href = $(this).attr('href');
|
8 |
|
9 |
// Get feed using jGFeed $.jGFeed( href, function(feeds) { // Check for errors if (!feeds) { // there was an error container.append('Error fetching feed.'); return false; }
|
10 |
|
11 |
container.hide(); container.removeClass('loading'); container.append('<h2>' + feeds.title + '</h2>'); |
12 |
|
13 |
// Process feed entries for (var i=0; i<feeds.entries.length; i++) { var entry = feeds.entries[i];
|
14 |
|
15 |
// Build HTML string for entry var html = '<div class="ajax-feed-item">'; html += '<hr /><h2><a href="' + entry.link + '">'; html += entry.title + '</a></h2>'; html += '<div
|
16 |
class="ajax-feed-date">'; html += entry.publishedDate + '</div>'; html += '<div class="ajax-feed-author"> Posted by '; html += entry.author + '</div>'; html += '<div |
17 |
class="ajax-feed-content-snippet">'; html += entry.contentSnippet + '</div>'; html += '</div>'; |
18 |
|
19 |
container.append(html); }
|
20 |
|
21 |
container.show('slow'); }, 5 ); // End jGFeed }); // End a.ajax-feed-trigger click event }); |
Si hace clic en cualquiera de los enlaces ahora, debería ver las noticias como se muestra en la siguiente captura de pantalla.



Paso 6: Agregar un enlace 'Leer más' para mostrar el contenido completo de las entradas de feeds
Ok, el ejemplo parece estar funcionando bastante bien, pero todavía hay muchos ajustes que podríamos hacer. En este caso, vamos a agregar un tipo de enlace "leer más" que mostrará el contenido completo de la entrada. Hasta ahora solo hemos utilizado la propiedad contentSnippet en cada objeto de entrada. Esto es útil porque queremos mostrar las entradas en una lista compacta, pero también tenemos el contenido completo en otra propiedad llamada 'contenido', por lo que agregaremos un enlace de más información (+/-) que alternará entre Fragmento y el contenido completo para que podamos leer la entrada completa del feed sin salir de nuestra página.
Para hacer esto, primero debemos agregar el contenido a la cadena HTML que estábamos construyendo dentro del bucle, pero vamos a establecer la altura de los divs de contenido en cero y su desbordamiento en 'oculto' para ocultarlos como nosotros Sólo los usaremos para guardar los datos reales. Nuestro enlace simplemente intercambiará el contenido de la división de fragmentos 'visible' por la división de contenido 'invisible'.
Justo antes de mostrar el feed al final de la función de devolución de llamada que pasamos a jGFeed, también tendremos que agregar el controlador de eventos onclick para nuestros enlaces "leer más". Hacemos esto de la misma manera que lo hicimos con los enlaces que usamos para obtener la fuente, usando el método click() de jQuery.
1 |
$(document).ready(function() { // Hook to click event for ajax-feed-trigger links $('a.ajax-feed-trigger').click(function(e) { // Prevent default click action e.preventDefault(); |
2 |
|
3 |
// Store reference to container object in local var var container = $('#ajax-feed-container');
|
4 |
|
5 |
// Empty container div and temporarily add "loading" style container.empty().addClass('loading');
|
6 |
|
7 |
// Get links href attribute var href = $(this).attr('href');
|
8 |
|
9 |
// Get feed using jGFeed $.jGFeed( href, function(feeds) { // Check for errors if (!feeds) { // there was an error container.append('Error fetching feed.'); return false; }
|
10 |
|
11 |
container.hide(); container.removeClass('loading'); container.append('<h2>' + feeds.title + '</h2>'); |
12 |
|
13 |
// Process feed entries for (var i=0; i<feeds.entries.length; i++) { var entry = feeds.entries[i];
|
14 |
|
15 |
// Build HTML string for entry var html = '<div class="ajax-feed-item">'; html += '<hr /><h2><a href="' + entry.link + '">'; html += entry.title + '</a></h2>'; html += '<div class="ajax-feed-date">'; html += entry.publishedDate + '</div>'; html += '<div class="ajax-feed-author"> Posted by '; html += entry.author + '</div>'; html += '<div class="ajax-feed-content-snippet">'; html += entry.contentSnippet + '</div>'; html += '<div id="ajax-feed-content-'+i; html += '" class="ajax-feed-content" '; html += 'style="height:0px; overflow:hidden;">'; html += entry.content + '</div>'; html += '<div><a class="ajax-feed-readmore" '; html += 'href="' + i + '">+</a></div>'; html += '</div>';
|
16 |
|
17 |
container.append(html); } |
18 |
|
19 |
// Hook to click event for ajax-feed-trigger links $('a.ajax-feed-readmore').click(function(e) { // Prevent default click action e.preventDefault();
|
20 |
|
21 |
var content_id = $(this).attr('href'); var div_id = 'ajax-feed-content-' + content_id; var content_div = $('#' + div_id); var content_txt = content_div.html(); var snippet_div = |
22 |
content_div.prev(); var snippet_txt = snippet_div.html(); |
23 |
|
24 |
// Swap text content between divs content_div.html(snippet_txt); snippet_div.html(content_txt);
|
25 |
|
26 |
if ($(this).html() === '-') { $(this).html('+'); } else { $(this).html('-'); } }); |
27 |
|
28 |
container.show('slow'); }, 5 ); // End jGFeed }); // End a.ajax-feed-trigger click event }); |
El lector ahora debe mostrar un botón '+' y '-' que alterna entre el fragmento de contenido y el contenido completo de cada entrada.



Paso 7: Diseñando el lector
El lector de feeds ahora funciona ... hurra! Pero seamos honestos, no se ve muy bien. Así que vamos a poner la guinda al pastel. A continuación, he incluido algunos estilos como ejemplo de cómo se podría personalizar el lector. Es posible que haya notado que usamos clases para cada uno de los elementos de nuestro marcado, por lo que debería ser relativamente fácil referirse a cada elemento de los selectores de CSS de la misma forma que los seleccionamos con jQuery.
1 |
/* Colours: red: #C74C44 dark red: #8C413A grey: #3F474C dark beige: #B5B095 beige: #DBD5B6 */
|
2 |
|
3 |
html { color: #F0F0F0; background-color: #8C413A; font-family: "Helvetica", sans-serif; } |
4 |
|
5 |
body { font-size: 12px; margin: 10px 20% 30px 20%; } |
6 |
|
7 |
div, ul, li { margin: 0; padding: 0; } |
8 |
|
9 |
img { border: 0; } |
10 |
|
11 |
li { list-style: none; } |
12 |
|
13 |
h1, h2, h3 { font-size: 100%; font-weight: normal; } |
14 |
|
15 |
h1 { color: #DBD5B6; font-size: 4.6em; line-height: 1.1em; text-shadow: 1px 1px 0.3em #3F474C; background-image: url(logo.png); background-repeat: no-repeat; padding: 16px 0 0 148px; margin: 0px; height: 114px; } |
16 |
|
17 |
h2 { color: #DBD5B6; font-size: 2.6em; text-shadow: 1px 1px #3F474C; padding: 0; margin: 0 0 25px 0; } |
18 |
|
19 |
a { color: #DBD5B6; text-decoration: none; } |
20 |
|
21 |
ul.menu { margin: 44px 0px 24px 0px; padding: 0px; } ul.menu li { display: inline; margin: 0px 5px 0px 0px; padding: 12px; background-color: #3F474C; border: 1px solid #B5B095; |
22 |
-moz-border-radius: 5px; -webkit-border-radius: 5px; font-size: 1.2em; text-shadow: 1px 1px #3F474C; } ul.menu li:hover { background-color: #B5B095; text-shadow: 1px 1px 0.2em #3F474C; } |
23 |
|
24 |
div#ajax-feed-wrapper { padding: 20px; overflow: hidden; background-color: #C74C44; border: 1px solid #B5B095; -moz-border-radius: 5px; -webkit-border-radius: 5px; } |
25 |
|
26 |
.loading { width: 36px; height: 36px; background-image: url(ajax-loader.gif); background-repeat: no-repeat; background-position: 20px 20px; } |
27 |
|
28 |
div.ajax-feed-item { background-color: #8C413A; padding: 10px; margin-bottom: 10px; } |
29 |
|
30 |
div.ajax-feed-item h3 { font-size: 1.8em; text-shadow: 1px 1px 0.3em #3F474C; padding: 0; margin: 3px 0 15px 0; } |
31 |
|
32 |
div.ajax-feed-date, div.ajax-feed-author { font-size: 0.8em; } |
33 |
|
34 |
div.ajax-feed-content-snippet { margin: 3px 0px 10px 0px; padding: 15px 5px 5px 5px; border-top: 1px solid #C74C44; text-shadow: 1px 1px #3F474C; } |
35 |
|
36 |
a.ajax-feed-readmore { display: table-cell; padding: 1px 5px; border: 1px solid #DBD5B6; } |
37 |
|
38 |
a.ajax-feed-readmore:hover { background-color: #B5B095; } |
Voila! Eso ya se ve mucho mejor ;-)






