12

I'm curious what situations exactly require the use of jquery's $(document).ready() or prototype's dom:loaded or any other variant of a handler for this event.

In all the browsers i've tested, it's entirely acceptable to begin interacting with html elements and the DOM immediately after the closing tag. (e.g.

<div id="myID">
 My Div
</div>
<script type="text/javascript">
$('#myID').initializeElement();
</script>

So at this point i'm wondering whether $(document).ready() is merely there to reduce the thinking involved in writing javascript code that runs during page load. In the case of using $(document).ready() there is regularly rendering issues such as popping and 'artifacts' between the browser first starting to draw the page and the javascript actually executing when the page is 'ready'.

Are there any scenarios where $(document).ready() is required?

Are there any reasons I shouldn't be writing initialization scripts as demonstrated?

Adil Shaikh
  • 44,509
  • 17
  • 89
  • 111
hannasm
  • 1,951
  • 4
  • 16
  • 25
  • possible duplicate of [jQuery: Why use document.ready if external JS at bottom of page?](http://stackoverflow.com/questions/1438883/jquery-why-use-document-ready-if-external-js-at-bottom-of-page) – Ciro Santilli OurBigBook.com Feb 06 '14 at 17:21

3 Answers3

10

The main reason is external files that are included in the head. When you include a file in your <head> it gets run immediately. This means if the JavaScript interacts with the DOM it needs to be wrapped in Dom Ready.

It's also needed for unobtrusive JavaScript and separations of concerns. Ideally your JavaScript and HTML are in separate files. If you follow this you will not have any in-line script tags in your HTML at all.

The second is to defend yourself against obscure browser bugs when you make mistakes. There are cases where it's not save to go and manipulate DOM elements immediately afterwards. (I'm looking at you IE6!)

The third reason is to keep your code clean.

Mixing script tags into your HTML makes spaghetti code.

some HTML
<script> ... </script>

some HTML
<script> ... </script>

some HTML
<script> ... </script>

some HTML
<script> ... </script>

some HTML
<script> ... </script>

some HTML
<script> ... </script>

some HTML
<script> ... </script>

We have code about ten times worse then that. It's a right pain to read / maintain

Raynos
  • 166,823
  • 56
  • 351
  • 396
  • i think it's rather obtrusive to initialize dom elements with $(document).ready() and as result see rendering issues. You do make some good points though. – hannasm May 15 '11 at 01:17
  • @SmokingRope what do you mean initialize DOM elements? Unobtrusive JavaScript is supposed to be used with progressive enhancement. You only enhance DOM elements that are already there with JavaScript once the DOM is loaded. – Raynos May 15 '11 at 01:19
  • By initialize i mean the same as your 'progressive enhancement'. Make a test html file the has 1MB worth of
    in it, load it up in your browser and use $(document).ready() to hide those divs. Whatever progressive enhancements you want won't take effect for several minutes / seconds after the browser has started rendering your page. This affect can also be exaggerated by network conditions so it may not show until your client hits your page from offsite.
    – hannasm May 15 '11 at 01:35
  • @SmokingRope your problem here is that your sending a 1MB HTML file. Your HTML page is supposed to work without JavaScript. If it's really that big, get JavaScript to inject a loading overlay as an inline script. If your page looks poor / messy without JavaScript then that's the problem in itself. – Raynos May 15 '11 at 01:36
  • You can observe the same affects with smaller pages, it's an example that *will* reproduce the problem. – hannasm May 15 '11 at 01:37
  • 2
    @SmokingRope the *right* way to avoid jumpy pages is to render them in the state they should be in. You shouldn't be using Javascript as a crutch this way. – Nicole May 15 '11 at 03:16
  • It's not possible to render the page in it's final state if you are using progressive enhancement. – hannasm May 15 '11 at 03:43
  • @SmokingPope It's possible to render it in the final non-JavaScript state. There shouldn't be large differences between that and the final JavaScript state in terms of overall layout / look and feel. – Raynos May 15 '11 at 03:47
  • I don't necessarily disagree with you, but this discourse is subjective and doesn't answer the question. See my own answer below for what i was really looking for. – hannasm May 16 '11 at 07:22
  • @SmokingRope I disagree with that. It does answer the question. It gives good reasons to prefer DOM loaders rather then in-line scripts. Mainly the usage of external files and unobtrusive JavaScript. – Raynos May 16 '11 at 07:43
6

In the case of external scripts $(document).ready() could be the only option. As for inline script it is a little different.

According to HTML 4.01 standard it seems a little ambiguous whether or not the initialization technique shown above is legal:

http://www.w3.org/TR/html401/interact/scripts.html#h-18.2.4

Scripts that are executed when a document is loaded may be able to modify the document's contents dynamically. The ability to do so depends on the scripting language itself (e.g., the "document.write" statement in the HTML object model supported by some vendors).

HTML documents are constrained to conform to the HTML DTD both before and after processing any SCRIPT elements.

In the HTML 5 draft it seems very clear that this practice is fully supported:

http://www.w3.org/TR/html5/scripting-1.html#scripting-1

The following sample shows how a script element can be used to define a function that is then used by other parts of the document. It also shows how a script element can be used to invoke script while the document is being parsed, in this case to initialize the form's output.

<script>
 function calculate(form) {
   var price = 52000;
   if (form.elements.brakes.checked)
     price += 1000;
   if (form.elements.radio.checked)
     price += 2500;
   if (form.elements.turbo.checked)
     price += 5000;
   if (form.elements.sticker.checked)
     price += 250;
   form.elements.result.value = price;
 }
</script>
<form name="pricecalc" onsubmit="return false">
 <fieldset>
  <legend>Work out the price of your car</legend>
  <p>Base cost: £52000.</p>
  <p>Select additional options:</p>
  <ul onchange="calculate(form)">
   <li><label><input type=checkbox name=brakes> Ceramic brakes (£1000)</label></li>
   <li><label><input type=checkbox name=radio> Satellite radio (£2500)</label></li>
   <li><label><input type=checkbox name=turbo> Turbo charger (£5000)</label></li>
   <li><label><input type=checkbox name=sticker> "XZ" sticker (£250)</label></li>
  </ul>
  <p>Total: £<output name=result></output></p>
 </fieldset>
 <script>
  calculate(document.forms.pricecalc);
 </script>
</form>
hannasm
  • 1,951
  • 4
  • 16
  • 25
  • 1
    +1 for pointing out the spec. but I would not trust IE to behave correctly with the HTML5 doc type. – Raynos May 16 '11 at 07:42
2

Everything inside it will load as soon as the DOM is loaded and before the page contents are loaded.

The $(document).ready() function has a ton of advantages over other ways of getting events to work. First of all, you don't have to put any "behavioral" markup in the HTML

With $(document).ready(), you can get your events to load or fire or whatever you want them to do before the window loads.

user622378
  • 2,318
  • 6
  • 42
  • 63