Páginas

Mostrando entradas con la etiqueta Web. Mostrar todas las entradas
Mostrando entradas con la etiqueta Web. Mostrar todas las entradas

lunes, 1 de junio de 2015

Para conseguir una versión offline del blog

Esta mañana, a solicitud de un compañero que quería mostrar una versión de su blog en una ubicación en la que no dispone de conexión a Internet (no me ha dado más detalles del caso, ni tampoco yo se los he pedido), he estado investigando sobre las diferentes soluciones que permiten obtener dicho objetivo. Las expondré a continuación, de forma más bien sumaria, porque existen muchísimas variaciones, permutaciones y combinaciones a partir de los tres grandes grupos de opciones posibles.
1. Generar una versión documental del blog.
La operación consiste en volcar el contenido de un blog a un formato documental –normalmente PDF– que pueda leerse sin conexión a Internet. Es obvio que tal solución sólo es aconsejable si no importa perder la interactividad del blog, su estructura de navegación y la disposición original de sus entradas, páginas, categorías, etiquetas, etc. En un artículo del pasado 22 de noviembre, titulado Hélice 12 y otros documentos en PDF, ya consideré algunas aplicaciones que podrían ser adecuadas para este propósito, pero esta mañana he descubierto, a partir de una consulta a los foros de WordPress, un servicio muy interesante. Se trata de BlogBooker, un servicio online cuyo rasgo característico es que opera a partir de los ficheros de exportación generados por BloggerLiveJournal y WordPress.
Y la verdad es que lo hace bastante bien, si he de juzgar a partir de mi propia experiencia, pues BlogBooker ha sido capaz de lidiar con el fichero de exportación de La Bitácora del Tigre, un monstruo de casi 10 MB. de texto plano y más de 116.000 líneas, cuyo resultado es un monumental PDF de nada menos que 1599 páginas, con paginación, índices, ilustraciones, comentarios e hipervínculos perfectamente funcionales, que tendré bien a mano para futuras contingencias. Evidentemente, no todo es perfecto en el mundo de las aplicaciones gratuitas –la maquetación y la forma de resolver el asunto de los enlaces incrustados, por poner dos ejemplos, distan mucho del óptimo deseable-, pero el producto final es del todo presentable.
Hay que tener en cuenta, además, que la solución ingeniada por BlogBooker tiene otra virtud muy aprovechable, y es el hecho de que, al estar basada en un fichero de exportación, cabe utilizarla para generar PDFs basados en cualquiera de los múltiples criterios que se pueden seleccionar para exportar un blog de WordPress. Es decir, se puede crear un PDF basado en autores, plazos cronológicos, tipo de contenido o estado de publicación, categorías, etiquetas, etc. Yo he probado a crear una versión documental de la sección de libros de La Bitácora del Tigre, mediante el plugin Advanced Export for WP & WPMU, y el resultado es tan bueno que estoy pensando en utilizarlo como carta de presentación para abrirme paso en el negocio editorial (es broma, porque no están los tiempos como para privarse de la condición de funcionario, por mucho descuento salarial que se nos venga encima).
2. Descargar una versión navegable del blog mediante un capturador web.
Los capturadores o web rippers (literalmente, ‘destripadores de webs’) son programas que se conectan a un sitio de Internet, lo leen y lo escriben a un soporte de almacenamiento, en forma de archivos estáticos. Existen multitud de aplicaciones que, de un modo u otro, encajan en esta definición (véase, por ejemplo, el epígrafe correspondiente en Softonic), y sus dos mayores ventajas son, en primer lugar, que resultan relativamente fáciles de utilizar, y en segundo lugar que permiten obtener una copia navegable del sitio, que se puede ejecutar localmente en un navegador sin conexión a Internet. Ahora bien, conviene tener en cuenta que la mayoría de esas aplicaciones dejan ciertos elementos fuera de su alcance, bien sean imágenes, determinados archivos multimedia o ciertas funcionalidades que no se pueden capturar.  Por otra parte, para sitios grandes y de estructura compleja, la definición del nivel de profundidad al que debe llegar la extracción del sitio puede resultar bastante complicada.
Yo he experimentado con diversos capturadores web en más de una ocasión, normalmente para hacer pruebas (es decir, sin una necesidad real de utilizar las capturas en un contexto en el que la conexión a Internet fuera imposible) y los resultados nunca han sido los apetecidos. La última vez que lo intenté con mi blog y uno de los programas más conocidos , HTTrack(una aplicación gratuita y multiplataforma, que tiene versiones para Windows y para varias distribuciones de Linux), el web ripper entró en una especie de bucle infinito, hasta que, después de más de diez horas de descarga y tras haber volcado al ordenador más de ¡4 GB. de datos!, tuve que detener el proceso.
En una prueba más reciente, realizada para la redacción de este artículo, y limitada a la ya citada categoría de ‘Libros’ de La Bitácora del Tigre, el HTTrack ha conseguido descargar los archivos correspondientes a dicha sección en algo menos de 16 minutos y con un peso de casi 22 MB., lo cual parece más razonable. Sin embargo, una vez ejecutado el sitio en el navegador local, he podido comprobar que los enlaces que remiten a los artículos de dicha función no envían al sitio almacenado en mi disco duro, sino a las URLs originales, por lo que la descarga carece de utilidad para los objetivos pretendidos. Probablemente este defecto no sea achacable a limitaciones intrínsecas en la funcionalidad del capturador web (a ningún programa se le pueden poner imposibles), pero sí pone de relieve las limitaciones inherentes a esta clase de aplicaciones, que fallan cuando se enfrentan a sitios con una estructura hipertextual tan densa y compleja como un blog realizado con WordPress.
3. Crear una copia exacta del blog mediante un servidor web ejecutable en local.
Esta es la opción más satisfactoria desde un punto de vista técnico, porque el resultado final puede ser un clon prácticamente exacto del blog original. Por el contrario, también es la más difícil de conseguir, porque exige la instalación de un servidor web (normalmente mediante un paquete preparado al efecto, como AppServerEasyPHPWampServer o XAMPP para Windows, o MAMP y XAMPP para Mac OS X, y no menciono las alternativas para Linux porque muchas distribuciones ya integran, aunque no las tengan activadas, las tres aplicaciones esenciales que forman parte de estos paquetes, es decir, el servidor Apache, el lenguaje de programación PHP y la base de datos MySQL), que ejecute exactamente la misma instalación y configuración del blog original, con sus mismas plantillas y extensiones, y por supuesto con un conjunto de datos idéntico. Si se dispone de los conocimientos para instalar y ejecutar en local un servidor web con los servicios anexos, (dependiendo de la complejidad del paquete, pueden incluir, además, un servidor FTP, un servidor de correo, etc.), es perfectamente factible obtener un blog con un porcentaje altísimo de funcionalidad y fidelidad al original.
Una rápida búsqueda por Internet permite encontrar una auténtica montaña de tutoriales sobre esta técnica, pero para no aburrir a mis lectores sólo ofreceré un puñado de referencias:
Una ventaja adicional de este tipo de soluciones, muy utilizadas por los profesionales de la creación de sitios web, es que permiten montar sitios de desarrollo en los que hacer pruebas y experimentos, y someter al blog a todos los tormentos imaginables, que serían del todo imprudentes en un sitio en producción. Se puede tener en un servidor local una copia sincronizada del blog original y experimentar sobre ella todos los ajustes que se consideren necesarios; sólo una vez que éstos hayan sido afinados y probados a plena satisfacción, el resultado se sube, mediante diversos procedimientos, al servidor de producción.
Por último, las instalaciones de un blog en servidor local tienen otra ventaja, y es que existen paquetes específicamente preparados para ejecutar el servidor web en un dispositivo portátil,como MoWeS Portable, diseñado para funcionar en llaves USB, o Server2Go, para unidades de CD o DVD (también XAMPP y algún otro de los paquetes ya mencionados pueden ser ejecutados en sus denominadas “versiones portables”, tal como expliqué, hace ya bastante tiempo en el artículo WordPress en un pincho). Estas versiones especializadas de los empaquetamientos de la tríada mágica –Apache, PHP y MySQL- son muy adecuadas para aquellos casos en que el objetivo es proporcionar una distribución autoejecutable de un sitio web dinámico, sea un blog, un portal, un LCMS, etc.
En todo caso, nunca hay que olvidarse de la condición esencial de la que hemos partido al comenzar este artículo, es decir, de la falta de conexión a Internet. Si carecemos de ella y nuestra bitácora llama a una imagen, a un vídeo o a un archivo de audio que se halle en otro servidor distinto al que se está ejecutando en local –y esto es muy frecuente en todos los sitios web que aprovechan la enorme variedad de servicios de la Web 2.0, y prácticamente no hay blog que no lo haga-, la funcionalidad asociada a dichos elementos será imposible. Por otra parte, sólo se puede obtener un clon exacto de un blog (de cualquier sitio web, en realidad, sea estático o dinámico) cuando se dispone de todos sus elementos de instalación. Dicho en otros términos: no se puede ejecutar en local un blog de WordPress.com (o, por referirme al caso con el que he empezando este artículo, de la plataforma Multiblog) con todas sus funcionalidades asociadas, porque es imposible recuperar de los servidores de dichos servicios todos los elementos que se la proporcionan. Lo mismo ocurre con un blog de Blogger: éste será exportable a local o a otra plataforma, servicio o aplicación gestora de blogs, pero no se podrá reproducir la instalación original, ya que depende de elementos imposibles de reproducir.

lunes, 27 de octubre de 2014

Crear un sencillo ÍNDICE con todas las entradas de tu blog

    Para crear un índice de entradas agrupadas según las etiquetas de vuestro blog, cread una página en “Creación de entradas / Editar páginas” pinchando sobre PÁGINA NUEVA. Y en la pestaña “Edición de HTML” pegad este código:

    <script style="text/javascript" src="http://sites.google.com/site/blogsmadeinspain/indice.js"></script>
    <script src="http://NOMBRE DE TU BLOG.blogspot.com/feeds/posts/default?max-results=9999&alt=json-in-script&callback=loadtoc"></script>
    Solo tienes que sustituir NOMBRE DE TU BLOG para adaptarlo a tu blog.
    Si deseas ordenar las entradas por su fecha de publicación, haced igual que antes, pero pegando este código:

    <script style="text/javascript" src="http://sites.google.com/site/blogsmadeinspain/indicefecha2.js"></script>
    <script src="http://NOMBRE DE TU BLOG.blogspot.com/feeds/posts/default?max-results=9999&alt=json-in-script&callback=loadtoc"></script>
    Sustituir NOMBRE DE TU BLOG para adaptarlo a vuestro blog.


Contenido del Archivo "indice.js"

var postTitle=new Array();var postUrl=new Array();var postMp3=new Array();var postDate=new Array();var postLabels=new Array();var postBaru=new Array();var sortBy="titleasc";var tocLoaded=false;var numChars=250;var postFilter="";var numberfeed=0;function loadtoc(a){function b(){if("entry" in a.feed){var d=a.feed.entry.length;numberfeed=d;ii=0;for(var h=0;h<d;h++){var n=a.feed.entry[h];var e=n.title.$t;var m=n.published.$t.substring(0,10);var j;for(var g=0;g<n.link.length;g++){if(n.link[g].rel=="alternate"){j=n.link[g].href;break}}var o="";for(var g=0;g<n.link.length;g++){if(n.link[g].rel=="enclosure"){o=n.link[g].href;break}}var c="";if("category" in n){for(var g=0;g<n.category.length;g++){c=n.category[g].term;var f=c.lastIndexOf(";");if(f!=-1){c=c.substring(0,f)}postLabels[ii]=c;postTitle[ii]=e;postDate[ii]=m;postUrl[ii]=j;postMp3[ii]=o;if(h<10){postBaru[ii]=true}else{postBaru[ii]=false}ii=ii+1}}}}}b();sortBy="titleasc";sortPosts(sortBy);sortlabel();tocLoaded=true;displayToc2();document.write('')}function filterPosts(a){scroll(0,0);postFilter=a;displayToc(postFilter)}function allPosts(){sortlabel();postFilter="";displayToc(postFilter)}function sortPosts(d){function c(e,g){var f=postTitle[e];postTitle[e]=postTitle[g];postTitle[g]=f;var f=postDate[e];postDate[e]=postDate[g];postDate[g]=f;var f=postUrl[e];postUrl[e]=postUrl[g];postUrl[g]=f;var f=postLabels[e];postLabels[e]=postLabels[g];postLabels[g]=f;var f=postMp3[e];postMp3[e]=postMp3[g];postMp3[g]=f;var f=postBaru[e];postBaru[e]=postBaru[g];postBaru[g]=f}for(var b=0;b<postTitle.length-1;b++){for(var a=b+1;a<postTitle.length;a++){if(d=="titleasc"){if(postTitle[b]>postTitle[a]){c(b,a)}}if(d=="titledesc"){if(postTitle[b]<postTitle[a]){c(b,a)}}if(d=="dateoldest"){if(postDate[b]>postDate[a]){c(b,a)}}if(d=="datenewest"){if(postDate[b]<postDate[a]){c(b,a)}}if(d=="orderlabel"){if(postLabels[b]>postLabels[a]){c(b,a)}}}}}function sortlabel(){sortBy="orderlabel";sortPosts(sortBy);var a=0;var b=0;while(b<postTitle.length){temp1=postLabels[b];firsti=a;do{a=a+1}while(postLabels[a]==temp1);b=a;sortPosts2(firsti,a);if(b>postTitle.length){break}}}function sortPosts2(d,c){function e(f,h){var g=postTitle[f];postTitle[f]=postTitle[h];postTitle[h]=g;var g=postDate[f];postDate[f]=postDate[h];postDate[h]=g;var g=postUrl[f];postUrl[f]=postUrl[h];postUrl[h]=g;var g=postLabels[f];postLabels[f]=postLabels[h];postLabels[h]=g;var g=postMp3[f];postMp3[f]=postMp3[h];postMp3[h]=g;var g=postBaru[f];postBaru[f]=postBaru[h];postBaru[h]=g}for(var b=d;b<c-1;b++){for(var a=b+1;a<c;a++){if(postTitle[b]>postTitle[a]){e(b,a)}}}}function displayToc(a){var l=0;var h="";var e="Judul Artikel";var m="Klik untuk sortir berdasarkan judul";var d="Tanggal";var k="Klik untuk Sortir bedasarkan tanggal";var c="Kategori";var j="";if(sortBy=="titleasc"){m+=" (descending)";k+=" (newest first)"}if(sortBy=="titledesc"){m+=" (ascending)";k+=" (newest first)"}if(sortBy=="dateoldest"){m+=" (ascending)";k+=" (newest first)"}if(sortBy=="datenewest"){m+=" (ascending)";k+=" (oldest first)"}if(postFilter!=""){j="Klik untuk menampilkan semua"}h+="<table>";h+="<tr>";h+='<td class="toc-header-col1">';h+='<a href="javascript:toggleTitleSort();" title="'+m+'">'+e+"</a>";h+="</td>";h+='<td class="toc-header-col2">';h+='<a href="javascript:toggleDateSort();" title="'+k+'">'+d+"</a>";h+="</td>";h+='<td class="toc-header-col3">';h+='<a href="javascript:allPosts();" title="'+j+'">'+c+"</a>";h+="</td>";h+='<td class="toc-header-col4">';h+="Download MP3";h+="</td>";h+="</tr>";for(var g=0;g<postTitle.length;g++){if(a==""){h+='<tr><td class="toc-entry-col1"><a href="'+postUrl[g]+'">'+postTitle[g]+'</a></td><td class="toc-entry-col2">'+postDate[g]+'</td><td class="toc-entry-col3">'+postLabels[g]+'</td><td class="toc-entry-col4"><a href="'+postMp3[g]+'">Download</a></td></tr>';l++}else{z=postLabels[g].lastIndexOf(a);if(z!=-1){h+='<tr><td class="toc-entry-col1"><a href="'+postUrl[g]+'">'+postTitle[g]+'</a></td><td class="toc-entry-col2">'+postDate[g]+'</td><td class="toc-entry-col3">'+postLabels[g]+'</td><td class="toc-entry-col4"><a href="'+postMp3[g]+'">Download</a></td></tr>';l++}}}h+="</table>";if(l==postTitle.length){var f='<span class="toc-note">Menampilkan Semua '+postTitle.length+" Artikel<br/></span>"}else{var f='<span class="toc-note">Menampilkan '+l+" artikel dengan kategori '";f+=postFilter+"' dari "+postTitle.length+" Total Artikel<br/></span>"}var b=document.getElementById("toc");b.innerHTML=f+h}function displayToc2(){var a=0;var b=0;while(b<postTitle.length){temp1=postLabels[b];document.write("<p/>");document.write('<p><a href="/search/label/'+temp1+'">'+temp1+"</a></p><ol>");firsti=a;do{document.write("<li>");document.write('<a href="'+postUrl[a]+'">'+postTitle[a]+"</a>");if(postBaru[a]==true){document.write(' - <strong><em><span style="color: rgb(255, 0, 0);">Nuevo!</span> </em></strong>')}document.write("</li>");a=a+1}while(postLabels[a]==temp1);b=a;document.write("</ol>");sortPosts2(firsti,a);if(b>postTitle.length){break}}}function toggleTitleSort(){if(sortBy=="titleasc"){sortBy="titledesc"}else{sortBy="titleasc"}sortPosts(sortBy);displayToc(postFilter)}function toggleDateSort(){if(sortBy=="datenewest"){sortBy="dateoldest"}else{sortBy="datenewest"}sortPosts(sortBy);displayToc(postFilter)}function showToc(){if(tocLoaded){displayToc(postFilter);var a=document.getElementById("toclink")}else{alert("Just wait... TOC is loading")}}function hideToc(){var a=document.getElementById("toc");a.innerHTML="";var b=document.getElementById("toclink");b.innerHTML='<a href="#" onclick="scroll(0,0); showToc(); Effect.toggle(\'toc-result\',\'blind\');">?? Menampilkan Daftar Isi</a> <img src="http://radiorodja.googlepages.com/new_1.gif"/>'}function looptemp2(){for(var a=0;a<numberfeed;a++){document.write("<br>");document.write('Post Link  : <a href="'+postUrl[a]+'">'+postTitle[a]+"</a><br>");document.write('Download mp3  : <a href="'+postMp3[a]+'">'+postTitle[a]+"</a><br>");document.write("<br>")}};

Contenido del archivo "indicefecha.js"

var postTitle=new Array();var postUrl=new Array();var postMp3=new Array();var postDate=new Array();var postYear=new Array();var postMonth=new Array();var postYearMonth=new Array();var postYearMonth2=new Array();var postTanggal=new Array();var postLabels=new Array();var postBaru=new Array();var sortBy="titleasc";var tocLoaded=false;var numChars=250;var postFilter="";var numberfeed=0;var month2=["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"];function loadtoc(a){function b(){if("entry" in a.feed){var d=a.feed.entry.length;numberfeed=d;ii=0;for(var h=0;h<d;h++){var m=a.feed.entry[h];var e=m.title.$t;var l=m.published.$t.substring(0,10);var p=m.published.$t.substring(5,7);var g=m.published.$t.substring(8,10);var n=month2[parseInt(p,10)-1]+" "+m.published.$t.substring(0,4);var c="/"+m.published.$t.substring(0,4)+"_"+p+"_01_archive.html";var j;for(var f=0;f<m.link.length;f++){if(m.link[f].rel=="alternate"){j=m.link[f].href;break}}var o="";for(var f=0;f<m.link.length;f++){if(m.link[f].rel=="enclosure"){o=m.link[f].href;break}}postTitle.push(e);postDate.push(l);postUrl.push(j);postYearMonth.push(n);postYearMonth2.push(c);postTanggal.push(g)}}}b();displayToc2();}function displayToc2(){var a=0;var b=0;while(b<postTitle.length){temp1=postYearMonth[b];document.write("<p/>");document.write('<p><a href="'+postYearMonth2[b]+'">'+temp1+"</a></p><ul>");firsti=a;do{document.write("<li>");document.write("["+postTanggal[a]+'] <a href="'+postUrl[a]+'">'+postTitle[a]+"</a>");document.write("</li>");a=a+1}while(postYearMonth[a]==temp1);b=a;document.write("</ul>");if(b>postTitle.length){break}}};



lunes, 13 de octubre de 2014

Rotacion de banners con Javascript

Un script Javascript para hacer que en un mismo espacio aparezcan rotando varios banner, en un intervalo de tiempo en la misma página.

Vamos a hacer un sistema de rotación de banners bien simple, programado en el lado del cliente con Javascript. En un espacio de la página se mostrará un banner y al cabo de unos segundos ese banner se cambiará por otro y luego por otro, hasta acabar con los banners disponibles, empezando luego otra vez por el primer banner. Todo ello en la misma página, sin necesidad de refrescarla.
El sistema es sencillo. Simplemente tenemos que hacer una función que se encargue de cambiar la imagen del banner actual por la imagen del banner siguiente. Además tendrá que cambiarse el enlace, pues suponemos que cada banner lleva a una página distinta.
Lo primero que vamos a ver es el código HTML que tendremos para visualizar el banner. Es el siguiente:
<a href="http://www.ibm.com/"><img src="ibm.gif" name="banner" width=120 height=41 border=0></a>
Como se puede ver, es un simple HTML para incluir un enlace y una imagen. Tanto el atributo href del banner como el src de la imagen están definidos con el primer banner a mostrar, para que mientras se cargue la página se muestre un anuncio, en lugar de aparecer la imagen rota. Nos debemos fijar también que a la imagen le hemos puesto un atributo name="banner", que es un nombre con el que haremos referencia a la imagen más tarde en el código Javascript.
Para definir los distintos banner y las URLs a las que van dirigidos cada banner, se crearán unos arrays con las imágenes de los banner y las URLs de destino.
//creo array de imágenes
array_imagen = new Array(4)
array_imagen[0] = new Image(120,41)
array_imagen[0].src = "ibm.gif"
array_imagen[1] = new Image(120,41)
array_imagen[1].src = "microsoft.gif"
array_imagen[2] = new Image(120,41)
array_imagen[2].src = "suse.gif"
array_imagen[3] = new Image(120,41)
array_imagen[3].src = "linux.gif"

//creo el array de URLs
array_url = new Array(4)
array_url[0] = "http://www.ibm..org/"
array_url[1] = "http://www.microsoft.com/"
array_url[2] = "http://www.suse.com/"
array_url[3] = "http://www.linux.com/"
Como hemos visto, en el array de imágenes hemos cargado una serie de objetos image, con el mismo tamaño y con sus atributos src (origen de las imágenes) distintos. En el array de URLs hemos cargado las distintas direcciones donde se dirigiría al navegador al pinchar cada banner.
Ahora veamos la función que se encargará de:
1) Actualizar la imagen para mostrar el banner siguiente
2) Actualizar el link del banner siguiente
3) Incrementar una variable que lleva la cuenta del banner que se tiene que mostrar
4) Llamarse a si misma con un retardo, para seguir la rotación de los banner.
Por cierto, la variable que se encargará de llevar la cuenta del banner que hay que mostrar se debe definir fuera de la función, para que sea global y su valor permanezca entre las distintas llamadas a la función.
//variable para llevar la cuenta de la imagen siguiente
contador = 0

//función para rotar el banner
function alternar_banner(){
    window.document["banner"].src = array_imagen[contador].src
    window.document.links[0].href = array_url[contador]
    contador ++
    contador = contador % array_imagen.length
    setTimeout("alternar_banner()",1000)
}
El código de la función es sencillo, pero contiene la mayor complejidad de este taller.
Con la primera sentencia se indica que el atributo src la imagen llamada "banner" debe actualizarse al src del array de imágenes que toca en este momento.
Con la segunda línea, indicamos que la URL de destino del enlace debe actualizarse a la que toque en el array_url. El enlace lo tenemos que referenciar con el índice cero "0" dentro del array de links de la jerarquía de objetos del navegador, pues es el primer enlace que hay en la página. Si hubiera otros enlaces por delante en el código HTML de la página, tendríamos que cambiar el índice "0" por el número de enlace correspondiente al banner.
Luego incrementamos en uno la variable contador, para pasar al siguiente índice de arrays de imágenes y banners, para que en la sucesiva llamada a la función se muestre el banner siguiente. Además, a fin de que no se nos desborde la variable contador, hacemos una operación "resto de la división" entre la longitud del array de banners.
Por último, hacemos una nueva llamada a la función, pero con un retardo de 1000 milisegundos, es decir, un segundo.
Con esto estaría todo el script comentado. Sólo nos quedaría hacer la llamada a la función una vez cargada la página, para que comiencen a rotar los banner una vez se haya terminado de mostrar la página. Esto lo hacemos con el atributo onload de la etiqueta <body>
<body onload="alternar_banner()">
Ahora podemos ver el código completo de la página web:
<html>
<head>
    <title>Rotación de banners con Javascript</title>
<script>
//creo array de imágenes
array_imagen = new Array(4)
array_imagen[0] = new Image(120,41)
array_imagen[0].src = "ibm.gif"
array_imagen[1] = new Image(120,41)
array_imagen[1].src = "microsoft.gif"
array_imagen[2] = new Image(120,41)
array_imagen[2].src = "suse.gif"
array_imagen[3] = new Image(120,41)
array_imagen[3].src = "linux.gif"

//creo el array de URLs
array_url = new Array(4)
array_url[0] = "http://www.ibm.org/"
array_url[1] = "http://www.microsoft.com/"
array_url[2] = "http://www.suse.com/"
array_url[3] = "http://www.linux.com/"

//variable para llevar la cuenta de la imagen siguiente
contador = 0

//función para rotar el banner
function alternar_banner(){
    window.document["banner"].src = array_imagen[contador].src
    window.document.links[0].href = array_url[contador]
    contador ++
    contador = contador % array_imagen.length
    setTimeout("alternar_banner()",1000)
} </script>
</head>

<body onload="alternar_banner()">

<a href="http://www.manual-de.com/#"><img src="#" name="banner" width=120 height=41 border=0></a>

</body>
</html>