Document Ready Function

Hello again,

I would like to know if I should keep on starting my JS functions with the document.ready function? Below is an example:


// Start Game
$(document).ready(function() {
	$('.startgame').click(function() {
		if ( progress === 1) {
			var startGame = confirm("Your current game will be lost, are you sure you want to start a new game?");
			if ( startGame === 1) {
				location.reload(true);
			}
		}
		else {
			location.reload(true);
		}
	});
});

// New game
$(document).ready(function() {
	$('newgame').click(function() {
		var newGame = confirm("Start a new game with the above settings?");
		if ( newGame === 1) {
			location.reload(true);
		}
	});
});

Thanks in advance.

You only need to use $(document).ready(function() { ... }); once per file.
You can just amalgamate all of your code in this.

Saying that, if you move all of your JS down to just before the closing </body> tag, you can very probably do away with the call to $(document).ready(function() { ... }); altogether.

Thanks, sir. :smiley:
So its fine if I do it like this?


$(document).ready(function() {

	// Global Variables
	var progress = 0;

	// Functions
	function gameInit() {
		var gameInit = confirm("Your current game will be lost, are you sure you want to start a new game?");
		if ( gameInit === true) {
			location.reload(true);
		}
	};

	// Start Game && New Game
	$('.startgame,.newgame').click(function() {
		if ( progress === 1) {
			gameInit();
		}
		else {
			var gameSettings = confirm("You are about to start a new game. Start the game with the above settings?");
			if ( gameSettings === 1) {
				location.reload(true);
			}
			else {
				gameSettings();
			}
		}
	});
});

Hi there,

This is a good start, although in your code, this line will throw an error:

gameSettings();

The reason for this is that you have previously assigned the variable gameSettings to the result of a confirm dialogue.

var gameSettings = confirm("You are about to start a new game. Start the game with the above settings?");

The disadvantage of this approach is that everything is in the global namespace and you have different bits of functionality intertwined throughout your code.

Now might be a good time to think about how to structure and organize your code, especially as it seems you are making a game - something that cannot usually be done in a few lines of Javascript.

One way of doing this, might be to use the module pattern.
You can read more about it here: http://css-tricks.com/how-do-you-structure-javascript-the-module-pattern-edition/

I have taken the liberty of rewriting the code you have so far:

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <title>Game</title>
  </head>
  
  <body>
    <button class="startgame">Start Game</button>
    <button class="newgame">New Game</button>
  
    <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
    <script>
      var s,
      Game = {
        settings: {
          buttons: $('.startgame, .newgame'),
          progress: 0,
          existingGameMessage: "Your current game will be lost, are you sure you want to start a new game?",
          newGameMessage: "You are about to start a new game. Start the game with the above settings?"
        },
        
        bindUIActions: function(){
          s.buttons.on("click", function(){
            Game.initializeNewGame();
          });
        },
        
        getConfirmation: function(msg){
          return confirm(msg);
        },
        
        invokeSettings: function(){
          //Do stuff here
        },
        
        displayExistingGameDialogue: function(){
          if (this.getConfirmation(s.existingGameMessage)){
            location.reload(true);
          }
        },
        
        displayNewGameDialogue: function(){
          if (this.getConfirmation(s.newGameMessage)){
            location.reload(true);
          } else {
            Game.invokeSettings();
          }
        },
        
        initializeNewGame: function(){
          if(s.progress){
            Game.displayExistingGameDialogue();
          } else {
            Game.displayNewGameDialogue();
          }
        },
      
        init: function(){
          s = this.settings;
          this.bindUIActions();
        }
      }
      
      Game.init();
    </script>
  </body>
</html>

Admittedly this results in a few more lines of code, but I’m sure you’ll agree, it is more readable and configurable.

HTH

You don’t even need document.ready at all - just move you script tag to immediately before the </body> tag and you will get the benefits of document.ready without that code and also the rest of your page will load faster because the JavaScript will be loaded after everything else.

Hey felgall,

I was trying to think of an occasion when document.ready would make sense given that you have your JS directly before the closing </body> tag, but couldn’t.
Can you?

This is in contrast to $(window).ready which executes when complete page is fully loaded and might be useful if you are doing something with images (for example).

Substituting a local image for any remote images that failed to load is the only example I have of where it is necessary to delay the execution of the JavaScript when it is attached just before the </body> tag. In that instance everything in the page needs to have loaded first as there isn’t an event triggered when all images have loaded but where other files may still not have finished loading. http://javascriptexample.net/basics29.php

Most other scripts that use images would work just as well if they started running immeediately even if all the images they use haven’t finished loading yet.

With the script just before the </body> the document.ready should trigger immediately so the only effect will be the very small extra delay to download the script due to that extra unnecessary statement. Getting rid of the document.ready call would make the code start running a minute fraction of a microsecond sooner and result in one less line of code to maintain.

Wow, that is a good read, sir. Thank you! :slight_smile:

Nice answer felgall, thank you.
I bookmarked the link.

Thinking about this over the last couple of days, I realised that one advantage of $(document).ready() is that it allows people who are less confident with JavaScript to place arbitrary code anywhere on the page and have it execute at the right time.

Possibly another situation might be where you’re using a script loader (eg. yepnope.js) to load your JS files asynchronously, and you have a callback that fires once a script has loaded, which may be before the DOM is ready.

So, you mean (for example) to avoid a situation where inline code which relies on an external library being loaded by yepnope, is executed before its dependency is ready?

I was thinking more of the situation where you might have a plugin that turns all divs with a certain class into some kind of widget. With a loader like yepnope, you can have a callback which will init the plugin as soon as it’s loaded, but as the code is being loaded in tandem with the markup, it’s possible that the callback could fire before the DOM is ready. Using the document ready function you could guard against that happening.

Ahh, I see.
That makes sense. Thanks.

I have only come across two instances wherew JavaScript needs to be attached in the head of the page. In those cases it is because you need it to run before the page content loads. When properly written every other JavaScript can go at the bottom before the </body> tag.

So document.ready is only really useful for those beginners who haven’t yet learnt how to write JavaScript properly - either because they simply copy other people’s antiquated code or they are learning from sites that were set up to teach how to write JavaScript for the Netscape browser that haven’t been updated to teach the completely different approach that ought to be used with modern browsers (there are lots of sites teaching outdated JavaScript and few teaching modern JavaScript).

This then would be a good occasion to help educate people that they shouldn’t place their scripting code anywhere else but at the end of the body, because loading a script is a blocking action that prevents anything else from happening on the page until after the script has been loaded and executed.

Placing the script at the end of the body achieves multiple benefits - not just that the page content is faster to appear, but in that your script has an easier time interacting with elements on the page.

Yup, will do (and have been doing).
What do you think about the use case that fretburner described?

Let’s take a look:

In that case, it would make sense to pass the callback to the plugin so that the callback is only called after the plugin is complete. This tends to be something where a specific example becomes useful for the discussion and exploration of the problem - otherwise a lot of handwaving occurs.

I think there’s a misunderstanding of what I was saying - the callback does fire after the plugin is loaded, that’s not the problem. The problem is that because the script is loaded in tandem with the page, there’s a chance for the plugin to be loaded and ready (and hence the callback to be fired) before the DOM is ready. This would especially be the case on the second visit to a page once the JS files have been cached by the browser. I’ve actually had this problem recently while using require.js.

Ahh, I can see that it would be a problem if YepNope is started before the end of the body. The rules change when doing such things, that’s for sure.