views:

199

answers:

7

I'm wanting to add a class to the body tag without waiting for the DOM to load, but I'm wanting to know if the following approach would be valid. I'm more concerned with validity than whether the browsers support it for now.

<body>
 $("body").addClass("active");
 ...
</body>

Thanks, Steve

+2  A: 

If the element doesn't exist in the DOM, the search will fail to find it and the action won't be applied. If you can't do it in the $(document).ready() function, you might want to try putting the code after the element being referenced. I believe this will work.

<body>
   <div id='topStories'></div>
   <script type='text/javascript'>
     $('div#topStories').addClass('active');
   </script>
</body>

If you need to add the class to the body, I would definitely use $(document).ready().

tvanfosson
So if I get you correctly, you're saying the element doesn't exist until it's been closed. Is that correct?
Steve Perks
I'm saying that is the safest way. I would assume that, since the element may not be fully specified (missing end tag), the browser wouldn't add it to the DOM until it had been fully parsed. I can't point at a standard that enforces this, though.
tvanfosson
Appreciated. I'll elaborate a little more and see I spark any more neurons - cheers.
Steve Perks
+2  A: 

Short answer: it depends. Apparently, according to my tests, the answer seems to be yes, depending on what you want. I just tested this:

<html>
<head>
    <style type="text/css">
     .foobar { background-color: #CCC; }
    </style>
</head>
<body>
    <script type="text/javascript">
     window.document.body.className = "foobar";
    </script>
    <div style="border: solid 1px"><br /></div>
    <script type="text/javascript">
    // happens before DOM is fully loaded:
     alert(window.document.body.className);
    </script>
    <span>Appears after the alert() call.</span>
</body>
</html>

In IE 7, when the alert() takes place, the value is set correctly, but the style hasn't yet been applied (it is quickly applied as soon as the DOM is finished loading).

In Firefox, the style has been applied by the time the alert() takes place.

Anyway, hope this is helpful to you.

Jason Bunting
A: 

That was VERY helpful.

To put a little real world to the question.

I build with the assumption that JavaScript isn't supported and then override with the JavaScript. The problem is, that when I have to wait for the DOM to load before my overrides kick in the site goes through the flicker stage as it's built. I'm hoping that if I can add a class of "active" to the body element before the rest of the site's loaded I'll be able to apply JavaScript assumed styles before the page renders.

What I don't want to do is to add this and then get a call when Firefox4 comes out that I shouldn't have done it.

If you take a look at a site I built, you'll see that it degrades gracefully, but that ficker bugs me (especially if an ad hangs the site up). I could take the other guys approach and just build it with JS assumed, but come on - that's just lazy...

Steve Perks
What was very helpful? Not sure what you are specifically referring to...
Jason Bunting
@Jason, The knowledge that FF and IE react differently. That essentially answers my initial question, but considering that Mar got me my solution, I had to give him the kudos. Wish I could have shared it :)
Steve Perks
+1  A: 

Basically, the answer is no. In IE6 and Firefox 2 (the browsers I have the most experience in), the element isn't in the DOM until after the close tag (or the page is done rendering, for invalid XHTML). I know that jQuery provides a convenience methods that seems to react quickly enough to avoid "flicker" in most cases. You would use it like so:

<script>
  $(document).ready(function() {
    $("body").addClass("active");
  });
</script>
<body>
  ..
  ..
  ..
</body>

But that's about it for javascript.

Of course, in the example you provided, you could easily just accomplish the same effect with:

<body class="active">
</body>
Adam N
+2  A: 

The .elementReady() plugin seems to be pretty close to what you're looking for.

It operates by using a setInterval loop, that exits as soon as document.getElementById() returns an element for a given id.

You could probably do a slight modification of that plugin (or commit an update/patch) to allow for generic selectors (at least for "tagNames") instead of just ids.

I don't believe there is any truly reliable cross-browser compatible way to address an element before it's loaded - other than this sort of setInterval hacking

Unless you are able to place your javascript command inside the target element like @JasonBunting suggests.

Már Örlygsson
A: 

Thanks ALL for the detailed answers guys - Adam, you provided the answer to my question, but Már gets the credit for answering my problem :) I'll certainly be taking a good look at the elementReady() plugin.

Cheers, Steve

Steve Perks
A: 

Rather than adding a class to your <body> tag you might find it easier to add a class to the <html> tag by doing:

<script type="text/javascript">
    document.documentElement.className = 'active';
</script>
Ian Oxley