21

I want to rewrite this line without using jQuery so it can be applied quicker (and before the downloading of the jQuery library). The line is...

$(document).ready(function() { $('body').addClass('javascript'); });

If I added it to the html element instead, would I be able to leave off the DOM ready part? One problem with this though is the validator doesn't like the class attribute on the html element, even if it is inserted with JS.

So, how would I rewrite that without jQuery?

alex
  • 438,662
  • 188
  • 837
  • 957
  • You'll need a DOM API, you can't do this in vanilla JS (you can't do much of anything in vanilla JS). ;) – Quentin Nov 25 '09 at 07:12
  • What exactly do you want to achieve? Do you want to tell CSS that JavaScript is available? Do you want to do it as early as possible using browser-specific events? Does simple "onload" event work for you? Any additional input would help to give you the right answer. – Eugene Lazutkin Nov 25 '09 at 07:26
  • @David: What's jQuery written in then? – Tim Down Nov 25 '09 at 09:12
  • 2
    @Tim Down: It's written in JS … and makes use of the DOM APIs (the W3C and the Microsoft one with adjustments for browser bugs), so it isn't "vanilla" (and note the smiley). – Quentin Nov 25 '09 at 09:57
  • @David: Aaaah, I think I see: by "vanilla JS" you mean just the language and none of the environment? – Tim Down Nov 25 '09 at 14:02
  • By "vanilla JS" I think "what a silly term" and can't resist gently mocking it. It might have been better to express the question in terms of 'minimal JS'. – Quentin Nov 25 '09 at 19:28
  • @David Sorry I have heard the phrase here before and thought it was well known. I also didn't mean to exclude the DOM API. – alex Nov 25 '09 at 23:03
  • 12
    Mocking those who are less informed is not funny or cool. We were all there once. And besides, helping him understand why his statement wasn't semantically perfect would have been more useful than being smugly superior. – Slobaum Mar 13 '13 at 20:04

8 Answers8

48

If you want to reproduce the jQuery's document.ready event, you can use the onreadystatechange or DOMContentLoaded events where applicable:

function domReady () {
  document.body.className += " javascript";
  // ...
}

// Mozilla, Opera, Webkit 
if ( document.addEventListener ) {
  document.addEventListener( "DOMContentLoaded", function(){
    document.removeEventListener( "DOMContentLoaded", arguments.callee, false);
    domReady();
  }, false );

// If IE event model is used
} else if ( document.attachEvent ) {
  // ensure firing before onload
  document.attachEvent("onreadystatechange", function(){
    if ( document.readyState === "complete" ) {
      document.detachEvent( "onreadystatechange", arguments.callee );
      domReady();
    }
  });
}
Christian C. Salvadó
  • 723,813
  • 173
  • 899
  • 828
  • See also: http://stackoverflow.com/questions/2304941/what-is-the-non-jquery-equivalent-of-document-ready – user456584 Jul 01 '13 at 01:49
  • 3
    Why are you detaching the readystatechange event? Does IE8 fire that event twice? Why? – John Dvorak Jul 09 '14 at 11:40
  • @Jan I'm guessing this was transcribed from the jQuery source which also adds a fallback listener to window.onload. So in the jQuery source, the first time the callback is invoked listeners need to be removed to avoid invoking twice, once for each event. But since this code doesn't include that fallback I don't think it's necessary to remove the listener. But I'm just speculating. – pgraham Sep 28 '15 at 03:34
  • If you are attempting to replicate the behaviour of jQuery 2.x, it does not include capability detection for `document.attachEvent` and always uses the DOMContentLoaded event. https://github.com/jquery/jquery/blob/master/src/core/ready.js – pgraham Sep 28 '15 at 03:39
  • @JanDvorak - In general it is good practice and can be beneficial to performance to remove listeners that are no longer needed. – Jimbo Jonny Jan 27 '16 at 23:04
  • Can anybody confirm that domReady get's called twice from line 10 atleast in Mozilla Firefox? Hard to understand why. – Manuel Arwed Schmidt Feb 16 '16 at 17:08
2

I dont know about vanilla JS, but you can write:

document.getElementsByTagName('body')[0].className += ' javascript';

at the bottom of the page (before closing the body tag).

David Hellsing
  • 97,234
  • 40
  • 163
  • 203
1

If your aim is to add the class to body immediately as the page is loaded, perhaps to hide no-JS-fallback elements, you could do that just immediately inside the body tag rather than waiting for any events:

<body>
    <script type="text/javascript">
        document.body.className+= ' javascript';
    </script>

(although in general if that's the aim it's better to remove the fallback elements as you go along replacing them with scripted elements, so that if one piece of script errors out all the other components on the page don't break.)

This is the fastest way to bind to elements: do so just immediately after creating them (inside the open tag if you only need to alter the elements; just after the close tag if you need to alter their contents). However this approach does tend to litter the page with ugly <script> blocks, which is why more people put the code all at the bottom or use an load/ready-handler.

bobince
  • 498,320
  • 101
  • 621
  • 807
0

If just dealing with modern browsers, you could place this just after the opening body tag.

<script>
     document.body.classList.add("javascript");
</script>
alex
  • 438,662
  • 188
  • 837
  • 957
0
window.onload = function() {
   var elmt =  document.getElementsByTagName('body');
   if(elmt){
      elmt[0].className = 'javascript';
   }
}

That should do it.

EDIT: Updated to get element by tag name not ID.

jaywon
  • 7,818
  • 10
  • 36
  • 47
  • @David, thx for the heads up. don't do a lot of jQuery so assumed that was to find an element by ID. – jaywon Nov 25 '09 at 06:57
  • 2
    I'm pretty sure `onload` is triggered after `$(document).ready` - I think it's waiting for all images to load, for example. – Kobi Nov 25 '09 at 06:57
  • 2
    document.body is cleaner (and slightly faster) then gEBTN[0]. – Quentin Nov 25 '09 at 07:13
0

Simple:

window.onload = function() {
  document.body.className = "javascript";
}

Or in HTML:

<body onload="document.body.className = 'javascript'">...</body>

Unless you want to differentiate between "before onload" and "after onload", you can do it statically:

<body class="javascript">...</body>
Eugene Lazutkin
  • 42,168
  • 8
  • 47
  • 56
  • 1
    I think he's trying to add the class, to indicate that javascript is enabled - hence your 3rd example wouldn't quite do. Also, pretty sure DOMReady fires before Load (which will wait for images & external resources) – K Prime Nov 25 '09 at 07:19
  • Feel free to ignore the 3rd example. In all fairness he didn't indicate what he wants to achieve by that. – Eugene Lazutkin Nov 25 '09 at 07:22
0

Did you try to put at the very end of your body the following?

<script>
    document.body.className = 'javascript';
</script>
Mic
  • 23,536
  • 8
  • 55
  • 69
0

just put this

<script>document.body.className += ' javascript';</script>

before </body> tag. Simple and easy (and very close) solution.

NilColor
  • 3,342
  • 2
  • 27
  • 44