Document Ready Fixed
Document Ready Fixed
Good News Everyone!
I put in an afternoon of work on jQuery, today, and squished some of
the more notorious bugs.
The most important of which was the $(document).ready() bug.The
premise for the bug was that two things would happen:
1) Occasionally, the function would fire too soon (in Firefox), before
the DOM was completely loaded.
2) ready() would fire if you embedded Adsense into your site (it was
assumed that this was due to document.write).
So, let me outline what I've done to make this "the best document
ready function ever".
In my tests, I've determined that it is NOT document.write that breaks
the DOM ready mechanism. To verify this, I even did this:
document.write = function(){};
and it still broke, so obviously the problem was much more complicated
than that.
As far as I can tell, this weird "only half the DOM is loaded" bug
only occurs when there's <script> tags embedded in the <body> of your
code that access the DOM in some way. This makes it virtually
impossible to detect.
For those of you aren't familiar with the problem, it's been an issue
that if you embed Adsense in your site, the jQuery DOM Ready kludge
would fire early - BUT with an operational DOM. The problem was that
you could do getElementsByTagName and getElementById but they wouldn't
be able to 'see' anything that was beyond the first external,
DOM-using, script in the page.
Since this issue *only* effects the kludge that has been in jQuery
since Day 1, and since it only effects Safari and Opera (since I've
since found better code for IE & Mozilla), I needed to find a
compromise. Essentially, whenever my kludge fires, claiming that the
DOM is loaded, I check to see if there are any <script> tags outside
of the <head> of the page. If that's the case, then I wait for
window.onload - since I have no other way of determining if the full
page has actually loaded. (If anyone else has any cool ideas, let me
know)
I've setup a test page, it has an Adsense referral banner, a long
loading image, numerous embedded document.writes(), and regular DOM
elements.
http://john.jquery.com/jquery/test/ready.html
Right now, the SVN version of jQuery successfully fires
$(document).ready() for every browser.
To make this happen, I've borrowed the code from this particular DOM
Ready implementation:
http://linguiste.org/projects/behaviour-DOMContentLoaded/example.html
as it helps to speed up the two most popular browsers: IE and Mozilla.
With that in mind, this is how it breaks down:
Internet Explorer & Mozilla:
If Adsense: Fires on DOM Ready
If long-loading Image: Fires on DOM Ready
If normal: Fires on DOM Ready
Safari & Opera:
If Adsense: Fires on Window Load
If long-loading Image: Fires on DOM Ready (Using kludge)
If normal: Fires on DOM Ready (Using kludge)
Additionally, I've fixed a couple bugs, and added a feature.
The broken slideDown/slideUp bug has been resolved. It looks as if it
was a problem with a typo in my code, from before.
I don't know if this was just me, but I was having trouble with #id
selectors in safari. I think I've fixed the problem now.
$.browser now contains a text string referring to what browser the
user is using. The string can either be 'opera', 'safari', 'mozilla',
or 'msie'. I needed this for the DOM Ready stuff and I figure it could
be useful for others as well.
All of these are in the latest SVN build of jQuery (revision 60):
http://jquery.com/src/dev/sane/
Let me know if you spot any problems with these fixes, as I'd like to
push them live ASAP.
--John