Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 50 additions & 1 deletion src/renderers/dom/client/ReactEventListener.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ var assign = require('Object.assign');
var getEventTarget = require('getEventTarget');
var getUnboundedScrollPosition = require('getUnboundedScrollPosition');

var DOCUMENT_FRAGMENT_NODE_TYPE = 11;

/**
* Finds the parent React component of `node`.
*
Expand Down Expand Up @@ -60,6 +62,17 @@ PooledClass.addPoolingTo(
);

function handleTopLevelImpl(bookKeeping) {
if (bookKeeping.nativeEvent.path) {
// New browsers have a path attribute on native events
handleTopLevelWithPath(bookKeeping);
} else {
// Legacy browsers don't have a path attribute on native events
handleTopLevelWithoutPath(bookKeeping);
}
}

// Legacy browsers don't have a path attribute on native events
function handleTopLevelWithoutPath(bookKeeping) {
var topLevelTarget = ReactMount.getFirstReactDOM(
getEventTarget(bookKeeping.nativeEvent)
) || window;
Expand All @@ -81,11 +94,47 @@ function handleTopLevelImpl(bookKeeping) {
bookKeeping.topLevelType,
topLevelTarget,
topLevelTargetID,
bookKeeping.nativeEvent
bookKeeping.nativeEvent,
getEventTarget(bookKeeping.nativeEvent)
);
}
}

// New browsers have a path attribute on native events
function handleTopLevelWithPath(bookKeeping) {
var path = bookKeeping.nativeEvent.path;
var currentNativeTarget = path[0];
for (var i = 0; i < path.length; i++) {
var currentPathElement = path[i];
var currentPathElemenId = ReactMount.getID(currentPathElement);
if (currentPathElement.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE) {
currentNativeTarget = path[i + 1];
}
if (ReactMount.isRenderedByReact(currentPathElement)) {
var newRootId = ReactInstanceHandles.getReactRootIDFromNodeID(
currentPathElemenId
);
bookKeeping.ancestors.push(currentPathElement);

var topLevelTargetID = ReactMount.getID(currentPathElement) || '';
ReactEventListener._handleTopLevel(
bookKeeping.topLevelType,
currentPathElement,
topLevelTargetID,
bookKeeping.nativeEvent,
currentNativeTarget
);

// Jump to the root of this React render tree
while (currentPathElemenId !== newRootId) {
i++;
currentPathElement = path[i];
currentPathElemenId = ReactMount.getID(currentPathElement);
}
}
}
}

function scrollValueMonitor(cb) {
var scrollPosition = getUnboundedScrollPosition(window);
cb(scrollPosition);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ var EnterLeaveEventPlugin = {
topLevelType,
topLevelTarget,
topLevelTargetID,
nativeEvent) {
nativeEvent,
nativeEventTarget) {
if (topLevelType === topLevelTypes.topMouseOver &&
(nativeEvent.relatedTarget || nativeEvent.fromElement)) {
return null;
Expand Down Expand Up @@ -110,7 +111,8 @@ var EnterLeaveEventPlugin = {
var leave = SyntheticMouseEvent.getPooled(
eventTypes.mouseLeave,
fromID,
nativeEvent
nativeEvent,
nativeEventTarget
);
leave.type = 'mouseleave';
leave.target = from;
Expand All @@ -119,7 +121,8 @@ var EnterLeaveEventPlugin = {
var enter = SyntheticMouseEvent.getPooled(
eventTypes.mouseEnter,
toID,
nativeEvent
nativeEvent,
nativeEventTarget
);
enter.type = 'mouseenter';
enter.target = to;
Expand Down
13 changes: 7 additions & 6 deletions src/renderers/dom/client/eventPlugins/SelectEventPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ function getSelection(node) {
* @param {object} nativeEvent
* @return {?SyntheticEvent}
*/
function constructSelectEvent(nativeEvent) {
function constructSelectEvent(nativeEvent, nativeEventTarget) {
// Ensure we have the right element, and that the user is not dragging a
// selection (this matches native `select` event behavior). In HTML5, select
// fires only on input and textarea thus if there's no focused element we
Expand All @@ -111,7 +111,8 @@ function constructSelectEvent(nativeEvent) {
var syntheticEvent = SyntheticEvent.getPooled(
eventTypes.select,
activeElementID,
nativeEvent
nativeEvent,
nativeEventTarget
);

syntheticEvent.type = 'select';
Expand Down Expand Up @@ -155,8 +156,8 @@ var SelectEventPlugin = {
topLevelType,
topLevelTarget,
topLevelTargetID,
nativeEvent) {

nativeEvent,
nativeEventTarget) {
if (!hasListener) {
return null;
}
Expand Down Expand Up @@ -185,7 +186,7 @@ var SelectEventPlugin = {
case topLevelTypes.topContextMenu:
case topLevelTypes.topMouseUp:
mouseDown = false;
return constructSelectEvent(nativeEvent);
return constructSelectEvent(nativeEvent, nativeEventTarget);

// Chrome and IE fire non-standard event when selection is changed (and
// sometimes when it hasn't).
Expand All @@ -196,7 +197,7 @@ var SelectEventPlugin = {
case topLevelTypes.topSelectionChange:
case topLevelTypes.topKeyDown:
case topLevelTypes.topKeyUp:
return constructSelectEvent(nativeEvent);
return constructSelectEvent(nativeEvent, nativeEventTarget);
}

return null;
Expand Down
6 changes: 4 additions & 2 deletions src/renderers/dom/client/eventPlugins/SimpleEventPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,8 @@ var SimpleEventPlugin = {
topLevelType,
topLevelTarget,
topLevelTargetID,
nativeEvent) {
nativeEvent,
nativeEventTarget) {
var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType];
if (!dispatchConfig) {
return null;
Expand Down Expand Up @@ -418,7 +419,8 @@ var SimpleEventPlugin = {
var event = EventConstructor.getPooled(
dispatchConfig,
topLevelTargetID,
nativeEvent
nativeEvent,
nativeEventTarget
);
EventPropagators.accumulateTwoPhaseDispatches(event);
return event;
Expand Down
6 changes: 4 additions & 2 deletions src/renderers/dom/client/eventPlugins/TapEventPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ var TapEventPlugin = {
topLevelType,
topLevelTarget,
topLevelTargetID,
nativeEvent) {
nativeEvent,
nativeEventTarget) {
if (!isStartish(topLevelType) && !isEndish(topLevelType)) {
return null;
}
Expand All @@ -122,7 +123,8 @@ var TapEventPlugin = {
event = SyntheticUIEvent.getPooled(
eventTypes.touchTap,
topLevelTargetID,
nativeEvent
nativeEvent,
nativeEventTarget
);
}
if (isStartish(topLevelType)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ describe('EnterLeaveEventPlugin', function() {
topLevelTypes.topMouseOver,
div,
ReactMount.getID(div),
{target: div}
{target: div},
div
);
expect(extracted.length).toBe(2);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ describe('SelectEventPlugin', function() {
topLevelEvent,
node,
ReactMount.getID(node),
{target: node}
{target: node},
node
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ var ClipboardEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticUIEvent}
*/
function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent) {
SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}

SyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ var CompositionEventInterface = {
function SyntheticCompositionEvent(
dispatchConfig,
dispatchMarker,
nativeEvent) {
SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
nativeEvent,
nativeEventTarget) {
SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}

SyntheticEvent.augmentClass(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ var DragEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticUIEvent}
*/
function SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent) {
SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
function SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}

SyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface);
Expand Down
11 changes: 6 additions & 5 deletions src/renderers/dom/client/syntheticEvents/SyntheticEvent.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ var PooledClass = require('PooledClass');

var assign = require('Object.assign');
var emptyFunction = require('emptyFunction');
var getEventTarget = require('getEventTarget');

/**
* @interface Event
* @see http://www.w3.org/TR/DOM-Level-3-Events/
*/
var EventInterface = {
path: null,
type: null,
target: getEventTarget,
// currentTarget is set when dispatching; no use in copying it here
currentTarget: emptyFunction.thatReturnsNull,
eventPhase: null,
Expand Down Expand Up @@ -54,10 +53,12 @@ var EventInterface = {
* @param {string} dispatchMarker Marker identifying the event target.
* @param {object} nativeEvent Native browser event.
*/
function SyntheticEvent(dispatchConfig, dispatchMarker, nativeEvent) {
function SyntheticEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
this.dispatchConfig = dispatchConfig;
this.dispatchMarker = dispatchMarker;
this.nativeEvent = nativeEvent;
this.target = nativeEventTarget;
this.currentTarget = nativeEventTarget;

var Interface = this.constructor.Interface;
for (var propName in Interface) {
Expand Down Expand Up @@ -156,9 +157,9 @@ SyntheticEvent.augmentClass = function(Class, Interface) {
Class.Interface = assign({}, Super.Interface, Interface);
Class.augmentClass = Super.augmentClass;

PooledClass.addPoolingTo(Class, PooledClass.threeArgumentPooler);
PooledClass.addPoolingTo(Class, PooledClass.fourArgumentPooler);
};

PooledClass.addPoolingTo(SyntheticEvent, PooledClass.threeArgumentPooler);
PooledClass.addPoolingTo(SyntheticEvent, PooledClass.fourArgumentPooler);

module.exports = SyntheticEvent;
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ var FocusEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticUIEvent}
*/
function SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent) {
SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
function SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}

SyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ var InputEventInterface = {
function SyntheticInputEvent(
dispatchConfig,
dispatchMarker,
nativeEvent) {
SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
nativeEvent,
nativeEventTarget) {
SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}

SyntheticEvent.augmentClass(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ var KeyboardEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticUIEvent}
*/
function SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent) {
SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
function SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}

SyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ var MouseEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticUIEvent}
*/
function SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent) {
SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
function SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}

SyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ var TouchEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticUIEvent}
*/
function SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent) {
SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
function SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}

SyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface);
Expand Down
4 changes: 2 additions & 2 deletions src/renderers/dom/client/syntheticEvents/SyntheticUIEvent.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ var UIEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticEvent}
*/
function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent) {
SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}

SyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ var WheelEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticMouseEvent}
*/
function SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent) {
SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
function SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}

SyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ describe('SyntheticEvent', function() {
SyntheticEvent = require('SyntheticEvent');

createEvent = function(nativeEvent) {
return SyntheticEvent.getPooled({}, '', nativeEvent);
var target = require('getEventTarget')(nativeEvent);
return SyntheticEvent.getPooled({}, '', nativeEvent, target);
};
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ describe('SyntheticWheelEvent', function() {
SyntheticWheelEvent = require('SyntheticWheelEvent');

createEvent = function(nativeEvent) {
return SyntheticWheelEvent.getPooled({}, '', nativeEvent);
var target = require('getEventTarget')(nativeEvent);
return SyntheticWheelEvent.getPooled({}, '', nativeEvent, target);
};
});

Expand Down
Loading