En ocasiones, ocurre que el evento onLoad, por ejemplo, de una imagen no es lanzado a la hora de cargar una página.

Imaginemos que en el script de una página, una vez cargado el DOM, añadimos una función determinada cuando carga la imagen de cabecera:
<script type="text/javascript">
  // Función que ejecutamos al cargar el DOM de la página
  window.onload = function() {
    var cabecera = document.getElementById("cabecera");
    // Funcion lanzada cuando carga la imagen 'cabecera'
    cabecera.onload = function() {
      alert("carga completa");
    }
  }
</script>

Nos encontraremos con que en algún navegador (por ejemplo, Internet Explorer) lanza la primera vez el evento, pero en las posteriores cargas este no es lanzado.

La razón es que, en la segunda carga, la imagen se encuentra cacheada y por tanto el navegador carga la imagen en cuanto inserta el elemento IMG, lanzando el correspondiente evento onLoad. Como en ese preciso momento todavía estamos cargando la estructura de la página y el evento no ha sido asignado (no se asigna hasta la carga completa de la estructura), cuando queremos asignarlo ya es demasiado tarde.

Otros navegadores como Mozilla Firefox no lanzan los eventos hasta que se ha completado la carga del DOM, haciendo inexistente este problema.

Una solución sencilla es comprobar, después de asignar el evento onLoad a la imagen, si esta ya se encuentra cargada complétamente. Nos serviremos del parámetro complete. Si nos devuelve true, lanzamos el evento onLoad manualmente.
<script type="text/javascript">
  // Función que ejecutamos al cargar el DOM de la página
  window.onload = function() {
    var cabecera = document.getElementById("cabecera");
    // Funcion lanzada cuando carga la imagen 'cabecera'
    cabecera.onload = function() {
      alert("carga completa");
    }
    if (cabecera.complete == true) cabecera.onload();
  }
</script>

Actualización:

Me comenta Marc Palau (y con toda la razón) que el ejemplo anterior no es válido porque onLoad no es lanzado hasta que carga toda la página, incluidas las imágenes. En este caso, nunca seran llamados los eventos onLoad de las imágenes porque se están definiendo después de haberlas cargado.

Para reproducir el error, he preparado una prueba en la que se testea el framework jQuery y la función addDOMLoadEvent (el ejemplo que ponen en el enlace añade la imagen dinámicamente y no lo reproduce). Del mismo modo, se presenta una solución para ambas basados en el mismo procedimiento comentado antes.

A modo de apunte, os dejo un método breve, usando jQuery, para resaltar los enlaces que apuntan a la página en la que nos encontramos. Muy útil, por ejemplo, para destacar en los menús la opción seleccionada automáticamente sin recurrir a PHP o a hacerlo manualmente:

$(document).ready( function() {

var loc = document.location.href.split(/[\?#]/).shift().replace(/\/$/, ”);

$(“a”).each(function() {

if (this.href == loc) $(this).addClass(“selected“);

});

} );

El funcionamiento es muy simple. Recorre todos los elementos <a> de la página y compara el parámetro href con la url actual. Si coincide, añade la clase ‘selected‘ a dicho elemento. La clase ’selected’ deberá estar definida dentro de los estilos css de la página.

Un ejemplo aquí.

Actualización: Ahora no tiene en cuenta si la URL tiene barra al final o no (como en el caso de las carpetas)

Una precarga (muy) sencilla para Flash (AS3).  Suponiendo que el primer fotograma está vacío, podemos incluir el siguiente código en la linea de tiempo principal:

stop(); root.loaderInfo.addEventListener(Event.COMPLETE, function(e:Event) { play(); });

Esto comenzará a reproducir el flash en cuanto termine de cargar. Además, podemos aprovechar el primer fotograma para poner un mensaje ‘cargando… ‘, que será lo que se muestre mientras se completa la carga.

Extendiendo el artículo original de aNieto2k, “for reverso para grandes interaciones en Javascript“, he modificado el test que ha creado para realizar una comparativa entre los bucles for y while, sumando o restando valores e incrementándolo mediante las formas i++ y ++i. En este caso, he fijado el número de iteraciones a 5.000.000.

El resultado: probadlo vosotros mismos. Yo obtuve los siguientes valores, con un Firefox 3.0.10:

[ for i++ ] tiempo: 246ms. (5000000 iteraciones)
[ while i++ ] tiempo: 225ms. (5000000 iteraciones)
[ for ++i ] tiempo: 247ms. (5000000 iteraciones)
[ while ++i ] tiempo: 221ms. (5000000 iteraciones)
[ for i-- ] tiempo: 229ms. (5000000 iteraciones)
[ while i-- ] tiempo: 213ms. (5000000 iteraciones)
[ for --i ] tiempo: 221ms. (5000000 iteraciones)
[ while --i ] tiempo: 212ms. (5000000 iteraciones)

Según estos resultados, en Javascript al menos, daría prácticamente igual emplear la forma i++ e ++i. El ganador, un while — por goleada :D .

Actualización: Acabo de probarlo en IE7, y salta una advertencia de que un script puede estar ralentizando la web (¡si la espera no llega a medio segundo!). Dicha advertencia falsea los tiempos de todas las pruebas (hasta que no pulsas ‘aceptar’ no para de correr el tiempo), así recomiendo ejecutarla en cualquier otro navegador. Por cierto, ¡¡impresionante cómo va el Chrome 2!!

CSS Naked Day. 9 de Abril

Abril 8th, 2009

Como aficionado de la creación de web estandar (porque me queda mucho que aprender) me he unido a esta iniciativa, idea de Dustin Diaz, que lleva funcionando desde 2006 y que año a año va acogiendo a más webs.

La idea no es ser uno más, sino que junto al resto de desarrolladores hagamos un poco de ruido de lo importante que es maquetar bien una web, teniendo en cuenta que al otro lado puede haber dificultades físicas o técnicas que impidan disfrutar del contenido de la web.

Puedes comprobar con tus propios ojos este hecho en cualquier página. Si usas Firefox pincha en Ver > Estilo de Página > Sin estilos, y debería desaparecer casi todo el apartado gráfico de la web.

Alternativamente, he hecho un pequeño script (bookmarklet) que hace mas o menos ese trabajo, para aquellos navegadores que no tengan esa opción. Solamente hay que copiarlo, ir a la página ‘victima’, pegar este código en la barra de dirección y darle intro.
javascript:function a() { function g(o) { return document.getElementsByTagName(o) } ; j=g("link"); for (i in j) { if (j[i].rel == "stylesheet") j[i].href = "" } j=g("style"); for (i in j) { j[i].innerHTML = "" }  }; a();

Eliminar estilos de la página actual

Mientras llega o no la revisión de CSS Level3 ¿Como quedarán mis páginas favoritas con bordes redondeados?
javascript:function a(c) { j=document.getElementsByTagName("*"); for (i in j) { if(j[i].style) j[i].style.WebkitBorderRadius=j[i].style.MozBorderRadius=c+"px"; } };a(15)

Aplicar bordes redondeados

Y un ejemplo de cómo queda:

Ejemplo de border-radius sobre w3.org

Qué cuco queda youtube :)

Youtube.com con bordes redondeados