3

We use the revealing module pattern to organise stuff into "namespaces". Some of the initialisation code (for the jQuery Validation plugin) should only be called after document load.

Namespace.Foo.Bar = (function($) {

  var init = function() {

    $(function() {                // <--- within DOM ready wrapper it never runs
      $.validator.setDefaults({
        // ...
      });
    });

    (function(){                  // <--- but within an IIFE it will run
      $.validator.setDefaults({
        // ...
      });
    })();

  };

  init();

  // public functions/variables
  return {
  };

}(jQuery));

When the $.validator.setDefaults bit is within a DOM ready wrapper, it never gets called, but when it is within an IIFE then it does get called.

Why? What is the "best" way to mark some module code to run after DOM ready?

EDITS: made sample code more illustrative of the problem

Bobby B
  • 2,237
  • 2
  • 19
  • 46
  • How do you know that it never runs? It should work as you posted. Could you make a demo maybe? – Bergi Aug 06 '13 at 13:09

3 Answers3

3

It doesn't work because of the way you are defining your functions (i.e. init). See var functionName = function() {} vs function functionName() {}

When executing init(), the init function is not yet defined, and you will get an error.

Namespace.Foo.Bar = (function($) {
    // init this module
   console.log(typeof init);   // this prints `undefined`
   init();                     // this throws an error

   // module initialisation
   var init = function() {
     ...
   }
   ...
}(jQuery));

You should either move the init() call to the end of the body of your function, or define your function using:

function init() { ... }
Community
  • 1
  • 1
José M. Pérez
  • 3,053
  • 19
  • 36
  • Edited Q to show init call after the declaration (which is how it was in the codebase btw), but the problem is still the same. – Bobby B Apr 13 '13 at 19:54
0

You should try $(document).ready()

http://docs.jquery.com/Tutorials:Introducing_$(document).ready()

cfs
  • 10,172
  • 2
  • 28
  • 43
0

I believe what you're looking for is something like this:

notice the difference between these two examples:

//working
var myNamespace = (function($) {
    $(function(){
        var init = (function(){
            var text = document.createTextNode("Everything's ready!");
            document.body.appendChild(text);
        })();
    });

}(jQuery));

//Error: Cannot call method 'appendChild' of null 
var myNamespace = (function($) {

        var init = (function(){
            var text = document.createTextNode("Everything's ready!");
            document.body.appendChild(text);
        })();


}(jQuery));

Though, what's happening here is that init() is effectively not accessible by anything else within the namespace, because it's taking place after the DOM has loaded.

Nonetheless, this is close to what you're having a problem with, I think...

I'm assuming that you want the DOM ready wrapper within your module for organizational purposes.

Also note that you have access to the module as you would normally from outside of the module:

//appends to the body: "Everything's ready!undefined
var myNamespace = (function($) {
   var private = " Hello world";
        $(function(){
            var hello =(function(){
                var text = document.createTextNode("Everything's ready!" +myNamespace.private);
                document.body.appendChild(text);
            }());
        });

    return{
        public: " Hello World"   
    }

}(jQuery));



 //works as expected 
    var myNamespace = (function($) {    
     var private = " Hello world";
     $(function(){
      var hello =(function(){
       var text = document.createTextNode("Everything's ready!" +myNamespace.public);
       document.body.appendChild(text);
      }());
     });

     return{
      public: " Hello World"   
     }   }(jQuery));
Dave
  • 723
  • 6
  • 19