diff --git a/src/renderers/dom/client/ReactBrowserEventEmitter.js b/src/renderers/dom/client/ReactBrowserEventEmitter.js index 5f5dc8d267..3f05b0d65c 100644 --- a/src/renderers/dom/client/ReactBrowserEventEmitter.js +++ b/src/renderers/dom/client/ReactBrowserEventEmitter.js @@ -287,7 +287,8 @@ var ReactBrowserEventEmitter = assign({}, ReactEventEmitterMixin, { ); } } else if (dependency === topLevelTypes.topFocus || - dependency === topLevelTypes.topBlur) { + dependency === topLevelTypes.topBlur || dependency === topLevelTypes.topFocusIn || + dependency === topLevelTypes.topFocusOut) { if (isEventSupported('focus', true)) { ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent( @@ -295,6 +296,16 @@ var ReactBrowserEventEmitter = assign({}, ReactEventEmitterMixin, { 'focus', mountAt ); + ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent( + topLevelTypes.topFocusIn, + 'focusin', + mountAt + ); + ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent( + topLevelTypes.topFocusOut, + 'focusout', + mountAt + ); ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent( topLevelTypes.topBlur, 'blur', @@ -318,6 +329,8 @@ var ReactBrowserEventEmitter = assign({}, ReactEventEmitterMixin, { // to make sure blur and focus event listeners are only attached once isListening[topLevelTypes.topBlur] = true; isListening[topLevelTypes.topFocus] = true; + isListening[topLevelTypes.topFocusIn] = true; + isListening[topLevelTypes.topFocusOut] = true; } else if (topEventMapping.hasOwnProperty(dependency)) { ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent( dependency, diff --git a/src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js b/src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js index 1a6855d286..06a483382b 100644 --- a/src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js +++ b/src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js @@ -37,6 +37,8 @@ var eventTypes = { topLevelTypes.topChange, topLevelTypes.topClick, topLevelTypes.topFocus, + topLevelTypes.topFocusIn, + topLevelTypes.topFocusOut, topLevelTypes.topInput, topLevelTypes.topKeyDown, topLevelTypes.topKeyUp, diff --git a/src/renderers/dom/client/eventPlugins/SimpleEventPlugin.js b/src/renderers/dom/client/eventPlugins/SimpleEventPlugin.js index f790e3fe9b..e2ee32e027 100644 --- a/src/renderers/dom/client/eventPlugins/SimpleEventPlugin.js +++ b/src/renderers/dom/client/eventPlugins/SimpleEventPlugin.js @@ -191,6 +191,18 @@ var eventTypes = { captured: keyOf({onFocusCapture: true}), }, }, + focusOut: { + phasedRegistrationNames: { + bubbled: keyOf({onFocusOut: true}), + captured: keyOf({onFocusOutCapture: true}), + }, + }, + focusIn: { + phasedRegistrationNames: { + bubbled: keyOf({onFocusIn: true}), + captured: keyOf({onFocusInCapture: true}), + }, + }, input: { phasedRegistrationNames: { bubbled: keyOf({onInput: true}), @@ -438,6 +450,8 @@ var topLevelEventsToDispatchConfig = { topEnded: eventTypes.ended, topError: eventTypes.error, topFocus: eventTypes.focus, + topFocusOut: eventTypes.focusOut, + topFocusIn: eventTypes.focusIn, topInput: eventTypes.input, topInvalid: eventTypes.invalid, topKeyDown: eventTypes.keyDown, @@ -545,6 +559,8 @@ var SimpleEventPlugin = { break; case topLevelTypes.topBlur: case topLevelTypes.topFocus: + case topLevelTypes.topFocusIn: + case topLevelTypes.topFocusOut: EventConstructor = SyntheticFocusEvent; break; case topLevelTypes.topClick: diff --git a/src/renderers/shared/event/EventConstants.js b/src/renderers/shared/event/EventConstants.js index 84a9e9d486..a156d21749 100644 --- a/src/renderers/shared/event/EventConstants.js +++ b/src/renderers/shared/event/EventConstants.js @@ -49,6 +49,8 @@ var topLevelTypes = keyMirror({ topEnded: null, topError: null, topFocus: null, + topFocusIn: null, + topFocusOut: null, topInput: null, topInvalid: null, topKeyDown: null,