8000 Event: Use only one focusin/out handler per matching window & document · jquery/jquery@9e15d6b · GitHub
[go: up one dir, main page]

Skip to content
/ jquery Public

Commit 9e15d6b

Browse files
authored
Event: Use only one focusin/out handler per matching window & document
The `doc` variable in: https://github.com/jquery/jquery/blob/3.4.1/src/event/focusin.js#L30 matched `document` for `document` & `window` for `window`, creating two separate wrapper event handlers & calling handlers twice if at least one `focusout` or `focusin` handler was attached on *both* `window` & `document`, or on `window` & another regular node. Also, fix the "focusin from an iframe" test to actually verify the behavior from commit 1cecf64 - the commit that introduced the regression - to make sure we don't regress on either front. Fixes gh-4652 Closes gh-4656
1 parent 966a709 commit 9e15d6b

File tree

2 files changed

+48
-10
lines changed

2 files changed

+48
-10
lines changed

src/event/focusin.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ if ( !support.focusin ) {
2727

2828
jQuery.event.special[ fix ] = {
2929
setup: function() {
30-
var doc = this.ownerDocument || this,
30+
31+
// Handle: regular nodes (via `this.ownerDocument`), window
32+
// (via `this.document`) & document (via `this`).
33+
var doc = this.ownerDocument || this.document || this,
3134
attaches = dataPriv.access( doc, fix );
3235

3336
if ( !attaches ) {
@@ -36,7 +39,7 @@ if ( !support.focusin ) {
3639
dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
3740
},
3841
teardown: function() {
39-
var doc = this.ownerDocument || this,
42+
var doc = this.ownerDocument || this.document || this,
4043
attaches = dataPriv.access( doc, fix ) - 1;
4144

4245
if ( !attaches ) {

test/unit/event.js

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2555,31 +2555,66 @@ testIframe(
25552555
function( assert, framejQuery, frameWin, frameDoc ) {
25562556
assert.expect( 1 );
25572557

2558-
var input = jQuery( frameDoc ).find( "#frame-input" );
2558+
var done = assert.async(),
2559+
focus = false,
2560+
input = jQuery( frameDoc ).find( "#frame-input" );
25592561

25602562
// Create a focusin handler on the parent; shouldn't affect the iframe's fate
25612563
jQuery( "body" ).on( "focusin.iframeTest", function() {
25622564
assert.ok( false, "fired a focusin event in the parent document" );
25632565
} );
25642566

25652567
input.on( "focusin", function() {
2568+
focus = true;
25662569
assert.ok( true, "fired a focusin event in the iframe" );
25672570
} );
25682571

25692572
// Avoid a native event; Chrome can't force focus to another frame
2570-
input.trigger( "focusin" );
2571-
2572-
// Must manually remove handler to avoid leaks in our data store
2573-
input.remove();
2574-
2575-
// Be sure it was removed; nothing should happen
2576-
input.trigger( "focusin" );
2573+
input[ 0 ].focus();
25772574

25782575
// Remove body handler manually since it's outside the fixture
25792576
jQuery( "body" ).off( "focusin.iframeTest" );
2577+
2578+
setTimeout( function() {
2579+
2580+
// DOM focus is unreliable in TestSwarm
2581+
if ( QUnit.isSwarm && !focus ) {
2582+
assert.ok( true, "GAP: Could not observe focus change" );
2583+
}
2584+
2585+
done();
2586+
}, 50 );
25802587
}
25812588
);
25822589

2590+
QUnit.test( "focusin on document & window", function( assert ) {
2591+
assert.expect( 1 );
2592+
2593+
var counter = 0,
2594+
input = jQuery( "<input />" );
2595+
2596+
input.appendTo( "#qunit-fixture" );
2597+
2598+
input[ 0 ].focus();
2599+
2600+
jQuery( window ).on( "focusout", function() {
2601+
counter++;
2602+
} );
2603+
jQuery( document ).on( "focusout", function() {
2604+
counter++;
2605+
} );
2606+
2607+
input[ 0 ].blur();
2608+
2609+
// DOM focus is unreliable in TestSwarm
2610+
if ( QUnit.isSwarm && counter === 0 ) {
2611+
assert.ok( true, "GAP: Could not observe focus change" );
2612+
}
2613+
2614+
assert.strictEqual( counter, 2,
2615+
"focusout handlers on document/window fired once only" );
2616+
} );
2617+
25832618
testIframe(
25842619
"jQuery.ready promise",
25852620
"event/promiseReady.html",

0 commit comments

Comments
 (0)
0