react 0.6.2 → 0.8.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 (204) hide show
  1. package/README.md +15 -217
  2. package/ReactJSErrors.js +40 -0
  3. package/addons.js +4 -0
  4. package/lib/$.js +46 -0
  5. package/lib/CSSCore.js +114 -0
  6. package/lib/CSSProperty.js +90 -0
  7. package/lib/CSSPropertyOperations.js +97 -0
  8. package/lib/CallbackRegistry.js +91 -0
  9. package/lib/ChangeEventPlugin.js +365 -0
  10. package/lib/CompositionEventPlugin.js +212 -0
  11. package/lib/DOMChildrenOperations.js +135 -0
  12. package/lib/DOMProperty.js +266 -0
  13. package/lib/DOMPropertyOperations.js +168 -0
  14. package/lib/Danger.js +186 -0
  15. package/lib/DefaultDOMPropertyConfig.js +187 -0
  16. package/lib/DefaultEventPluginOrder.js +44 -0
  17. package/lib/EnterLeaveEventPlugin.js +112 -0
  18. package/lib/EventConstants.js +73 -0
  19. package/lib/EventListener.js +61 -0
  20. package/lib/EventPluginHub.js +190 -0
  21. package/lib/EventPluginRegistry.js +237 -0
  22. package/lib/EventPluginUtils.js +185 -0
  23. package/lib/EventPropagators.js +179 -0
  24. package/lib/ExecutionEnvironment.js +41 -0
  25. package/lib/LinkedStateMixin.js +46 -0
  26. package/lib/LinkedValueMixin.js +68 -0
  27. package/lib/MobileSafariClickEventPlugin.js +63 -0
  28. package/lib/PooledClass.js +113 -0
  29. package/lib/React.js +71 -0
  30. package/lib/ReactChildren.js +132 -0
  31. package/lib/ReactComponent.js +515 -0
  32. package/lib/ReactComponentBrowserEnvironment.js +140 -0
  33. package/lib/ReactComponentEnvironment.js +24 -0
  34. package/lib/ReactCompositeComponent.js +1020 -0
  35. package/lib/ReactCurrentOwner.js +39 -0
  36. package/lib/ReactDOM.js +194 -0
  37. package/lib/ReactDOMButton.js +64 -0
  38. package/lib/ReactDOMComponent.js +374 -0
  39. package/lib/ReactDOMForm.js +52 -0
  40. package/lib/ReactDOMIDOperations.js +173 -0
  41. package/lib/ReactDOMInput.js +169 -0
  42. package/lib/ReactDOMOption.js +50 -0
  43. package/lib/ReactDOMSelect.js +160 -0
  44. package/lib/ReactDOMSelection.js +189 -0
  45. package/lib/ReactDOMTextarea.js +136 -0
  46. package/lib/ReactDefaultBatchingStrategy.js +75 -0
  47. package/lib/ReactDefaultInjection.js +91 -0
  48. package/lib/ReactDefaultPerf.js +407 -0
  49. package/lib/ReactErrorUtils.js +46 -0
  50. package/lib/ReactEventEmitter.js +341 -0
  51. package/lib/ReactEventEmitterMixin.js +89 -0
  52. package/lib/ReactEventTopLevelCallback.js +89 -0
  53. package/lib/ReactInputSelection.js +140 -0
  54. package/lib/ReactInstanceHandles.js +322 -0
  55. package/lib/ReactLink.js +54 -0
  56. package/lib/ReactMarkupChecksum.js +53 -0
  57. package/lib/ReactMount.js +617 -0
  58. package/lib/ReactMountReady.js +95 -0
  59. package/lib/ReactMultiChild.js +441 -0
  60. package/lib/ReactMultiChildUpdateTypes.js +36 -0
  61. package/lib/ReactOwner.js +146 -0
  62. package/lib/ReactPerf.js +88 -0
  63. package/lib/ReactPropTransferer.js +128 -0
  64. package/lib/ReactPropTypes.js +158 -0
  65. package/lib/ReactReconcileTransaction.js +161 -0
  66. package/lib/ReactServerRendering.js +62 -0
  67. package/lib/ReactStateSetters.js +111 -0
  68. package/lib/ReactTextComponent.js +94 -0
  69. package/lib/ReactTransitionEvents.js +97 -0
  70. package/lib/ReactTransitionGroup.js +112 -0
  71. package/lib/ReactTransitionKeySet.js +111 -0
  72. package/lib/ReactTransitionableChild.js +152 -0
  73. package/lib/ReactUpdates.js +145 -0
  74. package/lib/ReactWithAddons.js +41 -0
  75. package/lib/SelectEventPlugin.js +217 -0
  76. package/lib/SimpleEventPlugin.js +365 -0
  77. package/lib/SyntheticClipboardEvent.js +45 -0
  78. package/lib/SyntheticCompositionEvent.js +51 -0
  79. package/lib/SyntheticEvent.js +163 -0
  80. package/lib/SyntheticFocusEvent.js +44 -0
  81. package/lib/SyntheticKeyboardEvent.js +56 -0
  82. package/lib/SyntheticMouseEvent.js +85 -0
  83. package/lib/SyntheticTouchEvent.js +50 -0
  84. package/lib/SyntheticUIEvent.js +45 -0
  85. package/lib/SyntheticWheelEvent.js +63 -0
  86. package/lib/Transaction.js +251 -0
  87. package/lib/ViewportMetrics.js +37 -0
  88. package/lib/accumulate.js +54 -0
  89. package/lib/adler32.js +39 -0
  90. package/lib/containsNode.js +49 -0
  91. package/lib/copyProperties.js +54 -0
  92. package/lib/createArrayFrom.js +94 -0
  93. package/lib/createNodesFromMarkup.js +93 -0
  94. package/lib/createObjectFrom.js +61 -0
  95. package/lib/cx.js +44 -0
  96. package/lib/dangerousStyleValue.js +57 -0
  97. package/lib/emptyFunction.js +43 -0
  98. package/lib/escapeTextForBrowser.js +47 -0
  99. package/lib/ex.js +49 -0
  100. package/lib/filterAttributes.js +45 -0
  101. package/lib/flattenChildren.js +54 -0
  102. package/lib/forEachAccumulated.js +36 -0
  103. package/lib/ge.js +76 -0
  104. package/lib/getActiveElement.js +33 -0
  105. package/lib/getEventTarget.js +36 -0
  106. package/lib/getMarkupWrap.js +108 -0
  107. package/lib/getNodeForCharacterOffset.js +80 -0
  108. package/lib/getReactRootElementInContainer.js +40 -0
  109. package/lib/getTextContentAccessor.js +40 -0
  110. package/lib/getUnboundedScrollPosition.js +45 -0
  111. package/lib/hyphenate.js +35 -0
  112. package/lib/invariant.js +54 -0
  113. package/lib/isEventSupported.js +74 -0
  114. package/lib/isNode.js +33 -0
  115. package/lib/isTextInputElement.js +49 -0
  116. package/lib/isTextNode.js +30 -0
  117. package/lib/joinClasses.js +44 -0
  118. package/lib/keyMirror.js +58 -0
  119. package/lib/keyOf.js +41 -0
  120. package/lib/memoizeStringOnly.js +39 -0
  121. package/lib/merge.js +37 -0
  122. package/lib/mergeHelpers.js +137 -0
  123. package/lib/mergeInto.js +45 -0
  124. package/lib/mixInto.js +34 -0
  125. package/lib/mutateHTMLNodeWithMarkup.js +100 -0
  126. package/lib/objMap.js +47 -0
  127. package/lib/objMapKeyVal.js +47 -0
  128. package/lib/performanceNow.js +42 -0
  129. package/lib/shallowEqual.js +49 -0
  130. package/lib/traverseAllChildren.js +127 -0
  131. package/package.json +33 -21
  132. package/react.js +4 -0
  133. package/.npmignore +0 -7
  134. package/.travis.yml +0 -5
  135. package/Jakefile.js +0 -39
  136. package/LICENSE +0 -19
  137. package/browser-test/dist.html +0 -89
  138. package/browser-test/index.html +0 -85
  139. package/browser-test/min.html +0 -89
  140. package/dist/react.js +0 -3094
  141. package/dist/react.min.js +0 -22
  142. package/doc/advanced.md +0 -166
  143. package/doc/color-def.graffle +0 -938
  144. package/doc/color-def.png +0 -0
  145. package/doc/simple.dot +0 -25
  146. package/doc/simple.png +0 -0
  147. package/examples/longer-example.js +0 -41
  148. package/examples/simple.js +0 -45
  149. package/examples/using-ast-directly.js +0 -30
  150. package/examples/using-events1.js +0 -79
  151. package/examples/using-log-events.js +0 -43
  152. package/lib/base-task.js +0 -123
  153. package/lib/cb-task.js +0 -84
  154. package/lib/core.js +0 -138
  155. package/lib/dsl.js +0 -138
  156. package/lib/error.js +0 -55
  157. package/lib/event-collector.js +0 -81
  158. package/lib/event-manager.js +0 -85
  159. package/lib/eventemitter.js +0 -20
  160. package/lib/finalcb-first-task.js +0 -68
  161. package/lib/finalcb-task.js +0 -65
  162. package/lib/id.js +0 -22
  163. package/lib/input-parser.js +0 -56
  164. package/lib/log-events.js +0 -92
  165. package/lib/parse.js +0 -41
  166. package/lib/promise-resolve.js +0 -50
  167. package/lib/promise-task.js +0 -93
  168. package/lib/react.js +0 -59
  169. package/lib/ret-task.js +0 -71
  170. package/lib/sprintf.js +0 -18
  171. package/lib/status.js +0 -14
  172. package/lib/task.js +0 -251
  173. package/lib/track-tasks.js +0 -74
  174. package/lib/validate.js +0 -159
  175. package/lib/vcon.js +0 -90
  176. package/lib/when-task.js +0 -85
  177. package/src/dist.build.requirejs +0 -20
  178. package/test/ast.mocha.js +0 -136
  179. package/test/cb-task.mocha.js +0 -220
  180. package/test/core-deferred.mocha.js +0 -143
  181. package/test/core-when.mocha.js +0 -96
  182. package/test/core.mocha.js +0 -589
  183. package/test/dsl.mocha.js +0 -350
  184. package/test/event-manager.mocha.js +0 -119
  185. package/test/exec-options.mocha.js +0 -48
  186. package/test/finalcb-task.mocha.js +0 -58
  187. package/test/input-parser.mocha.js +0 -86
  188. package/test/mocha.opts +0 -2
  189. package/test/module-use.mocha.js +0 -147
  190. package/test/promise-auto-resolve.mocha.js +0 -68
  191. package/test/ret-task.mocha.js +0 -220
  192. package/test/task.mocha.js +0 -42
  193. package/test/validate-cb-task.mocha.js +0 -100
  194. package/test/validate-ret-task.mocha.js +0 -110
  195. package/test/validate.mocha.js +0 -324
  196. package/test/vcon.mocha.js +0 -193
  197. package/vendor/chai/chai.js +0 -2038
  198. package/vendor/jquery/jquery-1.7.1.js +0 -9266
  199. package/vendor/jquery/jquery-1.7.1.min.js +0 -4
  200. package/vendor/mocha/mocha.css +0 -135
  201. package/vendor/mocha/mocha.js +0 -3589
  202. package/vendor/node/util.js +0 -531
  203. package/vendor/requirejs/require.js +0 -2053
  204. package/vendor/requirejs/require.min.js +0 -33
@@ -0,0 +1,52 @@
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 ReactDOMForm
17
+ */
18
+
19
+ "use strict";
20
+
21
+ var ReactCompositeComponent = require("./ReactCompositeComponent");
22
+ var ReactDOM = require("./ReactDOM");
23
+ var ReactEventEmitter = require("./ReactEventEmitter");
24
+ var EventConstants = require("./EventConstants");
25
+
26
+ // Store a reference to the <form> `ReactDOMComponent`.
27
+ var form = ReactDOM.form;
28
+
29
+ /**
30
+ * Since onSubmit doesn't bubble OR capture on the top level in IE8, we need
31
+ * to capture it on the <form> element itself. There are lots of hacks we could
32
+ * do to accomplish this, but the most reliable is to make <form> a
33
+ * composite component and use `componentDidMount` to attach the event handlers.
34
+ */
35
+ var ReactDOMForm = ReactCompositeComponent.createClass({
36
+ render: function() {
37
+ // TODO: Instead of using `ReactDOM` directly, we should use JSX. However,
38
+ // `jshint` fails to parse JSX so in order for linting to work in the open
39
+ // source repo, we need to just use `ReactDOM.form`.
40
+ return this.transferPropsTo(form(null, this.props.children));
41
+ },
42
+
43
+ componentDidMount: function(node) {
44
+ ReactEventEmitter.trapBubbledEvent(
45
+ EventConstants.topLevelTypes.topSubmit,
46
+ 'submit',
47
+ node
48
+ );
49
+ }
50
+ });
51
+
52
+ module.exports = ReactDOMForm;
@@ -0,0 +1,173 @@
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 ReactDOMIDOperations
17
+ * @typechecks static-only
18
+ */
19
+
20
+ /*jslint evil: true */
21
+
22
+ "use strict";
23
+
24
+ var CSSPropertyOperations = require("./CSSPropertyOperations");
25
+ var DOMChildrenOperations = require("./DOMChildrenOperations");
26
+ var DOMPropertyOperations = require("./DOMPropertyOperations");
27
+ var ReactMount = require("./ReactMount");
28
+
29
+ var getTextContentAccessor = require("./getTextContentAccessor");
30
+ var invariant = require("./invariant");
31
+
32
+ /**
33
+ * Errors for properties that should not be updated with `updatePropertyById()`.
34
+ *
35
+ * @type {object}
36
+ * @private
37
+ */
38
+ var INVALID_PROPERTY_ERRORS = {
39
+ dangerouslySetInnerHTML:
40
+ '`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.',
41
+ style: '`style` must be set using `updateStylesByID()`.'
42
+ };
43
+
44
+ /**
45
+ * The DOM property to use when setting text content.
46
+ *
47
+ * @type {string}
48
+ * @private
49
+ */
50
+ var textContentAccessor = getTextContentAccessor() || 'NA';
51
+
52
+ var LEADING_SPACE = /^ /;
53
+
54
+ /**
55
+ * Operations used to process updates to DOM nodes. This is made injectable via
56
+ * `ReactComponent.DOMIDOperations`.
57
+ */
58
+ var ReactDOMIDOperations = {
59
+
60
+ /**
61
+ * Updates a DOM node with new property values. This should only be used to
62
+ * update DOM properties in `DOMProperty`.
63
+ *
64
+ * @param {string} id ID of the node to update.
65
+ * @param {string} name A valid property name, see `DOMProperty`.
66
+ * @param {*} value New value of the property.
67
+ * @internal
68
+ */
69
+ updatePropertyByID: function(id, name, value) {
70
+ var node = ReactMount.getNode(id);
71
+ ("production" !== process.env.NODE_ENV ? invariant(
72
+ !INVALID_PROPERTY_ERRORS.hasOwnProperty(name),
73
+ 'updatePropertyByID(...): %s',
74
+ INVALID_PROPERTY_ERRORS[name]
75
+ ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name)));
76
+
77
+ // If we're updating to null or undefined, we should remove the property
78
+ // from the DOM node instead of inadvertantly setting to a string. This
79
+ // brings us in line with the same behavior we have on initial render.
80
+ if (value != null) {
81
+ DOMPropertyOperations.setValueForProperty(node, name, value);
82
+ } else {
83
+ DOMPropertyOperations.deleteValueForProperty(node, name);
84
+ }
85
+ },
86
+
87
+ /**
88
+ * Updates a DOM node to remove a property. This should only be used to remove
89
+ * DOM properties in `DOMProperty`.
90
+ *
91
+ * @param {string} id ID of the node to update.
92
+ * @param {string} name A property name to remove, see `DOMProperty`.
93
+ * @internal
94
+ */
95
+ deletePropertyByID: function(id, name, value) {
96
+ var node = ReactMount.getNode(id);
97
+ ("production" !== process.env.NODE_ENV ? invariant(
98
+ !INVALID_PROPERTY_ERRORS.hasOwnProperty(name),
99
+ 'updatePropertyByID(...): %s',
100
+ INVALID_PROPERTY_ERRORS[name]
101
+ ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name)));
102
+ DOMPropertyOperations.deleteValueForProperty(node, name, value);
103
+ },
104
+
105
+ /**
106
+ * Updates a DOM node with new style values. If a value is specified as '',
107
+ * the corresponding style property will be unset.
108
+ *
109
+ * @param {string} id ID of the node to update.
110
+ * @param {object} styles Mapping from styles to values.
111
+ * @internal
112
+ */
113
+ updateStylesByID: function(id, styles) {
114
+ var node = ReactMount.getNode(id);
115
+ CSSPropertyOperations.setValueForStyles(node, styles);
116
+ },
117
+
118
+ /**
119
+ * Updates a DOM node's innerHTML.
120
+ *
121
+ * @param {string} id ID of the node to update.
122
+ * @param {string} html An HTML string.
123
+ * @internal
124
+ */
125
+ updateInnerHTMLByID: function(id, html) {
126
+ var node = ReactMount.getNode(id);
127
+ // HACK: IE8- normalize whitespace in innerHTML, removing leading spaces.
128
+ // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html
129
+ node.innerHTML = html.replace(LEADING_SPACE, '&nbsp;');
130
+ },
131
+
132
+ /**
133
+ * Updates a DOM node's text content set by `props.content`.
134
+ *
135
+ * @param {string} id ID of the node to update.
136
+ * @param {string} content Text content.
137
+ * @internal
138
+ */
139
+ updateTextContentByID: function(id, content) {
140
+ var node = ReactMount.getNode(id);
141
+ node[textContentAccessor] = content;
142
+ },
143
+
144
+ /**
145
+ * Replaces a DOM node that exists in the document with markup.
146
+ *
147
+ * @param {string} id ID of child to be replaced.
148
+ * @param {string} markup Dangerous markup to inject in place of child.
149
+ * @internal
150
+ * @see {Danger.dangerouslyReplaceNodeWithMarkup}
151
+ */
152
+ dangerouslyReplaceNodeWithMarkupByID: function(id, markup) {
153
+ var node = ReactMount.getNode(id);
154
+ DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup(node, markup);
155
+ },
156
+
157
+ /**
158
+ * Updates a component's children by processing a series of updates.
159
+ *
160
+ * @param {array<object>} updates List of update configurations.
161
+ * @param {array<string>} markup List of markup strings.
162
+ * @internal
163
+ */
164
+ dangerouslyProcessChildrenUpdates: function(updates, markup) {
165
+ for (var i = 0; i < updates.length; i++) {
166
+ updates[i].parentNode = ReactMount.getNode(updates[i].parentID);
167
+ }
168
+ DOMChildrenOperations.processUpdates(updates, markup);
169
+ }
170
+
171
+ };
172
+
173
+ module.exports = ReactDOMIDOperations;
@@ -0,0 +1,169 @@
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 ReactDOMInput
17
+ */
18
+
19
+ "use strict";
20
+
21
+ var DOMPropertyOperations = require("./DOMPropertyOperations");
22
+ var LinkedValueMixin = require("./LinkedValueMixin");
23
+ var ReactCompositeComponent = require("./ReactCompositeComponent");
24
+ var ReactDOM = require("./ReactDOM");
25
+ var ReactMount = require("./ReactMount");
26
+
27
+ var invariant = require("./invariant");
28
+ var merge = require("./merge");
29
+
30
+ // Store a reference to the <input> `ReactDOMComponent`.
31
+ var input = ReactDOM.input;
32
+
33
+ var instancesByReactID = {};
34
+
35
+ /**
36
+ * Implements an <input> native component that allows setting these optional
37
+ * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.
38
+ *
39
+ * If `checked` or `value` are not supplied (or null/undefined), user actions
40
+ * that affect the checked state or value will trigger updates to the element.
41
+ *
42
+ * If they are supplied (and not null/undefined), the rendered element will not
43
+ * trigger updates to the element. Instead, the props must change in order for
44
+ * the rendered element to be updated.
45
+ *
46
+ * The rendered element will be initialized as unchecked (or `defaultChecked`)
47
+ * with an empty value (or `defaultValue`).
48
+ *
49
+ * @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html
50
+ */
51
+ var ReactDOMInput = ReactCompositeComponent.createClass({
52
+ mixins: [LinkedValueMixin],
53
+
54
+ getInitialState: function() {
55
+ var defaultValue = this.props.defaultValue;
56
+ return {
57
+ checked: this.props.defaultChecked || false,
58
+ value: defaultValue != null ? defaultValue : null
59
+ };
60
+ },
61
+
62
+ shouldComponentUpdate: function() {
63
+ // Defer any updates to this component during the `onChange` handler.
64
+ return !this._isChanging;
65
+ },
66
+
67
+ render: function() {
68
+ // Clone `this.props` so we don't mutate the input.
69
+ var props = merge(this.props);
70
+
71
+ props.defaultChecked = null;
72
+ props.defaultValue = null;
73
+ props.checked =
74
+ this.props.checked != null ? this.props.checked : this.state.checked;
75
+
76
+ var value = this.getValue();
77
+ props.value = value != null ? value : this.state.value;
78
+
79
+ props.onChange = this._handleChange;
80
+
81
+ return input(props, this.props.children);
82
+ },
83
+
84
+ componentDidMount: function(rootNode) {
85
+ var id = ReactMount.getID(rootNode);
86
+ instancesByReactID[id] = this;
87
+ },
88
+
89
+ componentWillUnmount: function() {
90
+ var rootNode = this.getDOMNode();
91
+ var id = ReactMount.getID(rootNode);
92
+ delete instancesByReactID[id];
93
+ },
94
+
95
+ componentDidUpdate: function(prevProps, prevState, rootNode) {
96
+ if (this.props.checked != null) {
97
+ DOMPropertyOperations.setValueForProperty(
98
+ rootNode,
99
+ 'checked',
100
+ this.props.checked || false
101
+ );
102
+ }
103
+
104
+ var value = this.getValue();
105
+ if (value != null) {
106
+ // Cast `value` to a string to ensure the value is set correctly. While
107
+ // browsers typically do this as necessary, jsdom doesn't.
108
+ DOMPropertyOperations.setValueForProperty(rootNode, 'value', '' + value);
109
+ }
110
+ },
111
+
112
+ _handleChange: function(event) {
113
+ var returnValue;
114
+ var onChange = this.getOnChange();
115
+ if (onChange) {
116
+ this._isChanging = true;
117
+ returnValue = onChange(event);
118
+ this._isChanging = false;
119
+ }
120
+ this.setState({
121
+ checked: event.target.checked,
122
+ value: event.target.value
123
+ });
124
+
125
+ var name = this.props.name;
126
+ if (this.props.type === 'radio' && name != null) {
127
+ var rootNode = this.getDOMNode();
128
+ // If `rootNode.form` was non-null, then we could try `form.elements`,
129
+ // but that sometimes behaves strangely in IE8. We could also try using
130
+ // `form.getElementsByName`, but that will only return direct children
131
+ // and won't include inputs that use the HTML5 `form=` attribute. Since
132
+ // the input might not even be in a form, let's just use the global
133
+ // `getElementsByName` to ensure we don't miss anything.
134
+ var group = document.getElementsByName(name);
135
+ for (var i = 0, groupLen = group.length; i < groupLen; i++) {
136
+ var otherNode = group[i];
137
+ if (otherNode === rootNode ||
138
+ otherNode.nodeName !== 'INPUT' || otherNode.type !== 'radio' ||
139
+ otherNode.form !== rootNode.form) {
140
+ continue;
141
+ }
142
+ var otherID = ReactMount.getID(otherNode);
143
+ ("production" !== process.env.NODE_ENV ? invariant(
144
+ otherID,
145
+ 'ReactDOMInput: Mixing React and non-React radio inputs with the ' +
146
+ 'same `name` is not supported.'
147
+ ) : invariant(otherID));
148
+ var otherInstance = instancesByReactID[otherID];
149
+ ("production" !== process.env.NODE_ENV ? invariant(
150
+ otherInstance,
151
+ 'ReactDOMInput: Unknown radio button ID %s.',
152
+ otherID
153
+ ) : invariant(otherInstance));
154
+ // In some cases, this will actually change the `checked` state value.
155
+ // In other cases, there's no change but this forces a reconcile upon
156
+ // which componentDidUpdate will reset the DOM property to whatever it
157
+ // should be.
158
+ otherInstance.setState({
159
+ checked: false
160
+ });
161
+ }
162
+ }
163
+
164
+ return returnValue;
165
+ }
166
+
167
+ });
168
+
169
+ module.exports = ReactDOMInput;
@@ -0,0 +1,50 @@
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 ReactDOMOption
17
+ */
18
+
19
+ "use strict";
20
+
21
+ var ReactCompositeComponent = require("./ReactCompositeComponent");
22
+ var ReactDOM = require("./ReactDOM");
23
+
24
+ // Store a reference to the <option> `ReactDOMComponent`.
25
+ var option = ReactDOM.option;
26
+
27
+ /**
28
+ * Implements an <option> native component that warns when `selected` is set.
29
+ */
30
+ var ReactDOMOption = ReactCompositeComponent.createClass({
31
+
32
+ componentWillMount: function() {
33
+ // TODO (yungsters): Remove support for `selected` in <option>.
34
+ if (this.props.selected != null) {
35
+ if ("production" !== process.env.NODE_ENV) {
36
+ console.warn(
37
+ 'Use the `defaultValue` or `value` props on <select> instead of ' +
38
+ 'setting `selected` on <option>.'
39
+ );
40
+ }
41
+ }
42
+ },
43
+
44
+ render: function() {
45
+ return option(this.props, this.props.children);
46
+ }
47
+
48
+ });
49
+
50
+ module.exports = ReactDOMOption;
@@ -0,0 +1,160 @@
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 ReactDOMSelect
17
+ */
18
+
19
+ "use strict";
20
+
21
+ var LinkedValueMixin = require("./LinkedValueMixin");
22
+ var ReactCompositeComponent = require("./ReactCompositeComponent");
23
+ var ReactDOM = require("./ReactDOM");
24
+
25
+ var invariant = require("./invariant");
26
+ var merge = require("./merge");
27
+
28
+ // Store a reference to the <select> `ReactDOMComponent`.
29
+ var select = ReactDOM.select;
30
+
31
+ /**
32
+ * Validation function for `value` and `defaultValue`.
33
+ * @private
34
+ */
35
+ function selectValueType(props, propName, componentName) {
36
+ if (props[propName] == null) {
37
+ return;
38
+ }
39
+ if (props.multiple) {
40
+ ("production" !== process.env.NODE_ENV ? invariant(
41
+ Array.isArray(props[propName]),
42
+ 'The `%s` prop supplied to <select> must be an array if `multiple` is ' +
43
+ 'true.',
44
+ propName
45
+ ) : invariant(Array.isArray(props[propName])));
46
+ } else {
47
+ ("production" !== process.env.NODE_ENV ? invariant(
48
+ !Array.isArray(props[propName]),
49
+ 'The `%s` prop supplied to <select> must be a scalar value if ' +
50
+ '`multiple` is false.',
51
+ propName
52
+ ) : invariant(!Array.isArray(props[propName])));
53
+ }
54
+ }
55
+
56
+ /**
57
+ * If `value` is supplied, updates <option> elements on mount and update.
58
+ * @private
59
+ */
60
+ function updateOptions() {
61
+ /*jshint validthis:true */
62
+ var propValue = this.getValue();
63
+ var value = propValue != null ? propValue : this.state.value;
64
+ var options = this.getDOMNode().options;
65
+ var selectedValue = '' + value;
66
+
67
+ for (var i = 0, l = options.length; i < l; i++) {
68
+ var selected = this.props.multiple ?
69
+ selectedValue.indexOf(options[i].value) >= 0 :
70
+ selected = options[i].value === selectedValue;
71
+
72
+ if (selected !== options[i].selected) {
73
+ options[i].selected = selected;
74
+ }
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Implements a <select> native component that allows optionally setting the
80
+ * props `value` and `defaultValue`. If `multiple` is false, the prop must be a
81
+ * string. If `multiple` is true, the prop must be an array of strings.
82
+ *
83
+ * If `value` is not supplied (or null/undefined), user actions that change the
84
+ * selected option will trigger updates to the rendered options.
85
+ *
86
+ * If it is supplied (and not null/undefined), the rendered options will not
87
+ * update in response to user actions. Instead, the `value` prop must change in
88
+ * order for the rendered options to update.
89
+ *
90
+ * If `defaultValue` is provided, any options with the supplied values will be
91
+ * selected.
92
+ */
93
+ var ReactDOMSelect = ReactCompositeComponent.createClass({
94
+ mixins: [LinkedValueMixin],
95
+
96
+ propTypes: {
97
+ defaultValue: selectValueType,
98
+ value: selectValueType
99
+ },
100
+
101
+ getInitialState: function() {
102
+ return {value: this.props.defaultValue || (this.props.multiple ? [] : '')};
103
+ },
104
+
105
+ componentWillReceiveProps: function(nextProps) {
106
+ if (!this.props.multiple && nextProps.multiple) {
107
+ this.setState({value: [this.state.value]});
108
+ } else if (this.props.multiple && !nextProps.multiple) {
109
+ this.setState({value: this.state.value[0]});
110
+ }
111
+ },
112
+
113
+ shouldComponentUpdate: function() {
114
+ // Defer any updates to this component during the `onChange` handler.
115
+ return !this._isChanging;
116
+ },
117
+
118
+ render: function() {
119
+ // Clone `this.props` so we don't mutate the input.
120
+ var props = merge(this.props);
121
+
122
+ props.onChange = this._handleChange;
123
+ props.value = null;
124
+
125
+ return select(props, this.props.children);
126
+ },
127
+
128
+ componentDidMount: updateOptions,
129
+
130
+ componentDidUpdate: updateOptions,
131
+
132
+ _handleChange: function(event) {
133
+ var returnValue;
134
+ var onChange = this.getOnChange();
135
+ if (onChange) {
136
+ this._isChanging = true;
137
+ returnValue = onChange(event);
138
+ this._isChanging = false;
139
+ }
140
+
141
+ var selectedValue;
142
+ if (this.props.multiple) {
143
+ selectedValue = [];
144
+ var options = event.target.options;
145
+ for (var i = 0, l = options.length; i < l; i++) {
146
+ if (options[i].selected) {
147
+ selectedValue.push(options[i].value);
148
+ }
149
+ }
150
+ } else {
151
+ selectedValue = event.target.value;
152
+ }
153
+
154
+ this.setState({value: selectedValue});
155
+ return returnValue;
156
+ }
157
+
158
+ });
159
+
160
+ module.exports = ReactDOMSelect;