diff --git a/src/core/__tests__/ReactEvent-test.js b/src/core/__tests__/ReactEventEmitter-test.js similarity index 98% rename from src/core/__tests__/ReactEvent-test.js rename to src/core/__tests__/ReactEventEmitter-test.js index 9fb5fe9eb6..c2646d3332 100644 --- a/src/core/__tests__/ReactEvent-test.js +++ b/src/core/__tests__/ReactEventEmitter-test.js @@ -229,7 +229,7 @@ describe('ReactEventEmitter', function() { it('should invoke handlers that were removed while bubbling', function() { var handleParentClick = mocks.getMockFunction(); - var handleChildClick = function(abstractEvent) { + var handleChildClick = function(event) { ReactEventEmitter.deleteAllListeners(PARENT.id); }; ReactEventEmitter.putListener(CHILD.id, ON_CLICK_KEY, handleChildClick); @@ -240,7 +240,7 @@ describe('ReactEventEmitter', function() { it('should not invoke newly inserted handlers while bubbling', function() { var handleParentClick = mocks.getMockFunction(); - var handleChildClick = function(abstractEvent) { + var handleChildClick = function(event) { ReactEventEmitter.putListener(PARENT.id, ON_CLICK_KEY, handleParentClick); }; ReactEventEmitter.putListener(CHILD.id, ON_CLICK_KEY, handleChildClick); diff --git a/src/event/AbstractEvent.js b/src/event/AbstractEvent.js deleted file mode 100644 index ad14378a69..0000000000 --- a/src/event/AbstractEvent.js +++ /dev/null @@ -1,253 +0,0 @@ -/** - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule AbstractEvent - */ - -"use strict"; - -var BrowserEnv = require('BrowserEnv'); -var PooledClass = require('PooledClass'); -var TouchEventUtils = require('TouchEventUtils'); - -var emptyFunction = require('emptyFunction'); - -var MAX_POOL_SIZE = 20; - -/** - * AbstractEvent copy constructor. @see `PooledClass`. Provides a single place - * to define all cross browser normalization of DOM events. Does not attempt to - * extend a native event, rather creates a completely new object that has a - * reference to the nativeEvent through .nativeEvent member. The property .data - * should hold all data that is extracted from the event in a cross browser - * manner. Application code should use the data field when possible, not the - * unreliable native event. - */ -function AbstractEvent( - reactEventType, - reactTargetID, // Allows the abstract target to differ from native. - nativeEvent, - data) { - this.reactEventType = reactEventType; - this.reactTargetID = reactTargetID || ''; - this.nativeEvent = nativeEvent; - this.data = data; - // TODO: Deprecate storing target - doesn't always make sense for some types - this.target = nativeEvent && nativeEvent.target; - - /** - * As a performance optimization, we tag the existing event with the listeners - * (or listener [singular] if only one). This avoids having to package up an - * abstract event along with the set of listeners into a wrapping "dispatch" - * object. No one should ever read this property except event system and - * plugin/dispatcher code. We also tag the abstract event with a parallel - * ID array. _dispatchListeners[i] is being dispatched to a DOM node at ID - * _dispatchIDs[i]. The lengths should never, ever, ever be different. - */ - this._dispatchListeners = null; - this._dispatchIDs = null; - - this.isPropagationStopped = false; - this.isPersistent = emptyFunction.thatReturnsFalse; -} - -/** `PooledClass` looks for this. */ -AbstractEvent.poolSize = MAX_POOL_SIZE; - -/** - * `PooledClass` looks for `destructor` on each instance it releases. We need to - * ensure that we remove all references to listeners which could trap large - * amounts of memory in their closures. - */ -AbstractEvent.prototype.destructor = function() { - this.target = null; - this._dispatchListeners = null; - this._dispatchIDs = null; -}; - -/** - * Enhance the `AbstractEvent` class to have pooling abilities. We instruct - * `PooledClass` that our copy constructor accepts five arguments (this is just - * a performance optimization). These objects are instantiated frequently. - */ -PooledClass.addPoolingTo(AbstractEvent, PooledClass.fiveArgumentPooler); - -AbstractEvent.prototype.stopPropagation = function() { - this.isPropagationStopped = true; - if (this.nativeEvent.stopPropagation) { - this.nativeEvent.stopPropagation(); - } - // IE8 only understands cancelBubble, not stopPropagation(). - this.nativeEvent.cancelBubble = true; -}; - -AbstractEvent.prototype.preventDefault = function() { - AbstractEvent.preventDefaultOnNativeEvent(this.nativeEvent); -}; - -/** - * We clear out all dispatched `AbstractEvent`s after each event loop, adding - * them back into the pool. This allows a way to hold onto a reference that - * won't be added back into the pool. - */ -AbstractEvent.prototype.persist = function() { - this.isPersistent = emptyFunction.thatReturnsTrue; -}; - -/** - * Utility function for preventing default in cross browser manner. - */ -AbstractEvent.preventDefaultOnNativeEvent = function(nativeEvent) { - if (nativeEvent.preventDefault) { - nativeEvent.preventDefault(); - } else { - nativeEvent.returnValue = false; - } -}; - -/** - * @param {Element} target The target element. - */ -AbstractEvent.normalizeScrollDataFromTarget = function(target) { - return { - scrollTop: target.scrollTop, - scrollLeft: target.scrollLeft, - clientWidth: target.clientWidth, - clientHeight: target.clientHeight, - scrollHeight: target.scrollHeight, - scrollWidth: target.scrollWidth - }; -}; - -/* - * There are some normalizations that need to happen for various browsers. In - * addition to replacing the general event fixing with a framework such as - * jquery, we need to normalize mouse events here. Code below is mostly borrowed - * from: jScrollPane/script/jquery.mousewheel.js - */ -AbstractEvent.normalizeMouseWheelData = function(nativeEvent) { - var delta = 0; - var deltaX = 0; - var deltaY = 0; - - /* traditional scroll wheel data */ - if ( nativeEvent.wheelDelta ) { delta = nativeEvent.wheelDelta/120; } - if ( nativeEvent.detail ) { delta = -nativeEvent.detail/3; } - - /* Multidimensional scroll (touchpads) with deltas */ - deltaY = delta; - - /* Gecko based browsers */ - if (nativeEvent.axis !== undefined && - nativeEvent.axis === nativeEvent.HORIZONTAL_AXIS ) { - deltaY = 0; - deltaX = -delta; - } - - /* Webkit based browsers */ - if (nativeEvent.wheelDeltaY !== undefined ) { - deltaY = nativeEvent.wheelDeltaY/120; - } - if (nativeEvent.wheelDeltaX !== undefined ) { - deltaX = -nativeEvent.wheelDeltaX/120; - } - - return { delta: delta, deltaX: deltaX, deltaY: deltaY }; -}; - -/** - * I <3 Quirksmode.org: - * http://www.quirksmode.org/js/events_properties.html - */ -AbstractEvent.isNativeClickEventRightClick = function(nativeEvent) { - return nativeEvent.which ? nativeEvent.which === 3 : - nativeEvent.button ? nativeEvent.button === 2 : - false; -}; - -AbstractEvent.normalizePointerData = function(nativeEvent) { - return { - globalX: AbstractEvent.eventPageX(nativeEvent), - globalY: AbstractEvent.eventPageY(nativeEvent), - rightMouseButton: - AbstractEvent.isNativeClickEventRightClick(nativeEvent) - }; -}; - -AbstractEvent.normalizeDragEventData = - function(nativeEvent, globalX, globalY, startX, startY) { - return { - globalX: globalX, - globalY: globalY, - startX: startX, - startY: startY - }; - }; - -/** - * Warning: It is possible to move your finger on a touch surface, yet not - * effect the `eventPageX/Y` because the touch had caused a scroll that - * compensated for your movement. To track movements across the page, prevent - * default to avoid scrolling, and control scrolling in javascript. - */ - -/** - * Gets the exact position of a touch/mouse event on the page with respect to - * the document body. The only reason why this method is needed instead of using - * `TouchEventUtils.extractSingleTouch` is to support IE8-. Mouse events in all - * browsers except IE8- contain a pageY. IE8 and below require clientY - * computation: - * - * @param {Event} nativeEvent Native event, possibly touch or mouse. - * @return {number} Coordinate with respect to document body. - */ -AbstractEvent.eventPageY = function(nativeEvent) { - var singleTouch = TouchEventUtils.extractSingleTouch(nativeEvent); - if (singleTouch) { - return singleTouch.pageY; - } else if (typeof nativeEvent.pageY !== 'undefined') { - return nativeEvent.pageY; - } else { - return nativeEvent.clientY + BrowserEnv.currentPageScrollTop; - } -}; - -/** - * @see `AbstractEvent.eventPageY`. - * - * @param {Event} nativeEvent Native event, possibly touch or mouse. - * @return {number} Coordinate with respect to document body. - */ -AbstractEvent.eventPageX = function(nativeEvent) { - var singleTouch = TouchEventUtils.extractSingleTouch(nativeEvent); - if (singleTouch) { - return singleTouch.pageX; - } else if (typeof nativeEvent.pageX !== 'undefined') { - return nativeEvent.pageX; - } else { - return nativeEvent.clientX + BrowserEnv.currentPageScrollLeft; - } -}; - -/** - * @deprecated - */ -AbstractEvent.persistentCloneOf = function(abstractEvent) { - abstractEvent.persist(); - return abstractEvent; -}; - -module.exports = AbstractEvent; - diff --git a/src/event/EventPluginHub.js b/src/event/EventPluginHub.js index 03133e4906..ff0be9d8a1 100644 --- a/src/event/EventPluginHub.js +++ b/src/event/EventPluginHub.js @@ -65,7 +65,7 @@ var executeDispatchesAndRelease = function(event) { * Required. When a top-level event is fired, this method is expected to * extract synthetic events that will in turn be queued and dispatched. * - * `abstractEventTypes` {object} + * `eventTypes` {object} * Optional, plugins that fire events must publish a mapping of registration * names that are used to register listeners. Values of this mapping must * be objects that contain `registrationName` or `phasedRegistrationNames`. diff --git a/src/event/EventPluginRegistry.js b/src/event/EventPluginRegistry.js index 74ba7062b2..e9302eb495 100644 --- a/src/event/EventPluginRegistry.js +++ b/src/event/EventPluginRegistry.js @@ -60,7 +60,7 @@ function recomputePluginOrdering() { pluginName ); EventPluginRegistry.plugins[pluginIndex] = PluginModule; - var publishedEvents = PluginModule.abstractEventTypes; + var publishedEvents = PluginModule.eventTypes; for (var eventName in publishedEvents) { invariant( publishEventForPlugin(publishedEvents[eventName], PluginModule), @@ -198,7 +198,7 @@ var EventPluginRegistry = { * @internal */ getPluginModuleForEvent: function(event) { - var dispatchConfig = event.reactEventType; + var dispatchConfig = event.dispatchConfig; if (dispatchConfig.registrationName) { return EventPluginRegistry.registrationNames[ dispatchConfig.registrationName diff --git a/src/event/EventPluginUtils.js b/src/event/EventPluginUtils.js index 219090e77a..686f7073eb 100644 --- a/src/event/EventPluginUtils.js +++ b/src/event/EventPluginUtils.js @@ -19,7 +19,6 @@ "use strict"; var EventConstants = require('EventConstants'); -var AbstractEvent = require('AbstractEvent'); var invariant = require('invariant'); @@ -40,27 +39,11 @@ function isStartish(topLevelType) { topLevelType === topLevelTypes.topTouchStart; } -function storePageCoordsIn(obj, nativeEvent) { - var pageX = AbstractEvent.eventPageX(nativeEvent); - var pageY = AbstractEvent.eventPageY(nativeEvent); - obj.pageX = pageX; - obj.pageY = pageY; -} - -function eventDistance(coords, nativeEvent) { - var pageX = AbstractEvent.eventPageX(nativeEvent); - var pageY = AbstractEvent.eventPageY(nativeEvent); - return Math.pow( - Math.pow(pageX - coords.pageX, 2) + Math.pow(pageY - coords.pageY, 2), - 0.5 - ); -} - var validateEventDispatches; if (__DEV__) { - validateEventDispatches = function(abstractEvent) { - var dispatchListeners = abstractEvent._dispatchListeners; - var dispatchIDs = abstractEvent._dispatchIDs; + validateEventDispatches = function(event) { + var dispatchListeners = event._dispatchListeners; + var dispatchIDs = event._dispatchIDs; var listenersIsArr = Array.isArray(dispatchListeners); var idsIsArr = Array.isArray(dispatchIDs); @@ -71,53 +54,52 @@ if (__DEV__) { invariant( idsIsArr === listenersIsArr && IDsLen === listenersLen, - 'EventPluginUtils: Invalid `abstractEvent`.' + 'EventPluginUtils: Invalid `event`.' ); }; } /** - * Invokes `cb(abstractEvent, listener, id)`. Avoids using call if no scope is + * Invokes `cb(event, listener, id)`. Avoids using call if no scope is * provided. The `(listener,id)` pair effectively forms the "dispatch" but are * kept separate to conserve memory. */ -function forEachEventDispatch(abstractEvent, cb) { - var dispatchListeners = abstractEvent._dispatchListeners; - var dispatchIDs = abstractEvent._dispatchIDs; +function forEachEventDispatch(event, cb) { + var dispatchListeners = event._dispatchListeners; + var dispatchIDs = event._dispatchIDs; if (__DEV__) { - validateEventDispatches(abstractEvent); + validateEventDispatches(event); } if (Array.isArray(dispatchListeners)) { - var i; - for ( - i = 0; - i < dispatchListeners.length && !abstractEvent.isPropagationStopped; - i++) { + for (var i = 0; i < dispatchListeners.length; i++) { + if (event.isPropagationStopped()) { + break; + } // Listeners and IDs are two parallel arrays that are always in sync. - cb(abstractEvent, dispatchListeners[i], dispatchIDs[i]); + cb(event, dispatchListeners[i], dispatchIDs[i]); } } else if (dispatchListeners) { - cb(abstractEvent, dispatchListeners, dispatchIDs); + cb(event, dispatchListeners, dispatchIDs); } } /** * Default implementation of PluginModule.executeDispatch(). - * @param {AbstractEvent} AbstractEvent to handle + * @param {SyntheticEvent} SyntheticEvent to handle * @param {function} Application-level callback * @param {string} domID DOM id to pass to the callback. */ -function executeDispatch(abstractEvent, listener, domID) { - listener(abstractEvent, domID); +function executeDispatch(event, listener, domID) { + listener(event, domID); } /** * Standard/simple iteration through an event's collected dispatches. */ -function executeDispatchesInOrder(abstractEvent, executeDispatch) { - forEachEventDispatch(abstractEvent, executeDispatch); - abstractEvent._dispatchListeners = null; - abstractEvent._dispatchIDs = null; +function executeDispatchesInOrder(event, executeDispatch) { + forEachEventDispatch(event, executeDispatch); + event._dispatchListeners = null; + event._dispatchIDs = null; } /** @@ -127,25 +109,24 @@ function executeDispatchesInOrder(abstractEvent, executeDispatch) { * @returns id of the first dispatch execution who's listener returns true, or * null if no listener returned true. */ -function executeDispatchesInOrderStopAtTrue(abstractEvent) { - var dispatchListeners = abstractEvent._dispatchListeners; - var dispatchIDs = abstractEvent._dispatchIDs; +function executeDispatchesInOrderStopAtTrue(event) { + var dispatchListeners = event._dispatchListeners; + var dispatchIDs = event._dispatchIDs; if (__DEV__) { - validateEventDispatches(abstractEvent); + validateEventDispatches(event); } if (Array.isArray(dispatchListeners)) { - var i; - for ( - i = 0; - i < dispatchListeners.length && !abstractEvent.isPropagationStopped; - i++) { + for (var i = 0; i < dispatchListeners.length; i++) { + if (event.isPropagationStopped()) { + break; + } // Listeners and IDs are two parallel arrays that are always in sync. - if (dispatchListeners[i](abstractEvent, dispatchIDs[i])) { + if (dispatchListeners[i](event, dispatchIDs[i])) { return dispatchIDs[i]; } } } else if (dispatchListeners) { - if (dispatchListeners(abstractEvent, dispatchIDs)) { + if (dispatchListeners(event, dispatchIDs)) { return dispatchIDs; } } @@ -161,30 +142,30 @@ function executeDispatchesInOrderStopAtTrue(abstractEvent) { * * @returns The return value of executing the single dispatch. */ -function executeDirectDispatch(abstractEvent) { +function executeDirectDispatch(event) { if (__DEV__) { - validateEventDispatches(abstractEvent); + validateEventDispatches(event); } - var dispatchListener = abstractEvent._dispatchListeners; - var dispatchID = abstractEvent._dispatchIDs; + var dispatchListener = event._dispatchListeners; + var dispatchID = event._dispatchIDs; invariant( !Array.isArray(dispatchListener), - 'executeDirectDispatch(...): Invalid `abstractEvent`.' + 'executeDirectDispatch(...): Invalid `event`.' ); var res = dispatchListener ? - dispatchListener(abstractEvent, dispatchID) : + dispatchListener(event, dispatchID) : null; - abstractEvent._dispatchListeners = null; - abstractEvent._dispatchIDs = null; + event._dispatchListeners = null; + event._dispatchIDs = null; return res; } /** - * @param {AbstractEvent} abstractEvent + * @param {SyntheticEvent} event * @returns {bool} True iff number of dispatches accumulated is greater than 0. */ -function hasDispatches(abstractEvent) { - return !!abstractEvent._dispatchListeners; +function hasDispatches(event) { + return !!event._dispatchListeners; } /** @@ -194,8 +175,6 @@ var EventPluginUtils = { isEndish: isEndish, isMoveish: isMoveish, isStartish: isStartish, - storePageCoordsIn: storePageCoordsIn, - eventDistance: eventDistance, executeDispatchesInOrder: executeDispatchesInOrder, executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue, executeDirectDispatch: executeDirectDispatch, diff --git a/src/event/EventPropagators.js b/src/event/EventPropagators.js index e7534f7a2d..26127b5d00 100644 --- a/src/event/EventPropagators.js +++ b/src/event/EventPropagators.js @@ -56,19 +56,19 @@ var injection = { * Some event types have a notion of different registration names for different * "phases" of propagation. This finds listeners by a given phase. */ -function listenerAtPhase(id, abstractEvent, propagationPhase) { +function listenerAtPhase(id, event, propagationPhase) { var registrationName = - abstractEvent.reactEventType.phasedRegistrationNames[propagationPhase]; + event.dispatchConfig.phasedRegistrationNames[propagationPhase]; return getListener(id, registrationName); } /** - * Tags an `AbstractEvent` with dispatched listeners. Creating this function + * Tags a `SyntheticEvent` with dispatched listeners. Creating this function * here, allows us to not have to bind or create functions for each event. * Mutating the event's members allows us to not have to create a wrapping * "dispatch" object that pairs the event with the listener. */ -function accumulateDirectionalDispatches(domID, upwards, abstractEvent) { +function accumulateDirectionalDispatches(domID, upwards, event) { if (__DEV__) { if (!domID) { throw new Error('Dispatching id must not be null'); @@ -76,11 +76,10 @@ function accumulateDirectionalDispatches(domID, upwards, abstractEvent) { injection.validate(); } var phase = upwards ? PropagationPhases.bubbled : PropagationPhases.captured; - var listener = listenerAtPhase(domID, abstractEvent, phase); + var listener = listenerAtPhase(domID, event, phase); if (listener) { - abstractEvent._dispatchListeners = - accumulate(abstractEvent._dispatchListeners, listener); - abstractEvent._dispatchIDs = accumulate(abstractEvent._dispatchIDs, domID); + event._dispatchListeners = accumulate(event._dispatchListeners, listener); + event._dispatchIDs = accumulate(event._dispatchIDs, domID); } } @@ -91,12 +90,12 @@ function accumulateDirectionalDispatches(domID, upwards, abstractEvent) { * single traversal for the entire collection of events because each event may * have a different target. */ -function accumulateTwoPhaseDispatchesSingle(abstractEvent) { - if (abstractEvent && abstractEvent.reactEventType.phasedRegistrationNames) { +function accumulateTwoPhaseDispatchesSingle(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { injection.InstanceHandle.traverseTwoPhase( - abstractEvent.reactTargetID, + event.dispatchMarker, accumulateDirectionalDispatches, - abstractEvent + event ); } } @@ -105,36 +104,35 @@ function accumulateTwoPhaseDispatchesSingle(abstractEvent) { /** * Accumulates without regard to direction, does not look for phased * registration names. Same as `accumulateDirectDispatchesSingle` but without - * requiring that the `reactTargetID` be the same as the dispatched ID. + * requiring that the `dispatchMarker` be the same as the dispatched ID. */ -function accumulateDispatches(id, ignoredDirection, abstractEvent) { - if (abstractEvent && abstractEvent.reactEventType.registrationName) { - var registrationName = abstractEvent.reactEventType.registrationName; +function accumulateDispatches(id, ignoredDirection, event) { + if (event && event.dispatchConfig.registrationName) { + var registrationName = event.dispatchConfig.registrationName; var listener = getListener(id, registrationName); if (listener) { - abstractEvent._dispatchListeners = - accumulate(abstractEvent._dispatchListeners, listener); - abstractEvent._dispatchIDs = accumulate(abstractEvent._dispatchIDs, id); + event._dispatchListeners = accumulate(event._dispatchListeners, listener); + event._dispatchIDs = accumulate(event._dispatchIDs, id); } } } /** - * Accumulates dispatches on an `AbstractEvent`, but only for the - * `reactTargetID`. - * @param {AbstractEvent} abstractEvent + * Accumulates dispatches on an `SyntheticEvent`, but only for the + * `dispatchMarker`. + * @param {SyntheticEvent} event */ -function accumulateDirectDispatchesSingle(abstractEvent) { - if (abstractEvent && abstractEvent.reactEventType.registrationName) { - accumulateDispatches(abstractEvent.reactTargetID, null, abstractEvent); +function accumulateDirectDispatchesSingle(event) { + if (event && event.dispatchConfig.registrationName) { + accumulateDispatches(event.dispatchMarker, null, event); } } -function accumulateTwoPhaseDispatches(abstractEvents) { +function accumulateTwoPhaseDispatches(events) { if (__DEV__) { injection.validate(); } - forEachAccumulated(abstractEvents, accumulateTwoPhaseDispatchesSingle); + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); } function accumulateEnterLeaveDispatches(leave, enter, fromID, toID) { @@ -151,11 +149,11 @@ function accumulateEnterLeaveDispatches(leave, enter, fromID, toID) { } -function accumulateDirectDispatches(abstractEvents) { +function accumulateDirectDispatches(events) { if (__DEV__) { injection.validate(); } - forEachAccumulated(abstractEvents, accumulateDirectDispatchesSingle); + forEachAccumulated(events, accumulateDirectDispatchesSingle); } diff --git a/src/event/__tests__/EventPluginRegistry-test.js b/src/event/__tests__/EventPluginRegistry-test.js index c22d598cc7..f890a58169 100644 --- a/src/event/__tests__/EventPluginRegistry-test.js +++ b/src/event/__tests__/EventPluginRegistry-test.js @@ -155,13 +155,13 @@ describe('EventPluginRegistry', function() { it('should publish registration names of injected plugins', function() { var OnePlugin = createPlugin({ - abstractEventTypes: { + eventTypes: { click: {registrationName: 'onClick'}, focus: {registrationName: 'onFocus'} } }); var TwoPlugin = createPlugin({ - abstractEventTypes: { + eventTypes: { magic: { phasedRegistrationNames: { bubbled: 'onMagicBubble', @@ -189,12 +189,12 @@ describe('EventPluginRegistry', function() { it('should throw if multiple registration names collide', function() { var OnePlugin = createPlugin({ - abstractEventTypes: { + eventTypes: { photoCapture: {registrationName: 'onPhotoCapture'} } }); var TwoPlugin = createPlugin({ - abstractEventTypes: { + eventTypes: { photo: { phasedRegistrationNames: { bubbled: 'onPhotoBubble', @@ -219,7 +219,7 @@ describe('EventPluginRegistry', function() { it('should throw if an invalid event is published', function() { var OnePlugin = createPlugin({ - abstractEventTypes: { + eventTypes: { badEvent: {/* missing configuration */} } }); @@ -246,14 +246,14 @@ describe('EventPluginRegistry', function() { }; var OnePlugin = createPlugin({ - abstractEventTypes: { + eventTypes: { click: clickDispatchConfig, magic: magicDispatchConfig } }); - var clickEvent = {reactEventType: clickDispatchConfig}; - var magicEvent = {reactEventType: magicDispatchConfig}; + var clickEvent = {dispatchConfig: clickDispatchConfig}; + var magicEvent = {dispatchConfig: magicDispatchConfig}; expect(EventPluginRegistry.getPluginModuleForEvent(clickEvent)).toBe(null); expect(EventPluginRegistry.getPluginModuleForEvent(magicEvent)).toBe(null); diff --git a/src/eventPlugins/AnalyticsEventPluginFactory.js b/src/eventPlugins/AnalyticsEventPluginFactory.js index f10a77804a..c2cf1e6ff5 100644 --- a/src/eventPlugins/AnalyticsEventPluginFactory.js +++ b/src/eventPlugins/AnalyticsEventPluginFactory.js @@ -133,14 +133,14 @@ if (__DEV__) { } /** - * This plugin does not really extract any abstract events. Rather it just looks - * at the top level event and bumps up counters as appropriate + * This plugin does not really extract any synthetic events. Rather it just + * looks at the top-level event and bumps up counters as appropriate * * @param {string} topLevelType Record from `EventConstants`. * @param {DOMEventTarget} topLevelTarget The listening component root node. * @param {string} topLevelTargetID ID of `topLevelTarget`. * @param {object} nativeEvent Native browser event. - * @return {*} An accumulation of `AbstractEvent`s. + * @return {*} An accumulation of synthetic events. * @see {EventPluginHub.extractEvents} */ function extractEvents( diff --git a/src/eventPlugins/EnterLeaveEventPlugin.js b/src/eventPlugins/EnterLeaveEventPlugin.js index 6e149b33c3..e4967e91dd 100644 --- a/src/eventPlugins/EnterLeaveEventPlugin.js +++ b/src/eventPlugins/EnterLeaveEventPlugin.js @@ -19,11 +19,11 @@ "use strict"; +var EventConstants = require('EventConstants'); var EventPropagators = require('EventPropagators'); var ExecutionEnvironment = require('ExecutionEnvironment'); -var AbstractEvent = require('AbstractEvent'); -var EventConstants = require('EventConstants'); var ReactInstanceHandles = require('ReactInstanceHandles'); +var SyntheticMouseEvent = require('SyntheticMouseEvent'); var getDOMNodeID = require('getDOMNodeID'); var keyOf = require('keyOf'); @@ -31,78 +31,77 @@ var keyOf = require('keyOf'); var topLevelTypes = EventConstants.topLevelTypes; var getFirstReactDOM = ReactInstanceHandles.getFirstReactDOM; -var abstractEventTypes = { +var eventTypes = { mouseEnter: {registrationName: keyOf({onMouseEnter: null})}, mouseLeave: {registrationName: keyOf({onMouseLeave: null})} }; -/** - * For almost every interaction we care about, there will be a top-level - * `mouseover` and `mouseout` event that occurs so only pay attention to one of - * the two (to avoid duplicate events). We use the `mouseout` event. - * - * However, there's one interaction where there will be no `mouseout` event to - * rely on - mousing from outside the browser *into* the chrome. We detect this - * scenario and only in that case, we use the `mouseover` event. - * - * @param {string} topLevelType Record from `EventConstants`. - * @param {DOMEventTarget} topLevelTarget The listening component root node. - * @param {string} topLevelTargetID ID of `topLevelTarget`. - * @param {object} nativeEvent Native browser event. - * @return {*} An accumulation of `AbstractEvent`s. - * @see {EventPluginHub.extractEvents} - */ -var extractEvents = function( - topLevelType, - topLevelTarget, - topLevelTargetID, - nativeEvent) { - if (topLevelType === topLevelTypes.topMouseOver && - (nativeEvent.relatedTarget || nativeEvent.fromElement)) { - return null; - } - if (topLevelType !== topLevelTypes.topMouseOut && - topLevelType !== topLevelTypes.topMouseOver) { - return null; // Must not be a mouse in or mouse out - ignoring. - } - - var to, from; - if (topLevelType === topLevelTypes.topMouseOut) { - to = getFirstReactDOM(nativeEvent.relatedTarget || nativeEvent.toElement) || - ExecutionEnvironment.global; - from = topLevelTarget; - } else { - to = topLevelTarget; - from = ExecutionEnvironment.global; - } - - // Nothing pertains to our managed components. - if (from === to) { - return null; - } - - var fromID = from ? getDOMNodeID(from) : ''; - var toID = to ? getDOMNodeID(to) : ''; - - var leave = AbstractEvent.getPooled( - abstractEventTypes.mouseLeave, - fromID, - nativeEvent - ); - var enter = AbstractEvent.getPooled( - abstractEventTypes.mouseEnter, - toID, - nativeEvent - ); - - EventPropagators.accumulateEnterLeaveDispatches(leave, enter, fromID, toID); - - return [leave, enter]; -}; - var EnterLeaveEventPlugin = { - abstractEventTypes: abstractEventTypes, - extractEvents: extractEvents + + eventTypes: eventTypes, + + /** + * For almost every interaction we care about, there will be both a top-level + * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that + * we do not extract duplicate events. However, moving the mouse into the + * browser from outside will not fire a `mouseout` event. In this case, we use + * the `mouseover` top-level event. + * + * @param {string} topLevelType Record from `EventConstants`. + * @param {DOMEventTarget} topLevelTarget The listening component root node. + * @param {string} topLevelTargetID ID of `topLevelTarget`. + * @param {object} nativeEvent Native browser event. + * @return {*} An accumulation of synthetic events. + * @see {EventPluginHub.extractEvents} + */ + extractEvents: function( + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent) { + if (topLevelType === topLevelTypes.topMouseOver && + (nativeEvent.relatedTarget || nativeEvent.fromElement)) { + return null; + } + if (topLevelType !== topLevelTypes.topMouseOut && + topLevelType !== topLevelTypes.topMouseOver) { + // Must not be a mouse in or mouse out - ignoring. + return null; + } + + var from, to; + if (topLevelType === topLevelTypes.topMouseOut) { + from = topLevelTarget; + to = getFirstReactDOM(nativeEvent.relatedTarget || nativeEvent.toElement) + || ExecutionEnvironment.global; + } else { + from = ExecutionEnvironment.global; + to = topLevelTarget; + } + + if (from === to) { + // Nothing pertains to our managed components. + return null; + } + + var fromID = from ? getDOMNodeID(from) : ''; + var toID = to ? getDOMNodeID(to) : ''; + + var leave = SyntheticMouseEvent.getPooled( + eventTypes.mouseLeave, + fromID, + nativeEvent + ); + var enter = SyntheticMouseEvent.getPooled( + eventTypes.mouseEnter, + toID, + nativeEvent + ); + + EventPropagators.accumulateEnterLeaveDispatches(leave, enter, fromID, toID); + return [leave, enter]; + } + }; module.exports = EnterLeaveEventPlugin; diff --git a/src/eventPlugins/ResponderEventPlugin.js b/src/eventPlugins/ResponderEventPlugin.js index 235b381211..ec55663ca4 100644 --- a/src/eventPlugins/ResponderEventPlugin.js +++ b/src/eventPlugins/ResponderEventPlugin.js @@ -18,10 +18,10 @@ "use strict"; -var AbstractEvent = require('AbstractEvent'); var EventConstants = require('EventConstants'); var EventPluginUtils = require('EventPluginUtils'); var EventPropagators = require('EventPropagators'); +var SyntheticEvent = require('SyntheticEvent'); var accumulate = require('accumulate'); var keyOf = require('keyOf'); @@ -41,11 +41,7 @@ var executeDispatchesInOrderStopAtTrue = var responderID = null; var isPressing = false; -var getResponderID = function() { - return responderID; -}; - -var abstractEventTypes = { +var eventTypes = { /** * On a `touchStart`/`mouseDown`, is it desired that this element become the * responder? @@ -116,22 +112,22 @@ var abstractEventTypes = { * `extractEvents()`. * - These events that are returned from `extractEvents` are "deferred * dispatched events". - * - When returned from `extractEvents`, deferred dispatched events - * contain an "accumulation" of deferred dispatches. - * -- These deferred dispatches are accumulated/collected before they are - * returned, but processed at a later time by the `EventPluginHub` (hence the - * name deferred). + * - When returned from `extractEvents`, deferred-dispatched events contain an + * "accumulation" of deferred dispatches. + * - These deferred dispatches are accumulated/collected before they are + * returned, but processed at a later time by the `EventPluginHub` (hence the + * name deferred). * - * In the process of returning their deferred dispatched events, event plugins + * In the process of returning their deferred-dispatched events, event plugins * themselves can dispatch events on-demand without returning them from - * `extractEvents`. Plugins might want to do this, so that they can use - * event dispatching as a tool that helps them decide which events should be - * extracted in the first place. + * `extractEvents`. Plugins might want to do this, so that they can use event + * dispatching as a tool that helps them decide which events should be extracted + * in the first place. * * "On-Demand-Dispatched Events": * - * - On-demand dispatched are not returned from `extractEvents`. - * - On-demand dispatched events are dispatched during the process of returning + * - On-demand-dispatched events are not returned from `extractEvents`. + * - On-demand-dispatched events are dispatched during the process of returning * the deferred-dispatched events. * - They should not have side effects. * - They should be avoided, and/or eventually be replaced with another @@ -158,81 +154,81 @@ var abstractEventTypes = { * - `touchStart` (`EventPluginHub` dispatches as usual) * - `responderGrant/Reject` (`EventPluginHub` dispatches as usual) * - * @returns {Accumulation} - */ - -/** * @param {string} topLevelType Record from `EventConstants`. - * @param {string} renderedTargetID ID of deepest React rendered element. + * @param {string} topLevelTargetID ID of deepest React rendered element. * @param {object} nativeEvent Native browser event. - * @return {*} An accumulation of extracted `AbstractEvent`s. + * @return {*} An accumulation of synthetic events. */ -var setResponderAndExtractTransfer = - function(topLevelType, renderedTargetID, nativeEvent) { - var type; - var shouldSetEventType = - isStartish(topLevelType) ? abstractEventTypes.startShouldSetResponder : - isMoveish(topLevelType) ? abstractEventTypes.moveShouldSetResponder : - abstractEventTypes.scrollShouldSetResponder; +function setResponderAndExtractTransfer( + topLevelType, + topLevelTargetID, + nativeEvent) { + var shouldSetEventType = + isStartish(topLevelType) ? eventTypes.startShouldSetResponder : + isMoveish(topLevelType) ? eventTypes.moveShouldSetResponder : + eventTypes.scrollShouldSetResponder; - var bubbleShouldSetFrom = responderID || renderedTargetID; - var shouldSetEvent = AbstractEvent.getPooled( - shouldSetEventType, - bubbleShouldSetFrom, - topLevelType, - nativeEvent, - AbstractEvent.normalizePointerData(nativeEvent) - ); - EventPropagators.accumulateTwoPhaseDispatches(shouldSetEvent); - var wantsResponderID = executeDispatchesInOrderStopAtTrue(shouldSetEvent); - AbstractEvent.release(shouldSetEvent); + var bubbleShouldSetFrom = responderID || topLevelTargetID; + var shouldSetEvent = SyntheticEvent.getPooled( + shouldSetEventType, + bubbleShouldSetFrom, + nativeEvent + ); + EventPropagators.accumulateTwoPhaseDispatches(shouldSetEvent); + var wantsResponderID = executeDispatchesInOrderStopAtTrue(shouldSetEvent); + if (!shouldSetEvent.isPersistent()) { + shouldSetEvent.constructor.release(shouldSetEvent); + } - if (!wantsResponderID || wantsResponderID === responderID) { - return null; - } - var extracted; - var grantEvent = AbstractEvent.getPooled( - abstractEventTypes.responderGrant, - wantsResponderID, - topLevelType, + if (!wantsResponderID || wantsResponderID === responderID) { + return null; + } + var extracted; + var grantEvent = SyntheticEvent.getPooled( + eventTypes.responderGrant, + wantsResponderID, + nativeEvent + ); + + EventPropagators.accumulateDirectDispatches(grantEvent); + if (responderID) { + var terminationRequestEvent = SyntheticEvent.getPooled( + eventTypes.responderTerminationRequest, + responderID, nativeEvent ); - - EventPropagators.accumulateDirectDispatches(grantEvent); - if (responderID) { - type = abstractEventTypes.responderTerminationRequest; - var terminationRequestEvent = AbstractEvent.getPooled(type, responderID); - EventPropagators.accumulateDirectDispatches(terminationRequestEvent); - var shouldSwitch = !hasDispatches(terminationRequestEvent) || - executeDirectDispatch(terminationRequestEvent); - AbstractEvent.release(terminationRequestEvent); - if (shouldSwitch) { - var terminateType = abstractEventTypes.responderTerminate; - var terminateEvent = AbstractEvent.getPooled( - terminateType, - responderID, - topLevelType, - nativeEvent - ); - EventPropagators.accumulateDirectDispatches(terminateEvent); - extracted = accumulate(extracted, [grantEvent, terminateEvent]); - responderID = wantsResponderID; - } else { - var rejectEvent = AbstractEvent.getPooled( - abstractEventTypes.responderReject, - wantsResponderID, - topLevelType, - nativeEvent - ); - EventPropagators.accumulateDirectDispatches(rejectEvent); - extracted = accumulate(extracted, rejectEvent); - } - } else { - extracted = accumulate(extracted, grantEvent); - responderID = wantsResponderID; + EventPropagators.accumulateDirectDispatches(terminationRequestEvent); + var shouldSwitch = !hasDispatches(terminationRequestEvent) || + executeDirectDispatch(terminationRequestEvent); + if (!terminationRequestEvent.isPersistent()) { + terminationRequestEvent.constructor.release(terminationRequestEvent); } - return extracted; - }; + + if (shouldSwitch) { + var terminateType = eventTypes.responderTerminate; + var terminateEvent = SyntheticEvent.getPooled( + terminateType, + responderID, + nativeEvent + ); + EventPropagators.accumulateDirectDispatches(terminateEvent); + extracted = accumulate(extracted, [grantEvent, terminateEvent]); + responderID = wantsResponderID; + } else { + var rejectEvent = SyntheticEvent.getPooled( + eventTypes.responderReject, + wantsResponderID, + nativeEvent + ); + EventPropagators.accumulateDirectDispatches(rejectEvent); + extracted = accumulate(extracted, rejectEvent); + } + } else { + extracted = accumulate(extracted, grantEvent); + responderID = wantsResponderID; + } + return extracted; +} /** * A transfer is a negotiation between a currently set responder and the next @@ -241,9 +237,8 @@ var setResponderAndExtractTransfer = * currently a responder set (in other words as long as the user is pressing * down). * - * @param {EventConstants.topLevelTypes} topLevelType - * @return {boolean} Whether or not a transfer of responder could possibly - * occur. + * @param {string} topLevelType Record from `EventConstants`. + * @return {boolean} True if a transfer of responder could possibly occur. */ function canTriggerTransfer(topLevelType) { return topLevelType === EventConstants.topLevelTypes.topScroll || @@ -251,69 +246,71 @@ function canTriggerTransfer(topLevelType) { (isPressing && isMoveish(topLevelType)); } -/** - * @param {string} topLevelType Record from `EventConstants`. - * @param {DOMEventTarget} topLevelTarget The listening component root node. - * @param {string} topLevelTargetID ID of `topLevelTarget`. - * @param {object} nativeEvent Native browser event. - * @return {*} An accumulation of `AbstractEvent`s. - * @see {EventPluginHub.extractEvents} - */ -var extractEvents = function( - topLevelType, - topLevelTarget, - topLevelTargetID, - nativeEvent) { - var extracted; - // Must have missed an end event - reset the state here. - if (responderID && isStartish(topLevelType)) { - responderID = null; - } - if (isStartish(topLevelType)) { - isPressing = true; - } else if (isEndish(topLevelType)) { - isPressing = false; - } - if (canTriggerTransfer(topLevelType)) { - var transfer = setResponderAndExtractTransfer( - topLevelType, - topLevelTargetID, - nativeEvent - ); - if (transfer) { - extracted = accumulate(extracted, transfer); - } - } - // Now that we know the responder is set correctly, we can dispatch - // responder type events (directly to the responder). - var type = isMoveish(topLevelType) ? abstractEventTypes.responderMove : - isEndish(topLevelType) ? abstractEventTypes.responderRelease : - isStartish(topLevelType) ? abstractEventTypes.responderStart : null; - if (type) { - var data = AbstractEvent.normalizePointerData(nativeEvent); - var gesture = AbstractEvent.getPooled( - type, - responderID, - nativeEvent, - data - ); - EventPropagators.accumulateDirectDispatches(gesture); - extracted = accumulate(extracted, gesture); - } - if (type === abstractEventTypes.responderRelease) { - responderID = null; - } - return extracted; -}; - /** * Event plugin for formalizing the negotiation between claiming locks on * receiving touches. */ var ResponderEventPlugin = { - abstractEventTypes: abstractEventTypes, - extractEvents: extractEvents, - getResponderID: getResponderID + + getResponderID: function() { + return responderID; + }, + + eventTypes: eventTypes, + + /** + * @param {string} topLevelType Record from `EventConstants`. + * @param {DOMEventTarget} topLevelTarget The listening component root node. + * @param {string} topLevelTargetID ID of `topLevelTarget`. + * @param {object} nativeEvent Native browser event. + * @return {*} An accumulation of synthetic events. + * @see {EventPluginHub.extractEvents} + */ + extractEvents: function( + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent) { + var extracted; + // Must have missed an end event - reset the state here. + if (responderID && isStartish(topLevelType)) { + responderID = null; + } + if (isStartish(topLevelType)) { + isPressing = true; + } else if (isEndish(topLevelType)) { + isPressing = false; + } + if (canTriggerTransfer(topLevelType)) { + var transfer = setResponderAndExtractTransfer( + topLevelType, + topLevelTargetID, + nativeEvent + ); + if (transfer) { + extracted = accumulate(extracted, transfer); + } + } + // Now that we know the responder is set correctly, we can dispatch + // responder type events (directly to the responder). + var type = isMoveish(topLevelType) ? eventTypes.responderMove : + isEndish(topLevelType) ? eventTypes.responderRelease : + isStartish(topLevelType) ? eventTypes.responderStart : null; + if (type) { + var gesture = SyntheticEvent.getPooled( + type, + responderID || '', + nativeEvent + ); + EventPropagators.accumulateDirectDispatches(gesture); + extracted = accumulate(extracted, gesture); + } + if (type === eventTypes.responderRelease) { + responderID = null; + } + return extracted; + } + }; module.exports = ResponderEventPlugin; diff --git a/src/eventPlugins/SimpleEventPlugin.js b/src/eventPlugins/SimpleEventPlugin.js index 490dce2172..3f37f23246 100644 --- a/src/eventPlugins/SimpleEventPlugin.js +++ b/src/eventPlugins/SimpleEventPlugin.js @@ -18,201 +18,237 @@ "use strict"; -var AbstractEvent = require('AbstractEvent'); var EventConstants = require('EventConstants'); var EventPropagators = require('EventPropagators'); +var SyntheticEvent = require('SyntheticEvent'); +var SyntheticFocusEvent = require('SyntheticFocusEvent'); +var SyntheticKeyboardEvent = require('SyntheticKeyboardEvent'); +var SyntheticMouseEvent = require('SyntheticMouseEvent'); +var SyntheticMutationEvent = require('SyntheticMutationEvent'); +var SyntheticTouchEvent = require('SyntheticTouchEvent'); +var SyntheticUIEvent = require('SyntheticUIEvent'); +var SyntheticWheelEvent = require('SyntheticWheelEvent'); +var invariant = require('invariant'); var keyOf = require('keyOf'); var topLevelTypes = EventConstants.topLevelTypes; -var SimpleEventPlugin = { - abstractEventTypes: { - // Note: We do not allow listening to mouseOver events. Instead, use the - // onMouseEnter/onMouseLeave created by `EnterLeaveEventPlugin`. - mouseDown: { - phasedRegistrationNames: { - bubbled: keyOf({onMouseDown: true}), - captured: keyOf({onMouseDownCapture: true}) - } - }, - mouseUp: { - phasedRegistrationNames: { - bubbled: keyOf({onMouseUp: true}), - captured: keyOf({onMouseUpCapture: true}) - } - }, - mouseMove: { - phasedRegistrationNames: { - bubbled: keyOf({onMouseMove: true}), - captured: keyOf({onMouseMoveCapture: true}) - } - }, - doubleClick: { - phasedRegistrationNames: { - bubbled: keyOf({onDoubleClick: true}), - captured: keyOf({onDoubleClickCapture: true}) - } - }, - click: { - phasedRegistrationNames: { - bubbled: keyOf({onClick: true}), - captured: keyOf({onClickCapture: true}) - } - }, - wheel: { - phasedRegistrationNames: { - bubbled: keyOf({onWheel: true}), - captured: keyOf({onWheelCapture: true}) - } - }, - touchStart: { - phasedRegistrationNames: { - bubbled: keyOf({onTouchStart: true}), - captured: keyOf({onTouchStartCapture: true}) - } - }, - touchEnd: { - phasedRegistrationNames: { - bubbled: keyOf({onTouchEnd: true}), - captured: keyOf({onTouchEndCapture: true}) - } - }, - touchCancel: { - phasedRegistrationNames: { - bubbled: keyOf({onTouchCancel: true}), - captured: keyOf({onTouchCancelCapture: true}) - } - }, - touchMove: { - phasedRegistrationNames: { - bubbled: keyOf({onTouchMove: true}), - captured: keyOf({onTouchMoveCapture: true}) - } - }, - keyUp: { - phasedRegistrationNames: { - bubbled: keyOf({onKeyUp: true}), - captured: keyOf({onKeyUpCapture: true}) - } - }, - keyPress: { - phasedRegistrationNames: { - bubbled: keyOf({onKeyPress: true}), - captured: keyOf({onKeyPressCapture: true}) - } - }, - keyDown: { - phasedRegistrationNames: { - bubbled: keyOf({onKeyDown: true}), - captured: keyOf({onKeyDownCapture: true}) - } - }, - input: { - phasedRegistrationNames: { - bubbled: keyOf({onInput: true}), - captured: keyOf({onInputCapture: true}) - } - }, - focus: { - phasedRegistrationNames: { - bubbled: keyOf({onFocus: true}), - captured: keyOf({onFocusCapture: true}) - } - }, - blur: { - phasedRegistrationNames: { - bubbled: keyOf({onBlur: true}), - captured: keyOf({onBlurCapture: true}) - } - }, - scroll: { - phasedRegistrationNames: { - bubbled: keyOf({onScroll: true}), - captured: keyOf({onScrollCapture: true}) - } - }, - change: { - phasedRegistrationNames: { - bubbled: keyOf({onChange: true}), - captured: keyOf({onChangeCapture: true}) - } - }, - submit: { - phasedRegistrationNames: { - bubbled: keyOf({onSubmit: true}), - captured: keyOf({onSubmitCapture: true}) - } - }, - DOMCharacterDataModified: { - phasedRegistrationNames: { - bubbled: keyOf({onDOMCharacterDataModified: true}), - captured: keyOf({onDOMCharacterDataModifiedCapture: true}) - } - }, - drag: { - phasedRegistrationNames: { - bubbled: keyOf({onDrag: true}), - captured: keyOf({onDragCapture: true}) - } - }, - dragEnd: { - phasedRegistrationNames: { - bubbled: keyOf({onDragEnd: true}), - captured: keyOf({onDragEndCapture: true}) - } - }, - dragEnter: { - phasedRegistrationNames: { - bubbled: keyOf({onDragEnter: true}), - captured: keyOf({onDragEnterCapture: true}) - } - }, - dragExit: { - phasedRegistrationNames: { - bubbled: keyOf({onDragExit: true}), - captured: keyOf({onDragExitCapture: true}) - } - }, - dragLeave: { - phasedRegistrationNames: { - bubbled: keyOf({onDragLeave: true}), - captured: keyOf({onDragLeaveCapture: true}) - } - }, - dragOver: { - phasedRegistrationNames: { - bubbled: keyOf({onDragOver: true}), - captured: keyOf({onDragOverCapture: true}) - } - }, - dragStart: { - phasedRegistrationNames: { - bubbled: keyOf({onDragStart: true}), - captured: keyOf({onDragStartCapture: true}) - } - }, - drop: { - phasedRegistrationNames: { - bubbled: keyOf({onDrop: true}), - captured: keyOf({onDropCapture: true}) - } +var eventTypes = { + blur: { + phasedRegistrationNames: { + bubbled: keyOf({onBlur: true}), + captured: keyOf({onBlurCapture: true}) } }, + change: { + phasedRegistrationNames: { + bubbled: keyOf({onChange: true}), + captured: keyOf({onChangeCapture: true}) + } + }, + click: { + phasedRegistrationNames: { + bubbled: keyOf({onClick: true}), + captured: keyOf({onClickCapture: true}) + } + }, + doubleClick: { + phasedRegistrationNames: { + bubbled: keyOf({onDoubleClick: true}), + captured: keyOf({onDoubleClickCapture: true}) + } + }, + drag: { + phasedRegistrationNames: { + bubbled: keyOf({onDrag: true}), + captured: keyOf({onDragCapture: true}) + } + }, + dragEnd: { + phasedRegistrationNames: { + bubbled: keyOf({onDragEnd: true}), + captured: keyOf({onDragEndCapture: true}) + } + }, + dragEnter: { + phasedRegistrationNames: { + bubbled: keyOf({onDragEnter: true}), + captured: keyOf({onDragEnterCapture: true}) + } + }, + dragExit: { + phasedRegistrationNames: { + bubbled: keyOf({onDragExit: true}), + captured: keyOf({onDragExitCapture: true}) + } + }, + dragLeave: { + phasedRegistrationNames: { + bubbled: keyOf({onDragLeave: true}), + captured: keyOf({onDragLeaveCapture: true}) + } + }, + dragOver: { + phasedRegistrationNames: { + bubbled: keyOf({onDragOver: true}), + captured: keyOf({onDragOverCapture: true}) + } + }, + dragStart: { + phasedRegistrationNames: { + bubbled: keyOf({onDragStart: true}), + captured: keyOf({onDragStartCapture: true}) + } + }, + drop: { + phasedRegistrationNames: { + bubbled: keyOf({onDrop: true}), + captured: keyOf({onDropCapture: true}) + } + }, + focus: { + phasedRegistrationNames: { + bubbled: keyOf({onFocus: true}), + captured: keyOf({onFocusCapture: true}) + } + }, + input: { + phasedRegistrationNames: { + bubbled: keyOf({onInput: true}), + captured: keyOf({onInputCapture: true}) + } + }, + keyDown: { + phasedRegistrationNames: { + bubbled: keyOf({onKeyDown: true}), + captured: keyOf({onKeyDownCapture: true}) + } + }, + keyPress: { + phasedRegistrationNames: { + bubbled: keyOf({onKeyPress: true}), + captured: keyOf({onKeyPressCapture: true}) + } + }, + keyUp: { + phasedRegistrationNames: { + bubbled: keyOf({onKeyUp: true}), + captured: keyOf({onKeyUpCapture: true}) + } + }, + // Note: We do not allow listening to mouseOver events. Instead, use the + // onMouseEnter/onMouseLeave created by `EnterLeaveEventPlugin`. + mouseDown: { + phasedRegistrationNames: { + bubbled: keyOf({onMouseDown: true}), + captured: keyOf({onMouseDownCapture: true}) + } + }, + mouseMove: { + phasedRegistrationNames: { + bubbled: keyOf({onMouseMove: true}), + captured: keyOf({onMouseMoveCapture: true}) + } + }, + mouseUp: { + phasedRegistrationNames: { + bubbled: keyOf({onMouseUp: true}), + captured: keyOf({onMouseUpCapture: true}) + } + }, + scroll: { + phasedRegistrationNames: { + bubbled: keyOf({onScroll: true}), + captured: keyOf({onScrollCapture: true}) + } + }, + submit: { + phasedRegistrationNames: { + bubbled: keyOf({onSubmit: true}), + captured: keyOf({onSubmitCapture: true}) + } + }, + touchCancel: { + phasedRegistrationNames: { + bubbled: keyOf({onTouchCancel: true}), + captured: keyOf({onTouchCancelCapture: true}) + } + }, + touchEnd: { + phasedRegistrationNames: { + bubbled: keyOf({onTouchEnd: true}), + captured: keyOf({onTouchEndCapture: true}) + } + }, + touchMove: { + phasedRegistrationNames: { + bubbled: keyOf({onTouchMove: true}), + captured: keyOf({onTouchMoveCapture: true}) + } + }, + touchStart: { + phasedRegistrationNames: { + bubbled: keyOf({onTouchStart: true}), + captured: keyOf({onTouchStartCapture: true}) + } + }, + wheel: { + phasedRegistrationNames: { + bubbled: keyOf({onWheel: true}), + captured: keyOf({onWheelCapture: true}) + } + } +}; + +var topLevelEventsToDispatchConfig = { + topBlur: eventTypes.blur, + topChange: eventTypes.change, + topClick: eventTypes.click, + topDoubleClick: eventTypes.doubleClick, + topDOMCharacterDataModified: eventTypes.DOMCharacterDataModified, + topDrag: eventTypes.drag, + topDragEnd: eventTypes.dragEnd, + topDragEnter: eventTypes.dragEnter, + topDragExit: eventTypes.dragExit, + topDragLeave: eventTypes.dragLeave, + topDragOver: eventTypes.dragOver, + topDragStart: eventTypes.dragStart, + topDrop: eventTypes.drop, + topFocus: eventTypes.focus, + topInput: eventTypes.input, + topKeyDown: eventTypes.keyDown, + topKeyPress: eventTypes.keyPress, + topKeyUp: eventTypes.keyUp, + topMouseDown: eventTypes.mouseDown, + topMouseMove: eventTypes.mouseMove, + topMouseUp: eventTypes.mouseUp, + topScroll: eventTypes.scroll, + topSubmit: eventTypes.submit, + topTouchCancel: eventTypes.touchCancel, + topTouchEnd: eventTypes.touchEnd, + topTouchMove: eventTypes.touchMove, + topTouchStart: eventTypes.touchStart, + topWheel: eventTypes.wheel +}; + +var SimpleEventPlugin = { + + eventTypes: eventTypes, /** * Same as the default implementation, except cancels the event when return * value is false. * - * @param {AbstractEvent} AbstractEvent to handle - * @param {function} Application-level callback - * @param {string} domID DOM id to pass to the callback. + * @param {object} Event to be dispatched. + * @param {function} Application-level callback. + * @param {string} domID DOM ID to pass to the callback. */ - executeDispatch: function(abstractEvent, listener, domID) { - var returnValue = listener(abstractEvent, domID); + executeDispatch: function(event, listener, domID) { + var returnValue = listener(event, domID); if (returnValue === false) { - abstractEvent.stopPropagation(); - abstractEvent.preventDefault(); + event.stopPropagation(); + event.preventDefault(); } }, @@ -221,7 +257,7 @@ var SimpleEventPlugin = { * @param {DOMEventTarget} topLevelTarget The listening component root node. * @param {string} topLevelTargetID ID of `topLevelTarget`. * @param {object} nativeEvent Native browser event. - * @return {*} An accumulation of `AbstractEvent`s. + * @return {*} An accumulation of synthetic events. * @see {EventPluginHub.extractEvents} */ extractEvents: function( @@ -229,29 +265,30 @@ var SimpleEventPlugin = { topLevelTarget, topLevelTargetID, nativeEvent) { - var data; - var abstractEventType = - SimpleEventPlugin.topLevelTypesToAbstract[topLevelType]; - if (!abstractEventType) { + var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType]; + if (!dispatchConfig) { return null; } + var EventConstructor; switch(topLevelType) { - case topLevelTypes.topWheel: - data = AbstractEvent.normalizeMouseWheelData(nativeEvent); + case topLevelTypes.topChange: + case topLevelTypes.topInput: + case topLevelTypes.topSubmit: + // HTML Events + // @see http://www.w3.org/TR/html5/index.html#events-0 + EventConstructor = SyntheticEvent; break; - case topLevelTypes.topScroll: - data = AbstractEvent.normalizeScrollDataFromTarget(topLevelTarget); + case topLevelTypes.topKeyDown: + case topLevelTypes.topKeyPress: + case topLevelTypes.topKeyUp: + EventConstructor = SyntheticKeyboardEvent; + break; + case topLevelTypes.topBlur: + case topLevelTypes.topFocus: + EventConstructor = SyntheticFocusEvent; break; case topLevelTypes.topClick: case topLevelTypes.topDoubleClick: - case topLevelTypes.topChange: - case topLevelTypes.topDOMCharacterDataModified: - case topLevelTypes.topMouseDown: - case topLevelTypes.topMouseUp: - case topLevelTypes.topMouseMove: - case topLevelTypes.topTouchMove: - case topLevelTypes.topTouchStart: - case topLevelTypes.topTouchEnd: case topLevelTypes.topDrag: case topLevelTypes.topDragEnd: case topLevelTypes.topDragEnter: @@ -260,53 +297,41 @@ var SimpleEventPlugin = { case topLevelTypes.topDragOver: case topLevelTypes.topDragStart: case topLevelTypes.topDrop: - data = AbstractEvent.normalizePointerData(nativeEvent); - // todo: Use AbstractEvent.normalizeDragEventData for drag/drop? + case topLevelTypes.topMouseDown: + case topLevelTypes.topMouseMove: + case topLevelTypes.topMouseUp: + EventConstructor = SyntheticMouseEvent; + break; + case topLevelTypes.topDOMCharacterDataModified: + EventConstructor = SyntheticMutationEvent; + break; + case topLevelTypes.topTouchCancel: + case topLevelTypes.topTouchEnd: + case topLevelTypes.topTouchMove: + case topLevelTypes.topTouchStart: + EventConstructor = SyntheticTouchEvent; + break; + case topLevelTypes.topScroll: + EventConstructor = SyntheticUIEvent; + break; + case topLevelTypes.topWheel: + EventConstructor = SyntheticWheelEvent; break; - default: - data = null; } - var abstractEvent = AbstractEvent.getPooled( - abstractEventType, - topLevelTargetID, - nativeEvent, - data + invariant( + EventConstructor, + 'SimpleEventPlugin: Unhandled event type, `%s`.', + topLevelType ); - EventPropagators.accumulateTwoPhaseDispatches(abstractEvent); - return abstractEvent; + var event = EventConstructor.getPooled( + dispatchConfig, + topLevelTargetID, + nativeEvent + ); + EventPropagators.accumulateTwoPhaseDispatches(event); + return event; } -}; -SimpleEventPlugin.topLevelTypesToAbstract = { - topMouseDown: SimpleEventPlugin.abstractEventTypes.mouseDown, - topMouseUp: SimpleEventPlugin.abstractEventTypes.mouseUp, - topMouseMove: SimpleEventPlugin.abstractEventTypes.mouseMove, - topClick: SimpleEventPlugin.abstractEventTypes.click, - topDoubleClick: SimpleEventPlugin.abstractEventTypes.doubleClick, - topWheel: SimpleEventPlugin.abstractEventTypes.wheel, - topTouchStart: SimpleEventPlugin.abstractEventTypes.touchStart, - topTouchEnd: SimpleEventPlugin.abstractEventTypes.touchEnd, - topTouchMove: SimpleEventPlugin.abstractEventTypes.touchMove, - topTouchCancel: SimpleEventPlugin.abstractEventTypes.touchCancel, - topKeyUp: SimpleEventPlugin.abstractEventTypes.keyUp, - topKeyPress: SimpleEventPlugin.abstractEventTypes.keyPress, - topKeyDown: SimpleEventPlugin.abstractEventTypes.keyDown, - topInput: SimpleEventPlugin.abstractEventTypes.input, - topFocus: SimpleEventPlugin.abstractEventTypes.focus, - topBlur: SimpleEventPlugin.abstractEventTypes.blur, - topScroll: SimpleEventPlugin.abstractEventTypes.scroll, - topChange: SimpleEventPlugin.abstractEventTypes.change, - topSubmit: SimpleEventPlugin.abstractEventTypes.submit, - topDOMCharacterDataModified: - SimpleEventPlugin.abstractEventTypes.DOMCharacterDataModified, - topDrag: SimpleEventPlugin.abstractEventTypes.drag, - topDragEnd: SimpleEventPlugin.abstractEventTypes.dragEnd, - topDragEnter: SimpleEventPlugin.abstractEventTypes.dragEnter, - topDragExit: SimpleEventPlugin.abstractEventTypes.dragExit, - topDragLeave: SimpleEventPlugin.abstractEventTypes.dragLeave, - topDragOver: SimpleEventPlugin.abstractEventTypes.dragOver, - topDragStart: SimpleEventPlugin.abstractEventTypes.dragStart, - topDrop: SimpleEventPlugin.abstractEventTypes.drop }; module.exports = SimpleEventPlugin; diff --git a/src/eventPlugins/TapEventPlugin.js b/src/eventPlugins/TapEventPlugin.js index c36732881a..03293eaf16 100644 --- a/src/eventPlugins/TapEventPlugin.js +++ b/src/eventPlugins/TapEventPlugin.js @@ -19,25 +19,49 @@ "use strict"; -var AbstractEvent = require('AbstractEvent'); +var BrowserEnv = require('BrowserEnv'); var EventPluginUtils = require('EventPluginUtils'); var EventPropagators = require('EventPropagators'); +var SyntheticUIEvent = require('SyntheticUIEvent'); +var TouchEventUtils = require('TouchEventUtils'); var keyOf = require('keyOf'); var isStartish = EventPluginUtils.isStartish; var isEndish = EventPluginUtils.isEndish; -var storePageCoordsIn = EventPluginUtils.storePageCoordsIn; -var eventDistance = EventPluginUtils.eventDistance; /** - * The number of pixels that are tolerated in between a touchStart and - * touchEnd in order to still be considered a 'tap' event. + * Number of pixels that are tolerated in between a `touchStart` and `touchEnd` + * in order to still be considered a 'tap' event. */ var tapMoveThreshold = 10; var startCoords = {x: null, y: null}; -var abstractEventTypes = { +var Axis = { + x: {page: 'pageX', client: 'clientX', envScroll: 'currentPageScrollLeft'}, + y: {page: 'pageY', client: 'clientY', envScroll: 'currentPageScrollTop'} +}; + +function getAxisCoordOfEvent(axis, nativeEvent) { + var singleTouch = TouchEventUtils.extractSingleTouch(nativeEvent); + if (singleTouch) { + return singleTouch[axis.page]; + } + return axis.page in nativeEvent ? + nativeEvent[axis.page] : + nativeEvent[axis.client] + BrowserEnv[axis.envScroll]; +} + +function getDistance(coords, nativeEvent) { + var pageX = getAxisCoordOfEvent(Axis.x, nativeEvent); + var pageY = getAxisCoordOfEvent(Axis.y, nativeEvent); + return Math.pow( + Math.pow(pageX - coords.x, 2) + Math.pow(pageY - coords.y, 2), + 0.5 + ); +} + +var eventTypes = { touchTap: { phasedRegistrationNames: { bubbled: keyOf({onTouchTap: null}), @@ -46,46 +70,48 @@ var abstractEventTypes = { } }; -/** - * @param {string} topLevelType Record from `EventConstants`. - * @param {DOMEventTarget} topLevelTarget The listening component root node. - * @param {string} topLevelTargetID ID of `topLevelTarget`. - * @param {object} nativeEvent Native browser event. - * @return {*} An accumulation of `AbstractEvent`s. - * @see {EventPluginHub.extractEvents} - */ -var extractEvents = function( - topLevelType, - topLevelTarget, - topLevelTargetID, - nativeEvent) { - if (!isStartish(topLevelType) && !isEndish(topLevelType)) { - return; - } - var abstractEvent; - var dist = eventDistance(startCoords, nativeEvent); - if (isEndish(topLevelType) && dist < tapMoveThreshold) { - abstractEvent = AbstractEvent.getPooled( - abstractEventTypes.touchTap, - topLevelTargetID, - nativeEvent - ); - } - if (isStartish(topLevelType)) { - storePageCoordsIn(startCoords, nativeEvent); - } else if (isEndish(topLevelType)) { - startCoords.x = 0; - startCoords.y = 0; - } - EventPropagators.accumulateTwoPhaseDispatches(abstractEvent); - return abstractEvent; -}; - var TapEventPlugin = { + tapMoveThreshold: tapMoveThreshold, - startCoords: startCoords, - abstractEventTypes: abstractEventTypes, - extractEvents: extractEvents + + eventTypes: eventTypes, + + /** + * @param {string} topLevelType Record from `EventConstants`. + * @param {DOMEventTarget} topLevelTarget The listening component root node. + * @param {string} topLevelTargetID ID of `topLevelTarget`. + * @param {object} nativeEvent Native browser event. + * @return {*} An accumulation of synthetic events. + * @see {EventPluginHub.extractEvents} + */ + extractEvents: function( + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent) { + if (!isStartish(topLevelType) && !isEndish(topLevelType)) { + return null; + } + var event = null; + var distance = getDistance(startCoords, nativeEvent); + if (isEndish(topLevelType) && distance < tapMoveThreshold) { + event = SyntheticUIEvent.getPooled( + eventTypes.touchTap, + topLevelTargetID, + nativeEvent + ); + } + if (isStartish(topLevelType)) { + startCoords.x = getAxisCoordOfEvent(Axis.x, nativeEvent); + startCoords.y = getAxisCoordOfEvent(Axis.y, nativeEvent); + } else if (isEndish(topLevelType)) { + startCoords.x = 0; + startCoords.y = 0; + } + EventPropagators.accumulateTwoPhaseDispatches(event); + return event; + } + }; module.exports = TapEventPlugin; diff --git a/src/eventPlugins/TextChangeEventPlugin.js b/src/eventPlugins/TextChangeEventPlugin.js index ced2eb1093..1502c38098 100644 --- a/src/eventPlugins/TextChangeEventPlugin.js +++ b/src/eventPlugins/TextChangeEventPlugin.js @@ -18,18 +18,18 @@ "use strict"; -var AbstractEvent = require('AbstractEvent'); var EventConstants = require('EventConstants'); var EventPluginHub = require('EventPluginHub'); var EventPropagators = require('EventPropagators'); var ExecutionEnvironment = require('ExecutionEnvironment'); +var SyntheticEvent = require('SyntheticEvent'); var isEventSupported = require('isEventSupported'); var keyOf = require('keyOf'); var topLevelTypes = EventConstants.topLevelTypes; -var abstractEventTypes = { +var eventTypes = { textChange: { phasedRegistrationNames: { bubbled: keyOf({onTextChange: null}), @@ -121,29 +121,28 @@ var stopWatching = function() { * the value of the active element has changed. */ var handlePropertyChange = function(nativeEvent) { - var value; - var abstractEvent; - - if (nativeEvent.propertyName === "value") { - value = nativeEvent.srcElement.value; - if (value !== activeElementValue) { - activeElementValue = value; - - abstractEvent = AbstractEvent.getPooled( - abstractEventTypes.textChange, - activeElementID, - nativeEvent - ); - EventPropagators.accumulateTwoPhaseDispatches(abstractEvent); - - // If propertychange bubbled, we'd just bind to it like all the other - // events and have it go through ReactEventTopLevelCallback. Since it - // doesn't, we manually listen for the propertychange event and so we - // have to enqueue and process the abstract event manually. - EventPluginHub.enqueueEvents(abstractEvent); - EventPluginHub.processEventQueue(); - } + if (nativeEvent.propertyName !== "value") { + return; } + var value = nativeEvent.srcElement.value; + if (value === activeElementValue) { + return; + } + activeElementValue = value; + + var event = SyntheticEvent.getPooled( + eventTypes.textChange, + activeElementID, + nativeEvent + ); + EventPropagators.accumulateTwoPhaseDispatches(event); + + // If propertychange bubbled, we'd just bind to it like all the other events + // and have it go through ReactEventTopLevelCallback. Since it doesn't, we + // manually listen for the propertychange event and so we have to enqueue and + // process the abstract event manually. + EventPluginHub.enqueueEvents(event); + EventPluginHub.processEventQueue(); }; /** @@ -154,8 +153,7 @@ if (isInputSupported) { targetIDForTextChangeEvent = function( topLevelType, topLevelTarget, - topLevelTargetID, - nativeEvent) { + topLevelTargetID) { if (topLevelType === topLevelTypes.topInput) { // In modern browsers (i.e., not IE8 or IE9), the input event is exactly // what we want so fall through here and trigger an abstract event... @@ -171,8 +169,7 @@ if (isInputSupported) { targetIDForTextChangeEvent = function( topLevelType, topLevelTarget, - topLevelTargetID, - nativeEvent) { + topLevelTargetID) { if (topLevelType === topLevelTypes.topFocus) { // In IE8, we can capture almost all .value changes by adding a // propertychange handler and looking for events with propertyName @@ -214,40 +211,40 @@ if (isInputSupported) { }; } -/** - * @param {string} topLevelType Record from `EventConstants`. - * @param {DOMEventTarget} topLevelTarget The listening component root node. - * @param {string} topLevelTargetID ID of `topLevelTarget`. - * @param {object} nativeEvent Native browser event. - * @return {*} An accumulation of `AbstractEvent`s. - * @see {EventPluginHub.extractEvents} - */ -var extractEvents = function( - topLevelType, - topLevelTarget, - topLevelTargetID, - nativeEvent) { - var targetID = targetIDForTextChangeEvent( - topLevelType, - topLevelTarget, - topLevelTargetID, - nativeEvent - ); - - if (targetID) { - var abstractEvent = AbstractEvent.getPooled( - abstractEventTypes.textChange, - targetID, - nativeEvent - ); - EventPropagators.accumulateTwoPhaseDispatches(abstractEvent); - return abstractEvent; - } -}; - var TextChangeEventPlugin = { - abstractEventTypes: abstractEventTypes, - extractEvents: extractEvents + + eventTypes: eventTypes, + + /** + * @param {string} topLevelType Record from `EventConstants`. + * @param {DOMEventTarget} topLevelTarget The listening component root node. + * @param {string} topLevelTargetID ID of `topLevelTarget`. + * @param {object} nativeEvent Native browser event. + * @return {*} An accumulation of synthetic events. + * @see {EventPluginHub.extractEvents} + */ + extractEvents: function( + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent) { + var targetID = targetIDForTextChangeEvent( + topLevelType, + topLevelTarget, + topLevelTargetID + ); + + if (targetID) { + var event = SyntheticEvent.getPooled( + eventTypes.textChange, + targetID, + nativeEvent + ); + EventPropagators.accumulateTwoPhaseDispatches(event); + return event; + } + } + }; module.exports = TextChangeEventPlugin; diff --git a/src/eventPlugins/__tests__/ResponderEventPlugin-test.js b/src/eventPlugins/__tests__/ResponderEventPlugin-test.js index baec2ae60a..6917e6e8b7 100644 --- a/src/eventPlugins/__tests__/ResponderEventPlugin-test.js +++ b/src/eventPlugins/__tests__/ResponderEventPlugin-test.js @@ -23,21 +23,21 @@ var EventConstants; var EventPropagators; var ReactInstanceHandles; var ResponderEventPlugin; -var AbstractEvent; +var SyntheticEvent; var GRANDPARENT_ID = '.reactRoot[0]'; var PARENT_ID = '.reactRoot[0].0'; var CHILD_ID = '.reactRoot[0].0.0'; var topLevelTypes; -var responderAbstractEventTypes; +var responderEventTypes; var spies; var DUMMY_NATIVE_EVENT = {}; var DUMMY_RENDERED_TARGET = {}; var onStartShouldSetResponder = function(id, cb, capture) { - var registrationNames = responderAbstractEventTypes + var registrationNames = responderEventTypes .startShouldSetResponder .phasedRegistrationNames; CallbackRegistry.putListener( @@ -48,7 +48,7 @@ var onStartShouldSetResponder = function(id, cb, capture) { }; var onScrollShouldSetResponder = function(id, cb, capture) { - var registrationNames = responderAbstractEventTypes + var registrationNames = responderEventTypes .scrollShouldSetResponder .phasedRegistrationNames; CallbackRegistry.putListener( @@ -59,7 +59,7 @@ var onScrollShouldSetResponder = function(id, cb, capture) { }; var onMoveShouldSetResponder = function(id, cb, capture) { - var registrationNames = responderAbstractEventTypes + var registrationNames = responderEventTypes .moveShouldSetResponder .phasedRegistrationNames; CallbackRegistry.putListener( @@ -73,7 +73,7 @@ var onMoveShouldSetResponder = function(id, cb, capture) { var onResponderGrant = function(id, cb) { CallbackRegistry.putListener( id, - responderAbstractEventTypes.responderGrant.registrationName, + responderEventTypes.responderGrant.registrationName, cb ); }; @@ -165,44 +165,40 @@ var existsInExtraction = function(extracted, test) { * Helper validators. */ function assertGrantEvent(id, extracted) { - var test = function(abstractEvent) { - return abstractEvent instanceof AbstractEvent && - abstractEvent.reactEventType === - responderAbstractEventTypes.responderGrant && - abstractEvent.reactTargetID === id; + var test = function(event) { + return event instanceof SyntheticEvent && + event.dispatchConfig === responderEventTypes.responderGrant && + event.dispatchMarker === id; }; expect(ResponderEventPlugin.getResponderID()).toBe(id); expect(existsInExtraction(extracted, test)).toBe(true); } function assertResponderMoveEvent(id, extracted) { - var test = function(abstractEvent) { - return abstractEvent instanceof AbstractEvent && - abstractEvent.reactEventType === - responderAbstractEventTypes.responderMove && - abstractEvent.reactTargetID === id; + var test = function(event) { + return event instanceof SyntheticEvent && + event.dispatchConfig === responderEventTypes.responderMove && + event.dispatchMarker === id; }; expect(ResponderEventPlugin.getResponderID()).toBe(id); expect(existsInExtraction(extracted, test)).toBe(true); } function assertTerminateEvent(id, extracted) { - var test = function(abstractEvent) { - return abstractEvent instanceof AbstractEvent && - abstractEvent.reactEventType === - responderAbstractEventTypes.responderTerminate && - abstractEvent.reactTargetID === id; + var test = function(event) { + return event instanceof SyntheticEvent && + event.dispatchConfig === responderEventTypes.responderTerminate && + event.dispatchMarker === id; }; expect(ResponderEventPlugin.getResponderID()).not.toBe(id); expect(existsInExtraction(extracted, test)).toBe(true); } function assertRelease(id, extracted) { - var test = function(abstractEvent) { - return abstractEvent instanceof AbstractEvent && - abstractEvent.reactEventType === - responderAbstractEventTypes.responderRelease && - abstractEvent.reactTargetID === id; + var test = function(event) { + return event instanceof SyntheticEvent && + event.dispatchConfig === responderEventTypes.responderRelease && + event.dispatchMarker === id; }; expect(ResponderEventPlugin.getResponderID()).toBe(null); expect(existsInExtraction(extracted, test)).toBe(true); @@ -226,12 +222,12 @@ describe('ResponderEventPlugin', function() { beforeEach(function() { require('mock-modules').dumpCache(); - AbstractEvent = require('AbstractEvent'); CallbackRegistry = require('CallbackRegistry'); EventConstants = require('EventConstants'); EventPropagators = require('EventPropagators'); ReactInstanceHandles = require('ReactInstanceHandles'); ResponderEventPlugin = require('ResponderEventPlugin'); + SyntheticEvent = require('SyntheticEvent'); EventPropagators.injection.injectInstanceHandle(ReactInstanceHandles); // dumpCache, in open-source tests, only resets existing mocks. It does not @@ -240,7 +236,7 @@ describe('ResponderEventPlugin', function() { CallbackRegistry.__purge(); topLevelTypes = EventConstants.topLevelTypes; - responderAbstractEventTypes = ResponderEventPlugin.abstractEventTypes; + responderEventTypes = ResponderEventPlugin.eventTypes; spies = { onStartShouldSetResponderChild: function() {}, diff --git a/src/test/ReactTestUtils.js b/src/test/ReactTestUtils.js index a3520ede64..95651d5c90 100644 --- a/src/test/ReactTestUtils.js +++ b/src/test/ReactTestUtils.js @@ -187,7 +187,7 @@ var ReactTestUtils = { * on and `Element` node. * @param topLevelType {Object} A type from `EventConstants.topLevelTypes` * @param {!Element} node The dom to simulate an event occurring on. - * @param {?Event} fakeNativeEvent Fake native event to pass to ReactEvent. + * @param {?Event} fakeNativeEvent Fake native event to use in SyntheticEvent. */ simulateEventOnNode: function(topLevelType, node, fakeNativeEvent) { var virtualHandler = @@ -203,7 +203,7 @@ var ReactTestUtils = { * on the `ReactNativeComponent` `comp`. * @param topLevelType {Object} A type from `EventConstants.topLevelTypes`. * @param comp {!ReactNativeComponent} - * @param {?Event} fakeNativeEvent Fake native event to pass to ReactEvent. + * @param {?Event} fakeNativeEvent Fake native event to use in SyntheticEvent. */ simulateEventOnDOMComponent: function(topLevelType, comp, fakeNativeEvent) { var reactRootID = comp._rootNodeID || comp._rootDomId; @@ -280,7 +280,7 @@ for (eventType in topLevelTypes) { eventType.charAt(3).toLowerCase() + eventType.substr(4) : eventType; /** * @param {!Element || ReactNativeComponent} domComponentOrNode - * @param {?Event} nativeEventData Fake native event to pass to ReactEvent. + * @param {?Event} nativeEventData Fake native event to use in SyntheticEvent. */ ReactTestUtils.Simulate[convenienceName] = makeSimulator(eventType); }