react 0.6.3 → 0.9.0-rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/README.md +10 -222
  2. package/addons.js +1 -0
  3. package/lib/AutoFocusMixin.js +30 -0
  4. package/lib/CSSCore.js +115 -0
  5. package/lib/CSSProperty.js +121 -0
  6. package/lib/CSSPropertyOperations.js +97 -0
  7. package/lib/ChangeEventPlugin.js +387 -0
  8. package/lib/ClientReactRootIndex.js +30 -0
  9. package/lib/CompositionEventPlugin.js +260 -0
  10. package/lib/DOMChildrenOperations.js +165 -0
  11. package/lib/DOMProperty.js +268 -0
  12. package/lib/DOMPropertyOperations.js +181 -0
  13. package/lib/Danger.js +187 -0
  14. package/lib/DefaultDOMPropertyConfig.js +197 -0
  15. package/lib/DefaultEventPluginOrder.js +44 -0
  16. package/lib/EnterLeaveEventPlugin.js +145 -0
  17. package/lib/EventConstants.js +76 -0
  18. package/lib/EventListener.js +69 -0
  19. package/lib/EventPluginHub.js +291 -0
  20. package/lib/EventPluginRegistry.js +260 -0
  21. package/lib/EventPluginUtils.js +214 -0
  22. package/lib/EventPropagators.js +143 -0
  23. package/lib/ExecutionEnvironment.js +44 -0
  24. package/lib/LinkedStateMixin.js +46 -0
  25. package/lib/LinkedValueUtils.js +161 -0
  26. package/lib/MobileSafariClickEventPlugin.js +63 -0
  27. package/lib/PooledClass.js +119 -0
  28. package/lib/React.js +95 -0
  29. package/lib/ReactCSSTransitionGroup.js +65 -0
  30. package/lib/ReactCSSTransitionGroupChild.js +138 -0
  31. package/lib/ReactChildren.js +132 -0
  32. package/lib/ReactComponent.js +550 -0
  33. package/lib/ReactComponentBrowserEnvironment.js +158 -0
  34. package/lib/ReactComponentEnvironment.js +26 -0
  35. package/lib/ReactCompositeComponent.js +1455 -0
  36. package/lib/ReactContext.js +67 -0
  37. package/lib/ReactCurrentOwner.js +39 -0
  38. package/lib/ReactDOM.js +207 -0
  39. package/lib/ReactDOMButton.js +68 -0
  40. package/lib/ReactDOMComponent.js +399 -0
  41. package/lib/ReactDOMForm.js +59 -0
  42. package/lib/ReactDOMIDOperations.js +218 -0
  43. package/lib/ReactDOMImg.js +58 -0
  44. package/lib/ReactDOMInput.js +181 -0
  45. package/lib/ReactDOMOption.js +51 -0
  46. package/lib/ReactDOMSelect.js +179 -0
  47. package/lib/ReactDOMSelection.js +189 -0
  48. package/lib/ReactDOMTextarea.js +140 -0
  49. package/lib/ReactDefaultBatchingStrategy.js +75 -0
  50. package/lib/ReactDefaultInjection.js +115 -0
  51. package/lib/ReactDefaultPerf.js +244 -0
  52. package/lib/ReactDefaultPerfAnalysis.js +199 -0
  53. package/lib/ReactErrorUtils.js +37 -0
  54. package/lib/ReactEventEmitter.js +337 -0
  55. package/lib/ReactEventEmitterMixin.js +57 -0
  56. package/lib/ReactEventTopLevelCallback.js +109 -0
  57. package/lib/ReactInjection.js +39 -0
  58. package/lib/ReactInputSelection.js +140 -0
  59. package/lib/ReactInstanceHandles.js +338 -0
  60. package/lib/ReactLink.js +54 -0
  61. package/lib/ReactMarkupChecksum.js +53 -0
  62. package/lib/ReactMount.js +641 -0
  63. package/lib/ReactMountReady.js +95 -0
  64. package/lib/ReactMultiChild.js +425 -0
  65. package/lib/ReactMultiChildUpdateTypes.js +38 -0
  66. package/lib/ReactOwner.js +154 -0
  67. package/lib/ReactPerf.js +85 -0
  68. package/lib/ReactPropTransferer.js +147 -0
  69. package/lib/ReactPropTypeLocationNames.js +31 -0
  70. package/lib/ReactPropTypeLocations.js +29 -0
  71. package/lib/ReactPropTypes.js +359 -0
  72. package/lib/ReactPutListenerQueue.js +61 -0
  73. package/lib/ReactReconcileTransaction.js +181 -0
  74. package/lib/ReactRootIndex.js +36 -0
  75. package/lib/ReactServerRendering.js +59 -0
  76. package/lib/ReactStateSetters.js +111 -0
  77. package/lib/ReactTextComponent.js +99 -0
  78. package/lib/ReactTransitionChildMapping.js +106 -0
  79. package/lib/ReactTransitionEvents.js +97 -0
  80. package/lib/ReactTransitionGroup.js +187 -0
  81. package/lib/ReactUpdates.js +148 -0
  82. package/lib/ReactWithAddons.js +46 -0
  83. package/lib/SelectEventPlugin.js +200 -0
  84. package/lib/ServerReactRootIndex.js +36 -0
  85. package/lib/SimpleEventPlugin.js +413 -0
  86. package/lib/SyntheticClipboardEvent.js +51 -0
  87. package/lib/SyntheticCompositionEvent.js +51 -0
  88. package/lib/SyntheticDragEvent.js +44 -0
  89. package/lib/SyntheticEvent.js +164 -0
  90. package/lib/SyntheticFocusEvent.js +44 -0
  91. package/lib/SyntheticKeyboardEvent.js +58 -0
  92. package/lib/SyntheticMouseEvent.js +85 -0
  93. package/lib/SyntheticTouchEvent.js +50 -0
  94. package/lib/SyntheticUIEvent.js +45 -0
  95. package/lib/SyntheticWheelEvent.js +66 -0
  96. package/lib/Transaction.js +276 -0
  97. package/lib/ViewportMetrics.js +37 -0
  98. package/lib/accumulate.js +54 -0
  99. package/lib/adler32.js +39 -0
  100. package/lib/cloneWithProps.js +59 -0
  101. package/lib/containsNode.js +49 -0
  102. package/lib/copyProperties.js +54 -0
  103. package/lib/createArrayFrom.js +91 -0
  104. package/lib/createFullPageComponent.js +63 -0
  105. package/lib/createNodesFromMarkup.js +93 -0
  106. package/lib/createObjectFrom.js +61 -0
  107. package/lib/cx.js +44 -0
  108. package/lib/dangerousStyleValue.js +57 -0
  109. package/lib/emptyFunction.js +43 -0
  110. package/lib/escapeTextForBrowser.js +47 -0
  111. package/lib/flattenChildren.js +57 -0
  112. package/lib/forEachAccumulated.js +36 -0
  113. package/lib/getActiveElement.js +34 -0
  114. package/lib/getEventKey.js +85 -0
  115. package/lib/getEventTarget.js +36 -0
  116. package/lib/getMarkupWrap.js +118 -0
  117. package/lib/getNodeForCharacterOffset.js +80 -0
  118. package/lib/getReactRootElementInContainer.js +40 -0
  119. package/lib/getTextContentAccessor.js +42 -0
  120. package/lib/getUnboundedScrollPosition.js +45 -0
  121. package/lib/hyphenate.js +35 -0
  122. package/lib/invariant.js +62 -0
  123. package/lib/isEventSupported.js +70 -0
  124. package/lib/isNode.js +33 -0
  125. package/lib/isTextInputElement.js +49 -0
  126. package/lib/isTextNode.js +30 -0
  127. package/lib/joinClasses.js +44 -0
  128. package/lib/keyMirror.js +58 -0
  129. package/lib/keyOf.js +41 -0
  130. package/lib/memoizeStringOnly.js +39 -0
  131. package/lib/merge.js +37 -0
  132. package/lib/mergeHelpers.js +136 -0
  133. package/lib/mergeInto.js +45 -0
  134. package/lib/mixInto.js +34 -0
  135. package/lib/objMap.js +47 -0
  136. package/lib/objMapKeyVal.js +47 -0
  137. package/lib/onlyChild.js +43 -0
  138. package/lib/performanceNow.js +42 -0
  139. package/lib/shallowEqual.js +49 -0
  140. package/lib/shouldUpdateReactComponent.js +58 -0
  141. package/lib/toArray.js +75 -0
  142. package/lib/traverseAllChildren.js +189 -0
  143. package/lib/warning.js +40 -0
  144. package/package.json +32 -21
  145. package/react.js +1 -0
  146. package/.npmignore +0 -7
  147. package/.travis.yml +0 -5
  148. package/Jakefile.js +0 -39
  149. package/LICENSE +0 -19
  150. package/browser-test/dist.html +0 -90
  151. package/browser-test/index.html +0 -86
  152. package/browser-test/min.html +0 -90
  153. package/dist/react.js +0 -3107
  154. package/dist/react.min.js +0 -22
  155. package/doc/advanced.md +0 -174
  156. package/doc/color-def.graffle +0 -938
  157. package/doc/color-def.png +0 -0
  158. package/doc/simple.dot +0 -25
  159. package/doc/simple.png +0 -0
  160. package/examples/longer-example.js +0 -41
  161. package/examples/simple.js +0 -45
  162. package/examples/using-ast-directly.js +0 -30
  163. package/examples/using-events1.js +0 -79
  164. package/examples/using-log-events.js +0 -43
  165. package/lib/base-task.js +0 -123
  166. package/lib/cb-task.js +0 -84
  167. package/lib/core.js +0 -138
  168. package/lib/dsl.js +0 -138
  169. package/lib/error.js +0 -55
  170. package/lib/event-collector.js +0 -81
  171. package/lib/event-manager.js +0 -89
  172. package/lib/eventemitter.js +0 -20
  173. package/lib/finalcb-first-task.js +0 -68
  174. package/lib/finalcb-task.js +0 -65
  175. package/lib/id.js +0 -22
  176. package/lib/input-parser.js +0 -56
  177. package/lib/log-events.js +0 -101
  178. package/lib/parse.js +0 -41
  179. package/lib/promise-resolve.js +0 -50
  180. package/lib/promise-task.js +0 -93
  181. package/lib/react.js +0 -59
  182. package/lib/ret-task.js +0 -71
  183. package/lib/sprintf.js +0 -18
  184. package/lib/status.js +0 -14
  185. package/lib/task.js +0 -251
  186. package/lib/track-tasks.js +0 -74
  187. package/lib/validate.js +0 -159
  188. package/lib/vcon.js +0 -90
  189. package/lib/when-task.js +0 -85
  190. package/src/dist.build.requirejs +0 -20
  191. package/test/ast.mocha.js +0 -136
  192. package/test/cb-task.mocha.js +0 -220
  193. package/test/core-deferred.mocha.js +0 -143
  194. package/test/core-when.mocha.js +0 -96
  195. package/test/core.mocha.js +0 -589
  196. package/test/dsl.mocha.js +0 -350
  197. package/test/event-manager.mocha.js +0 -119
  198. package/test/exec-options.mocha.js +0 -48
  199. package/test/finalcb-task.mocha.js +0 -58
  200. package/test/input-parser.mocha.js +0 -86
  201. package/test/log-events.mocha.js +0 -88
  202. package/test/mocha.opts +0 -2
  203. package/test/module-use.mocha.js +0 -147
  204. package/test/promise-auto-resolve.mocha.js +0 -68
  205. package/test/ret-task.mocha.js +0 -220
  206. package/test/task.mocha.js +0 -42
  207. package/test/validate-cb-task.mocha.js +0 -100
  208. package/test/validate-ret-task.mocha.js +0 -110
  209. package/test/validate.mocha.js +0 -324
  210. package/test/vcon.mocha.js +0 -193
  211. package/vendor/chai/chai.js +0 -2038
  212. package/vendor/jquery/jquery-1.7.1.js +0 -9266
  213. package/vendor/jquery/jquery-1.7.1.min.js +0 -4
  214. package/vendor/mocha/mocha.css +0 -135
  215. package/vendor/mocha/mocha.js +0 -3589
  216. package/vendor/node/util.js +0 -531
  217. package/vendor/requirejs/require.js +0 -2053
  218. package/vendor/requirejs/require.min.js +0 -33
@@ -0,0 +1,51 @@
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
+ displayName: 'ReactDOMOption',
32
+
33
+ componentWillMount: function() {
34
+ // TODO (yungsters): Remove support for `selected` in <option>.
35
+ if (this.props.selected != null) {
36
+ if ("production" !== process.env.NODE_ENV) {
37
+ console.warn(
38
+ 'Use the `defaultValue` or `value` props on <select> instead of ' +
39
+ 'setting `selected` on <option>.'
40
+ );
41
+ }
42
+ }
43
+ },
44
+
45
+ render: function() {
46
+ return option(this.props, this.props.children);
47
+ }
48
+
49
+ });
50
+
51
+ module.exports = ReactDOMOption;
@@ -0,0 +1,179 @@
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 AutoFocusMixin = require("./AutoFocusMixin");
22
+ var LinkedValueUtils = require("./LinkedValueUtils");
23
+ var ReactCompositeComponent = require("./ReactCompositeComponent");
24
+ var ReactDOM = require("./ReactDOM");
25
+
26
+ var invariant = require("./invariant");
27
+ var merge = require("./merge");
28
+
29
+ // Store a reference to the <select> `ReactDOMComponent`.
30
+ var select = ReactDOM.select;
31
+
32
+ /**
33
+ * Validation function for `value` and `defaultValue`.
34
+ * @private
35
+ */
36
+ function selectValueType(props, propName, componentName) {
37
+ if (props[propName] == null) {
38
+ return;
39
+ }
40
+ if (props.multiple) {
41
+ ("production" !== process.env.NODE_ENV ? invariant(
42
+ Array.isArray(props[propName]),
43
+ 'The `%s` prop supplied to <select> must be an array if `multiple` is ' +
44
+ 'true.',
45
+ propName
46
+ ) : invariant(Array.isArray(props[propName])));
47
+ } else {
48
+ ("production" !== process.env.NODE_ENV ? invariant(
49
+ !Array.isArray(props[propName]),
50
+ 'The `%s` prop supplied to <select> must be a scalar value if ' +
51
+ '`multiple` is false.',
52
+ propName
53
+ ) : invariant(!Array.isArray(props[propName])));
54
+ }
55
+ }
56
+
57
+ /**
58
+ * If `value` is supplied, updates <option> elements on mount and update.
59
+ * @param {ReactComponent} component Instance of ReactDOMSelect
60
+ * @param {?*} propValue For uncontrolled components, null/undefined. For
61
+ * controlled components, a string (or with `multiple`, a list of strings).
62
+ * @private
63
+ */
64
+ function updateOptions(component, propValue) {
65
+ var multiple = component.props.multiple;
66
+ var value = propValue != null ? propValue : component.state.value;
67
+ var options = component.getDOMNode().options;
68
+ var selectedValue, i, l;
69
+ if (multiple) {
70
+ selectedValue = {};
71
+ for (i = 0, l = value.length; i < l; ++i) {
72
+ selectedValue['' + value[i]] = true;
73
+ }
74
+ } else {
75
+ selectedValue = '' + value;
76
+ }
77
+ for (i = 0, l = options.length; i < l; i++) {
78
+ var selected = multiple ?
79
+ selectedValue.hasOwnProperty(options[i].value) :
80
+ options[i].value === selectedValue;
81
+
82
+ if (selected !== options[i].selected) {
83
+ options[i].selected = selected;
84
+ }
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Implements a <select> native component that allows optionally setting the
90
+ * props `value` and `defaultValue`. If `multiple` is false, the prop must be a
91
+ * string. If `multiple` is true, the prop must be an array of strings.
92
+ *
93
+ * If `value` is not supplied (or null/undefined), user actions that change the
94
+ * selected option will trigger updates to the rendered options.
95
+ *
96
+ * If it is supplied (and not null/undefined), the rendered options will not
97
+ * update in response to user actions. Instead, the `value` prop must change in
98
+ * order for the rendered options to update.
99
+ *
100
+ * If `defaultValue` is provided, any options with the supplied values will be
101
+ * selected.
102
+ */
103
+ var ReactDOMSelect = ReactCompositeComponent.createClass({
104
+ displayName: 'ReactDOMSelect',
105
+
106
+ mixins: [AutoFocusMixin, LinkedValueUtils.Mixin],
107
+
108
+ propTypes: {
109
+ defaultValue: selectValueType,
110
+ value: selectValueType
111
+ },
112
+
113
+ getInitialState: function() {
114
+ return {value: this.props.defaultValue || (this.props.multiple ? [] : '')};
115
+ },
116
+
117
+ componentWillReceiveProps: function(nextProps) {
118
+ if (!this.props.multiple && nextProps.multiple) {
119
+ this.setState({value: [this.state.value]});
120
+ } else if (this.props.multiple && !nextProps.multiple) {
121
+ this.setState({value: this.state.value[0]});
122
+ }
123
+ },
124
+
125
+ shouldComponentUpdate: function() {
126
+ // Defer any updates to this component during the `onChange` handler.
127
+ return !this._isChanging;
128
+ },
129
+
130
+ render: function() {
131
+ // Clone `this.props` so we don't mutate the input.
132
+ var props = merge(this.props);
133
+
134
+ props.onChange = this._handleChange;
135
+ props.value = null;
136
+
137
+ return select(props, this.props.children);
138
+ },
139
+
140
+ componentDidMount: function() {
141
+ updateOptions(this, LinkedValueUtils.getValue(this));
142
+ },
143
+
144
+ componentDidUpdate: function() {
145
+ var value = LinkedValueUtils.getValue(this);
146
+ if (value != null) {
147
+ updateOptions(this, value);
148
+ }
149
+ },
150
+
151
+ _handleChange: function(event) {
152
+ var returnValue;
153
+ var onChange = LinkedValueUtils.getOnChange(this);
154
+ if (onChange) {
155
+ this._isChanging = true;
156
+ returnValue = onChange.call(this, event);
157
+ this._isChanging = false;
158
+ }
159
+
160
+ var selectedValue;
161
+ if (this.props.multiple) {
162
+ selectedValue = [];
163
+ var options = event.target.options;
164
+ for (var i = 0, l = options.length; i < l; i++) {
165
+ if (options[i].selected) {
166
+ selectedValue.push(options[i].value);
167
+ }
168
+ }
169
+ } else {
170
+ selectedValue = event.target.value;
171
+ }
172
+
173
+ this.setState({value: selectedValue});
174
+ return returnValue;
175
+ }
176
+
177
+ });
178
+
179
+ module.exports = ReactDOMSelect;
@@ -0,0 +1,189 @@
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 ReactDOMSelection
17
+ */
18
+
19
+ "use strict";
20
+
21
+ var getNodeForCharacterOffset = require("./getNodeForCharacterOffset");
22
+ var getTextContentAccessor = require("./getTextContentAccessor");
23
+
24
+ /**
25
+ * Get the appropriate anchor and focus node/offset pairs for IE.
26
+ *
27
+ * The catch here is that IE's selection API doesn't provide information
28
+ * about whether the selection is forward or backward, so we have to
29
+ * behave as though it's always forward.
30
+ *
31
+ * IE text differs from modern selection in that it behaves as though
32
+ * block elements end with a new line. This means character offsets will
33
+ * differ between the two APIs.
34
+ *
35
+ * @param {DOMElement} node
36
+ * @return {object}
37
+ */
38
+ function getIEOffsets(node) {
39
+ var selection = document.selection;
40
+ var selectedRange = selection.createRange();
41
+ var selectedLength = selectedRange.text.length;
42
+
43
+ // Duplicate selection so we can move range without breaking user selection.
44
+ var fromStart = selectedRange.duplicate();
45
+ fromStart.moveToElementText(node);
46
+ fromStart.setEndPoint('EndToStart', selectedRange);
47
+
48
+ var startOffset = fromStart.text.length;
49
+ var endOffset = startOffset + selectedLength;
50
+
51
+ return {
52
+ start: startOffset,
53
+ end: endOffset
54
+ };
55
+ }
56
+
57
+ /**
58
+ * @param {DOMElement} node
59
+ * @return {?object}
60
+ */
61
+ function getModernOffsets(node) {
62
+ var selection = window.getSelection();
63
+
64
+ if (selection.rangeCount === 0) {
65
+ return null;
66
+ }
67
+
68
+ var anchorNode = selection.anchorNode;
69
+ var anchorOffset = selection.anchorOffset;
70
+ var focusNode = selection.focusNode;
71
+ var focusOffset = selection.focusOffset;
72
+
73
+ var currentRange = selection.getRangeAt(0);
74
+ var rangeLength = currentRange.toString().length;
75
+
76
+ var tempRange = currentRange.cloneRange();
77
+ tempRange.selectNodeContents(node);
78
+ tempRange.setEnd(currentRange.startContainer, currentRange.startOffset);
79
+
80
+ var start = tempRange.toString().length;
81
+ var end = start + rangeLength;
82
+
83
+ // Detect whether the selection is backward.
84
+ var detectionRange = document.createRange();
85
+ detectionRange.setStart(anchorNode, anchorOffset);
86
+ detectionRange.setEnd(focusNode, focusOffset);
87
+ var isBackward = detectionRange.collapsed;
88
+ detectionRange.detach();
89
+
90
+ return {
91
+ start: isBackward ? end : start,
92
+ end: isBackward ? start : end
93
+ };
94
+ }
95
+
96
+ /**
97
+ * @param {DOMElement|DOMTextNode} node
98
+ * @param {object} offsets
99
+ */
100
+ function setIEOffsets(node, offsets) {
101
+ var range = document.selection.createRange().duplicate();
102
+ var start, end;
103
+
104
+ if (typeof offsets.end === 'undefined') {
105
+ start = offsets.start;
106
+ end = start;
107
+ } else if (offsets.start > offsets.end) {
108
+ start = offsets.end;
109
+ end = offsets.start;
110
+ } else {
111
+ start = offsets.start;
112
+ end = offsets.end;
113
+ }
114
+
115
+ range.moveToElementText(node);
116
+ range.moveStart('character', start);
117
+ range.setEndPoint('EndToStart', range);
118
+ range.moveEnd('character', end - start);
119
+ range.select();
120
+ }
121
+
122
+ /**
123
+ * In modern non-IE browsers, we can support both forward and backward
124
+ * selections.
125
+ *
126
+ * Note: IE10+ supports the Selection object, but it does not support
127
+ * the `extend` method, which means that even in modern IE, it's not possible
128
+ * to programatically create a backward selection. Thus, for all IE
129
+ * versions, we use the old IE API to create our selections.
130
+ *
131
+ * @param {DOMElement|DOMTextNode} node
132
+ * @param {object} offsets
133
+ */
134
+ function setModernOffsets(node, offsets) {
135
+ var selection = window.getSelection();
136
+
137
+ var length = node[getTextContentAccessor()].length;
138
+ var start = Math.min(offsets.start, length);
139
+ var end = typeof offsets.end === 'undefined' ?
140
+ start : Math.min(offsets.end, length);
141
+
142
+ // IE 11 uses modern selection, but doesn't support the extend method.
143
+ // Flip backward selections, so we can set with a single range.
144
+ if (!selection.extend && start > end) {
145
+ var temp = end;
146
+ end = start;
147
+ start = temp;
148
+ }
149
+
150
+ var startMarker = getNodeForCharacterOffset(node, start);
151
+ var endMarker = getNodeForCharacterOffset(node, end);
152
+
153
+ if (startMarker && endMarker) {
154
+ var range = document.createRange();
155
+ range.setStart(startMarker.node, startMarker.offset);
156
+ selection.removeAllRanges();
157
+
158
+ if (start > end) {
159
+ selection.addRange(range);
160
+ selection.extend(endMarker.node, endMarker.offset);
161
+ } else {
162
+ range.setEnd(endMarker.node, endMarker.offset);
163
+ selection.addRange(range);
164
+ }
165
+
166
+ range.detach();
167
+ }
168
+ }
169
+
170
+ var ReactDOMSelection = {
171
+ /**
172
+ * @param {DOMElement} node
173
+ */
174
+ getOffsets: function(node) {
175
+ var getOffsets = document.selection ? getIEOffsets : getModernOffsets;
176
+ return getOffsets(node);
177
+ },
178
+
179
+ /**
180
+ * @param {DOMElement|DOMTextNode} node
181
+ * @param {object} offsets
182
+ */
183
+ setOffsets: function(node, offsets) {
184
+ var setOffsets = document.selection ? setIEOffsets : setModernOffsets;
185
+ setOffsets(node, offsets);
186
+ }
187
+ };
188
+
189
+ module.exports = ReactDOMSelection;
@@ -0,0 +1,140 @@
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 ReactDOMTextarea
17
+ */
18
+
19
+ "use strict";
20
+
21
+ var AutoFocusMixin = require("./AutoFocusMixin");
22
+ var DOMPropertyOperations = require("./DOMPropertyOperations");
23
+ var LinkedValueUtils = require("./LinkedValueUtils");
24
+ var ReactCompositeComponent = require("./ReactCompositeComponent");
25
+ var ReactDOM = require("./ReactDOM");
26
+
27
+ var invariant = require("./invariant");
28
+ var merge = require("./merge");
29
+
30
+ // Store a reference to the <textarea> `ReactDOMComponent`.
31
+ var textarea = ReactDOM.textarea;
32
+
33
+ /**
34
+ * Implements a <textarea> native component that allows setting `value`, and
35
+ * `defaultValue`. This differs from the traditional DOM API because value is
36
+ * usually set as PCDATA children.
37
+ *
38
+ * If `value` is not supplied (or null/undefined), user actions that affect the
39
+ * value will trigger updates to the element.
40
+ *
41
+ * If `value` is supplied (and not null/undefined), the rendered element will
42
+ * not trigger updates to the element. Instead, the `value` prop must change in
43
+ * order for the rendered element to be updated.
44
+ *
45
+ * The rendered element will be initialized with an empty value, the prop
46
+ * `defaultValue` if specified, or the children content (deprecated).
47
+ */
48
+ var ReactDOMTextarea = ReactCompositeComponent.createClass({
49
+ displayName: 'ReactDOMTextarea',
50
+
51
+ mixins: [AutoFocusMixin, LinkedValueUtils.Mixin],
52
+
53
+ getInitialState: function() {
54
+ var defaultValue = this.props.defaultValue;
55
+ // TODO (yungsters): Remove support for children content in <textarea>.
56
+ var children = this.props.children;
57
+ if (children != null) {
58
+ if ("production" !== process.env.NODE_ENV) {
59
+ console.warn(
60
+ 'Use the `defaultValue` or `value` props instead of setting ' +
61
+ 'children on <textarea>.'
62
+ );
63
+ }
64
+ ("production" !== process.env.NODE_ENV ? invariant(
65
+ defaultValue == null,
66
+ 'If you supply `defaultValue` on a <textarea>, do not pass children.'
67
+ ) : invariant(defaultValue == null));
68
+ if (Array.isArray(children)) {
69
+ ("production" !== process.env.NODE_ENV ? invariant(
70
+ children.length <= 1,
71
+ '<textarea> can only have at most one child.'
72
+ ) : invariant(children.length <= 1));
73
+ children = children[0];
74
+ }
75
+
76
+ defaultValue = '' + children;
77
+ }
78
+ if (defaultValue == null) {
79
+ defaultValue = '';
80
+ }
81
+ var value = LinkedValueUtils.getValue(this);
82
+ return {
83
+ // We save the initial value so that `ReactDOMComponent` doesn't update
84
+ // `textContent` (unnecessary since we update value).
85
+ // The initial value can be a boolean or object so that's why it's
86
+ // forced to be a string.
87
+ initialValue: '' + (value != null ? value : defaultValue),
88
+ value: defaultValue
89
+ };
90
+ },
91
+
92
+ shouldComponentUpdate: function() {
93
+ // Defer any updates to this component during the `onChange` handler.
94
+ return !this._isChanging;
95
+ },
96
+
97
+ render: function() {
98
+ // Clone `this.props` so we don't mutate the input.
99
+ var props = merge(this.props);
100
+ var value = LinkedValueUtils.getValue(this);
101
+
102
+ ("production" !== process.env.NODE_ENV ? invariant(
103
+ props.dangerouslySetInnerHTML == null,
104
+ '`dangerouslySetInnerHTML` does not make sense on <textarea>.'
105
+ ) : invariant(props.dangerouslySetInnerHTML == null));
106
+
107
+ props.defaultValue = null;
108
+ props.value = value != null ? value : this.state.value;
109
+ props.onChange = this._handleChange;
110
+
111
+ // Always set children to the same thing. In IE9, the selection range will
112
+ // get reset if `textContent` is mutated.
113
+ return textarea(props, this.state.initialValue);
114
+ },
115
+
116
+ componentDidUpdate: function(prevProps, prevState, prevContext) {
117
+ var value = LinkedValueUtils.getValue(this);
118
+ if (value != null) {
119
+ var rootNode = this.getDOMNode();
120
+ // Cast `value` to a string to ensure the value is set correctly. While
121
+ // browsers typically do this as necessary, jsdom doesn't.
122
+ DOMPropertyOperations.setValueForProperty(rootNode, 'value', '' + value);
123
+ }
124
+ },
125
+
126
+ _handleChange: function(event) {
127
+ var returnValue;
128
+ var onChange = LinkedValueUtils.getOnChange(this);
129
+ if (onChange) {
130
+ this._isChanging = true;
131
+ returnValue = onChange.call(this, event);
132
+ this._isChanging = false;
133
+ }
134
+ this.setState({value: event.target.value});
135
+ return returnValue;
136
+ }
137
+
138
+ });
139
+
140
+ module.exports = ReactDOMTextarea;