Skip to content

Commit

Permalink
Fixes #7340. Use a single capturing handler to simulate bubbling focu…
Browse files Browse the repository at this point in the history
…sin/focusout event on non-IE browsers. Allow native DOM methods to fire events other than the currently active one back into jQuery.
  • Loading branch information
dmethvin committed Mar 5, 2011
1 parent 2d0bc7c commit 55ec6a7
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 9 deletions.
32 changes: 23 additions & 9 deletions src/event.js
Expand Up @@ -70,10 +70,10 @@ jQuery.event = {
}

if ( !eventHandle ) {
elemData.handle = eventHandle = function() {
elemData.handle = eventHandle = function( e ) {
// Handle the second event of a trigger and when
// an event is called after a page has unloaded
return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
jQuery.event.handle.apply( eventHandle.elem, arguments ) :
undefined;
};
Expand Down Expand Up @@ -380,7 +380,7 @@ jQuery.event = {
target[ "on" + targetType ] = null;
}

jQuery.event.triggered = true;
jQuery.event.triggered = event.type;
target[ targetType ]();
}

Expand All @@ -391,7 +391,7 @@ jQuery.event = {
target[ "on" + targetType ] = old;
}

jQuery.event.triggered = false;
jQuery.event.triggered = undefined;
}
}
},
Expand Down Expand Up @@ -868,19 +868,33 @@ function trigger( type, elem, args ) {
// Create "bubbling" focus and blur events
if ( document.addEventListener ) {
jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {

// Attach a single capturing handler while someone wants focusin/focusout
var attaches = 0;

jQuery.event.special[ fix ] = {
setup: function() {
this.addEventListener( orig, handler, true );
if ( attaches++ === 0 ) {
document.addEventListener( orig, handler, true );
}
},
teardown: function() {
this.removeEventListener( orig, handler, true );
if ( --attaches === 0 ) {
document.removeEventListener( orig, handler, true );
}
}
};

function handler( e ) {
e = jQuery.event.fix( e );
function handler( donor ) {
// Donor event is always a native one; fix it and switch its type.
// Let focusin/out handler cancel the donor focus/blur event.
var e = jQuery.event.fix( donor );
e.type = fix;
return jQuery.event.handle.call( this, e );
e.originalEvent = {};
jQuery.event.trigger( e, null, e.target );
if ( e.isDefaultPrevented() ) {
donor.preventDefault();
}
}
});
}
Expand Down
25 changes: 25 additions & 0 deletions test/unit/event.js
Expand Up @@ -1966,6 +1966,31 @@ test("window resize", function() {
ok( !jQuery._data(window, "__events__"), "Make sure all the events are gone." );
});

test("focusin bubbles", function() {
expect(4);

var input = jQuery( '<input type="text" />' ).prependTo( "body" ),
order = 0;

jQuery( "body" ).bind( "focusin.focusinBubblesTest", function(){
equals( 1, order++, "focusin on the body second" );
});

input.bind( "focusin.focusinBubblesTest", function(){
equals( 0, order++, "focusin on the element first" );
});

// DOM focus method
input[0].focus();
// jQuery trigger, which calls DOM focus
order = 0;
input[0].blur();
input.trigger( "focus" );

input.remove();
jQuery( "body" ).unbind( "focusin.focusinBubblesTest" );
});

/*
test("jQuery(function($) {})", function() {
stop();
Expand Down

0 comments on commit 55ec6a7

Please sign in to comment.