jQuery document ready bug in Safari / WebKit

There is an issue with the jQuery 1.3.2 document ready function in WebKit based browsers that which can cause numerous problems if you are manipulating the DOM, in my situation getting the width / height of an element.

Using the .width() and .height() methods were working fine in every other browser but Safari, which I thought was a little bit odd. After trying to come up with an alternative method of coding calculating the heights and comparing them in FireBug and Web Inspector, I set about Googling the problem.

The only problem was that I had no idea what to search for, so started with the term “jquery height in safari”. The first result looked promising but took a fair bit of reading, although it proved to be worth while in the end. One comment pointed out that you should try to:

use jQuery(window).load() instead of jQuery(document).ready()

I tried this and straight away saw the results that were expected. The problem was that I didn’t really want to stop using the preferred document ready method ($(function() { … });), so searched the jQuery Bug Tracker for any sign of a bug report.

I eventually found one highlighting the exact problem I was having, issue #5521. The solution came in the form of a patch the document ready function that targets Safari.

+ if (jQuery.browser.safari && document.readyState != "complete") {
+ setTimeout( arguments.callee, 100 );
+ return;
+ }

It doesn’t look like this fix (nor any other form of solution) have been included in the latest nightly build, so I’m opting for the window load solution for now.

EDIT: Another solution to this problem is  to simply include any CSS files before the inclusion of the jQuery file. I found this by browsing the bug tracker and coming across ticket #3690.

23 Replies to “jQuery document ready bug in Safari / WebKit”

  1. I don’t find that only including jQuery after CSS helps. I got around it by just setting the img tag’s width and height attributes, because I know the values in my CMS already.

    I wonder if this kind of bug in library code doesn’t positively affect webkit’s benchmark performance, because that event fires earlier than it should.

  2. About the “patch” you mentionned, note that ‘jQuery.browser.safari’ returns true also for Chrome (based on Safari’s Webkit), this can lead to confusion.

    For greater readability, we can use ‘$.browser.webkit’ who will return true for any webkit based browser.

    thanks for the article,

    kat

  3. I owe you beer. Oh my goodness… two and half days this problem has been driving me insane. Thank you! I went with your jQuery(window).load() suggestion, the positioning of the CSS made no difference.

    1. @IanP I sat head in hands over this issue for a number of hours so decided to share a few solutions.

      I’m glad this has help save a few other people like yourself a great deal of time and frustration.

      Oh and does the offer of free beer still stand?! 🙂

  4. Thanks so much for pointing out that this is a known/tracked issue with jQuery. I wasted a nice sunny afternoon wondering WTF was happening, and why Chrome/Safari would run the script as intended as long as I was hitting the Back button in the browser to access the page. Reloading the page would cause the slideshow I’m implementing to disappear.

    Moving the JS files to the bottom of the page worked for me.

    Using window.load wasn’t possible because of FOUC (not to be confused with f#ck!!!).

  5. thanks , man 4 hours later I get the solution, I just have to load css before the javascript.. that’s weird…

    Awesome post!!!

  6. I don’t find that only including jQuery after CSS helps. I got around it by just setting the img tag’s width and height attributes, because I know the values in my CMS already. I wonder if this kind of bug in library code doesn’t positively affect webkit’s benchmark performance, because that event fires earlier than it should.

  7. I owe you beer. Oh my goodness… two and half days this
    problem has been driving me insane. Thank you! I went with your
    jQuery(window).load() suggestion, the positioning of the CSS made
    no difference.

Leave a Reply