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