Skip to content

Commit 1776e3d

Browse files
committed
Event: Warn about late use of $(window).on("load"...)
Fixes #200
1 parent 057e1f4 commit 1776e3d

File tree

4 files changed

+62
-0
lines changed

4 files changed

+62
-0
lines changed

src/event.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
var oldLoad = jQuery.fn.load,
2+
oldEventAdd = jQuery.event.add,
23
originalFix = jQuery.event.fix;
34

45
jQuery.event.props = [];
@@ -35,6 +36,15 @@ jQuery.event.fix = function( originalEvent ) {
3536
return fixHook && fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
3637
};
3738

39+
jQuery.event.add = function( elem, types ) {
40+
41+
// This misses the multiple-types case but that seems awfully rare
42+
if ( elem === window && types === "load" && document.readyState === "complete" ) {
43+
migrateWarn( "$(window).on('load'...) called after load event occurred" );
44+
}
45+
return oldEventAdd.apply( this, arguments );
46+
};
47+
3848
jQuery.each( [ "load", "unload", "error" ], function( _, name ) {
3949

4050
jQuery.fn[ name ] = function() {

test/event-lateload.html

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>jQuery Migrate late load event binding test</title>
6+
7+
<!-- Load a jQuery and jquery-migrate plugin file based on URL -->
8+
<script src="testinit.js"></script>
9+
<script>
10+
TestManager.loadProject( "jquery", "git" );
11+
</script>
12+
<script src="iframeTest.js"></script>
13+
<script>
14+
jQuery.noConflict();
15+
TestManager.loadProject( "jquery-migrate", "dev", true );
16+
</script>
17+
<script>
18+
var loaded = jQuery.Deferred();
19+
20+
// No warning here, document isn't yet loaded
21+
jQuery( window ).on( "load", function() {
22+
loaded.resolve();
23+
});
24+
25+
jQuery.when( jQuery.ready, loaded ).then( function() {
26+
27+
// This .on() call should warn
28+
jQuery( window ).on( "load", jQuery.noop );
29+
30+
startIframeTest();
31+
} );
32+
</script>
33+
</head>
34+
<body>
35+
<p>jQuery Migrate late load event binding test</p>
36+
</body>
37+
</html>

test/event.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,12 @@ TestManager.runIframeTest( "jQuery.event.fixHooks", "event-fixHooks.html",
145145
assert.equal( jQuery.migrateWarnings.length, 2, "warnings: " +
146146
JSON.stringify( jQuery.migrateWarnings ) );
147147
} );
148+
149+
TestManager.runIframeTest( "Load within a ready handler", "event-lateload.html",
150+
function( assert, jQuery, window, document, log ) {
151+
assert.expect( 2 );
152+
153+
assert.equal( jQuery.migrateWarnings.length, 1, "warnings: " +
154+
JSON.stringify( jQuery.migrateWarnings ) );
155+
assert.ok( /load/.test( jQuery.migrateWarnings[ 0 ] ), "message ok" );
156+
} );

warnings.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,9 @@ See jQuery-ui [commit](https://github.com/jquery/jquery-ui/commit/c0093b599fcd58
193193
**Cause:** The code on the page has used the `jQuery.event.props` or `jQuery.event.fixHooks` data structures. These were used in previous versions to affect the properties that are copied from the native event to the jQuery event each time an event is delivered, but they had the potential to create performance issues. Versions of jQuery Mobile before 1.5 make use of this API and require jQuery Migrate to run properly.
194194

195195
**Solution:** The most popular use of these data structures are to add properties for touch or pointer events, and those properties are now supported by default with a newer high-performance approach in jQuery 3.0 that only retrieves the properties on first access. If you are using jQuery Mobile, check the [jquerymobile.com](https://jquerymobile.com) site for updates. If you are using plugins such as [pointerTouch](https://github.com/timmywil/jquery.event.pointertouch) or [touchHooks](https://github.com/aarongloege/jquery.touchHooks), simply remove them as they are no longer needed.
196+
197+
### JQMIGRATE: $(window).on('load'...) called after load event occurred
198+
199+
**Cause:** The calling code has attempted to attach a `load` event to `window` after the page has already loaded. That means the handler will never run and so is probably not what the caller intended. This can occur when the event attachment is made too late, for example, in a jQuery ready handler. It can also occur when a file is loaded dynamically with jQuery after the page has loaded, for example using the `$.getScript()` method.
200+
201+
**Solution:** If a function `fn` does not actually depend on all page assets being fully loaded, switch to a ready handler `$( fn )` which runs earlier and will aways run `fn` even if the script that contains the code loads long after the page has fully loaded. If `fn` actually does depend on the script being fully loaded, check `document.readyState`. If the value is `"complete"` run the function immediately, otherwise use `$(window).on( "load", fn )`.

0 commit comments

Comments
 (0)