views:

93

answers:

4

I have multiple document.ready functions on a page and I want a function to be called when all my document.ready functions have been executed. I simply want the function to be called at the very end, after all other document.ready functions have executed. An example of this could be that each document.ready function increments a global variable when it has been executed, and the last function needs to check the value of that variable at the very end.

Any ideas ?

+1  A: 

First idea (for small apps): Tidy up

You can just put everything in one $().ready() call. It might nieed refactoring, but it's the right thing to do in most cases.

Second idea: A Mediator [pattern]

Create a mediator class that will register functions and call its register() instead of $().ready(). When all functions are registered You just loop over the collection and run them in the single and only $().ready() and You have a point in code that is just after all is executed.

I am currently developing a kind of a framework for jquery applications that has a mediator. I might stick together a small version including the mediator if You're interested.

naugtur
A: 

Why not just calling it after all the others ?

$(function(){
  func1();
  ...
  funcN();
  functionThatNeedsToBeCalledAfter();
});

Of course you will have to cleanup your code to have only 1 place where the document ready function is used... but then your code would be more readable so it's worth it.

marcgg
+4  A: 

This will be enough:

$(function () {
    window.setTimeout(function () {
        // your stuff here
    }, 0);
});

This postpones the execution of your function after all other in the document ready queue are executed.

Marko Dumic
You can test it here: http://jsfiddle.net/65Ve5/3/
Marko Dumic
cleaner than my idea, i like it
markcial
+1. Neat trick, I did not know about that. I would think the JS engine would optimise the `setTimeout(f, 0)` away. Is this behaviour specified somewhere, or did you stumble upon it yourself?
janmoesen
@janmoesen: 0 is not really a zero, as you can see here: https://developer.mozilla.org/en/DOM/window.setTimeout#Minimum_delay_and_timeout_nesting and code is guaranteed to run as separate execution, which is just what we need as all onDomReady functions are executed in one run in a loop (line 373: http://github.com/jquery/jquery/blob/master/src/core.js).
Marko Dumic
Thankoyu Marko, but can you please explain me the concept of giving the 0 as delay please,
Umair
@Umair: http://stackoverflow.com/questions/1360238/myfunction-vs-window-settimeoutmyfunction-0
Marko Dumic
naugtur
@naugtur: this is not a hack as it behaves as expected/documented; and it does not run immediately as you can easily prove by measuring. Can you provide some additional info on *potential cross-browser problems*?
Marko Dumic
@Marko Ok, it's not immediately. I wanted the explanation to be short. The cross browser problem might show up in older IE. It had issues with setTimeout with 0 behaving different than normal code execution. Is it documented for IE? I just feel this trick might stop working when somebody starts using iframes or something that causes weird delays in IE
naugtur
@naugtur: I think you might be referring to unreliability of (native) `window.onLoad` event in IE? jQuery does not rely on that to tell if the *DOM* is ready. It checks (every 13ms) for existence of `document.body` and then fires all the scripts in the queue. I see no problem there.
Marko Dumic
A: 

little hacky but might work, create a variable inside jquery scope like that

$.imDone = false

then create a function with setTimeout called after short time to lookup for the variable ser to true

var theLastFunctionToCall = function(){
  alert('I m the last being called!')
}
var trigger = function(){
  $.imDone?theLastFunctionToCall():window.setTimeout(trigger,10);
}
trigger();

I only recommend this when u have different $(document).ready in different big js files, but if you can refactor i sincerelly recommend an optimal solution.

markcial