Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80536 views
1
/**
2
* Copyright 2013-2015, Facebook, Inc.
3
* All rights reserved.
4
*
5
* This source code is licensed under the BSD-style license found in the
6
* LICENSE file in the root directory of this source tree. An additional grant
7
* of patent rights can be found in the PATENTS file in the same directory.
8
*
9
* @providesModule EventPluginUtils
10
*/
11
12
'use strict';
13
14
var EventConstants = require("./EventConstants");
15
16
var invariant = require("./invariant");
17
18
/**
19
* Injected dependencies:
20
*/
21
22
/**
23
* - `Mount`: [required] Module that can convert between React dom IDs and
24
* actual node references.
25
*/
26
var injection = {
27
Mount: null,
28
injectMount: function(InjectedMount) {
29
injection.Mount = InjectedMount;
30
if ("production" !== process.env.NODE_ENV) {
31
("production" !== process.env.NODE_ENV ? invariant(
32
InjectedMount && InjectedMount.getNode,
33
'EventPluginUtils.injection.injectMount(...): Injected Mount module ' +
34
'is missing getNode.'
35
) : invariant(InjectedMount && InjectedMount.getNode));
36
}
37
}
38
};
39
40
var topLevelTypes = EventConstants.topLevelTypes;
41
42
function isEndish(topLevelType) {
43
return topLevelType === topLevelTypes.topMouseUp ||
44
topLevelType === topLevelTypes.topTouchEnd ||
45
topLevelType === topLevelTypes.topTouchCancel;
46
}
47
48
function isMoveish(topLevelType) {
49
return topLevelType === topLevelTypes.topMouseMove ||
50
topLevelType === topLevelTypes.topTouchMove;
51
}
52
function isStartish(topLevelType) {
53
return topLevelType === topLevelTypes.topMouseDown ||
54
topLevelType === topLevelTypes.topTouchStart;
55
}
56
57
58
var validateEventDispatches;
59
if ("production" !== process.env.NODE_ENV) {
60
validateEventDispatches = function(event) {
61
var dispatchListeners = event._dispatchListeners;
62
var dispatchIDs = event._dispatchIDs;
63
64
var listenersIsArr = Array.isArray(dispatchListeners);
65
var idsIsArr = Array.isArray(dispatchIDs);
66
var IDsLen = idsIsArr ? dispatchIDs.length : dispatchIDs ? 1 : 0;
67
var listenersLen = listenersIsArr ?
68
dispatchListeners.length :
69
dispatchListeners ? 1 : 0;
70
71
("production" !== process.env.NODE_ENV ? invariant(
72
idsIsArr === listenersIsArr && IDsLen === listenersLen,
73
'EventPluginUtils: Invalid `event`.'
74
) : invariant(idsIsArr === listenersIsArr && IDsLen === listenersLen));
75
};
76
}
77
78
/**
79
* Invokes `cb(event, listener, id)`. Avoids using call if no scope is
80
* provided. The `(listener,id)` pair effectively forms the "dispatch" but are
81
* kept separate to conserve memory.
82
*/
83
function forEachEventDispatch(event, cb) {
84
var dispatchListeners = event._dispatchListeners;
85
var dispatchIDs = event._dispatchIDs;
86
if ("production" !== process.env.NODE_ENV) {
87
validateEventDispatches(event);
88
}
89
if (Array.isArray(dispatchListeners)) {
90
for (var i = 0; i < dispatchListeners.length; i++) {
91
if (event.isPropagationStopped()) {
92
break;
93
}
94
// Listeners and IDs are two parallel arrays that are always in sync.
95
cb(event, dispatchListeners[i], dispatchIDs[i]);
96
}
97
} else if (dispatchListeners) {
98
cb(event, dispatchListeners, dispatchIDs);
99
}
100
}
101
102
/**
103
* Default implementation of PluginModule.executeDispatch().
104
* @param {SyntheticEvent} SyntheticEvent to handle
105
* @param {function} Application-level callback
106
* @param {string} domID DOM id to pass to the callback.
107
*/
108
function executeDispatch(event, listener, domID) {
109
event.currentTarget = injection.Mount.getNode(domID);
110
var returnValue = listener(event, domID);
111
event.currentTarget = null;
112
return returnValue;
113
}
114
115
/**
116
* Standard/simple iteration through an event's collected dispatches.
117
*/
118
function executeDispatchesInOrder(event, cb) {
119
forEachEventDispatch(event, cb);
120
event._dispatchListeners = null;
121
event._dispatchIDs = null;
122
}
123
124
/**
125
* Standard/simple iteration through an event's collected dispatches, but stops
126
* at the first dispatch execution returning true, and returns that id.
127
*
128
* @return id of the first dispatch execution who's listener returns true, or
129
* null if no listener returned true.
130
*/
131
function executeDispatchesInOrderStopAtTrueImpl(event) {
132
var dispatchListeners = event._dispatchListeners;
133
var dispatchIDs = event._dispatchIDs;
134
if ("production" !== process.env.NODE_ENV) {
135
validateEventDispatches(event);
136
}
137
if (Array.isArray(dispatchListeners)) {
138
for (var i = 0; i < dispatchListeners.length; i++) {
139
if (event.isPropagationStopped()) {
140
break;
141
}
142
// Listeners and IDs are two parallel arrays that are always in sync.
143
if (dispatchListeners[i](event, dispatchIDs[i])) {
144
return dispatchIDs[i];
145
}
146
}
147
} else if (dispatchListeners) {
148
if (dispatchListeners(event, dispatchIDs)) {
149
return dispatchIDs;
150
}
151
}
152
return null;
153
}
154
155
/**
156
* @see executeDispatchesInOrderStopAtTrueImpl
157
*/
158
function executeDispatchesInOrderStopAtTrue(event) {
159
var ret = executeDispatchesInOrderStopAtTrueImpl(event);
160
event._dispatchIDs = null;
161
event._dispatchListeners = null;
162
return ret;
163
}
164
165
/**
166
* Execution of a "direct" dispatch - there must be at most one dispatch
167
* accumulated on the event or it is considered an error. It doesn't really make
168
* sense for an event with multiple dispatches (bubbled) to keep track of the
169
* return values at each dispatch execution, but it does tend to make sense when
170
* dealing with "direct" dispatches.
171
*
172
* @return The return value of executing the single dispatch.
173
*/
174
function executeDirectDispatch(event) {
175
if ("production" !== process.env.NODE_ENV) {
176
validateEventDispatches(event);
177
}
178
var dispatchListener = event._dispatchListeners;
179
var dispatchID = event._dispatchIDs;
180
("production" !== process.env.NODE_ENV ? invariant(
181
!Array.isArray(dispatchListener),
182
'executeDirectDispatch(...): Invalid `event`.'
183
) : invariant(!Array.isArray(dispatchListener)));
184
var res = dispatchListener ?
185
dispatchListener(event, dispatchID) :
186
null;
187
event._dispatchListeners = null;
188
event._dispatchIDs = null;
189
return res;
190
}
191
192
/**
193
* @param {SyntheticEvent} event
194
* @return {bool} True iff number of dispatches accumulated is greater than 0.
195
*/
196
function hasDispatches(event) {
197
return !!event._dispatchListeners;
198
}
199
200
/**
201
* General utilities that are useful in creating custom Event Plugins.
202
*/
203
var EventPluginUtils = {
204
isEndish: isEndish,
205
isMoveish: isMoveish,
206
isStartish: isStartish,
207
208
executeDirectDispatch: executeDirectDispatch,
209
executeDispatch: executeDispatch,
210
executeDispatchesInOrder: executeDispatchesInOrder,
211
executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue,
212
hasDispatches: hasDispatches,
213
injection: injection,
214
useTouchEvents: false
215
};
216
217
module.exports = EventPluginUtils;
218
219