Problema:
Cargar js archivos de forma asíncrona, a continuación, comprobar para ver si el DOM se carga antes de la devolución de llamada desde la carga de los archivos se ejecuta.carga JavaScript asíncrono, a continuación, comprobar DOM cargado antes de ejecutar devolución de llamada
editar: No usamos jQuery; usamos Prototipo
editar: agregó más comentarios al ejemplo de código.
Hola chicos,
estoy tratando de cargar todos mis archivos js de forma asíncrona con el fin de evitar que se bloquea el resto de la página. Pero cuando los scripts se cargan y se llama a la devolución de llamada, necesito saber si el DOM se ha cargado o no, así que sé cómo estructurar la devolución de llamada. Vea a continuación:
//load asynchronously
(function(){
var e = document.createElement('script');
e.type = "text/javascript";
e.async = true;
e.src = srcstr;
// a little magic to make the callback happen
if(navigator.userAgent.indexOf("Opera")){
e.text = "initPage();";
}else if(navigator.userAgent.indexOf("MSIE")){
e.onreadystatechange = initPage;
}else{
e.innerHTML = "initPage();";
}
// attach the file to the document
document.getElementsByTagName('head')[0].appendChild(e);
})();
initPageHelper = function(){
//requires DOM be loaded
}
initPage = function(){
if(domLoaded){ // if dom is already loaded, just call the function
initPageHelper();
}else{ //if dom is not loaded, attach the function to be run when it does load
document.observe("dom:loaded", initPageHelper);
}
}
La devolución de llamada se llama correctamente debido a un poco de magia detrás de las escenas que se pueden aprender acerca de esta charla Google: http://www.youtube.com/watch?v=52gL93S3usU&feature=related
¿Cuál es el más fácil, el método multi-navegador por preguntar si el DOM ya ha cargado?
EDIT
Aquí está la solución completa que fui.
Incluí el prototipo y el gestor de scripts asíncrono utilizando el método normal. La vida es mucho más fácil con el prototipo, así que estoy dispuesto a bloquear ese guión.
<script type="text/javascript" src="prototype/prototype.js"></script>
<script type="text/javascript" src="asyncLoader.js"></script>
Y, de hecho, en mi código que minified los dos archivos anteriores y ponerlos juntos en un solo archivo para minimizar el tiempo de transferencia y peticiones http.
Luego defino lo que quiero ejecutar cuando se carga el DOM, y luego llamo a la función para cargar los otros scripts.
<script type="text/javascript">
initPage = function(){
...
}
</script>
<script type="text/javascript">
loadScriptAsync("scriptaculous/scriptaculous.js", initPage);
loadScriptAsync("scriptaculous/effects.js", initPage);
loadScriptAsync("scriptaculous/controls.js", initPage);
...
loadScriptAsync("mypage.js", initPage);
</script>
Del mismo modo, las solicitudes anteriores están en realidad comprimidas en una httpRequest utilizando un minificador. Se dejan separados aquí para facilitar la lectura. Hay un fragmento en la parte inferior de esta publicación que muestra cómo se ve el código con el minificador.
El código para asyncLoader.js es la siguiente:
/**
* Allows you to load js files asynchronously, with a callback that can be
* called immediately after the script loads, OR after the script loads and
* after the DOM is loaded.
*
* Prototype.js must be loaded first.
*
* For best results, create a regular script tag that calls a minified, combined
* file that contains Prototype.js, and this file. Then all subsequent scripts
* should be loaded using this function.
*
*/
var onload_queue = [];
var dom_loaded = false;
function loadScriptAsync(src, callback, run_immediately) {
var script = document.createElement('script');
script.type = "text/javascript";
script.async = true;
script.src = src;
if("undefined" != typeof callback){
script.onload = function() {
if (dom_loaded || run_immediately)
callback();
else
onload_queue.push(callback);
// clean up for IE and Opera
script.onload = null;
script.onreadystatechange = null;
};
script.onreadystatechange = function() {
if (script.readyState == 'complete'){
if (dom_loaded || run_immediately)
callback();
else
onload_queue.push(callback);
// clean up for IE and Opera
script.onload = null;
script.onreadystatechange = null;
}else if(script.readyState == 'loaded'){
eval(script);
if (dom_loaded || run_immediately)
callback();
else
onload_queue.push(callback);
// clean up for IE and Opera
script.onload = null;
script.onreadystatechange = null;
}
};
}
var head = document.getElementsByTagName('head')[0];
head.appendChild(script);
}
document.observe("dom:loaded", function(){
dom_loaded = true;
var len = onload_queue.length;
for (var i = 0; i < len; i++) {
onload_queue[i]();
}
onload_queue = null;
});
I añadido la opción de ejecutar una secuencia de comandos inmediatamente, si tiene secuencias de comandos que no se basan en la página DOM estar totalmente cargado.
Las solicitudes minified realmente se ven como:
<script type="text/javascript" src="/min/?b=javascript/lib&f=prototype/prototype.js,asyncLoader.js"></script>
<script type="text/javascript"> initPage = function(e){...}</script>
<script type="text/javascript">
srcstr = "/min/?f=<?=implode(',', $js_files)?>";
loadScriptAsync(srcstr, initPage);
</script>
Están usando el plugin de: http://code.google.com/p/minify/
Gracias por la ayuda !!
-K
que haría uso de eventos de jQuery $ (document) ready(). La forma más sencilla y cruzada que conozco. – Yoni
Puede usar un marcador que puede establecer cuando DOM está cargado y buscar ese indicador en su callback fn. – Rajat
puede marcar una respuesta como aceptada si su problema fue resuelto. – galambalazs