react 0.7.1 → 0.10.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 (223) hide show
  1. package/README.md +10 -231
  2. package/addons.js +1 -0
  3. package/lib/AutoFocusMixin.js +32 -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 +171 -0
  11. package/lib/DOMProperty.js +270 -0
  12. package/lib/DOMPropertyOperations.js +181 -0
  13. package/lib/Danger.js +187 -0
  14. package/lib/DefaultDOMPropertyConfig.js +196 -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 +295 -0
  20. package/lib/EventPluginRegistry.js +281 -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 +160 -0
  26. package/lib/MobileSafariClickEventPlugin.js +63 -0
  27. package/lib/PooledClass.js +119 -0
  28. package/lib/React.js +97 -0
  29. package/lib/ReactBrowserComponentMixin.js +42 -0
  30. package/lib/ReactCSSTransitionGroup.js +65 -0
  31. package/lib/ReactCSSTransitionGroupChild.js +138 -0
  32. package/lib/ReactChildren.js +132 -0
  33. package/lib/ReactComponent.js +595 -0
  34. package/lib/ReactComponentBrowserEnvironment.js +124 -0
  35. package/lib/ReactCompositeComponent.js +1587 -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 +69 -0
  40. package/lib/ReactDOMComponent.js +416 -0
  41. package/lib/ReactDOMForm.js +62 -0
  42. package/lib/ReactDOMIDOperations.js +218 -0
  43. package/lib/ReactDOMImg.js +61 -0
  44. package/lib/ReactDOMInput.js +182 -0
  45. package/lib/ReactDOMOption.js +55 -0
  46. package/lib/ReactDOMSelect.js +180 -0
  47. package/lib/ReactDOMSelection.js +189 -0
  48. package/lib/ReactDOMTextarea.js +144 -0
  49. package/lib/ReactDefaultBatchingStrategy.js +75 -0
  50. package/lib/ReactDefaultInjection.js +125 -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 +339 -0
  55. package/lib/ReactEventEmitterMixin.js +57 -0
  56. package/lib/ReactEventTopLevelCallback.js +149 -0
  57. package/lib/ReactInjection.js +43 -0
  58. package/lib/ReactInputSelection.js +141 -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 +649 -0
  63. package/lib/ReactMountReady.js +95 -0
  64. package/lib/ReactMultiChild.js +432 -0
  65. package/lib/ReactMultiChildUpdateTypes.js +38 -0
  66. package/lib/ReactOwner.js +159 -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 +182 -0
  74. package/lib/ReactRootIndex.js +36 -0
  75. package/lib/ReactServerRendering.js +89 -0
  76. package/lib/ReactServerRenderingTransaction.js +116 -0
  77. package/lib/ReactStateSetters.js +111 -0
  78. package/lib/ReactTestUtils.js +394 -0
  79. package/lib/ReactTextComponent.js +121 -0
  80. package/lib/ReactTransitionChildMapping.js +106 -0
  81. package/lib/ReactTransitionEvents.js +97 -0
  82. package/lib/ReactTransitionGroup.js +187 -0
  83. package/lib/ReactUpdates.js +148 -0
  84. package/lib/ReactWithAddons.js +53 -0
  85. package/lib/SelectEventPlugin.js +200 -0
  86. package/lib/ServerReactRootIndex.js +36 -0
  87. package/lib/SimpleEventPlugin.js +413 -0
  88. package/lib/SyntheticClipboardEvent.js +51 -0
  89. package/lib/SyntheticCompositionEvent.js +51 -0
  90. package/lib/SyntheticDragEvent.js +44 -0
  91. package/lib/SyntheticEvent.js +164 -0
  92. package/lib/SyntheticFocusEvent.js +44 -0
  93. package/lib/SyntheticKeyboardEvent.js +58 -0
  94. package/lib/SyntheticMouseEvent.js +85 -0
  95. package/lib/SyntheticTouchEvent.js +50 -0
  96. package/lib/SyntheticUIEvent.js +45 -0
  97. package/lib/SyntheticWheelEvent.js +66 -0
  98. package/lib/Transaction.js +276 -0
  99. package/lib/ViewportMetrics.js +37 -0
  100. package/lib/accumulate.js +54 -0
  101. package/lib/adler32.js +39 -0
  102. package/lib/cloneWithProps.js +59 -0
  103. package/lib/containsNode.js +49 -0
  104. package/lib/copyProperties.js +54 -0
  105. package/lib/createArrayFrom.js +91 -0
  106. package/lib/createFullPageComponent.js +63 -0
  107. package/lib/createNodesFromMarkup.js +93 -0
  108. package/lib/createObjectFrom.js +61 -0
  109. package/lib/cx.js +44 -0
  110. package/lib/dangerousStyleValue.js +57 -0
  111. package/lib/emptyFunction.js +43 -0
  112. package/lib/emptyObject.js +27 -0
  113. package/lib/escapeTextForBrowser.js +47 -0
  114. package/lib/flattenChildren.js +57 -0
  115. package/lib/focusNode.js +33 -0
  116. package/lib/forEachAccumulated.js +36 -0
  117. package/lib/getActiveElement.js +34 -0
  118. package/lib/getEventKey.js +85 -0
  119. package/lib/getEventTarget.js +36 -0
  120. package/lib/getMarkupWrap.js +118 -0
  121. package/lib/getNodeForCharacterOffset.js +80 -0
  122. package/lib/getReactRootElementInContainer.js +40 -0
  123. package/lib/getTextContentAccessor.js +42 -0
  124. package/lib/getUnboundedScrollPosition.js +45 -0
  125. package/lib/hyphenate.js +35 -0
  126. package/lib/instantiateReactComponent.js +70 -0
  127. package/lib/invariant.js +62 -0
  128. package/lib/isEventSupported.js +70 -0
  129. package/lib/isNode.js +33 -0
  130. package/lib/isTextInputElement.js +49 -0
  131. package/lib/isTextNode.js +30 -0
  132. package/lib/joinClasses.js +44 -0
  133. package/lib/keyMirror.js +58 -0
  134. package/lib/keyOf.js +41 -0
  135. package/lib/memoizeStringOnly.js +39 -0
  136. package/lib/merge.js +37 -0
  137. package/lib/mergeHelpers.js +136 -0
  138. package/lib/mergeInto.js +45 -0
  139. package/lib/mixInto.js +34 -0
  140. package/lib/monitorCodeUse.js +37 -0
  141. package/lib/objMap.js +47 -0
  142. package/lib/objMapKeyVal.js +47 -0
  143. package/lib/onlyChild.js +43 -0
  144. package/lib/performanceNow.js +42 -0
  145. package/lib/shallowEqual.js +49 -0
  146. package/lib/shouldUpdateReactComponent.js +61 -0
  147. package/lib/toArray.js +75 -0
  148. package/lib/traverseAllChildren.js +190 -0
  149. package/lib/update.js +159 -0
  150. package/lib/warning.js +48 -0
  151. package/package.json +33 -31
  152. package/react.js +1 -0
  153. package/.npmignore +0 -7
  154. package/.travis.yml +0 -7
  155. package/Jakefile.js +0 -39
  156. package/LICENSE +0 -19
  157. package/browser-test/dist.html +0 -90
  158. package/browser-test/index.html +0 -86
  159. package/browser-test/min.html +0 -90
  160. package/dist/react.js +0 -3141
  161. package/dist/react.min.js +0 -22
  162. package/doc/advanced.md +0 -175
  163. package/doc/color-def.graffle +0 -938
  164. package/doc/color-def.png +0 -0
  165. package/doc/simple.dot +0 -25
  166. package/doc/simple.png +0 -0
  167. package/examples/longer-example.js +0 -41
  168. package/examples/simple.js +0 -45
  169. package/examples/using-ast-directly.js +0 -30
  170. package/examples/using-events1.js +0 -79
  171. package/examples/using-log-events.js +0 -43
  172. package/lib/base-task.js +0 -120
  173. package/lib/cb-task.js +0 -84
  174. package/lib/core.js +0 -138
  175. package/lib/dsl.js +0 -138
  176. package/lib/error.js +0 -55
  177. package/lib/event-collector.js +0 -81
  178. package/lib/event-manager.js +0 -89
  179. package/lib/eventemitter.js +0 -20
  180. package/lib/finalcb-first-task.js +0 -68
  181. package/lib/finalcb-task.js +0 -65
  182. package/lib/id.js +0 -22
  183. package/lib/input-parser.js +0 -56
  184. package/lib/log-events.js +0 -101
  185. package/lib/parse.js +0 -41
  186. package/lib/promise-resolve.js +0 -50
  187. package/lib/promise-task.js +0 -93
  188. package/lib/react.js +0 -59
  189. package/lib/ret-task.js +0 -71
  190. package/lib/sprintf.js +0 -18
  191. package/lib/status.js +0 -14
  192. package/lib/task.js +0 -251
  193. package/lib/track-tasks.js +0 -74
  194. package/lib/validate.js +0 -159
  195. package/lib/vcon.js +0 -113
  196. package/lib/when-task.js +0 -84
  197. package/src/dist.build.requirejs +0 -20
  198. package/test/ast.mocha.js +0 -136
  199. package/test/cb-task.mocha.js +0 -220
  200. package/test/core-deferred.mocha.js +0 -143
  201. package/test/core-when.mocha.js +0 -96
  202. package/test/core.mocha.js +0 -589
  203. package/test/dsl.mocha.js +0 -352
  204. package/test/event-manager.mocha.js +0 -119
  205. package/test/exec-options.mocha.js +0 -48
  206. package/test/finalcb-task.mocha.js +0 -58
  207. package/test/input-parser.mocha.js +0 -86
  208. package/test/log-events.mocha.js +0 -88
  209. package/test/mocha.opts +0 -2
  210. package/test/module-use.mocha.js +0 -164
  211. package/test/promise-auto-resolve.mocha.js +0 -68
  212. package/test/ret-task.mocha.js +0 -220
  213. package/test/task.mocha.js +0 -42
  214. package/test/validate-cb-task.mocha.js +0 -100
  215. package/test/validate-ret-task.mocha.js +0 -110
  216. package/test/validate.mocha.js +0 -324
  217. package/test/vcon.mocha.js +0 -193
  218. package/vendor/chai/chai.js +0 -4251
  219. package/vendor/jquery/jquery-1.7.1.js +0 -9266
  220. package/vendor/jquery/jquery-1.7.1.min.js +0 -4
  221. package/vendor/node/util.js +0 -531
  222. package/vendor/requirejs/require.js +0 -2045
  223. package/vendor/requirejs/require.min.js +0 -36
@@ -0,0 +1,54 @@
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 ReactLink
17
+ * @typechecks static-only
18
+ */
19
+
20
+ "use strict";
21
+
22
+ /**
23
+ * ReactLink encapsulates a common pattern in which a component wants to modify
24
+ * a prop received from its parent. ReactLink allows the parent to pass down a
25
+ * value coupled with a callback that, when invoked, expresses an intent to
26
+ * modify that value. For example:
27
+ *
28
+ * React.createClass({
29
+ * getInitialState: function() {
30
+ * return {value: ''};
31
+ * },
32
+ * render: function() {
33
+ * var valueLink = new ReactLink(this.state.value, this._handleValueChange);
34
+ * return <input valueLink={valueLink} />;
35
+ * },
36
+ * this._handleValueChange: function(newValue) {
37
+ * this.setState({value: newValue});
38
+ * }
39
+ * });
40
+ *
41
+ * We have provided some sugary mixins to make the creation and
42
+ * consumption of ReactLink easier; see LinkedValueUtils and LinkedStateMixin.
43
+ */
44
+
45
+ /**
46
+ * @param {*} value current value of the link
47
+ * @param {function} requestChange callback to request a change
48
+ */
49
+ function ReactLink(value, requestChange) {
50
+ this.value = value;
51
+ this.requestChange = requestChange;
52
+ }
53
+
54
+ module.exports = ReactLink;
@@ -0,0 +1,53 @@
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 ReactMarkupChecksum
17
+ */
18
+
19
+ "use strict";
20
+
21
+ var adler32 = require("./adler32");
22
+
23
+ var ReactMarkupChecksum = {
24
+ CHECKSUM_ATTR_NAME: 'data-react-checksum',
25
+
26
+ /**
27
+ * @param {string} markup Markup string
28
+ * @return {string} Markup string with checksum attribute attached
29
+ */
30
+ addChecksumToMarkup: function(markup) {
31
+ var checksum = adler32(markup);
32
+ return markup.replace(
33
+ '>',
34
+ ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '="' + checksum + '">'
35
+ );
36
+ },
37
+
38
+ /**
39
+ * @param {string} markup to use
40
+ * @param {DOMElement} element root React element
41
+ * @returns {boolean} whether or not the markup is the same
42
+ */
43
+ canReuseMarkup: function(markup, element) {
44
+ var existingChecksum = element.getAttribute(
45
+ ReactMarkupChecksum.CHECKSUM_ATTR_NAME
46
+ );
47
+ existingChecksum = existingChecksum && parseInt(existingChecksum, 10);
48
+ var markupChecksum = adler32(markup);
49
+ return markupChecksum === existingChecksum;
50
+ }
51
+ };
52
+
53
+ module.exports = ReactMarkupChecksum;
@@ -0,0 +1,649 @@
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 ReactMount
17
+ */
18
+
19
+ "use strict";
20
+
21
+ var DOMProperty = require("./DOMProperty");
22
+ var ReactEventEmitter = require("./ReactEventEmitter");
23
+ var ReactInstanceHandles = require("./ReactInstanceHandles");
24
+ var ReactPerf = require("./ReactPerf");
25
+
26
+ var containsNode = require("./containsNode");
27
+ var getReactRootElementInContainer = require("./getReactRootElementInContainer");
28
+ var instantiateReactComponent = require("./instantiateReactComponent");
29
+ var invariant = require("./invariant");
30
+ var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
31
+
32
+ var SEPARATOR = ReactInstanceHandles.SEPARATOR;
33
+
34
+ var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
35
+ var nodeCache = {};
36
+
37
+ var ELEMENT_NODE_TYPE = 1;
38
+ var DOC_NODE_TYPE = 9;
39
+
40
+ /** Mapping from reactRootID to React component instance. */
41
+ var instancesByReactRootID = {};
42
+
43
+ /** Mapping from reactRootID to `container` nodes. */
44
+ var containersByReactRootID = {};
45
+
46
+ if ("production" !== process.env.NODE_ENV) {
47
+ /** __DEV__-only mapping from reactRootID to root elements. */
48
+ var rootElementsByReactRootID = {};
49
+ }
50
+
51
+ // Used to store breadth-first search state in findComponentRoot.
52
+ var findComponentRootReusableArray = [];
53
+
54
+ /**
55
+ * @param {DOMElement} container DOM element that may contain a React component.
56
+ * @return {?string} A "reactRoot" ID, if a React component is rendered.
57
+ */
58
+ function getReactRootID(container) {
59
+ var rootElement = getReactRootElementInContainer(container);
60
+ return rootElement && ReactMount.getID(rootElement);
61
+ }
62
+
63
+ /**
64
+ * Accessing node[ATTR_NAME] or calling getAttribute(ATTR_NAME) on a form
65
+ * element can return its control whose name or ID equals ATTR_NAME. All
66
+ * DOM nodes support `getAttributeNode` but this can also get called on
67
+ * other objects so just return '' if we're given something other than a
68
+ * DOM node (such as window).
69
+ *
70
+ * @param {?DOMElement|DOMWindow|DOMDocument|DOMTextNode} node DOM node.
71
+ * @return {string} ID of the supplied `domNode`.
72
+ */
73
+ function getID(node) {
74
+ var id = internalGetID(node);
75
+ if (id) {
76
+ if (nodeCache.hasOwnProperty(id)) {
77
+ var cached = nodeCache[id];
78
+ if (cached !== node) {
79
+ ("production" !== process.env.NODE_ENV ? invariant(
80
+ !isValid(cached, id),
81
+ 'ReactMount: Two valid but unequal nodes with the same `%s`: %s',
82
+ ATTR_NAME, id
83
+ ) : invariant(!isValid(cached, id)));
84
+
85
+ nodeCache[id] = node;
86
+ }
87
+ } else {
88
+ nodeCache[id] = node;
89
+ }
90
+ }
91
+
92
+ return id;
93
+ }
94
+
95
+ function internalGetID(node) {
96
+ // If node is something like a window, document, or text node, none of
97
+ // which support attributes or a .getAttribute method, gracefully return
98
+ // the empty string, as if the attribute were missing.
99
+ return node && node.getAttribute && node.getAttribute(ATTR_NAME) || '';
100
+ }
101
+
102
+ /**
103
+ * Sets the React-specific ID of the given node.
104
+ *
105
+ * @param {DOMElement} node The DOM node whose ID will be set.
106
+ * @param {string} id The value of the ID attribute.
107
+ */
108
+ function setID(node, id) {
109
+ var oldID = internalGetID(node);
110
+ if (oldID !== id) {
111
+ delete nodeCache[oldID];
112
+ }
113
+ node.setAttribute(ATTR_NAME, id);
114
+ nodeCache[id] = node;
115
+ }
116
+
117
+ /**
118
+ * Finds the node with the supplied React-generated DOM ID.
119
+ *
120
+ * @param {string} id A React-generated DOM ID.
121
+ * @return {DOMElement} DOM node with the suppled `id`.
122
+ * @internal
123
+ */
124
+ function getNode(id) {
125
+ if (!nodeCache.hasOwnProperty(id) || !isValid(nodeCache[id], id)) {
126
+ nodeCache[id] = ReactMount.findReactNodeByID(id);
127
+ }
128
+ return nodeCache[id];
129
+ }
130
+
131
+ /**
132
+ * A node is "valid" if it is contained by a currently mounted container.
133
+ *
134
+ * This means that the node does not have to be contained by a document in
135
+ * order to be considered valid.
136
+ *
137
+ * @param {?DOMElement} node The candidate DOM node.
138
+ * @param {string} id The expected ID of the node.
139
+ * @return {boolean} Whether the node is contained by a mounted container.
140
+ */
141
+ function isValid(node, id) {
142
+ if (node) {
143
+ ("production" !== process.env.NODE_ENV ? invariant(
144
+ internalGetID(node) === id,
145
+ 'ReactMount: Unexpected modification of `%s`',
146
+ ATTR_NAME
147
+ ) : invariant(internalGetID(node) === id));
148
+
149
+ var container = ReactMount.findReactContainerForID(id);
150
+ if (container && containsNode(container, node)) {
151
+ return true;
152
+ }
153
+ }
154
+
155
+ return false;
156
+ }
157
+
158
+ /**
159
+ * Causes the cache to forget about one React-specific ID.
160
+ *
161
+ * @param {string} id The ID to forget.
162
+ */
163
+ function purgeID(id) {
164
+ delete nodeCache[id];
165
+ }
166
+
167
+ var deepestNodeSoFar = null;
168
+ function findDeepestCachedAncestorImpl(ancestorID) {
169
+ var ancestor = nodeCache[ancestorID];
170
+ if (ancestor && isValid(ancestor, ancestorID)) {
171
+ deepestNodeSoFar = ancestor;
172
+ } else {
173
+ // This node isn't populated in the cache, so presumably none of its
174
+ // descendants are. Break out of the loop.
175
+ return false;
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Return the deepest cached node whose ID is a prefix of `targetID`.
181
+ */
182
+ function findDeepestCachedAncestor(targetID) {
183
+ deepestNodeSoFar = null;
184
+ ReactInstanceHandles.traverseAncestors(
185
+ targetID,
186
+ findDeepestCachedAncestorImpl
187
+ );
188
+
189
+ var foundNode = deepestNodeSoFar;
190
+ deepestNodeSoFar = null;
191
+ return foundNode;
192
+ }
193
+
194
+ /**
195
+ * Mounting is the process of initializing a React component by creatings its
196
+ * representative DOM elements and inserting them into a supplied `container`.
197
+ * Any prior content inside `container` is destroyed in the process.
198
+ *
199
+ * ReactMount.renderComponent(
200
+ * component,
201
+ * document.getElementById('container')
202
+ * );
203
+ *
204
+ * <div id="container"> <-- Supplied `container`.
205
+ * <div data-reactid=".3"> <-- Rendered reactRoot of React
206
+ * // ... component.
207
+ * </div>
208
+ * </div>
209
+ *
210
+ * Inside of `container`, the first element rendered is the "reactRoot".
211
+ */
212
+ var ReactMount = {
213
+ /** Time spent generating markup. */
214
+ totalInstantiationTime: 0,
215
+
216
+ /** Time spent inserting markup into the DOM. */
217
+ totalInjectionTime: 0,
218
+
219
+ /** Whether support for touch events should be initialized. */
220
+ useTouchEvents: false,
221
+
222
+ /** Exposed for debugging purposes **/
223
+ _instancesByReactRootID: instancesByReactRootID,
224
+
225
+ /**
226
+ * This is a hook provided to support rendering React components while
227
+ * ensuring that the apparent scroll position of its `container` does not
228
+ * change.
229
+ *
230
+ * @param {DOMElement} container The `container` being rendered into.
231
+ * @param {function} renderCallback This must be called once to do the render.
232
+ */
233
+ scrollMonitor: function(container, renderCallback) {
234
+ renderCallback();
235
+ },
236
+
237
+ /**
238
+ * Take a component that's already mounted into the DOM and replace its props
239
+ * @param {ReactComponent} prevComponent component instance already in the DOM
240
+ * @param {ReactComponent} nextComponent component instance to render
241
+ * @param {DOMElement} container container to render into
242
+ * @param {?function} callback function triggered on completion
243
+ */
244
+ _updateRootComponent: function(
245
+ prevComponent,
246
+ nextComponent,
247
+ container,
248
+ callback) {
249
+ var nextProps = nextComponent.props;
250
+ ReactMount.scrollMonitor(container, function() {
251
+ prevComponent.replaceProps(nextProps, callback);
252
+ });
253
+
254
+ if ("production" !== process.env.NODE_ENV) {
255
+ // Record the root element in case it later gets transplanted.
256
+ rootElementsByReactRootID[getReactRootID(container)] =
257
+ getReactRootElementInContainer(container);
258
+ }
259
+
260
+ return prevComponent;
261
+ },
262
+
263
+ /**
264
+ * Register a component into the instance map and starts scroll value
265
+ * monitoring
266
+ * @param {ReactComponent} nextComponent component instance to render
267
+ * @param {DOMElement} container container to render into
268
+ * @return {string} reactRoot ID prefix
269
+ */
270
+ _registerComponent: function(nextComponent, container) {
271
+ ("production" !== process.env.NODE_ENV ? invariant(
272
+ container && (
273
+ container.nodeType === ELEMENT_NODE_TYPE ||
274
+ container.nodeType === DOC_NODE_TYPE
275
+ ),
276
+ '_registerComponent(...): Target container is not a DOM element.'
277
+ ) : invariant(container && (
278
+ container.nodeType === ELEMENT_NODE_TYPE ||
279
+ container.nodeType === DOC_NODE_TYPE
280
+ )));
281
+
282
+ ReactEventEmitter.ensureScrollValueMonitoring();
283
+
284
+ var reactRootID = ReactMount.registerContainer(container);
285
+ instancesByReactRootID[reactRootID] = nextComponent;
286
+ return reactRootID;
287
+ },
288
+
289
+ /**
290
+ * Render a new component into the DOM.
291
+ * @param {ReactComponent} nextComponent component instance to render
292
+ * @param {DOMElement} container container to render into
293
+ * @param {boolean} shouldReuseMarkup if we should skip the markup insertion
294
+ * @return {ReactComponent} nextComponent
295
+ */
296
+ _renderNewRootComponent: ReactPerf.measure(
297
+ 'ReactMount',
298
+ '_renderNewRootComponent',
299
+ function(
300
+ nextComponent,
301
+ container,
302
+ shouldReuseMarkup) {
303
+
304
+ var componentInstance = instantiateReactComponent(nextComponent);
305
+ var reactRootID = ReactMount._registerComponent(
306
+ componentInstance,
307
+ container
308
+ );
309
+ componentInstance.mountComponentIntoNode(
310
+ reactRootID,
311
+ container,
312
+ shouldReuseMarkup
313
+ );
314
+
315
+ if ("production" !== process.env.NODE_ENV) {
316
+ // Record the root element in case it later gets transplanted.
317
+ rootElementsByReactRootID[reactRootID] =
318
+ getReactRootElementInContainer(container);
319
+ }
320
+
321
+ return componentInstance;
322
+ }
323
+ ),
324
+
325
+ /**
326
+ * Renders a React component into the DOM in the supplied `container`.
327
+ *
328
+ * If the React component was previously rendered into `container`, this will
329
+ * perform an update on it and only mutate the DOM as necessary to reflect the
330
+ * latest React component.
331
+ *
332
+ * @param {ReactComponent} nextComponent Component instance to render.
333
+ * @param {DOMElement} container DOM element to render into.
334
+ * @param {?function} callback function triggered on completion
335
+ * @return {ReactComponent} Component instance rendered in `container`.
336
+ */
337
+ renderComponent: function(nextComponent, container, callback) {
338
+ var prevComponent = instancesByReactRootID[getReactRootID(container)];
339
+
340
+ if (prevComponent) {
341
+ if (shouldUpdateReactComponent(prevComponent, nextComponent)) {
342
+ return ReactMount._updateRootComponent(
343
+ prevComponent,
344
+ nextComponent,
345
+ container,
346
+ callback
347
+ );
348
+ } else {
349
+ ReactMount.unmountComponentAtNode(container);
350
+ }
351
+ }
352
+
353
+ var reactRootElement = getReactRootElementInContainer(container);
354
+ var containerHasReactMarkup =
355
+ reactRootElement && ReactMount.isRenderedByReact(reactRootElement);
356
+
357
+ var shouldReuseMarkup = containerHasReactMarkup && !prevComponent;
358
+
359
+ var component = ReactMount._renderNewRootComponent(
360
+ nextComponent,
361
+ container,
362
+ shouldReuseMarkup
363
+ );
364
+ callback && callback.call(component);
365
+ return component;
366
+ },
367
+
368
+ /**
369
+ * Constructs a component instance of `constructor` with `initialProps` and
370
+ * renders it into the supplied `container`.
371
+ *
372
+ * @param {function} constructor React component constructor.
373
+ * @param {?object} props Initial props of the component instance.
374
+ * @param {DOMElement} container DOM element to render into.
375
+ * @return {ReactComponent} Component instance rendered in `container`.
376
+ */
377
+ constructAndRenderComponent: function(constructor, props, container) {
378
+ return ReactMount.renderComponent(constructor(props), container);
379
+ },
380
+
381
+ /**
382
+ * Constructs a component instance of `constructor` with `initialProps` and
383
+ * renders it into a container node identified by supplied `id`.
384
+ *
385
+ * @param {function} componentConstructor React component constructor
386
+ * @param {?object} props Initial props of the component instance.
387
+ * @param {string} id ID of the DOM element to render into.
388
+ * @return {ReactComponent} Component instance rendered in the container node.
389
+ */
390
+ constructAndRenderComponentByID: function(constructor, props, id) {
391
+ var domNode = document.getElementById(id);
392
+ ("production" !== process.env.NODE_ENV ? invariant(
393
+ domNode,
394
+ 'Tried to get element with id of "%s" but it is not present on the page.',
395
+ id
396
+ ) : invariant(domNode));
397
+ return ReactMount.constructAndRenderComponent(constructor, props, domNode);
398
+ },
399
+
400
+ /**
401
+ * Registers a container node into which React components will be rendered.
402
+ * This also creates the "reactRoot" ID that will be assigned to the element
403
+ * rendered within.
404
+ *
405
+ * @param {DOMElement} container DOM element to register as a container.
406
+ * @return {string} The "reactRoot" ID of elements rendered within.
407
+ */
408
+ registerContainer: function(container) {
409
+ var reactRootID = getReactRootID(container);
410
+ if (reactRootID) {
411
+ // If one exists, make sure it is a valid "reactRoot" ID.
412
+ reactRootID = ReactInstanceHandles.getReactRootIDFromNodeID(reactRootID);
413
+ }
414
+ if (!reactRootID) {
415
+ // No valid "reactRoot" ID found, create one.
416
+ reactRootID = ReactInstanceHandles.createReactRootID();
417
+ }
418
+ containersByReactRootID[reactRootID] = container;
419
+ return reactRootID;
420
+ },
421
+
422
+ /**
423
+ * Unmounts and destroys the React component rendered in the `container`.
424
+ *
425
+ * @param {DOMElement} container DOM element containing a React component.
426
+ * @return {boolean} True if a component was found in and unmounted from
427
+ * `container`
428
+ */
429
+ unmountComponentAtNode: function(container) {
430
+ var reactRootID = getReactRootID(container);
431
+ var component = instancesByReactRootID[reactRootID];
432
+ if (!component) {
433
+ return false;
434
+ }
435
+ ReactMount.unmountComponentFromNode(component, container);
436
+ delete instancesByReactRootID[reactRootID];
437
+ delete containersByReactRootID[reactRootID];
438
+ if ("production" !== process.env.NODE_ENV) {
439
+ delete rootElementsByReactRootID[reactRootID];
440
+ }
441
+ return true;
442
+ },
443
+
444
+ /**
445
+ * Unmounts a component and removes it from the DOM.
446
+ *
447
+ * @param {ReactComponent} instance React component instance.
448
+ * @param {DOMElement} container DOM element to unmount from.
449
+ * @final
450
+ * @internal
451
+ * @see {ReactMount.unmountComponentAtNode}
452
+ */
453
+ unmountComponentFromNode: function(instance, container) {
454
+ instance.unmountComponent();
455
+
456
+ if (container.nodeType === DOC_NODE_TYPE) {
457
+ container = container.documentElement;
458
+ }
459
+
460
+ // http://jsperf.com/emptying-a-node
461
+ while (container.lastChild) {
462
+ container.removeChild(container.lastChild);
463
+ }
464
+ },
465
+
466
+ /**
467
+ * Finds the container DOM element that contains React component to which the
468
+ * supplied DOM `id` belongs.
469
+ *
470
+ * @param {string} id The ID of an element rendered by a React component.
471
+ * @return {?DOMElement} DOM element that contains the `id`.
472
+ */
473
+ findReactContainerForID: function(id) {
474
+ var reactRootID = ReactInstanceHandles.getReactRootIDFromNodeID(id);
475
+ var container = containersByReactRootID[reactRootID];
476
+
477
+ if ("production" !== process.env.NODE_ENV) {
478
+ var rootElement = rootElementsByReactRootID[reactRootID];
479
+ if (rootElement && rootElement.parentNode !== container) {
480
+ ("production" !== process.env.NODE_ENV ? invariant(
481
+ // Call internalGetID here because getID calls isValid which calls
482
+ // findReactContainerForID (this function).
483
+ internalGetID(rootElement) === reactRootID,
484
+ 'ReactMount: Root element ID differed from reactRootID.'
485
+ ) : invariant(// Call internalGetID here because getID calls isValid which calls
486
+ // findReactContainerForID (this function).
487
+ internalGetID(rootElement) === reactRootID));
488
+
489
+ var containerChild = container.firstChild;
490
+ if (containerChild &&
491
+ reactRootID === internalGetID(containerChild)) {
492
+ // If the container has a new child with the same ID as the old
493
+ // root element, then rootElementsByReactRootID[reactRootID] is
494
+ // just stale and needs to be updated. The case that deserves a
495
+ // warning is when the container is empty.
496
+ rootElementsByReactRootID[reactRootID] = containerChild;
497
+ } else {
498
+ console.warn(
499
+ 'ReactMount: Root element has been removed from its original ' +
500
+ 'container. New container:', rootElement.parentNode
501
+ );
502
+ }
503
+ }
504
+ }
505
+
506
+ return container;
507
+ },
508
+
509
+ /**
510
+ * Finds an element rendered by React with the supplied ID.
511
+ *
512
+ * @param {string} id ID of a DOM node in the React component.
513
+ * @return {DOMElement} Root DOM node of the React component.
514
+ */
515
+ findReactNodeByID: function(id) {
516
+ var reactRoot = ReactMount.findReactContainerForID(id);
517
+ return ReactMount.findComponentRoot(reactRoot, id);
518
+ },
519
+
520
+ /**
521
+ * True if the supplied `node` is rendered by React.
522
+ *
523
+ * @param {*} node DOM Element to check.
524
+ * @return {boolean} True if the DOM Element appears to be rendered by React.
525
+ * @internal
526
+ */
527
+ isRenderedByReact: function(node) {
528
+ if (node.nodeType !== 1) {
529
+ // Not a DOMElement, therefore not a React component
530
+ return false;
531
+ }
532
+ var id = ReactMount.getID(node);
533
+ return id ? id.charAt(0) === SEPARATOR : false;
534
+ },
535
+
536
+ /**
537
+ * Traverses up the ancestors of the supplied node to find a node that is a
538
+ * DOM representation of a React component.
539
+ *
540
+ * @param {*} node
541
+ * @return {?DOMEventTarget}
542
+ * @internal
543
+ */
544
+ getFirstReactDOM: function(node) {
545
+ var current = node;
546
+ while (current && current.parentNode !== current) {
547
+ if (ReactMount.isRenderedByReact(current)) {
548
+ return current;
549
+ }
550
+ current = current.parentNode;
551
+ }
552
+ return null;
553
+ },
554
+
555
+ /**
556
+ * Finds a node with the supplied `targetID` inside of the supplied
557
+ * `ancestorNode`. Exploits the ID naming scheme to perform the search
558
+ * quickly.
559
+ *
560
+ * @param {DOMEventTarget} ancestorNode Search from this root.
561
+ * @pararm {string} targetID ID of the DOM representation of the component.
562
+ * @return {DOMEventTarget} DOM node with the supplied `targetID`.
563
+ * @internal
564
+ */
565
+ findComponentRoot: function(ancestorNode, targetID) {
566
+ var firstChildren = findComponentRootReusableArray;
567
+ var childIndex = 0;
568
+
569
+ var deepestAncestor = findDeepestCachedAncestor(targetID) || ancestorNode;
570
+
571
+ firstChildren[0] = deepestAncestor.firstChild;
572
+ firstChildren.length = 1;
573
+
574
+ while (childIndex < firstChildren.length) {
575
+ var child = firstChildren[childIndex++];
576
+ var targetChild;
577
+
578
+ while (child) {
579
+ var childID = ReactMount.getID(child);
580
+ if (childID) {
581
+ // Even if we find the node we're looking for, we finish looping
582
+ // through its siblings to ensure they're cached so that we don't have
583
+ // to revisit this node again. Otherwise, we make n^2 calls to getID
584
+ // when visiting the many children of a single node in order.
585
+
586
+ if (targetID === childID) {
587
+ targetChild = child;
588
+ } else if (ReactInstanceHandles.isAncestorIDOf(childID, targetID)) {
589
+ // If we find a child whose ID is an ancestor of the given ID,
590
+ // then we can be sure that we only want to search the subtree
591
+ // rooted at this child, so we can throw out the rest of the
592
+ // search state.
593
+ firstChildren.length = childIndex = 0;
594
+ firstChildren.push(child.firstChild);
595
+ }
596
+
597
+ } else {
598
+ // If this child had no ID, then there's a chance that it was
599
+ // injected automatically by the browser, as when a `<table>`
600
+ // element sprouts an extra `<tbody>` child as a side effect of
601
+ // `.innerHTML` parsing. Optimistically continue down this
602
+ // branch, but not before examining the other siblings.
603
+ firstChildren.push(child.firstChild);
604
+ }
605
+
606
+ child = child.nextSibling;
607
+ }
608
+
609
+ if (targetChild) {
610
+ // Emptying firstChildren/findComponentRootReusableArray is
611
+ // not necessary for correctness, but it helps the GC reclaim
612
+ // any nodes that were left at the end of the search.
613
+ firstChildren.length = 0;
614
+
615
+ return targetChild;
616
+ }
617
+ }
618
+
619
+ firstChildren.length = 0;
620
+
621
+ ("production" !== process.env.NODE_ENV ? invariant(
622
+ false,
623
+ 'findComponentRoot(..., %s): Unable to find element. This probably ' +
624
+ 'means the DOM was unexpectedly mutated (e.g., by the browser), ' +
625
+ 'usually due to forgetting a <tbody> when using tables or nesting <p> ' +
626
+ 'or <a> tags. Try inspecting the child nodes of the element with React ' +
627
+ 'ID `%s`.',
628
+ targetID,
629
+ ReactMount.getID(ancestorNode)
630
+ ) : invariant(false));
631
+ },
632
+
633
+
634
+ /**
635
+ * React ID utilities.
636
+ */
637
+
638
+ getReactRootID: getReactRootID,
639
+
640
+ getID: getID,
641
+
642
+ setID: setID,
643
+
644
+ getNode: getNode,
645
+
646
+ purgeID: purgeID
647
+ };
648
+
649
+ module.exports = ReactMount;