react 0.6.3 → 0.9.0-rc1

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 (218) hide show
  1. package/README.md +10 -222
  2. package/addons.js +1 -0
  3. package/lib/AutoFocusMixin.js +30 -0
  4. package/lib/CSSCore.js +115 -0
  5. package/lib/CSSProperty.js +121 -0
  6. package/lib/CSSPropertyOperations.js +97 -0
  7. package/lib/ChangeEventPlugin.js +387 -0
  8. package/lib/ClientReactRootIndex.js +30 -0
  9. package/lib/CompositionEventPlugin.js +260 -0
  10. package/lib/DOMChildrenOperations.js +165 -0
  11. package/lib/DOMProperty.js +268 -0
  12. package/lib/DOMPropertyOperations.js +181 -0
  13. package/lib/Danger.js +187 -0
  14. package/lib/DefaultDOMPropertyConfig.js +197 -0
  15. package/lib/DefaultEventPluginOrder.js +44 -0
  16. package/lib/EnterLeaveEventPlugin.js +145 -0
  17. package/lib/EventConstants.js +76 -0
  18. package/lib/EventListener.js +69 -0
  19. package/lib/EventPluginHub.js +291 -0
  20. package/lib/EventPluginRegistry.js +260 -0
  21. package/lib/EventPluginUtils.js +214 -0
  22. package/lib/EventPropagators.js +143 -0
  23. package/lib/ExecutionEnvironment.js +44 -0
  24. package/lib/LinkedStateMixin.js +46 -0
  25. package/lib/LinkedValueUtils.js +161 -0
  26. package/lib/MobileSafariClickEventPlugin.js +63 -0
  27. package/lib/PooledClass.js +119 -0
  28. package/lib/React.js +95 -0
  29. package/lib/ReactCSSTransitionGroup.js +65 -0
  30. package/lib/ReactCSSTransitionGroupChild.js +138 -0
  31. package/lib/ReactChildren.js +132 -0
  32. package/lib/ReactComponent.js +550 -0
  33. package/lib/ReactComponentBrowserEnvironment.js +158 -0
  34. package/lib/ReactComponentEnvironment.js +26 -0
  35. package/lib/ReactCompositeComponent.js +1455 -0
  36. package/lib/ReactContext.js +67 -0
  37. package/lib/ReactCurrentOwner.js +39 -0
  38. package/lib/ReactDOM.js +207 -0
  39. package/lib/ReactDOMButton.js +68 -0
  40. package/lib/ReactDOMComponent.js +399 -0
  41. package/lib/ReactDOMForm.js +59 -0
  42. package/lib/ReactDOMIDOperations.js +218 -0
  43. package/lib/ReactDOMImg.js +58 -0
  44. package/lib/ReactDOMInput.js +181 -0
  45. package/lib/ReactDOMOption.js +51 -0
  46. package/lib/ReactDOMSelect.js +179 -0
  47. package/lib/ReactDOMSelection.js +189 -0
  48. package/lib/ReactDOMTextarea.js +140 -0
  49. package/lib/ReactDefaultBatchingStrategy.js +75 -0
  50. package/lib/ReactDefaultInjection.js +115 -0
  51. package/lib/ReactDefaultPerf.js +244 -0
  52. package/lib/ReactDefaultPerfAnalysis.js +199 -0
  53. package/lib/ReactErrorUtils.js +37 -0
  54. package/lib/ReactEventEmitter.js +337 -0
  55. package/lib/ReactEventEmitterMixin.js +57 -0
  56. package/lib/ReactEventTopLevelCallback.js +109 -0
  57. package/lib/ReactInjection.js +39 -0
  58. package/lib/ReactInputSelection.js +140 -0
  59. package/lib/ReactInstanceHandles.js +338 -0
  60. package/lib/ReactLink.js +54 -0
  61. package/lib/ReactMarkupChecksum.js +53 -0
  62. package/lib/ReactMount.js +641 -0
  63. package/lib/ReactMountReady.js +95 -0
  64. package/lib/ReactMultiChild.js +425 -0
  65. package/lib/ReactMultiChildUpdateTypes.js +38 -0
  66. package/lib/ReactOwner.js +154 -0
  67. package/lib/ReactPerf.js +85 -0
  68. package/lib/ReactPropTransferer.js +147 -0
  69. package/lib/ReactPropTypeLocationNames.js +31 -0
  70. package/lib/ReactPropTypeLocations.js +29 -0
  71. package/lib/ReactPropTypes.js +359 -0
  72. package/lib/ReactPutListenerQueue.js +61 -0
  73. package/lib/ReactReconcileTransaction.js +181 -0
  74. package/lib/ReactRootIndex.js +36 -0
  75. package/lib/ReactServerRendering.js +59 -0
  76. package/lib/ReactStateSetters.js +111 -0
  77. package/lib/ReactTextComponent.js +99 -0
  78. package/lib/ReactTransitionChildMapping.js +106 -0
  79. package/lib/ReactTransitionEvents.js +97 -0
  80. package/lib/ReactTransitionGroup.js +187 -0
  81. package/lib/ReactUpdates.js +148 -0
  82. package/lib/ReactWithAddons.js +46 -0
  83. package/lib/SelectEventPlugin.js +200 -0
  84. package/lib/ServerReactRootIndex.js +36 -0
  85. package/lib/SimpleEventPlugin.js +413 -0
  86. package/lib/SyntheticClipboardEvent.js +51 -0
  87. package/lib/SyntheticCompositionEvent.js +51 -0
  88. package/lib/SyntheticDragEvent.js +44 -0
  89. package/lib/SyntheticEvent.js +164 -0
  90. package/lib/SyntheticFocusEvent.js +44 -0
  91. package/lib/SyntheticKeyboardEvent.js +58 -0
  92. package/lib/SyntheticMouseEvent.js +85 -0
  93. package/lib/SyntheticTouchEvent.js +50 -0
  94. package/lib/SyntheticUIEvent.js +45 -0
  95. package/lib/SyntheticWheelEvent.js +66 -0
  96. package/lib/Transaction.js +276 -0
  97. package/lib/ViewportMetrics.js +37 -0
  98. package/lib/accumulate.js +54 -0
  99. package/lib/adler32.js +39 -0
  100. package/lib/cloneWithProps.js +59 -0
  101. package/lib/containsNode.js +49 -0
  102. package/lib/copyProperties.js +54 -0
  103. package/lib/createArrayFrom.js +91 -0
  104. package/lib/createFullPageComponent.js +63 -0
  105. package/lib/createNodesFromMarkup.js +93 -0
  106. package/lib/createObjectFrom.js +61 -0
  107. package/lib/cx.js +44 -0
  108. package/lib/dangerousStyleValue.js +57 -0
  109. package/lib/emptyFunction.js +43 -0
  110. package/lib/escapeTextForBrowser.js +47 -0
  111. package/lib/flattenChildren.js +57 -0
  112. package/lib/forEachAccumulated.js +36 -0
  113. package/lib/getActiveElement.js +34 -0
  114. package/lib/getEventKey.js +85 -0
  115. package/lib/getEventTarget.js +36 -0
  116. package/lib/getMarkupWrap.js +118 -0
  117. package/lib/getNodeForCharacterOffset.js +80 -0
  118. package/lib/getReactRootElementInContainer.js +40 -0
  119. package/lib/getTextContentAccessor.js +42 -0
  120. package/lib/getUnboundedScrollPosition.js +45 -0
  121. package/lib/hyphenate.js +35 -0
  122. package/lib/invariant.js +62 -0
  123. package/lib/isEventSupported.js +70 -0
  124. package/lib/isNode.js +33 -0
  125. package/lib/isTextInputElement.js +49 -0
  126. package/lib/isTextNode.js +30 -0
  127. package/lib/joinClasses.js +44 -0
  128. package/lib/keyMirror.js +58 -0
  129. package/lib/keyOf.js +41 -0
  130. package/lib/memoizeStringOnly.js +39 -0
  131. package/lib/merge.js +37 -0
  132. package/lib/mergeHelpers.js +136 -0
  133. package/lib/mergeInto.js +45 -0
  134. package/lib/mixInto.js +34 -0
  135. package/lib/objMap.js +47 -0
  136. package/lib/objMapKeyVal.js +47 -0
  137. package/lib/onlyChild.js +43 -0
  138. package/lib/performanceNow.js +42 -0
  139. package/lib/shallowEqual.js +49 -0
  140. package/lib/shouldUpdateReactComponent.js +58 -0
  141. package/lib/toArray.js +75 -0
  142. package/lib/traverseAllChildren.js +189 -0
  143. package/lib/warning.js +40 -0
  144. package/package.json +32 -21
  145. package/react.js +1 -0
  146. package/.npmignore +0 -7
  147. package/.travis.yml +0 -5
  148. package/Jakefile.js +0 -39
  149. package/LICENSE +0 -19
  150. package/browser-test/dist.html +0 -90
  151. package/browser-test/index.html +0 -86
  152. package/browser-test/min.html +0 -90
  153. package/dist/react.js +0 -3107
  154. package/dist/react.min.js +0 -22
  155. package/doc/advanced.md +0 -174
  156. package/doc/color-def.graffle +0 -938
  157. package/doc/color-def.png +0 -0
  158. package/doc/simple.dot +0 -25
  159. package/doc/simple.png +0 -0
  160. package/examples/longer-example.js +0 -41
  161. package/examples/simple.js +0 -45
  162. package/examples/using-ast-directly.js +0 -30
  163. package/examples/using-events1.js +0 -79
  164. package/examples/using-log-events.js +0 -43
  165. package/lib/base-task.js +0 -123
  166. package/lib/cb-task.js +0 -84
  167. package/lib/core.js +0 -138
  168. package/lib/dsl.js +0 -138
  169. package/lib/error.js +0 -55
  170. package/lib/event-collector.js +0 -81
  171. package/lib/event-manager.js +0 -89
  172. package/lib/eventemitter.js +0 -20
  173. package/lib/finalcb-first-task.js +0 -68
  174. package/lib/finalcb-task.js +0 -65
  175. package/lib/id.js +0 -22
  176. package/lib/input-parser.js +0 -56
  177. package/lib/log-events.js +0 -101
  178. package/lib/parse.js +0 -41
  179. package/lib/promise-resolve.js +0 -50
  180. package/lib/promise-task.js +0 -93
  181. package/lib/react.js +0 -59
  182. package/lib/ret-task.js +0 -71
  183. package/lib/sprintf.js +0 -18
  184. package/lib/status.js +0 -14
  185. package/lib/task.js +0 -251
  186. package/lib/track-tasks.js +0 -74
  187. package/lib/validate.js +0 -159
  188. package/lib/vcon.js +0 -90
  189. package/lib/when-task.js +0 -85
  190. package/src/dist.build.requirejs +0 -20
  191. package/test/ast.mocha.js +0 -136
  192. package/test/cb-task.mocha.js +0 -220
  193. package/test/core-deferred.mocha.js +0 -143
  194. package/test/core-when.mocha.js +0 -96
  195. package/test/core.mocha.js +0 -589
  196. package/test/dsl.mocha.js +0 -350
  197. package/test/event-manager.mocha.js +0 -119
  198. package/test/exec-options.mocha.js +0 -48
  199. package/test/finalcb-task.mocha.js +0 -58
  200. package/test/input-parser.mocha.js +0 -86
  201. package/test/log-events.mocha.js +0 -88
  202. package/test/mocha.opts +0 -2
  203. package/test/module-use.mocha.js +0 -147
  204. package/test/promise-auto-resolve.mocha.js +0 -68
  205. package/test/ret-task.mocha.js +0 -220
  206. package/test/task.mocha.js +0 -42
  207. package/test/validate-cb-task.mocha.js +0 -100
  208. package/test/validate-ret-task.mocha.js +0 -110
  209. package/test/validate.mocha.js +0 -324
  210. package/test/vcon.mocha.js +0 -193
  211. package/vendor/chai/chai.js +0 -2038
  212. package/vendor/jquery/jquery-1.7.1.js +0 -9266
  213. package/vendor/jquery/jquery-1.7.1.min.js +0 -4
  214. package/vendor/mocha/mocha.css +0 -135
  215. package/vendor/mocha/mocha.js +0 -3589
  216. package/vendor/node/util.js +0 -531
  217. package/vendor/requirejs/require.js +0 -2053
  218. package/vendor/requirejs/require.min.js +0 -33
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Copyright 2013 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 CSSPropertyOperations
17
+ * @typechecks static-only
18
+ */
19
+
20
+ "use strict";
21
+
22
+ var CSSProperty = require("./CSSProperty");
23
+
24
+ var dangerousStyleValue = require("./dangerousStyleValue");
25
+ var escapeTextForBrowser = require("./escapeTextForBrowser");
26
+ var hyphenate = require("./hyphenate");
27
+ var memoizeStringOnly = require("./memoizeStringOnly");
28
+
29
+ var processStyleName = memoizeStringOnly(function(styleName) {
30
+ return escapeTextForBrowser(hyphenate(styleName));
31
+ });
32
+
33
+ /**
34
+ * Operations for dealing with CSS properties.
35
+ */
36
+ var CSSPropertyOperations = {
37
+
38
+ /**
39
+ * Serializes a mapping of style properties for use as inline styles:
40
+ *
41
+ * > createMarkupForStyles({width: '200px', height: 0})
42
+ * "width:200px;height:0;"
43
+ *
44
+ * Undefined values are ignored so that declarative programming is easier.
45
+ *
46
+ * @param {object} styles
47
+ * @return {?string}
48
+ */
49
+ createMarkupForStyles: function(styles) {
50
+ var serialized = '';
51
+ for (var styleName in styles) {
52
+ if (!styles.hasOwnProperty(styleName)) {
53
+ continue;
54
+ }
55
+ var styleValue = styles[styleName];
56
+ if (styleValue != null) {
57
+ serialized += processStyleName(styleName) + ':';
58
+ serialized += dangerousStyleValue(styleName, styleValue) + ';';
59
+ }
60
+ }
61
+ return serialized || null;
62
+ },
63
+
64
+ /**
65
+ * Sets the value for multiple styles on a node. If a value is specified as
66
+ * '' (empty string), the corresponding style property will be unset.
67
+ *
68
+ * @param {DOMElement} node
69
+ * @param {object} styles
70
+ */
71
+ setValueForStyles: function(node, styles) {
72
+ var style = node.style;
73
+ for (var styleName in styles) {
74
+ if (!styles.hasOwnProperty(styleName)) {
75
+ continue;
76
+ }
77
+ var styleValue = dangerousStyleValue(styleName, styles[styleName]);
78
+ if (styleValue) {
79
+ style[styleName] = styleValue;
80
+ } else {
81
+ var expansion = CSSProperty.shorthandPropertyExpansions[styleName];
82
+ if (expansion) {
83
+ // Shorthand property that IE8 won't like unsetting, so unset each
84
+ // component to placate it
85
+ for (var individualStyleName in expansion) {
86
+ style[individualStyleName] = '';
87
+ }
88
+ } else {
89
+ style[styleName] = '';
90
+ }
91
+ }
92
+ }
93
+ }
94
+
95
+ };
96
+
97
+ module.exports = CSSPropertyOperations;
@@ -0,0 +1,387 @@
1
+ /**
2
+ * Copyright 2013 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 ChangeEventPlugin
17
+ */
18
+
19
+ "use strict";
20
+
21
+ var EventConstants = require("./EventConstants");
22
+ var EventPluginHub = require("./EventPluginHub");
23
+ var EventPropagators = require("./EventPropagators");
24
+ var ExecutionEnvironment = require("./ExecutionEnvironment");
25
+ var ReactUpdates = require("./ReactUpdates");
26
+ var SyntheticEvent = require("./SyntheticEvent");
27
+
28
+ var isEventSupported = require("./isEventSupported");
29
+ var isTextInputElement = require("./isTextInputElement");
30
+ var keyOf = require("./keyOf");
31
+
32
+ var topLevelTypes = EventConstants.topLevelTypes;
33
+
34
+ var eventTypes = {
35
+ change: {
36
+ phasedRegistrationNames: {
37
+ bubbled: keyOf({onChange: null}),
38
+ captured: keyOf({onChangeCapture: null})
39
+ },
40
+ dependencies: [
41
+ topLevelTypes.topBlur,
42
+ topLevelTypes.topChange,
43
+ topLevelTypes.topClick,
44
+ topLevelTypes.topFocus,
45
+ topLevelTypes.topInput,
46
+ topLevelTypes.topKeyDown,
47
+ topLevelTypes.topKeyUp,
48
+ topLevelTypes.topSelectionChange
49
+ ]
50
+ }
51
+ };
52
+
53
+ /**
54
+ * For IE shims
55
+ */
56
+ var activeElement = null;
57
+ var activeElementID = null;
58
+ var activeElementValue = null;
59
+ var activeElementValueProp = null;
60
+
61
+ /**
62
+ * SECTION: handle `change` event
63
+ */
64
+ function shouldUseChangeEvent(elem) {
65
+ return (
66
+ elem.nodeName === 'SELECT' ||
67
+ (elem.nodeName === 'INPUT' && elem.type === 'file')
68
+ );
69
+ }
70
+
71
+ var doesChangeEventBubble = false;
72
+ if (ExecutionEnvironment.canUseDOM) {
73
+ // See `handleChange` comment below
74
+ doesChangeEventBubble = isEventSupported('change') && (
75
+ !('documentMode' in document) || document.documentMode > 8
76
+ );
77
+ }
78
+
79
+ function manualDispatchChangeEvent(nativeEvent) {
80
+ var event = SyntheticEvent.getPooled(
81
+ eventTypes.change,
82
+ activeElementID,
83
+ nativeEvent
84
+ );
85
+ EventPropagators.accumulateTwoPhaseDispatches(event);
86
+
87
+ // If change and propertychange bubbled, we'd just bind to it like all the
88
+ // other events and have it go through ReactEventTopLevelCallback. Since it
89
+ // doesn't, we manually listen for the events and so we have to enqueue and
90
+ // process the abstract event manually.
91
+ //
92
+ // Batching is necessary here in order to ensure that all event handlers run
93
+ // before the next rerender (including event handlers attached to ancestor
94
+ // elements instead of directly on the input). Without this, controlled
95
+ // components don't work properly in conjunction with event bubbling because
96
+ // the component is rerendered and the value reverted before all the event
97
+ // handlers can run. See https://github.com/facebook/react/issues/708.
98
+ ReactUpdates.batchedUpdates(runEventInBatch, event);
99
+ }
100
+
101
+ function runEventInBatch(event) {
102
+ EventPluginHub.enqueueEvents(event);
103
+ EventPluginHub.processEventQueue();
104
+ }
105
+
106
+ function startWatchingForChangeEventIE8(target, targetID) {
107
+ activeElement = target;
108
+ activeElementID = targetID;
109
+ activeElement.attachEvent('onchange', manualDispatchChangeEvent);
110
+ }
111
+
112
+ function stopWatchingForChangeEventIE8() {
113
+ if (!activeElement) {
114
+ return;
115
+ }
116
+ activeElement.detachEvent('onchange', manualDispatchChangeEvent);
117
+ activeElement = null;
118
+ activeElementID = null;
119
+ }
120
+
121
+ function getTargetIDForChangeEvent(
122
+ topLevelType,
123
+ topLevelTarget,
124
+ topLevelTargetID) {
125
+ if (topLevelType === topLevelTypes.topChange) {
126
+ return topLevelTargetID;
127
+ }
128
+ }
129
+ function handleEventsForChangeEventIE8(
130
+ topLevelType,
131
+ topLevelTarget,
132
+ topLevelTargetID) {
133
+ if (topLevelType === topLevelTypes.topFocus) {
134
+ // stopWatching() should be a noop here but we call it just in case we
135
+ // missed a blur event somehow.
136
+ stopWatchingForChangeEventIE8();
137
+ startWatchingForChangeEventIE8(topLevelTarget, topLevelTargetID);
138
+ } else if (topLevelType === topLevelTypes.topBlur) {
139
+ stopWatchingForChangeEventIE8();
140
+ }
141
+ }
142
+
143
+
144
+ /**
145
+ * SECTION: handle `input` event
146
+ */
147
+ var isInputEventSupported = false;
148
+ if (ExecutionEnvironment.canUseDOM) {
149
+ // IE9 claims to support the input event but fails to trigger it when
150
+ // deleting text, so we ignore its input events
151
+ isInputEventSupported = isEventSupported('input') && (
152
+ !('documentMode' in document) || document.documentMode > 9
153
+ );
154
+ }
155
+
156
+ /**
157
+ * (For old IE.) Replacement getter/setter for the `value` property that gets
158
+ * set on the active element.
159
+ */
160
+ var newValueProp = {
161
+ get: function() {
162
+ return activeElementValueProp.get.call(this);
163
+ },
164
+ set: function(val) {
165
+ // Cast to a string so we can do equality checks.
166
+ activeElementValue = '' + val;
167
+ activeElementValueProp.set.call(this, val);
168
+ }
169
+ };
170
+
171
+ /**
172
+ * (For old IE.) Starts tracking propertychange events on the passed-in element
173
+ * and override the value property so that we can distinguish user events from
174
+ * value changes in JS.
175
+ */
176
+ function startWatchingForValueChange(target, targetID) {
177
+ activeElement = target;
178
+ activeElementID = targetID;
179
+ activeElementValue = target.value;
180
+ activeElementValueProp = Object.getOwnPropertyDescriptor(
181
+ target.constructor.prototype,
182
+ 'value'
183
+ );
184
+
185
+ Object.defineProperty(activeElement, 'value', newValueProp);
186
+ activeElement.attachEvent('onpropertychange', handlePropertyChange);
187
+ }
188
+
189
+ /**
190
+ * (For old IE.) Removes the event listeners from the currently-tracked element,
191
+ * if any exists.
192
+ */
193
+ function stopWatchingForValueChange() {
194
+ if (!activeElement) {
195
+ return;
196
+ }
197
+
198
+ // delete restores the original property definition
199
+ delete activeElement.value;
200
+ activeElement.detachEvent('onpropertychange', handlePropertyChange);
201
+
202
+ activeElement = null;
203
+ activeElementID = null;
204
+ activeElementValue = null;
205
+ activeElementValueProp = null;
206
+ }
207
+
208
+ /**
209
+ * (For old IE.) Handles a propertychange event, sending a `change` event if
210
+ * the value of the active element has changed.
211
+ */
212
+ function handlePropertyChange(nativeEvent) {
213
+ if (nativeEvent.propertyName !== 'value') {
214
+ return;
215
+ }
216
+ var value = nativeEvent.srcElement.value;
217
+ if (value === activeElementValue) {
218
+ return;
219
+ }
220
+ activeElementValue = value;
221
+
222
+ manualDispatchChangeEvent(nativeEvent);
223
+ }
224
+
225
+ /**
226
+ * If a `change` event should be fired, returns the target's ID.
227
+ */
228
+ function getTargetIDForInputEvent(
229
+ topLevelType,
230
+ topLevelTarget,
231
+ topLevelTargetID) {
232
+ if (topLevelType === topLevelTypes.topInput) {
233
+ // In modern browsers (i.e., not IE8 or IE9), the input event is exactly
234
+ // what we want so fall through here and trigger an abstract event
235
+ return topLevelTargetID;
236
+ }
237
+ }
238
+
239
+ // For IE8 and IE9.
240
+ function handleEventsForInputEventIE(
241
+ topLevelType,
242
+ topLevelTarget,
243
+ topLevelTargetID) {
244
+ if (topLevelType === topLevelTypes.topFocus) {
245
+ // In IE8, we can capture almost all .value changes by adding a
246
+ // propertychange handler and looking for events with propertyName
247
+ // equal to 'value'
248
+ // In IE9, propertychange fires for most input events but is buggy and
249
+ // doesn't fire when text is deleted, but conveniently, selectionchange
250
+ // appears to fire in all of the remaining cases so we catch those and
251
+ // forward the event if the value has changed
252
+ // In either case, we don't want to call the event handler if the value
253
+ // is changed from JS so we redefine a setter for `.value` that updates
254
+ // our activeElementValue variable, allowing us to ignore those changes
255
+ //
256
+ // stopWatching() should be a noop here but we call it just in case we
257
+ // missed a blur event somehow.
258
+ stopWatchingForValueChange();
259
+ startWatchingForValueChange(topLevelTarget, topLevelTargetID);
260
+ } else if (topLevelType === topLevelTypes.topBlur) {
261
+ stopWatchingForValueChange();
262
+ }
263
+ }
264
+
265
+ // For IE8 and IE9.
266
+ function getTargetIDForInputEventIE(
267
+ topLevelType,
268
+ topLevelTarget,
269
+ topLevelTargetID) {
270
+ if (topLevelType === topLevelTypes.topSelectionChange ||
271
+ topLevelType === topLevelTypes.topKeyUp ||
272
+ topLevelType === topLevelTypes.topKeyDown) {
273
+ // On the selectionchange event, the target is just document which isn't
274
+ // helpful for us so just check activeElement instead.
275
+ //
276
+ // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire
277
+ // propertychange on the first input event after setting `value` from a
278
+ // script and fires only keydown, keypress, keyup. Catching keyup usually
279
+ // gets it and catching keydown lets us fire an event for the first
280
+ // keystroke if user does a key repeat (it'll be a little delayed: right
281
+ // before the second keystroke). Other input methods (e.g., paste) seem to
282
+ // fire selectionchange normally.
283
+ if (activeElement && activeElement.value !== activeElementValue) {
284
+ activeElementValue = activeElement.value;
285
+ return activeElementID;
286
+ }
287
+ }
288
+ }
289
+
290
+
291
+ /**
292
+ * SECTION: handle `click` event
293
+ */
294
+ function shouldUseClickEvent(elem) {
295
+ // Use the `click` event to detect changes to checkbox and radio inputs.
296
+ // This approach works across all browsers, whereas `change` does not fire
297
+ // until `blur` in IE8.
298
+ return (
299
+ elem.nodeName === 'INPUT' &&
300
+ (elem.type === 'checkbox' || elem.type === 'radio')
301
+ );
302
+ }
303
+
304
+ function getTargetIDForClickEvent(
305
+ topLevelType,
306
+ topLevelTarget,
307
+ topLevelTargetID) {
308
+ if (topLevelType === topLevelTypes.topClick) {
309
+ return topLevelTargetID;
310
+ }
311
+ }
312
+
313
+ /**
314
+ * This plugin creates an `onChange` event that normalizes change events
315
+ * across form elements. This event fires at a time when it's possible to
316
+ * change the element's value without seeing a flicker.
317
+ *
318
+ * Supported elements are:
319
+ * - input (see `isTextInputElement`)
320
+ * - textarea
321
+ * - select
322
+ */
323
+ var ChangeEventPlugin = {
324
+
325
+ eventTypes: eventTypes,
326
+
327
+ /**
328
+ * @param {string} topLevelType Record from `EventConstants`.
329
+ * @param {DOMEventTarget} topLevelTarget The listening component root node.
330
+ * @param {string} topLevelTargetID ID of `topLevelTarget`.
331
+ * @param {object} nativeEvent Native browser event.
332
+ * @return {*} An accumulation of synthetic events.
333
+ * @see {EventPluginHub.extractEvents}
334
+ */
335
+ extractEvents: function(
336
+ topLevelType,
337
+ topLevelTarget,
338
+ topLevelTargetID,
339
+ nativeEvent) {
340
+
341
+ var getTargetIDFunc, handleEventFunc;
342
+ if (shouldUseChangeEvent(topLevelTarget)) {
343
+ if (doesChangeEventBubble) {
344
+ getTargetIDFunc = getTargetIDForChangeEvent;
345
+ } else {
346
+ handleEventFunc = handleEventsForChangeEventIE8;
347
+ }
348
+ } else if (isTextInputElement(topLevelTarget)) {
349
+ if (isInputEventSupported) {
350
+ getTargetIDFunc = getTargetIDForInputEvent;
351
+ } else {
352
+ getTargetIDFunc = getTargetIDForInputEventIE;
353
+ handleEventFunc = handleEventsForInputEventIE;
354
+ }
355
+ } else if (shouldUseClickEvent(topLevelTarget)) {
356
+ getTargetIDFunc = getTargetIDForClickEvent;
357
+ }
358
+
359
+ if (getTargetIDFunc) {
360
+ var targetID = getTargetIDFunc(
361
+ topLevelType,
362
+ topLevelTarget,
363
+ topLevelTargetID
364
+ );
365
+ if (targetID) {
366
+ var event = SyntheticEvent.getPooled(
367
+ eventTypes.change,
368
+ targetID,
369
+ nativeEvent
370
+ );
371
+ EventPropagators.accumulateTwoPhaseDispatches(event);
372
+ return event;
373
+ }
374
+ }
375
+
376
+ if (handleEventFunc) {
377
+ handleEventFunc(
378
+ topLevelType,
379
+ topLevelTarget,
380
+ topLevelTargetID
381
+ );
382
+ }
383
+ }
384
+
385
+ };
386
+
387
+ module.exports = ChangeEventPlugin;