Why doesn't jQuery's document.ready from a dynamic append() wait for external scripts/styles?
I'm having an issue with jQuery's document.ready trigger function. I'm not sure if this is due to jQuery or due to the browsers' behavior but here's what happens: when you try to dynamically load a script using the .append() method and also set a handler for document.ready(), the document.ready() event will be triggered before the external script/css file will be loaded. This does not apply for script/css files that are on the same domain - if they are on the same domain the document.ready trigger will wait for them to load.
Here's a sample of code that shows the error:
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js">&l开发者_JAVA百科t;/script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
var html = '<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js" type="text/javascript"><' + '/script>'
+ '<script type="text/javascript">$(document).ready(function() {alert(typeof jQuery.ui);})</' + 'script>';
$('body').append(html);
});
</script>
</body>
</html>
Instead of getting an alert with "object" we get an alert with "undefined".
Thank you and kind regards.
EDIT: Someone else experienced a similar problem and they used a solution that first loads the external scripts and then loads the HTML/plain JS. The link is: http://snipplr.com/view/43449/load-external-scripts-first-for-injected-dom-html-content/. Anyway, I'm not happy with this solution as it implies several changes in the code and I'm not sure if it's 100% reliable on all browsers.
1. Loading with the DOM
As Niklas said, your dom is already ready.
You may apply this method
jQuery.getScript("url",function () { /* on success.. do this */ });
http://api.jquery.com/jQuery.getScript/
http://jsfiddle.net/4crRw/
2. Adding them together
http://jsfiddle.net/4crRw/2/
$(document).ready(function ()
{
var alertWhenDone = function (requiredObjects, callback)
{
this.callback = callback;
this.required = requiredObjects;
this.addDone = function (label) {
// remove it from the list
this.required.splice(this.required.indexOf(label),1);
if (this.required.length === 0)
{
this.callback();
}
};
return this;
};
var alertdone = alertWhenDone(['ui','swfloader','font'], function () {
alert('done');
});
jQuery.getScript('http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js',
function () {
alertdone.addDone('ui');
});
jQuery.getScript('https://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js',
function () {
alertdone.addDone('swfloader');
});
jQuery.getScript('https://ajax.googleapis.com/ajax/libs/webfont/1.0.19/webfont.js',
function () {
alertdone.addDone('font');
});
});
Instead of using:
$(document).ready(function()
You should use:
$(window).load(function()
It will wait for external content to be already loaded (e.g. images, fonts)
The jquery .ready()
function, starts as soon as the DOM hierarchy is completely loaded. This usually happens after all images have been loaded. The reason that it does not wait until the scripts/css documents are loaded is because they are "linked" meaning they are loaded externally and then remain in cache while the main code is translated into a view-able page.
If the script you currently have in the $document.ready(function{})
relies on external assets, use the <body onload="function()">
or $document.ready($document.load(asset),function{})
if you want to load specific documents/assets then the function or script.
The <body onload="function()">
function is different from the .ready()
function because the .ready()
function waits for the DOM to be built (as I said earlier) and the <body onload="function()">
function waits for the page, not the DOM, to actually start to load or render. The .load()
function is event more different, because it load assets, files, or even snips of code into the page. Using this method, in theory would be good because then there should be no need to append anything to the body.
Greater information (and a more thorough explanation) can be found at http://api.jquery.com/ready/ and http://api.jquery.com/load/.
I hope this helps.
精彩评论