aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Sherov <mike.sherov@gmail.com>2012-04-23 15:43:26 -0400
committerDave Methvin <dave.methvin@gmail.com>2012-04-23 15:44:27 -0400
commit54fab3174c7844959b374e98b453c048b60de0d0 (patch)
tree1cd99ad3c26d55537d02b03bc3828b5b3ec555ca
parent58ed62ed12cb48d9224f699e86e197804ca5ece4 (diff)
downloadjquery-54fab3174c7844959b374e98b453c048b60de0d0.tar.gz
jquery-54fab3174c7844959b374e98b453c048b60de0d0.zip
Fix #10067. Create jQuery.quickReady; closes gh-736.
Allows us to get to the ready state sooner by not waiting for iframes to load. If that causes backcompat pain, use `jQuery.quickReady = false` as prescribed by your developer.
-rw-r--r--src/core.js16
-rw-r--r--test/data/event/asyncQuickReadyFalse.html32
-rw-r--r--test/data/event/asyncQuickReadyTrue.html30
-rw-r--r--test/data/event/longLoad.php6
-rw-r--r--test/data/event/syncReady.html17
-rw-r--r--test/data/support/bodyBackground.html2
-rw-r--r--test/data/support/boxModelIE.html2
-rw-r--r--test/data/support/hiddenIFrameFF.html7
-rw-r--r--test/data/support/testElementCrash.html7
-rw-r--r--test/data/testinit.js25
-rw-r--r--test/unit/event.js20
-rw-r--r--test/unit/support.js33
12 files changed, 149 insertions, 48 deletions
diff --git a/src/core.js b/src/core.js
index f317666ce..22f186336 100644
--- a/src/core.js
+++ b/src/core.js
@@ -375,6 +375,9 @@ jQuery.extend({
// the ready event fires. See #6781
readyWait: 1,
+ // should we fire ready on readyState "interactive" ?
+ quickReady: true,
+
// Hold (or release) the ready event
holdReady: function( hold ) {
if ( hold ) {
@@ -386,6 +389,12 @@ jQuery.extend({
// Handle when the DOM is ready
ready: function( wait ) {
+ // user wasn't necessarily given the chance to set jQuery.quickReady before bindReady
+ // so we check here for quickReady instead
+ if ( !jQuery.quickReady && document.readyState === "interactive" ) {
+ return;
+ }
+
// Either a released hold or an DOMready/load event and not yet ready
if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
@@ -420,9 +429,9 @@ jQuery.extend({
// Catch cases where $(document).ready() is called after the
// browser event has already occurred.
- if ( document.readyState === "complete" ) {
+ if ( document.readyState !== "loading" ) {
// Handle it asynchronously to allow scripts the opportunity to delay ready
- return setTimeout( jQuery.ready, 1 );
+ setTimeout( jQuery.ready, 1 );
}
// Mozilla, Opera and webkit nightlies currently support this event
@@ -915,6 +924,7 @@ rootjQuery = jQuery(document);
// Cleanup functions for the document ready method
if ( document.addEventListener ) {
DOMContentLoaded = function() {
+ jQuery.quickReady = true;
document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
jQuery.ready();
};
@@ -922,7 +932,7 @@ if ( document.addEventListener ) {
} else if ( document.attachEvent ) {
DOMContentLoaded = function() {
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
- if ( document.readyState === "complete" ) {
+ if ( document.readyState === "complete" || ( jQuery.quickReady && document.readyState === "interactive" ) ) {
document.detachEvent( "onreadystatechange", DOMContentLoaded );
jQuery.ready();
}
diff --git a/test/data/event/asyncQuickReadyFalse.html b/test/data/event/asyncQuickReadyFalse.html
new file mode 100644
index 000000000..935269749
--- /dev/null
+++ b/test/data/event/asyncQuickReadyFalse.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<title>Test case for jQuery ticket #10067</title>
+<script type="text/javascript">
+
+// ready should fire callback after the iframe fires the callback
+setTimeout(function () {
+ el = document.createElement('script');
+ el.type = 'text/javascript';
+ el.onload = function () {
+ jQuery.quickReady = false;
+ jQuery(document).ready(function () {
+ // unfortunately, Opera 11.6 and lower has a bug where
+ // document.readyState is "complete" before all subresources
+ // are loaded, so we need this check here for tests to pass
+ if ( document.readyState !== "complete" ) {
+ window.parent.iframeCallback(false);
+ }
+ });
+ }
+ document.getElementsByTagName('head')[0].appendChild(el);
+ el.src = "../include_js.php";
+}, 1000);
+</script>
+</head>
+<body>
+<!-- long loading iframe -->
+<iframe src="longLoad.php?sleep=3&return=true" style="width: 1px; height: 1px"></iframe>
+</body>
+</html> \ No newline at end of file
diff --git a/test/data/event/asyncQuickReadyTrue.html b/test/data/event/asyncQuickReadyTrue.html
new file mode 100644
index 000000000..cdcb82128
--- /dev/null
+++ b/test/data/event/asyncQuickReadyTrue.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<title>Test case for jQuery ticket #10067</title>
+<script type="text/javascript">
+// browsers that implement the non-standard event API will load the iframe
+// before loading up jQuery, so quickReady has no effect here
+if( document.attachEvent ){
+ window.parent.iframeCallback(true);
+} else {
+ setTimeout(function () {
+ el = document.createElement('script');
+ el.type = 'text/javascript';
+ el.onload = function () {
+ jQuery(document).ready(function () {
+ window.parent.iframeCallback(true);
+ });
+ }
+ document.getElementsByTagName('head')[0].appendChild(el);
+ el.src = "../include_js.php";
+ }, 1000);
+}
+</script>
+</head>
+<body>
+<!-- long loading iframe -->
+<iframe src="longLoad.php?sleep=30&return=false" style="width: 1px; height: 1px"></iframe>
+</body>
+</html> \ No newline at end of file
diff --git a/test/data/event/longLoad.php b/test/data/event/longLoad.php
new file mode 100644
index 000000000..ba1d43f82
--- /dev/null
+++ b/test/data/event/longLoad.php
@@ -0,0 +1,6 @@
+<?php
+sleep((int)$_GET['sleep']);
+?>
+<script type="text/javascript">
+window.parent.parent.iframeCallback(<?php echo $_GET['return'];?>);
+</script> \ No newline at end of file
diff --git a/test/data/event/syncReady.html b/test/data/event/syncReady.html
new file mode 100644
index 000000000..b9dbb2280
--- /dev/null
+++ b/test/data/event/syncReady.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<title>Test case for jQuery ticket #10067</title>
+<script type="text/javascript" src="../include_js.php"></script>
+</head>
+<body>
+<script type="text/javascript">
+jQuery(document).ready(function () {
+ window.parent.iframeCallback(true);
+});
+</script>
+<!-- long loading iframe -->
+<iframe src="longLoad.php?sleep=10&return=false" style="width: 1px; height: 1px"></iframe>
+</body>
+</html> \ No newline at end of file
diff --git a/test/data/support/bodyBackground.html b/test/data/support/bodyBackground.html
index 0f12e75f9..4f0105a1d 100644
--- a/test/data/support/bodyBackground.html
+++ b/test/data/support/bodyBackground.html
@@ -21,7 +21,7 @@
</div>
<script>
jQuery(function() {
- window.parent.supportCallback( jQuery( "body" ).css( "backgroundColor" ), jQuery.support );
+ window.parent.iframeCallback( jQuery( "body" ).css( "backgroundColor" ), jQuery.support );
});
</script>
</body>
diff --git a/test/data/support/boxModelIE.html b/test/data/support/boxModelIE.html
index ca647a281..24e4c6100 100644
--- a/test/data/support/boxModelIE.html
+++ b/test/data/support/boxModelIE.html
@@ -3,7 +3,7 @@
<body>
<script src="../include_js.php"></script>
<script>
- jQuery(function() { window.parent.supportCallback( document.compatMode, jQuery.support.boxModel ) });
+ jQuery(function() { window.parent.iframeCallback( document.compatMode, jQuery.support.boxModel ) });
</script>
</body>
</html>
diff --git a/test/data/support/hiddenIFrameFF.html b/test/data/support/hiddenIFrameFF.html
deleted file mode 100644
index c2dda8cd4..000000000
--- a/test/data/support/hiddenIFrameFF.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<html>
- <head>
- <script src="../include_js.php"></script>
- </head>
- <body>
- </body>
-</html>
diff --git a/test/data/support/testElementCrash.html b/test/data/support/testElementCrash.html
index 583ca7b0f..6ef9651da 100644
--- a/test/data/support/testElementCrash.html
+++ b/test/data/support/testElementCrash.html
@@ -7,14 +7,11 @@
background: url('http://s1.postimage.org/2d2r8xih0/body_background.png');
}
</style>
- <script src="../../../src/core.js"></script>
- <script src="../../../src/callbacks.js"></script>
- <script src="../../../src/deferred.js"></script>
- <script src="../../../src/support.js"></script>
+ <script src="../include_js.php"></script>
</head>
<body>
<script>
- window.parent.supportCallback();
+ window.parent.iframeCallback();
</script>
</body>
</html>
diff --git a/test/data/testinit.js b/test/data/testinit.js
index 1f775c1d7..9a27f5287 100644
--- a/test/data/testinit.js
+++ b/test/data/testinit.js
@@ -192,7 +192,7 @@ function url(value) {
});
function loadFixture() {
- var src = "./data/" + fileName + ".html?" + parseInt( Math.random()*1000, 10 ),
+ var src = url("./data/" + fileName + ".html"),
iframe = jQuery("<iframe />").css({
width: 500, height: 500, position: "absolute", top: -600, left: -600, visibility: "hidden"
}).appendTo("body")[0];
@@ -200,6 +200,29 @@ function url(value) {
return iframe;
}
};
+
+ this.testIframeWithCallback = function( title, fileName, func ) {
+
+ test( title, function() {
+ var iframe;
+
+ stop();
+ window.iframeCallback = function() {
+ var self = this,
+ args = arguments;
+ setTimeout(function() {
+ window.iframeCallback = undefined;
+ iframe.remove();
+ func.apply( self, args );
+ func = function() {};
+ start();
+ }, 0 );
+ };
+ iframe = jQuery( "<div/>" ).append(
+ jQuery( "<iframe/>" ).attr( "src", url("./data/" + fileName + ".html") )
+ ).appendTo( "body" );
+ });
+ }
}());
// Sandbox start for great justice
diff --git a/test/unit/event.js b/test/unit/event.js
index 172f3a82a..545cc05bc 100644
--- a/test/unit/event.js
+++ b/test/unit/event.js
@@ -2794,6 +2794,26 @@ test("fixHooks extensions", function() {
jQuery.event.fixHooks.click = saved;
});
+testIframeWithCallback( "jQuery.ready sync load", "event/syncReady", function( isOk ) {
+ expect(1);
+ ok( isOk, "jQuery loaded synchronously fires ready before all sub-resources are loaded" );
+});
+
+// async loaded tests expect jQuery to be loaded as a single file
+// if we're not doing PHP concat, then we fall back to document.write
+// which breaks order of execution on async loaded files
+if ( hasPHP ) {
+ testIframeWithCallback( "jQuery.ready async load with quickReady true", "event/asyncQuickReadyTrue", function( isOk ) {
+ expect(1);
+ ok( isOk, "jQuery loaded asynchronously with quickReady true fires ready before all sub-resources are loaded" );
+ });
+
+ testIframeWithCallback( "jQuery.ready async load with quickReady false", "event/asyncQuickReadyFalse", function( isOk ) {
+ expect(1);
+ ok( isOk, "jQuery loaded asynchronously with quickReady false fires ready after all sub-resources are loaded" );
+ });
+}
+
(function(){
// This code must be run before DOM ready!
var notYetReady, noEarlyExecution,
diff --git a/test/unit/support.js b/test/unit/support.js
index a9243be51..7582d4bc4 100644
--- a/test/unit/support.js
+++ b/test/unit/support.js
@@ -1,37 +1,10 @@
module("support", { teardown: moduleTeardown });
-function supportIFrameTest( title, url, noDisplay, func ) {
-
- if ( noDisplay !== true ) {
- func = noDisplay;
- noDisplay = false;
- }
-
- test( title, function() {
- var iframe;
-
- stop();
- window.supportCallback = function() {
- var self = this,
- args = arguments;
- setTimeout( function() {
- window.supportCallback = undefined;
- iframe.remove();
- func.apply( self, args );
- start();
- }, 0 );
- };
- iframe = jQuery( "<div/>" ).css( "display", noDisplay ? "none" : "block" ).append(
- jQuery( "<iframe/>" ).attr( "src", "data/support/" + url + ".html" )
- ).appendTo( "body" );
- });
-}
-
-supportIFrameTest( "proper boxModel in compatMode CSS1Compat (IE6 and IE7)", "boxModelIE", function( compatMode, boxModel ) {
+testIframeWithCallback( "proper boxModel in compatMode CSS1Compat (IE6 and IE7)", "support/boxModelIE", function( compatMode, boxModel ) {
ok( compatMode !== "CSS1Compat" || boxModel, "boxModel properly detected" );
});
-supportIFrameTest( "body background is not lost if set prior to loading jQuery (#9238)", "bodyBackground", function( color, support ) {
+testIframeWithCallback( "body background is not lost if set prior to loading jQuery (#9238)", "support/bodyBackground", function( color, support ) {
expect( 2 );
var i,
passed = true,
@@ -56,7 +29,7 @@ supportIFrameTest( "body background is not lost if set prior to loading jQuery (
ok( passed, "Same support properties" );
});
-supportIFrameTest( "A background on the testElement does not cause IE8 to crash (#9823)", "testElementCrash", function() {
+testIframeWithCallback( "A background on the testElement does not cause IE8 to crash (#9823)", "support/testElementCrash", function() {
expect(1);
ok( true, "IE8 does not crash" );
});