You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
6.6 KiB
217 lines
6.6 KiB
/** |
|
* Copyright 2013-2015, Facebook, Inc. |
|
* All rights reserved. |
|
* |
|
* This source code is licensed under the BSD-style license found in the |
|
* LICENSE file in the root directory of this source tree. An additional grant |
|
* of patent rights can be found in the PATENTS file in the same directory. |
|
* |
|
* @providesModule EventPluginUtils |
|
*/ |
|
|
|
'use strict'; |
|
|
|
var EventConstants = require("./EventConstants"); |
|
|
|
var invariant = require("./invariant"); |
|
|
|
/** |
|
* Injected dependencies: |
|
*/ |
|
|
|
/** |
|
* - `Mount`: [required] Module that can convert between React dom IDs and |
|
* actual node references. |
|
*/ |
|
var injection = { |
|
Mount: null, |
|
injectMount: function(InjectedMount) { |
|
injection.Mount = InjectedMount; |
|
if ("production" !== process.env.NODE_ENV) { |
|
("production" !== process.env.NODE_ENV ? invariant( |
|
InjectedMount && InjectedMount.getNode, |
|
'EventPluginUtils.injection.injectMount(...): Injected Mount module ' + |
|
'is missing getNode.' |
|
) : invariant(InjectedMount && InjectedMount.getNode)); |
|
} |
|
} |
|
}; |
|
|
|
var topLevelTypes = EventConstants.topLevelTypes; |
|
|
|
function isEndish(topLevelType) { |
|
return topLevelType === topLevelTypes.topMouseUp || |
|
topLevelType === topLevelTypes.topTouchEnd || |
|
topLevelType === topLevelTypes.topTouchCancel; |
|
} |
|
|
|
function isMoveish(topLevelType) { |
|
return topLevelType === topLevelTypes.topMouseMove || |
|
topLevelType === topLevelTypes.topTouchMove; |
|
} |
|
function isStartish(topLevelType) { |
|
return topLevelType === topLevelTypes.topMouseDown || |
|
topLevelType === topLevelTypes.topTouchStart; |
|
} |
|
|
|
|
|
var validateEventDispatches; |
|
if ("production" !== process.env.NODE_ENV) { |
|
validateEventDispatches = function(event) { |
|
var dispatchListeners = event._dispatchListeners; |
|
var dispatchIDs = event._dispatchIDs; |
|
|
|
var listenersIsArr = Array.isArray(dispatchListeners); |
|
var idsIsArr = Array.isArray(dispatchIDs); |
|
var IDsLen = idsIsArr ? dispatchIDs.length : dispatchIDs ? 1 : 0; |
|
var listenersLen = listenersIsArr ? |
|
dispatchListeners.length : |
|
dispatchListeners ? 1 : 0; |
|
|
|
("production" !== process.env.NODE_ENV ? invariant( |
|
idsIsArr === listenersIsArr && IDsLen === listenersLen, |
|
'EventPluginUtils: Invalid `event`.' |
|
) : invariant(idsIsArr === listenersIsArr && IDsLen === listenersLen)); |
|
}; |
|
} |
|
|
|
/** |
|
* 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(event, cb) { |
|
var dispatchListeners = event._dispatchListeners; |
|
var dispatchIDs = event._dispatchIDs; |
|
if ("production" !== process.env.NODE_ENV) { |
|
validateEventDispatches(event); |
|
} |
|
if (Array.isArray(dispatchListeners)) { |
|
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(event, dispatchListeners[i], dispatchIDs[i]); |
|
} |
|
} else if (dispatchListeners) { |
|
cb(event, dispatchListeners, dispatchIDs); |
|
} |
|
} |
|
|
|
/** |
|
* Default implementation of PluginModule.executeDispatch(). |
|
* @param {SyntheticEvent} SyntheticEvent to handle |
|
* @param {function} Application-level callback |
|
* @param {string} domID DOM id to pass to the callback. |
|
*/ |
|
function executeDispatch(event, listener, domID) { |
|
event.currentTarget = injection.Mount.getNode(domID); |
|
var returnValue = listener(event, domID); |
|
event.currentTarget = null; |
|
return returnValue; |
|
} |
|
|
|
/** |
|
* Standard/simple iteration through an event's collected dispatches. |
|
*/ |
|
function executeDispatchesInOrder(event, cb) { |
|
forEachEventDispatch(event, cb); |
|
event._dispatchListeners = null; |
|
event._dispatchIDs = null; |
|
} |
|
|
|
/** |
|
* Standard/simple iteration through an event's collected dispatches, but stops |
|
* at the first dispatch execution returning true, and returns that id. |
|
* |
|
* @return id of the first dispatch execution who's listener returns true, or |
|
* null if no listener returned true. |
|
*/ |
|
function executeDispatchesInOrderStopAtTrueImpl(event) { |
|
var dispatchListeners = event._dispatchListeners; |
|
var dispatchIDs = event._dispatchIDs; |
|
if ("production" !== process.env.NODE_ENV) { |
|
validateEventDispatches(event); |
|
} |
|
if (Array.isArray(dispatchListeners)) { |
|
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](event, dispatchIDs[i])) { |
|
return dispatchIDs[i]; |
|
} |
|
} |
|
} else if (dispatchListeners) { |
|
if (dispatchListeners(event, dispatchIDs)) { |
|
return dispatchIDs; |
|
} |
|
} |
|
return null; |
|
} |
|
|
|
/** |
|
* @see executeDispatchesInOrderStopAtTrueImpl |
|
*/ |
|
function executeDispatchesInOrderStopAtTrue(event) { |
|
var ret = executeDispatchesInOrderStopAtTrueImpl(event); |
|
event._dispatchIDs = null; |
|
event._dispatchListeners = null; |
|
return ret; |
|
} |
|
|
|
/** |
|
* Execution of a "direct" dispatch - there must be at most one dispatch |
|
* accumulated on the event or it is considered an error. It doesn't really make |
|
* sense for an event with multiple dispatches (bubbled) to keep track of the |
|
* return values at each dispatch execution, but it does tend to make sense when |
|
* dealing with "direct" dispatches. |
|
* |
|
* @return The return value of executing the single dispatch. |
|
*/ |
|
function executeDirectDispatch(event) { |
|
if ("production" !== process.env.NODE_ENV) { |
|
validateEventDispatches(event); |
|
} |
|
var dispatchListener = event._dispatchListeners; |
|
var dispatchID = event._dispatchIDs; |
|
("production" !== process.env.NODE_ENV ? invariant( |
|
!Array.isArray(dispatchListener), |
|
'executeDirectDispatch(...): Invalid `event`.' |
|
) : invariant(!Array.isArray(dispatchListener))); |
|
var res = dispatchListener ? |
|
dispatchListener(event, dispatchID) : |
|
null; |
|
event._dispatchListeners = null; |
|
event._dispatchIDs = null; |
|
return res; |
|
} |
|
|
|
/** |
|
* @param {SyntheticEvent} event |
|
* @return {bool} True iff number of dispatches accumulated is greater than 0. |
|
*/ |
|
function hasDispatches(event) { |
|
return !!event._dispatchListeners; |
|
} |
|
|
|
/** |
|
* General utilities that are useful in creating custom Event Plugins. |
|
*/ |
|
var EventPluginUtils = { |
|
isEndish: isEndish, |
|
isMoveish: isMoveish, |
|
isStartish: isStartish, |
|
|
|
executeDirectDispatch: executeDirectDispatch, |
|
executeDispatch: executeDispatch, |
|
executeDispatchesInOrder: executeDispatchesInOrder, |
|
executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue, |
|
hasDispatches: hasDispatches, |
|
injection: injection, |
|
useTouchEvents: false |
|
}; |
|
|
|
module.exports = EventPluginUtils;
|
|
|