62

I have a first.js file included in the page index.php that have something like this:

$(function(){

    $("#my_slider").slider("value", 10);

});

And them in index.php I have some dynamicly created slidders:

<?php function slidders($config, $addon)
{
    $return = '
    <script type="text/javascript">
        $(function() {
            $("#slider_'.$addon['p_cod'].'").slider({
            min: '.$config['min'].',
            max: '.$config['max'].',
            step: '.$config['step'].',
            slide: function(event, ui) {
                $("#cod_'.$addon['p_cod'].'").val(ui.value);
                $(".cod_'.$addon['p_cod'].'").html(ui.value+"'.@$unit.'");
            },
            change: function(event, ui) { 
                $("#cod_'.$addon['p_cod'].'").change();
            }
        });
            $("#cod_'.$addon['p_cod'].'").val($("#slider_'.$addon['p_cod'].'").slider("value"));
            $(".cod_'.$addon['p_cod'].'").html($("#slider_'.$addon['p_cod'].'").slider("value")+"'.@$unit.'");
    });
    </script>';
    return $return;
} ?>

The problem is, because my index.php sliders are being instantiated after my first.js I can't set up a value there, is there any event like "after all $(document).ready() have run" that I can use in first.js to manipulate the sliders created in index.php?

David Espart
  • 11,520
  • 7
  • 36
  • 50
mjsilva
  • 1,327
  • 3
  • 13
  • 21

6 Answers6

74

Dont know how to tell when the last $(document).ready() function fired, but $(window).load() function fires after the $(document).ready()

Offir
  • 3,252
  • 3
  • 41
  • 73
John Hartsock
  • 85,422
  • 23
  • 131
  • 146
  • Thanks John that was the solution I just changed my $(function(){("#my_slider").slider("value", 10);}); for $(window).load(function(){("#my_slider").slider("value", 10);}); and it worked. Cheers brother! – mjsilva Jun 09 '10 at 18:47
  • 8
    Twist on this answer: sometimes document ready fires after window.load. http://stackoverflow.com/questions/20133159/the-window-load-event-fires-before-that-document-ready-event-with-cache – Toby Jan 10 '14 at 04:02
63

The safest thing to do is to invoke $(window).load() inside $(document).ready(). This will preserve execution order in all cases by making sure that your run-last code is not passed to $(window).load() until all $(document).ready() scripts have completed. Without this there are possible race conditions in some browsers where $(window).load() may be invoked after all $(document).ready() scripts have started but before all $(document).ready() scripts have finished.

$(document).ready(function() {
    $(window).load(function() {
        // this code will run after all other $(document).ready() scripts
        // have completely finished, AND all page elements are fully loaded.
    });
});
Thaeli
  • 1,078
  • 9
  • 12
  • 1
    -1 I don't mean to be disrespectful, but this doesn't sound true. Can you explain further or leave a reference? What browsers can this occur in and what do they do differently? I can only see this being true if JS events were multithreaded (or the DOMDocumentReady handler in jQuery yielded), and even then, I don't think your fix would address the issue. – Toby Dec 28 '13 at 22:05
  • 3
    More details at this SO question: [Window Load Inside A Document Ready](http://stackoverflow.com/questions/5006922/window-load-inside-a-document-ready) Definitely occurs in IE8. This is a belt-and-suspenders approach; it's harmless and avoids some edge cases. – Thaeli Dec 30 '13 at 19:58
  • Note that, as of the latest versions of jQuery (3+), you'll want to use `$(window).on("load", function(){ //.... });`. Ran into strange errors (`url.indexOf is not a function`) until I switched it to the newer syntax. More on this here: https://stackoverflow.com/a/37915907/177416: `.load, .unload, and .error, deprecated since jQuery 1.8, are no more. Use .on() to register listeners.` – Alex Feb 10 '21 at 15:43
19

Based on Ian's answer I figured this out (tested - working):

jQuery(document).ready(function() {
    jQuery(document).ready(function() {
        /* CODE HERE IS EXECUTED AS THE LAST .ready-CALLBACK */
    });
});

Of course this is because the ready callbacks are invoked in the order they where assigned. At the moment, when your outer ready callback is invoked, all other scripts should have their ready callbacks already assigned. So assigning your ready callback (the inner one) now will lead to yours being the last one.

Matteo B.
  • 3,906
  • 2
  • 29
  • 43
14

Try this neat trick/gross hack:

$(function(){
    $(function(){

        $("#my_slider").slider("value", 10);

    });
});

Looks stupid right? It works because jQuery executes event handlers in the order they were added. Adding an event handler in your event handler is about as late as you can (just make sure you're not doing this on any of the sliders accidentally; it's very easy to do).

Proof of concept. http://jsfiddle.net/9HhnX/

Toby
  • 647
  • 4
  • 14
3

One of the goals of jQuery's $(document).ready() function is that the standard javascript window.onload event won't run until everything on the page is loaded (including images, etc.), even though functions can usefully start running well before that. So $(document).ready() runs as soon as the DOM hierarchy is constructed.

Given this, one option would be to run your "after everything else" script on page load. This won't guarantee that all of the $(document).ready() scripts have completed, though.

A better but more complicated option is to create a function that checks for the existence of the sliders, and if they don't exist, calls "setTimeout" on itself, so it can wait a few milliseconds and try again.

(To answer your specific question, no, there is no "after all $(document).ready() have run" callback.)

Jacob Mattison
  • 50,258
  • 9
  • 107
  • 126
0

You would be better to add a unique class to your sliders rather than the #my_slider since that will only fire for the element with id = my_slider.

If you want to have the same functionality you should check out .live from jquery it will put the same functionality onto elements that are added after the binding.

If that will not work for you then when you add the new sliders you will have to go through them in the DOM and call the necessary function.

darren102
  • 2,830
  • 1
  • 22
  • 24
  • Hi darren102, my sliders have unique Ids, the codded that I posted does not reelect my running code, I just post it has it is as an example of what I was trying to accomplish. Sorry if that causes som confusion, I'm still a newb in asking questions @ stackoverflow :P – mjsilva Jun 09 '10 at 18:50