15

I am doing QUnit testing in an IFRAME and have a recursive JavaScript function that loads all of the scripts from the parent page into the IFRAME before starting QUnit. This works great. My problem is that some of our scripts use document.ready to make stuff start.

Something such as:

$(document).ready(function () {
    // blah
});

to do do their work. I'd prefer to not change production code just to account for tests and I don't want these production scripts to think the IFRAME document is "ready" until every scripts is loaded.

How I can delay "document.ready" itself?

Here is my pseudocode to give you an example to work from:

scripts[0] = "/foo/bar.js";
scripts[1] = "/blah/blah.js";

function RecursiveScriptStart(){
    // I want to set document.ready = false right here!
    if(scripts.length == 0) {
        QUnitStart();
        return;
    }
    RecursiveScriptLoader(0, scripts);
}

function RecursiveScriptLoader(currentScriptID, scripts) {
    $.getScript(scripts[currentScriptID], function () {
        if (currentScriptID == (scripts.length - 1)) {
            QUnitStart();
        }
        else {
            RecursiveScriptLoader(currentScriptID + 1, scripts);
        }
    });
}


function QUnitStart() {
        // I want to set document.ready = true right here!
        QUnit.stop();
        QUnit.start();
}

The actual code is similar, but involves a jquery selector populating the array "scripts[]" with JavaScript tag "src" properties.

Thanks!

David
  • 233
  • 1
  • 3
  • 9

5 Answers5

23

If you're using jQuery 1.6+ then you can use holdReady. Just set $.holdReady(true) at the top of your script and then in the beginning of QUnitStart set $.holdReady(false).

Petr Vostrel
  • 2,324
  • 16
  • 23
mVChr
  • 49,587
  • 11
  • 107
  • 104
  • 1
    @htellez without jQuery you wouldn't have a `$(document).ready()` block, so in order to answer that question we'd have to know more details about what you're using instead. Perhaps it's better asked as a separate question rather than in a comment to this one. – mVChr Jul 24 '14 at 08:20
5

This code worked for me; To invoke $(window).load() inside $(document).ready()

$(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.
    });
});

This method would 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.

Omari Victor Omosa
  • 2,814
  • 2
  • 24
  • 46
4

If your using jQuery 1.6 or higher you can use holdReady to delay the ready event being fired.

For 1.4.3 or higher you can use $.readyWait property to delay the ready event, Demo Here (not my code)

if your interested in figuring out how jquery handles the ready event search for the line

jQuery( document ).trigger( "ready" ).unbind( "ready" );

in your developer copy of jquery.js

Glen Solsberry
  • 11,960
  • 15
  • 69
  • 94
Robert Beuligmann
  • 1,434
  • 10
  • 13
0

Just to fill in where others left off, you may use this load order in your test.html

<script src="jquery.js"></script>
<script src="qunit.js"></script>
<script>$.holdReady(true);</script>
<script src="theThingIwantToTest.js"></script>
<script src="theTestScript.js"></script>
Theodor
  • 5,536
  • 15
  • 41
  • 55
0
<html lang="en">
    <head>
        <meta charset="utf-8">
        <script type="text/javascript">
            window.setInterval(function() {
                console.log(document.getElementById('waitForMe'));
            }, 500);
        </script>
    </head>
    <body>
        Before
        <script type="text/javascript" src="/php-with-sleep.php"></script>
        After
        <div id="waitForMe"></div>
    </body>
</html>

Extended test, I have tested RequireJs domReady plugin

<html lang="en">
    <head>
        <meta charset="utf-8">
        <script type="text/javascript" src="/vendor/require/require.js"></script>
        <script type="text/javascript">
            window.setInterval(function() {
                console.log(document.getElementById('waitForMe'));
            }, 500);

            require.config({
                baseUrl: '/',
                paths: {
                    domReady: 'vendor/require/plugin/dom-ready',
                    jQuery: 'vendor/jquery'

                },
                shim: {
                    async: {
                        exports: 'async'
                    },
                    jQuery: {
                        exports: 'jQuery'
                    }
                }
            });

            require(['domReady', 'jQuery'], function(domReady, $) {
                console.log('jQuery loaded');
                $(function() {
                    console.log('jQuery dom ready');
                });

                domReady(function() {
                    console.log('domReady requireJs plugin, callback');
                })
            });

            require(['domReady!', 'jQuery'], function(domReady, $) {
                console.log('domReady! (no callback)');
            });

            require(['domReady', 'jQuery'], function(domReady, $) {
                console.log('domReady plugin loaded');
            });
        </script>
    </head>
    <body>
        Before
        <script type="text/javascript" src="/php-with-sleep.php"></script>
        After
        <div id="waitForMe"></div>
    </body>
</html>