Thursday 9 July 2009

jQuery Firefox error: Could not convert JavaScript argument arg 0 [nsIDOMViewCSS.getComputedStyle]

Update 3rd of March 2016: I've tested for this bug with the latest versions of Internet Explorer, Firefox and Chrome, using the latest jQuery libraries (1.12.1, 2.2.1 and 3.0.0.beta) and it could not be reproduced. The rest of the article may be obsolete.

So I am building this new jQuery based control and I am terribly smug about it until I run the test site on FireFox. Kaboom! Nothing is working. Why? Because FireFox has some issues with the computed style on hidden elements and jQuery people just don't want to fix the problem. But hey, jQuery is open source, right?

So, let's detail the problem. Here is a jQuery bug posting that explains far better than I could what is going on. Apparently, the offsetParent of a hidden element is null in FireFox and the jQuery core function returns the document object when null is given as a parameter [ $(null)==document ]. Then running the FireFox specific function for getting the computed style [ document.defaultView.getComputedStyle(element,null) ] throws an error because the element is now document and it has no style, only its body has.

So, why not fix that? The FireFox error text is '[Exception... "Could not convert JavaScript argument arg 0 [nsIDOMViewCSS.getComputedStyle]" nsresult: "0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS)" location: "JS frame :: /jqueryJsFile/ :: anonymous :: line 1349" data: no]'.

The line number might vary with the type of jQuery file version you are using and the amount of modifications you have done to it. What you should find at said line is something like: var computedStyle = defaultView.getComputedStyle(elem, null);.

Solution: Just add above it if (elem == document) elem = document.body; and it solves this particular issue.

In the minifyied version look for var M=q.getComputedStyle(I,null) and add before it if (I==document) I=document.body;


It would be far more elegant to address the problem where the offsetParent is assumed to be not null, but with so many plugins for jQuery, you can't just test them all.

14 comments:

  1. great post! just helped me out a lot. thanks :)

    ReplyDelete
  2. Great! I've taken a lot of trouble with the same issue.
    It causes of an error at Opera and Firefox.
    Thank you. :)

    ReplyDelete
  3. Thank you, sir. Just what I needed. Saved me a headache.

    ReplyDelete
  4. thanks tons!
    What up with the Cats? i kind of love it. I wish this layout were a little friendlier because you have great content. Thanks thanks thanks

    ReplyDelete
  5. I am glad you like the content. I am not great at web design, so if you have any suggestions, I am willing to listen. You might like the "low band version" of the blog, accessible via the link under the title.

    ReplyDelete
  6. Thanks man! saved me a lot of debugging time.

    ReplyDelete
  7. Just what I needed. Thanks a lot!

    ReplyDelete
  8. It didn't work for jquery-1.5. Can you test yourself?

    I've find the error line 5900

    if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
    ret = computedStyle.getPropertyValue( name );
    if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
    ret = jQuery.style( elem, name );
    }
    }


    and added above it
    if (elem == document) elem = document.body;

    but it continues to throw an error

    ReplyDelete
  9. It would be helpful if you could replicate the error in a small piece of code and send it to me. Then I will fix it for you.

    ReplyDelete
  10. "var M=q.getComputedStyle(I,null)" isn't present in jquery-1.6.2.min.js, dang..

    ReplyDelete
  11. All you have to do is debug it and see where the error is generated, then add a bit of code that checks for elem not being document, but document.body.

    ReplyDelete
  12. thanks a lot dude!
    you save me a lot of hours!

    ReplyDelete
  13. Not =>
    var computedStyle = defaultView.getComputedStyle(elem, null);

    Did you mean =>
    var getcomputedStyle = defaultView.getComputedStyle(elem, null);

    ReplyDelete
  14. No :) I meant what I wrote. But be warned that this post is pretty dated. I don't know how relevant it remains.

    ReplyDelete