2

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 ?

Umair Jabbar
  • 3,596
  • 5
  • 30
  • 42

4 Answers4

7

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
  • 9,848
  • 4
  • 29
  • 33
  • cleaner than my idea, i like it – markcial Mar 18 '10 at 11:18
  • +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 Mar 18 '10 at 11:20
  • 1
    @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 Mar 18 '10 at 11:27
  • Thankoyu Marko, but can you please explain me the concept of giving the 0 as delay please, – Umair Jabbar Mar 18 '10 at 11:38
  • @Umair: http://stackoverflow.com/questions/1360238/myfunction-vs-window-settimeoutmyfunction-0 – Marko Dumic Mar 18 '10 at 11:41
  • Zero as delay causes it to run immediately and setTimeout causes a new "thread" of execution. This is a hack and I wouldn't expect it to be safe to use. It has a potential for cross-browser problems and weird bugs if You do something really big&complicated. Still an interesting hack I'm going to remember :) – naugtur Mar 18 '10 at 11:51
  • @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 Mar 18 '10 at 11:56
  • @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 Mar 18 '10 at 12:30
  • @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 Mar 18 '10 at 13:06
1

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
  • 16,827
  • 5
  • 70
  • 113
0

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
  • 65,020
  • 52
  • 178
  • 231
0

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
  • 9,041
  • 4
  • 31
  • 41