SitePoint Sponsor

User Tag List

Results 1 to 19 of 19
  1. #1
    SitePoint Member
    Join Date
    Jun 2013
    Posts
    7
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Smile 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:

    Code JavaScript:
    // 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.

  2. #2
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,871
    Mentioned
    206 Post(s)
    Tagged
    12 Thread(s)
    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.

  3. #3
    SitePoint Member
    Join Date
    Jun 2013
    Posts
    7
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks, sir.
    So its fine if I do it like this?

    Code JavaScript:
    $(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();
    			}
    		}
    	});
    });

  4. #4
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,871
    Mentioned
    206 Post(s)
    Tagged
    12 Thread(s)
    Hi there,

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

    Code JavaScript:
    gameSettings();

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

    Code JavaScript:
    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-str...ttern-edition/

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

    Code:
    <!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
    Last edited by Pullo; Jun 30, 2013 at 12:21. Reason: Forgot link

  5. #5
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,784
    Mentioned
    25 Post(s)
    Tagged
    1 Thread(s)
    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.
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  6. #6
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,871
    Mentioned
    206 Post(s)
    Tagged
    12 Thread(s)
    Hey felgall,

    Quote Originally Posted by felgall View Post
    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.
    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).

  7. #7
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,784
    Mentioned
    25 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by Pullo View Post
    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.
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  8. #8
    SitePoint Member
    Join Date
    Jun 2013
    Posts
    7
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Pullo View Post
    Hi there,

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

    Code JavaScript:
    gameSettings();

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

    Code JavaScript:
    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-str...ttern-edition/

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

    Code:
    <!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
    Wow, that is a good read, sir. Thank you!

  9. #9
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,871
    Mentioned
    206 Post(s)
    Tagged
    12 Thread(s)
    Quote Originally Posted by felgall View Post
    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.
    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.

  10. #10
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,387
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    Quote Originally Posted by Pullo View Post
    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.

  11. #11
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,871
    Mentioned
    206 Post(s)
    Tagged
    12 Thread(s)
    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?

  12. #12
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,387
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    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.

  13. #13
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,871
    Mentioned
    206 Post(s)
    Tagged
    12 Thread(s)
    Ahh, I see.
    That makes sense. Thanks.

  14. #14
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,784
    Mentioned
    25 Post(s)
    Tagged
    1 Thread(s)
    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).
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  15. #15
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,678
    Mentioned
    99 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by Pullo View Post
    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.
    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.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  16. #16
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,871
    Mentioned
    206 Post(s)
    Tagged
    12 Thread(s)
    Quote Originally Posted by paul_wilkins View Post
    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?

  17. #17
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,678
    Mentioned
    99 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by Pullo View Post
    Yup, will do (and have been doing).
    What do you think about the use case that fretburner described?
    Let's take a look:

    Quote Originally Posted by fretburner View Post
    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.
    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.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  18. #18
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,387
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    Quote Originally Posted by paul_wilkins View Post
    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.
    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.

  19. #19
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,678
    Mentioned
    99 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by fretburner View Post
    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.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •