views:

1224

answers:

5

I have a problem with a page where I am trying to get colorbox (a kind of lightbox for jQuery) working. It doesn't work apparently due to the document.body being null in FireFox (3.5.3). This is not the case in Safari (4.0.3) where the colorbox works.

Something that jumps out at me is that (I'm using Drupal 6) drupal has appended a script tag to set some JavaScript variables at the very bottom of the page, below the closing body and html tags. Otherwise I don't see a problem. Unfortunately I'm having a lot of trouble getting it not to do that. Could it be this that's causing FF to have issues with the body?

Using colorbox's example files in Firefox does work (and the document.body is defined there).

Is there any way I could use jQuery to refill the document.body property with something from $() perhaps, or should I keep banging at drupal to not put a script tag outside the html tags (easier said than done)?

To clarify the document.body is null even after the page is done loading. Here's a Firebug console capture:

>>> document.body
null
>>> $().attr('body')
null
+4  A: 

The usual reason document.body is null is because you're executing script before the <body> tag(*) has been encountered. Without seeing code I can't say for sure, but that'd be the usual reason. Move where you've put the scripts.

(*: or another element such as <p> that the browser knows can't occur outside of a body, in which case it silently adds a <body> to fix up your missing markup. A difference in parsing of certain usually-in-body-tags might explain why Safari allows you to get away with it.)

Could it be this that's causing FF to have issues with the body?

No. It's broken markup and Drupal shouldn't do it, but closing the </body> doesn't stop document.body referencing the proper DOM Node.

Is there any way I could use jQuery to refill the document.body

No, document.body is only reflecting basically the same as document.getElementsByTagName('body')[0], so trying to set it is not sensible, and if you can't find a body with document.body, jQuery won't be able to find it with $('body') either.

bobince
I get what you're saying and generally agree, except that in this case I get null for document.body and the correct value with `$('body')` so perhaps, somewhere in some document.body was assigned to null?
dlamblin
You can't assign to document.body; you will get a JavaScript error in every browser. Is it possible you have instead simply accidentally defined a global variable called ‘document’, which is hiding access to the real document object?
bobince
or, jQuery has built in checks that allow it to return the non-null value for `$('body')`. ie. it makes sure (or waits) `<body>` is loaded.
cottsak
I'm not sure such a thing is possible... anyway it doesn't. See line 90 of jQuery 1.4.2 for what it *does* do now, which is to optimise the `('body')` case to just pick up `document.body` directly. (This is a bit wrong too, as if `document.body` is `null` you will now get a wrapper list with one item, `null`, instead of a zero-length list.)
bobince
A: 

Well this is odd, but just adding this line at the bottom of my $(document).ready(function(){}); fixed whatever was breaking the body:

  if(null==document.body){document.body = $('body')[0];}

But I'll have to look more at why it got broken in the first place, and also why it didn't break in safari.

dlamblin
+1  A: 

There should not be any output from Drupal below the body tag. Check your themes page.tpl.php file. The end should look pretty much like this:

<!-- BEGIN closure: must always be last element in body -->
    <?php print $closure; ?>
<!-- END closure -->

</body>
</html>

There should be no print statement below the output of the $closure variable, as this needs to be the last content output (but still within the body).

Henrik Opel
Thanks, I agree with what you say, and I do have the statement inside my body tag of my theme, and just above a google analytics tag.
dlamblin
Interesting - normally the google analytics tag would be part of the content of the $closure variable, not a separate output below. Are you using the google_analytics module or did you put the tag there yourself?
Henrik Opel
You might want to remove the analytics tag temporarily to see if this affects your problem - if it does, add it back via `drupal_add_js()` with `$scope='footer'`, then it will be part of the $closure variable.
Henrik Opel
+1  A: 

Don't you use another JS framework along with jQuery ? If so, did you take care of how to load both libraries so that they remain compatible (order, compatibility fix...) ?

Open SEO
A: 

Hi, sorry this answer isn't in jquery (I've been wrestling with something similar over the last couple of hours with prototype).

Basically, the top answer from bobince is quite quite helpful, however you can re-assign the document body the trick is finding it.

This is prototype but you get the idea,

body = $("content").ancestors().last().children[1];

Where content is some defined element on the page you can find with usual selectors, any can be used it doesn't really matter, from there you traverse to the top and then down and along to the body element.

Hope that helps, like I said my problem was only similar, not sure how this will go for you, but I hope it at least triggers an idea for someone.

jim