react 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/README.md +0 -8
  2. package/addons.js +0 -3
  3. package/lib/AutoFocusMixin.js +32 -0
  4. package/lib/CSSCore.js +23 -22
  5. package/lib/CSSProperty.js +32 -1
  6. package/lib/CSSPropertyOperations.js +1 -1
  7. package/lib/ChangeEventPlugin.js +27 -5
  8. package/lib/ClientReactRootIndex.js +30 -0
  9. package/lib/CompositionEventPlugin.js +58 -10
  10. package/lib/DOMChildrenOperations.js +39 -3
  11. package/lib/DOMProperty.js +9 -5
  12. package/lib/DOMPropertyOperations.js +21 -8
  13. package/lib/Danger.js +9 -8
  14. package/lib/DefaultDOMPropertyConfig.js +23 -14
  15. package/lib/DefaultEventPluginOrder.js +1 -1
  16. package/lib/EnterLeaveEventPlugin.js +38 -5
  17. package/lib/EventConstants.js +4 -1
  18. package/lib/EventListener.js +42 -34
  19. package/lib/EventPluginHub.js +118 -13
  20. package/lib/EventPluginRegistry.js +62 -18
  21. package/lib/EventPluginUtils.js +33 -4
  22. package/lib/EventPropagators.js +7 -43
  23. package/lib/ExecutionEnvironment.js +4 -1
  24. package/lib/LinkedStateMixin.js +1 -1
  25. package/lib/LinkedValueUtils.js +160 -0
  26. package/lib/MobileSafariClickEventPlugin.js +1 -1
  27. package/lib/PooledClass.js +7 -1
  28. package/lib/React.js +30 -4
  29. package/lib/ReactBrowserComponentMixin.js +42 -0
  30. package/lib/ReactCSSTransitionGroup.js +65 -0
  31. package/lib/{ReactTransitionableChild.js → ReactCSSTransitionGroupChild.js} +22 -36
  32. package/lib/ReactChildren.js +4 -4
  33. package/lib/ReactComponent.js +163 -83
  34. package/lib/ReactComponentBrowserEnvironment.js +55 -71
  35. package/lib/ReactCompositeComponent.js +686 -119
  36. package/lib/ReactContext.js +67 -0
  37. package/lib/ReactCurrentOwner.js +1 -1
  38. package/lib/ReactDOM.js +19 -6
  39. package/lib/ReactDOMButton.js +6 -1
  40. package/lib/ReactDOMComponent.js +66 -24
  41. package/lib/ReactDOMForm.js +13 -3
  42. package/lib/ReactDOMIDOperations.js +106 -61
  43. package/lib/ReactDOMImg.js +61 -0
  44. package/lib/ReactDOMInput.js +28 -15
  45. package/lib/ReactDOMOption.js +13 -8
  46. package/lib/ReactDOMSelect.js +38 -18
  47. package/lib/ReactDOMSelection.js +1 -1
  48. package/lib/ReactDOMTextarea.js +19 -11
  49. package/lib/ReactDefaultBatchingStrategy.js +1 -1
  50. package/lib/ReactDefaultInjection.js +60 -26
  51. package/lib/ReactDefaultPerf.js +208 -371
  52. package/lib/ReactDefaultPerfAnalysis.js +199 -0
  53. package/lib/ReactErrorUtils.js +6 -15
  54. package/lib/ReactEventEmitter.js +144 -146
  55. package/lib/ReactEventEmitterMixin.js +1 -33
  56. package/lib/ReactEventTopLevelCallback.js +75 -15
  57. package/lib/ReactInjection.js +43 -0
  58. package/lib/ReactInputSelection.js +3 -2
  59. package/lib/ReactInstanceHandles.js +36 -20
  60. package/lib/ReactLink.js +2 -2
  61. package/lib/ReactMarkupChecksum.js +1 -1
  62. package/lib/ReactMount.js +136 -104
  63. package/lib/ReactMountReady.js +2 -2
  64. package/lib/ReactMultiChild.js +40 -49
  65. package/lib/ReactMultiChildUpdateTypes.js +3 -1
  66. package/lib/ReactOwner.js +17 -4
  67. package/lib/ReactPerf.js +6 -9
  68. package/lib/ReactPropTransferer.js +41 -22
  69. package/lib/ReactPropTypeLocationNames.js +31 -0
  70. package/lib/{ReactComponentEnvironment.js → ReactPropTypeLocations.js} +11 -6
  71. package/lib/ReactPropTypes.js +249 -48
  72. package/lib/ReactPutListenerQueue.js +61 -0
  73. package/lib/ReactReconcileTransaction.js +28 -7
  74. package/lib/ReactRootIndex.js +36 -0
  75. package/lib/ReactServerRendering.js +46 -19
  76. package/lib/ReactServerRenderingTransaction.js +116 -0
  77. package/lib/ReactStateSetters.js +1 -1
  78. package/lib/ReactTestUtils.js +394 -0
  79. package/lib/ReactTextComponent.js +33 -6
  80. package/lib/{ReactTransitionKeySet.js → ReactTransitionChildMapping.js} +43 -48
  81. package/lib/ReactTransitionEvents.js +1 -1
  82. package/lib/ReactTransitionGroup.js +133 -58
  83. package/lib/ReactUpdates.js +15 -12
  84. package/lib/ReactWithAddons.js +15 -3
  85. package/lib/SelectEventPlugin.js +23 -40
  86. package/lib/ServerReactRootIndex.js +36 -0
  87. package/lib/SimpleEventPlugin.js +55 -7
  88. package/lib/SyntheticClipboardEvent.js +8 -2
  89. package/lib/SyntheticCompositionEvent.js +1 -1
  90. package/lib/SyntheticDragEvent.js +44 -0
  91. package/lib/SyntheticEvent.js +3 -2
  92. package/lib/SyntheticFocusEvent.js +1 -1
  93. package/lib/SyntheticKeyboardEvent.js +5 -3
  94. package/lib/SyntheticMouseEvent.js +1 -1
  95. package/lib/SyntheticTouchEvent.js +1 -1
  96. package/lib/SyntheticUIEvent.js +1 -1
  97. package/lib/SyntheticWheelEvent.js +11 -8
  98. package/lib/Transaction.js +62 -37
  99. package/lib/ViewportMetrics.js +1 -1
  100. package/lib/accumulate.js +1 -1
  101. package/lib/adler32.js +1 -1
  102. package/lib/cloneWithProps.js +59 -0
  103. package/lib/containsNode.js +1 -1
  104. package/lib/copyProperties.js +1 -1
  105. package/lib/createArrayFrom.js +11 -14
  106. package/lib/createFullPageComponent.js +63 -0
  107. package/lib/createNodesFromMarkup.js +1 -1
  108. package/lib/createObjectFrom.js +1 -1
  109. package/lib/cx.js +3 -3
  110. package/lib/dangerousStyleValue.js +1 -1
  111. package/lib/emptyFunction.js +1 -1
  112. package/lib/emptyObject.js +27 -0
  113. package/lib/escapeTextForBrowser.js +1 -1
  114. package/lib/flattenChildren.js +6 -3
  115. package/lib/focusNode.js +33 -0
  116. package/lib/forEachAccumulated.js +1 -1
  117. package/lib/getActiveElement.js +5 -4
  118. package/lib/getEventKey.js +85 -0
  119. package/lib/getEventTarget.js +1 -1
  120. package/lib/getMarkupWrap.js +11 -1
  121. package/lib/getNodeForCharacterOffset.js +1 -1
  122. package/lib/getReactRootElementInContainer.js +1 -1
  123. package/lib/getTextContentAccessor.js +6 -4
  124. package/lib/getUnboundedScrollPosition.js +3 -3
  125. package/lib/hyphenate.js +1 -1
  126. package/lib/instantiateReactComponent.js +70 -0
  127. package/lib/invariant.js +20 -12
  128. package/lib/isEventSupported.js +8 -12
  129. package/lib/isNode.js +2 -2
  130. package/lib/isTextInputElement.js +1 -1
  131. package/lib/isTextNode.js +1 -1
  132. package/lib/joinClasses.js +1 -1
  133. package/lib/keyMirror.js +1 -1
  134. package/lib/keyOf.js +1 -1
  135. package/lib/memoizeStringOnly.js +1 -1
  136. package/lib/merge.js +1 -1
  137. package/lib/mergeHelpers.js +6 -7
  138. package/lib/mergeInto.js +1 -1
  139. package/lib/mixInto.js +1 -1
  140. package/lib/monitorCodeUse.js +37 -0
  141. package/lib/objMap.js +1 -1
  142. package/lib/objMapKeyVal.js +1 -1
  143. package/lib/onlyChild.js +43 -0
  144. package/lib/performanceNow.js +1 -1
  145. package/lib/shallowEqual.js +1 -1
  146. package/lib/shouldUpdateReactComponent.js +61 -0
  147. package/lib/toArray.js +75 -0
  148. package/lib/traverseAllChildren.js +72 -9
  149. package/lib/update.js +159 -0
  150. package/lib/warning.js +48 -0
  151. package/package.json +3 -3
  152. package/react.js +0 -3
  153. package/ReactJSErrors.js +0 -40
  154. package/lib/$.js +0 -46
  155. package/lib/CallbackRegistry.js +0 -91
  156. package/lib/LinkedValueMixin.js +0 -68
  157. package/lib/ex.js +0 -49
  158. package/lib/filterAttributes.js +0 -45
  159. package/lib/ge.js +0 -76
  160. package/lib/mutateHTMLNodeWithMarkup.js +0 -100
@@ -0,0 +1,199 @@
1
+ /**
2
+ * Copyright 2013-2014 Facebook, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * @providesModule ReactDefaultPerfAnalysis
17
+ */
18
+
19
+ var merge = require("./merge");
20
+
21
+ // Don't try to save users less than 1.2ms (a number I made up)
22
+ var DONT_CARE_THRESHOLD = 1.2;
23
+ var DOM_OPERATION_TYPES = {
24
+ 'mountImageIntoNode': 'set innerHTML',
25
+ INSERT_MARKUP: 'set innerHTML',
26
+ MOVE_EXISTING: 'move',
27
+ REMOVE_NODE: 'remove',
28
+ TEXT_CONTENT: 'set textContent',
29
+ 'updatePropertyByID': 'update attribute',
30
+ 'deletePropertyByID': 'delete attribute',
31
+ 'updateStylesByID': 'update styles',
32
+ 'updateInnerHTMLByID': 'set innerHTML',
33
+ 'dangerouslyReplaceNodeWithMarkupByID': 'replace'
34
+ };
35
+
36
+ function getTotalTime(measurements) {
37
+ // TODO: return number of DOM ops? could be misleading.
38
+ // TODO: measure dropped frames after reconcile?
39
+ // TODO: log total time of each reconcile and the top-level component
40
+ // class that triggered it.
41
+ var totalTime = 0;
42
+ for (var i = 0; i < measurements.length; i++) {
43
+ var measurement = measurements[i];
44
+ totalTime += measurement.totalTime;
45
+ }
46
+ return totalTime;
47
+ }
48
+
49
+ function getDOMSummary(measurements) {
50
+ var items = [];
51
+ for (var i = 0; i < measurements.length; i++) {
52
+ var measurement = measurements[i];
53
+ var id;
54
+
55
+ for (id in measurement.writes) {
56
+ measurement.writes[id].forEach(function(write) {
57
+ items.push({
58
+ id: id,
59
+ type: DOM_OPERATION_TYPES[write.type] || write.type,
60
+ args: write.args
61
+ });
62
+ });
63
+ }
64
+ }
65
+ return items;
66
+ }
67
+
68
+ function getExclusiveSummary(measurements) {
69
+ var candidates = {};
70
+ var displayName;
71
+
72
+ for (var i = 0; i < measurements.length; i++) {
73
+ var measurement = measurements[i];
74
+ var allIDs = merge(measurement.exclusive, measurement.inclusive);
75
+
76
+ for (var id in allIDs) {
77
+ displayName = measurement.displayNames[id].current;
78
+
79
+ candidates[displayName] = candidates[displayName] || {
80
+ componentName: displayName,
81
+ inclusive: 0,
82
+ exclusive: 0,
83
+ count: 0
84
+ };
85
+ if (measurement.exclusive[id]) {
86
+ candidates[displayName].exclusive += measurement.exclusive[id];
87
+ }
88
+ if (measurement.inclusive[id]) {
89
+ candidates[displayName].inclusive += measurement.inclusive[id];
90
+ }
91
+ if (measurement.counts[id]) {
92
+ candidates[displayName].count += measurement.counts[id];
93
+ }
94
+ }
95
+ }
96
+
97
+ // Now make a sorted array with the results.
98
+ var arr = [];
99
+ for (displayName in candidates) {
100
+ if (candidates[displayName].exclusive >= DONT_CARE_THRESHOLD) {
101
+ arr.push(candidates[displayName]);
102
+ }
103
+ }
104
+
105
+ arr.sort(function(a, b) {
106
+ return b.exclusive - a.exclusive;
107
+ });
108
+
109
+ return arr;
110
+ }
111
+
112
+ function getInclusiveSummary(measurements, onlyClean) {
113
+ var candidates = {};
114
+ var inclusiveKey;
115
+
116
+ for (var i = 0; i < measurements.length; i++) {
117
+ var measurement = measurements[i];
118
+ var allIDs = merge(measurement.exclusive, measurement.inclusive);
119
+ var cleanComponents;
120
+
121
+ if (onlyClean) {
122
+ cleanComponents = getUnchangedComponents(measurement);
123
+ }
124
+
125
+ for (var id in allIDs) {
126
+ if (onlyClean && !cleanComponents[id]) {
127
+ continue;
128
+ }
129
+
130
+ var displayName = measurement.displayNames[id];
131
+
132
+ // Inclusive time is not useful for many components without knowing where
133
+ // they are instantiated. So we aggregate inclusive time with both the
134
+ // owner and current displayName as the key.
135
+ inclusiveKey = displayName.owner + ' > ' + displayName.current;
136
+
137
+ candidates[inclusiveKey] = candidates[inclusiveKey] || {
138
+ componentName: inclusiveKey,
139
+ time: 0,
140
+ count: 0
141
+ };
142
+
143
+ if (measurement.inclusive[id]) {
144
+ candidates[inclusiveKey].time += measurement.inclusive[id];
145
+ }
146
+ if (measurement.counts[id]) {
147
+ candidates[inclusiveKey].count += measurement.counts[id];
148
+ }
149
+ }
150
+ }
151
+
152
+ // Now make a sorted array with the results.
153
+ var arr = [];
154
+ for (inclusiveKey in candidates) {
155
+ if (candidates[inclusiveKey].time >= DONT_CARE_THRESHOLD) {
156
+ arr.push(candidates[inclusiveKey]);
157
+ }
158
+ }
159
+
160
+ arr.sort(function(a, b) {
161
+ return b.time - a.time;
162
+ });
163
+
164
+ return arr;
165
+ }
166
+
167
+ function getUnchangedComponents(measurement) {
168
+ // For a given reconcile, look at which components did not actually
169
+ // render anything to the DOM and return a mapping of their ID to
170
+ // the amount of time it took to render the entire subtree.
171
+ var cleanComponents = {};
172
+ var dirtyLeafIDs = Object.keys(measurement.writes);
173
+ var allIDs = merge(measurement.exclusive, measurement.inclusive);
174
+
175
+ for (var id in allIDs) {
176
+ var isDirty = false;
177
+ // For each component that rendered, see if a component that triggerd
178
+ // a DOM op is in its subtree.
179
+ for (var i = 0; i < dirtyLeafIDs.length; i++) {
180
+ if (dirtyLeafIDs[i].indexOf(id) === 0) {
181
+ isDirty = true;
182
+ break;
183
+ }
184
+ }
185
+ if (!isDirty && measurement.counts[id] > 0) {
186
+ cleanComponents[id] = true;
187
+ }
188
+ }
189
+ return cleanComponents;
190
+ }
191
+
192
+ var ReactDefaultPerfAnalysis = {
193
+ getExclusiveSummary: getExclusiveSummary,
194
+ getInclusiveSummary: getInclusiveSummary,
195
+ getDOMSummary: getDOMSummary,
196
+ getTotalTime: getTotalTime
197
+ };
198
+
199
+ module.exports = ReactDefaultPerfAnalysis;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2013 Facebook, Inc.
2
+ * Copyright 2013-2014 Facebook, Inc.
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -17,29 +17,20 @@
17
17
  * @typechecks
18
18
  */
19
19
 
20
+ "use strict";
21
+
20
22
  var ReactErrorUtils = {
21
23
  /**
22
24
  * Creates a guarded version of a function. This is supposed to make debugging
23
- * of event handlers easier. This implementation provides only basic error
24
- * logging and re-throws the error.
25
+ * of event handlers easier. To aid debugging with the browser's debugger,
26
+ * this currently simply returns the original function.
25
27
  *
26
28
  * @param {function} func Function to be executed
27
29
  * @param {string} name The name of the guard
28
30
  * @return {function}
29
31
  */
30
32
  guard: function(func, name) {
31
- if ("production" !== process.env.NODE_ENV) {
32
- return function guarded() {
33
- try {
34
- return func.apply(this, arguments);
35
- } catch(ex) {
36
- console.error(name + ': ' + ex.message);
37
- throw ex;
38
- }
39
- };
40
- } else {
41
- return func;
42
- }
33
+ return func;
43
34
  }
44
35
  };
45
36
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2013 Facebook, Inc.
2
+ * Copyright 2013-2014 Facebook, Inc.
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
22
22
  var EventConstants = require("./EventConstants");
23
23
  var EventListener = require("./EventListener");
24
24
  var EventPluginHub = require("./EventPluginHub");
25
+ var EventPluginRegistry = require("./EventPluginRegistry");
25
26
  var ExecutionEnvironment = require("./ExecutionEnvironment");
26
27
  var ReactEventEmitterMixin = require("./ReactEventEmitterMixin");
27
28
  var ViewportMetrics = require("./ViewportMetrics");
@@ -60,21 +61,80 @@ var merge = require("./merge");
60
61
  * | ReactEvent | . | | |TapEvent | |------------|
61
62
  * | Emitter | . | |<---+|Plugin | |other plugin|
62
63
  * | | . | | +-----------+ | utilities |
63
- * | +-----------.---------+ | +------------+
64
- * | | | . +----|---------+
65
- * +-----|------+ . | ^ +-----------+
66
- * | . | | |Enter/Leave|
67
- * + . | +-------+|Plugin |
68
- * +-------------+ . v +-----------+
69
- * | application | . +----------+
70
- * |-------------| . | callback |
71
- * | | . | registry |
72
- * | | . +----------+
64
+ * | +-----------.--->| | +------------+
65
+ * | | | . +--------------+
66
+ * +-----|------+ . ^ +-----------+
67
+ * | . | |Enter/Leave|
68
+ * + . +-------+|Plugin |
69
+ * +-------------+ . +-----------+
70
+ * | application | .
71
+ * |-------------| .
72
+ * | | .
73
+ * | | .
73
74
  * +-------------+ .
74
75
  * .
75
76
  * React Core . General Purpose Event Plugin System
76
77
  */
77
78
 
79
+ var alreadyListeningTo = {};
80
+ var isMonitoringScrollValue = false;
81
+ var reactTopListenersCounter = 0;
82
+
83
+ // For events like 'submit' which don't consistently bubble (which we trap at a
84
+ // lower node than `document`), binding at `document` would cause duplicate
85
+ // events so we don't include them here
86
+ var topEventMapping = {
87
+ topBlur: 'blur',
88
+ topChange: 'change',
89
+ topClick: 'click',
90
+ topCompositionEnd: 'compositionend',
91
+ topCompositionStart: 'compositionstart',
92
+ topCompositionUpdate: 'compositionupdate',
93
+ topContextMenu: 'contextmenu',
94
+ topCopy: 'copy',
95
+ topCut: 'cut',
96
+ topDoubleClick: 'dblclick',
97
+ topDrag: 'drag',
98
+ topDragEnd: 'dragend',
99
+ topDragEnter: 'dragenter',
100
+ topDragExit: 'dragexit',
101
+ topDragLeave: 'dragleave',
102
+ topDragOver: 'dragover',
103
+ topDragStart: 'dragstart',
104
+ topDrop: 'drop',
105
+ topFocus: 'focus',
106
+ topInput: 'input',
107
+ topKeyDown: 'keydown',
108
+ topKeyPress: 'keypress',
109
+ topKeyUp: 'keyup',
110
+ topMouseDown: 'mousedown',
111
+ topMouseMove: 'mousemove',
112
+ topMouseOut: 'mouseout',
113
+ topMouseOver: 'mouseover',
114
+ topMouseUp: 'mouseup',
115
+ topPaste: 'paste',
116
+ topScroll: 'scroll',
117
+ topSelectionChange: 'selectionchange',
118
+ topTouchCancel: 'touchcancel',
119
+ topTouchEnd: 'touchend',
120
+ topTouchMove: 'touchmove',
121
+ topTouchStart: 'touchstart',
122
+ topWheel: 'wheel'
123
+ };
124
+
125
+ /**
126
+ * To ensure no conflicts with other potential React instances on the page
127
+ */
128
+ var topListenersIDKey = "_reactListenersID" + String(Math.random()).slice(2);
129
+
130
+ function getListeningForDocument(mountAt) {
131
+ if (mountAt[topListenersIDKey] == null) {
132
+ mountAt[topListenersIDKey] = reactTopListenersCounter++;
133
+ alreadyListeningTo[mountAt[topListenersIDKey]] = {};
134
+ }
135
+ return alreadyListeningTo[mountAt[topListenersIDKey]];
136
+ }
137
+
78
138
  /**
79
139
  * Traps top-level events by using event bubbling.
80
140
  *
@@ -111,21 +171,6 @@ function trapCapturedEvent(topLevelType, handlerBaseName, element) {
111
171
  );
112
172
  }
113
173
 
114
- /**
115
- * Listens to window scroll and resize events. We cache scroll values so that
116
- * application code can access them without triggering reflows.
117
- *
118
- * NOTE: Scroll events do not bubble.
119
- *
120
- * @private
121
- * @see http://www.quirksmode.org/dom/events/scroll.html
122
- */
123
- function registerScrollValueMonitoring() {
124
- var refresh = ViewportMetrics.refreshScrollValues;
125
- EventListener.listen(window, 'scroll', refresh);
126
- EventListener.listen(window, 'resize', refresh);
127
- }
128
-
129
174
  /**
130
175
  * `ReactEventEmitter` is used to attach top-level event listeners. For example:
131
176
  *
@@ -143,37 +188,13 @@ var ReactEventEmitter = merge(ReactEventEmitterMixin, {
143
188
  */
144
189
  TopLevelCallbackCreator: null,
145
190
 
146
- /**
147
- * Ensures that top-level event delegation listeners are installed.
148
- *
149
- * There are issues with listening to both touch events and mouse events on
150
- * the top-level, so we make the caller choose which one to listen to. (If
151
- * there's a touch top-level listeners, anchors don't receive clicks for some
152
- * reason, and only in some cases).
153
- *
154
- * @param {boolean} touchNotMouse Listen to touch events instead of mouse.
155
- * @param {DOMDocument} contentDocument DOM document to listen on
156
- */
157
- ensureListening: function(touchNotMouse, contentDocument) {
158
- ("production" !== process.env.NODE_ENV ? invariant(
159
- ExecutionEnvironment.canUseDOM,
160
- 'ensureListening(...): Cannot toggle event listening in a Worker ' +
161
- 'thread. This is likely a bug in the framework. Please report ' +
162
- 'immediately.'
163
- ) : invariant(ExecutionEnvironment.canUseDOM));
164
- ("production" !== process.env.NODE_ENV ? invariant(
165
- ReactEventEmitter.TopLevelCallbackCreator,
166
- 'ensureListening(...): Cannot be called without a top level callback ' +
167
- 'creator being injected.'
168
- ) : invariant(ReactEventEmitter.TopLevelCallbackCreator));
169
- // Call out to base implementation.
170
- ReactEventEmitterMixin.ensureListening.call(
171
- ReactEventEmitter,
172
- {
173
- touchNotMouse: touchNotMouse,
174
- contentDocument: contentDocument
175
- }
176
- );
191
+ injection: {
192
+ /**
193
+ * @param {function} TopLevelCallbackCreator
194
+ */
195
+ injectTopLevelCallbackCreator: function(TopLevelCallbackCreator) {
196
+ ReactEventEmitter.TopLevelCallbackCreator = TopLevelCallbackCreator;
197
+ }
177
198
  },
178
199
 
179
200
  /**
@@ -220,108 +241,86 @@ var ReactEventEmitter = merge(ReactEventEmitterMixin, {
220
241
  * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but
221
242
  * they bubble to document.
222
243
  *
223
- * @param {boolean} touchNotMouse Listen to touch events instead of mouse.
244
+ * @param {string} registrationName Name of listener (e.g. `onClick`).
224
245
  * @param {DOMDocument} contentDocument Document which owns the container
225
- * @private
226
- * @see http://www.quirksmode.org/dom/events/keys.html.
227
246
  */
228
- listenAtTopLevel: function(touchNotMouse, contentDocument) {
229
- ("production" !== process.env.NODE_ENV ? invariant(
230
- !contentDocument._isListening,
231
- 'listenAtTopLevel(...): Cannot setup top-level listener more than once.'
232
- ) : invariant(!contentDocument._isListening));
233
- var topLevelTypes = EventConstants.topLevelTypes;
247
+ listenTo: function(registrationName, contentDocument) {
234
248
  var mountAt = contentDocument;
249
+ var isListening = getListeningForDocument(mountAt);
250
+ var dependencies = EventPluginRegistry.
251
+ registrationNameDependencies[registrationName];
235
252
 
236
- registerScrollValueMonitoring();
237
- trapBubbledEvent(topLevelTypes.topMouseOver, 'mouseover', mountAt);
238
- trapBubbledEvent(topLevelTypes.topMouseDown, 'mousedown', mountAt);
239
- trapBubbledEvent(topLevelTypes.topMouseUp, 'mouseup', mountAt);
240
- trapBubbledEvent(topLevelTypes.topMouseMove, 'mousemove', mountAt);
241
- trapBubbledEvent(topLevelTypes.topMouseOut, 'mouseout', mountAt);
242
- trapBubbledEvent(topLevelTypes.topClick, 'click', mountAt);
243
- trapBubbledEvent(topLevelTypes.topDoubleClick, 'dblclick', mountAt);
244
- trapBubbledEvent(topLevelTypes.topContextMenu, 'contextmenu', mountAt);
245
- if (touchNotMouse) {
246
- trapBubbledEvent(topLevelTypes.topTouchStart, 'touchstart', mountAt);
247
- trapBubbledEvent(topLevelTypes.topTouchEnd, 'touchend', mountAt);
248
- trapBubbledEvent(topLevelTypes.topTouchMove, 'touchmove', mountAt);
249
- trapBubbledEvent(topLevelTypes.topTouchCancel, 'touchcancel', mountAt);
250
- }
251
- trapBubbledEvent(topLevelTypes.topKeyUp, 'keyup', mountAt);
252
- trapBubbledEvent(topLevelTypes.topKeyPress, 'keypress', mountAt);
253
- trapBubbledEvent(topLevelTypes.topKeyDown, 'keydown', mountAt);
254
- trapBubbledEvent(topLevelTypes.topInput, 'input', mountAt);
255
- trapBubbledEvent(topLevelTypes.topChange, 'change', mountAt);
256
- trapBubbledEvent(
257
- topLevelTypes.topSelectionChange,
258
- 'selectionchange',
259
- mountAt
260
- );
253
+ var topLevelTypes = EventConstants.topLevelTypes;
254
+ for (var i = 0, l = dependencies.length; i < l; i++) {
255
+ var dependency = dependencies[i];
256
+ if (!isListening[dependency]) {
257
+ var topLevelType = topLevelTypes[dependency];
261
258
 
262
- trapBubbledEvent(
263
- topLevelTypes.topCompositionEnd,
264
- 'compositionend',
265
- mountAt
266
- );
267
- trapBubbledEvent(
268
- topLevelTypes.topCompositionStart,
269
- 'compositionstart',
270
- mountAt
271
- );
272
- trapBubbledEvent(
273
- topLevelTypes.topCompositionUpdate,
274
- 'compositionupdate',
275
- mountAt
276
- );
259
+ if (topLevelType === topLevelTypes.topWheel) {
260
+ if (isEventSupported('wheel')) {
261
+ trapBubbledEvent(topLevelTypes.topWheel, 'wheel', mountAt);
262
+ } else if (isEventSupported('mousewheel')) {
263
+ trapBubbledEvent(topLevelTypes.topWheel, 'mousewheel', mountAt);
264
+ } else {
265
+ // Firefox needs to capture a different mouse scroll event.
266
+ // @see http://www.quirksmode.org/dom/events/tests/scroll.html
267
+ trapBubbledEvent(
268
+ topLevelTypes.topWheel,
269
+ 'DOMMouseScroll',
270
+ mountAt);
271
+ }
272
+ } else if (topLevelType === topLevelTypes.topScroll) {
277
273
 
278
- if (isEventSupported('drag')) {
279
- trapBubbledEvent(topLevelTypes.topDrag, 'drag', mountAt);
280
- trapBubbledEvent(topLevelTypes.topDragEnd, 'dragend', mountAt);
281
- trapBubbledEvent(topLevelTypes.topDragEnter, 'dragenter', mountAt);
282
- trapBubbledEvent(topLevelTypes.topDragExit, 'dragexit', mountAt);
283
- trapBubbledEvent(topLevelTypes.topDragLeave, 'dragleave', mountAt);
284
- trapBubbledEvent(topLevelTypes.topDragOver, 'dragover', mountAt);
285
- trapBubbledEvent(topLevelTypes.topDragStart, 'dragstart', mountAt);
286
- trapBubbledEvent(topLevelTypes.topDrop, 'drop', mountAt);
287
- }
274
+ if (isEventSupported('scroll', true)) {
275
+ trapCapturedEvent(topLevelTypes.topScroll, 'scroll', mountAt);
276
+ } else {
277
+ trapBubbledEvent(topLevelTypes.topScroll, 'scroll', window);
278
+ }
279
+ } else if (topLevelType === topLevelTypes.topFocus ||
280
+ topLevelType === topLevelTypes.topBlur) {
288
281
 
289
- if (isEventSupported('wheel')) {
290
- trapBubbledEvent(topLevelTypes.topWheel, 'wheel', mountAt);
291
- } else if (isEventSupported('mousewheel')) {
292
- trapBubbledEvent(topLevelTypes.topWheel, 'mousewheel', mountAt);
293
- } else {
294
- // Firefox needs to capture a different mouse scroll event.
295
- // @see http://www.quirksmode.org/dom/events/tests/scroll.html
296
- trapBubbledEvent(topLevelTypes.topWheel, 'DOMMouseScroll', mountAt);
297
- }
282
+ if (isEventSupported('focus', true)) {
283
+ trapCapturedEvent(topLevelTypes.topFocus, 'focus', mountAt);
284
+ trapCapturedEvent(topLevelTypes.topBlur, 'blur', mountAt);
285
+ } else if (isEventSupported('focusin')) {
286
+ // IE has `focusin` and `focusout` events which bubble.
287
+ // @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
288
+ trapBubbledEvent(topLevelTypes.topFocus, 'focusin', mountAt);
289
+ trapBubbledEvent(topLevelTypes.topBlur, 'focusout', mountAt);
290
+ }
298
291
 
299
- // IE<9 does not support capturing so just trap the bubbled event there.
300
- if (isEventSupported('scroll', true)) {
301
- trapCapturedEvent(topLevelTypes.topScroll, 'scroll', mountAt);
302
- } else {
303
- trapBubbledEvent(topLevelTypes.topScroll, 'scroll', window);
304
- }
292
+ // to make sure blur and focus event listeners are only attached once
293
+ isListening[topLevelTypes.topBlur] = true;
294
+ isListening[topLevelTypes.topFocus] = true;
295
+ } else if (topEventMapping[dependency]) {
296
+ trapBubbledEvent(topLevelType, topEventMapping[dependency], mountAt);
297
+ }
305
298
 
306
- if (isEventSupported('focus', true)) {
307
- trapCapturedEvent(topLevelTypes.topFocus, 'focus', mountAt);
308
- trapCapturedEvent(topLevelTypes.topBlur, 'blur', mountAt);
309
- } else if (isEventSupported('focusin')) {
310
- // IE has `focusin` and `focusout` events which bubble.
311
- // @see
312
- // http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
313
- trapBubbledEvent(topLevelTypes.topFocus, 'focusin', mountAt);
314
- trapBubbledEvent(topLevelTypes.topBlur, 'focusout', mountAt);
299
+ isListening[dependency] = true;
300
+ }
315
301
  }
302
+ },
316
303
 
317
- if (isEventSupported('copy')) {
318
- trapBubbledEvent(topLevelTypes.topCopy, 'copy', mountAt);
319
- trapBubbledEvent(topLevelTypes.topCut, 'cut', mountAt);
320
- trapBubbledEvent(topLevelTypes.topPaste, 'paste', mountAt);
304
+ /**
305
+ * Listens to window scroll and resize events. We cache scroll values so that
306
+ * application code can access them without triggering reflows.
307
+ *
308
+ * NOTE: Scroll events do not bubble.
309
+ *
310
+ * @see http://www.quirksmode.org/dom/events/scroll.html
311
+ */
312
+ ensureScrollValueMonitoring: function(){
313
+ if (!isMonitoringScrollValue) {
314
+ var refresh = ViewportMetrics.refreshScrollValues;
315
+ EventListener.listen(window, 'scroll', refresh);
316
+ EventListener.listen(window, 'resize', refresh);
317
+ isMonitoringScrollValue = true;
321
318
  }
322
319
  },
323
320
 
324
- registrationNames: EventPluginHub.registrationNames,
321
+ eventNameDispatchConfigs: EventPluginHub.eventNameDispatchConfigs,
322
+
323
+ registrationNameModules: EventPluginHub.registrationNameModules,
325
324
 
326
325
  putListener: EventPluginHub.putListener,
327
326
 
@@ -337,5 +336,4 @@ var ReactEventEmitter = merge(ReactEventEmitterMixin, {
337
336
 
338
337
  });
339
338
 
340
-
341
339
  module.exports = ReactEventEmitter;