NOTA: este post está escrito hace muchos años y está totalmente obsoleto. En la actualidad no es necesario ya que existe un evento específico en el navegador, DOMContentLoaded, que se encarga de ello. Basta con añadir un manejador de la manera habitual: window.addEventListener('DOMContentLoaded', function(ev) { //Haz lo que quieras cuando cargue el DOM });. Así que no es necesario que sigas leyendo 😉 Lo dejo por histórico.

Esto a simple vista es una tarea sencilla, ya que de toda la vida las páginas HTML disponen de un evento onload que nos permite detectar cuando el documento ha cargado por completo.

Por ejemplo, si escribimos:

   1: <body onload="doWhatYouNeed();">
   2: ......
   3: </body>

spongebob_readyEn cuanto el documento esté completamente cargado se llamará de manera automática a la función doWhatYouNeed.

Esto nos asegura que cuando se llame a la función todos los elementos de la página estarán cargados y listos para su uso, incluyendo los que hay que cargar en una segunda fase tras la carga del HTML de la página: imágenes, CSS, etc...

Sin embargo en muchas ocasiones nos hará falta detectar una fase anterior en el ciclo de vida de la página: cuando la jerarquía de objetos está lista para ser utilizada. Esto implica que se ha interpretado todo el HTML, se han cargado los scripts y por lo tanto se puede manipular el contenido del documento sin problemas. En este momento puede que todavía no se hayan cargado las imágenes y otros elementos, pero podemos manipular sin problemas el DOM ya que éste ha sido generado por completo.

jQuery nos ofrece el método ready()para detectar esta circunstancia, facilitándonos mucho la vida, pues basta con definir una función dentro de éste para que sea llamada en cuanto la página esté lista para ser manipulada.

En este post explicaré como conseguir esta misma funcionalidad directamente con JavaScript y para todos los navegadores del mercado, sin utilizar ninguna biblioteca externa.

La propiedad readyState

Esta propiedad readyState, del objeto document, disponible en todos los navegadores actuales (en Firefox desde la versión 3.6), nos devuelve una cadena de texto que indica el estado actual de la página. Los valores que puede tener son los siguientes, ordenados por el momento en el que se producen dentro del ciclo de vida de la página:

uninitialized No se ha inicializado aún
loading Se están empezando a cargar los datos de la página, e interpretando el HTML
loaded Se han cargado ya los elementos en la jerarquía de la página
interactive El usuario ya puede interactuar con los elementos de la página aunque todavía no estén cargados todos (por ejemplo, faltan las imágenes).
complete Se ha terminado de cargar la página completamente

De acuerdo. Entonces a partir de esta propiedad es sencillo determinar en qué estado se encuentra nuestra página, y si está en estado loaded o superior entonces sabemos que podemos ya interactuar con el DOM desde nuestros scripts.

Pero ¿cómo detectamos el cambio de estado?

Detectar el cambio de estado

Internet Explorer y Ópera ofrecen un evento para la página muy útil llamado onreadystatechange. Es posible interceptarlo y cada vez que cambie el estado se nos notificará de ello, pudiendo actuar en consecuencia. El problema que tiene su uso es que no es multiplataforma, ya que no funcionará en Firefox, ni Chrome ni Safari, ni en los navegadores móviles.

Entonces ¿cómo podemos hacer para solventar este problema?

Vamos a tomar otro camino y lo que haremos será comprobar en intervalos muy cortos el estado actual de la página usando un temporizador de JavaScript.

El código es muy sencillo:

   1: var tmrReady = setInterval(isPageFullyLoaded, 100);
   2:  
   3: function isPageFullyLoaded() {
   4:     if (document.readyState == "loaded" || document.readyState == "interactive" || document.readyState == "complete") {
   5:         doWhatYouWant();
   6:         clearInterval(tmrReady);
   7:     }
   8: }

Como vemos lo que se hace es crear un temporizador periódico, que cada 100 milisegundos llame a la función isPageFullyLoaded. En ésta lo que se hace es comprobar si el documento se encuentra actualmente en alguna de las fases en las que ya es posible manipular el DOM, en cuyo caso llamamos a la función que nos interese, para hacer lo que sea, y además (y esto es muy importante), eliminamos el temporizador pues ya no nos va a resultar útil.

Podríamos usar un intervalo menor (por ejemplo de 50 milisegundos) pero normalmente con 100 es más que suficiente y no así cargamos menos la ejecución inicial de la página.

Con este truco podremos detectar el estado de la página de forma muy sencilla y conseguir lo mismo que el ready de jQuery sin necesidad de cargar toda la biblioteca jQuery para algo tan pequeño.

¡Espero que te resulte útil!

Para saber más: JavaScript profesional para desarrolladores y diseñadores web

💪🏻 ¿Este post te ha ayudado?, ¿has aprendido algo nuevo?
Pues NO te pido que me invites a un café... Te pido algo más fácil y mucho mejor

Escrito por un humano, no por una IA