1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | 'use strict';
|
10 |
|
11 | var _prodInvariant = require('./reactProdInvariant'),
|
12 | _assign = require('object-assign');
|
13 |
|
14 | var DOMPropertyOperations = require('./DOMPropertyOperations');
|
15 | var LinkedValueUtils = require('./LinkedValueUtils');
|
16 | var ReactDOMComponentTree = require('./ReactDOMComponentTree');
|
17 | var ReactUpdates = require('./ReactUpdates');
|
18 |
|
19 | var invariant = require('fbjs/lib/invariant');
|
20 | var warning = require('fbjs/lib/warning');
|
21 |
|
22 | var didWarnValueLink = false;
|
23 | var didWarnCheckedLink = false;
|
24 | var didWarnValueDefaultValue = false;
|
25 | var didWarnCheckedDefaultChecked = false;
|
26 | var didWarnControlledToUncontrolled = false;
|
27 | var didWarnUncontrolledToControlled = false;
|
28 |
|
29 | function forceUpdateIfMounted() {
|
30 | if (this._rootNodeID) {
|
31 |
|
32 | ReactDOMInput.updateWrapper(this);
|
33 | }
|
34 | }
|
35 |
|
36 | function isControlled(props) {
|
37 | var usesChecked = props.type === 'checkbox' || props.type === 'radio';
|
38 | return usesChecked ? props.checked != null : props.value != null;
|
39 | }
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 | var ReactDOMInput = {
|
58 | getHostProps: function (inst, props) {
|
59 | var value = LinkedValueUtils.getValue(props);
|
60 | var checked = LinkedValueUtils.getChecked(props);
|
61 |
|
62 | var hostProps = _assign({
|
63 |
|
64 |
|
65 | type: undefined,
|
66 |
|
67 |
|
68 | step: undefined,
|
69 |
|
70 |
|
71 | min: undefined,
|
72 | max: undefined
|
73 | }, props, {
|
74 | defaultChecked: undefined,
|
75 | defaultValue: undefined,
|
76 | value: value != null ? value : inst._wrapperState.initialValue,
|
77 | checked: checked != null ? checked : inst._wrapperState.initialChecked,
|
78 | onChange: inst._wrapperState.onChange
|
79 | });
|
80 |
|
81 | return hostProps;
|
82 | },
|
83 |
|
84 | mountWrapper: function (inst, props) {
|
85 | if (process.env.NODE_ENV !== 'production') {
|
86 | LinkedValueUtils.checkPropTypes('input', props, inst._currentElement._owner);
|
87 |
|
88 | var owner = inst._currentElement._owner;
|
89 |
|
90 | if (props.valueLink !== undefined && !didWarnValueLink) {
|
91 | process.env.NODE_ENV !== 'production' ? warning(false, '`valueLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;
|
92 | didWarnValueLink = true;
|
93 | }
|
94 | if (props.checkedLink !== undefined && !didWarnCheckedLink) {
|
95 | process.env.NODE_ENV !== 'production' ? warning(false, '`checkedLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;
|
96 | didWarnCheckedLink = true;
|
97 | }
|
98 | if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) {
|
99 | process.env.NODE_ENV !== 'production' ? warning(false, '%s contains an input of type %s with both checked and defaultChecked props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
|
100 | didWarnCheckedDefaultChecked = true;
|
101 | }
|
102 | if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {
|
103 | process.env.NODE_ENV !== 'production' ? warning(false, '%s contains an input of type %s with both value and defaultValue props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
|
104 | didWarnValueDefaultValue = true;
|
105 | }
|
106 | }
|
107 |
|
108 | var defaultValue = props.defaultValue;
|
109 | inst._wrapperState = {
|
110 | initialChecked: props.checked != null ? props.checked : props.defaultChecked,
|
111 | initialValue: props.value != null ? props.value : defaultValue,
|
112 | listeners: null,
|
113 | onChange: _handleChange.bind(inst),
|
114 | controlled: isControlled(props)
|
115 | };
|
116 | },
|
117 |
|
118 | updateWrapper: function (inst) {
|
119 | var props = inst._currentElement.props;
|
120 |
|
121 | if (process.env.NODE_ENV !== 'production') {
|
122 | var controlled = isControlled(props);
|
123 | var owner = inst._currentElement._owner;
|
124 |
|
125 | if (!inst._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) {
|
126 | process.env.NODE_ENV !== 'production' ? warning(false, '%s is changing an uncontrolled input of type %s to be controlled. ' + 'Input elements should not switch from uncontrolled to controlled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
|
127 | didWarnUncontrolledToControlled = true;
|
128 | }
|
129 | if (inst._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) {
|
130 | process.env.NODE_ENV !== 'production' ? warning(false, '%s is changing a controlled input of type %s to be uncontrolled. ' + 'Input elements should not switch from controlled to uncontrolled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
|
131 | didWarnControlledToUncontrolled = true;
|
132 | }
|
133 | }
|
134 |
|
135 |
|
136 | var checked = props.checked;
|
137 | if (checked != null) {
|
138 | DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'checked', checked || false);
|
139 | }
|
140 |
|
141 | var node = ReactDOMComponentTree.getNodeFromInstance(inst);
|
142 | var value = LinkedValueUtils.getValue(props);
|
143 | if (value != null) {
|
144 | if (value === 0 && node.value === '') {
|
145 | node.value = '0';
|
146 |
|
147 | } else if (props.type === 'number') {
|
148 |
|
149 | var valueAsNumber = parseFloat(node.value, 10) || 0;
|
150 |
|
151 | if (
|
152 |
|
153 | value != valueAsNumber ||
|
154 |
|
155 | value == valueAsNumber && node.value != value) {
|
156 |
|
157 |
|
158 | node.value = '' + value;
|
159 | }
|
160 | } else if (node.value !== '' + value) {
|
161 |
|
162 |
|
163 | node.value = '' + value;
|
164 | }
|
165 | } else {
|
166 | if (props.value == null && props.defaultValue != null) {
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 | if (node.defaultValue !== '' + props.defaultValue) {
|
176 | node.defaultValue = '' + props.defaultValue;
|
177 | }
|
178 | }
|
179 | if (props.checked == null && props.defaultChecked != null) {
|
180 | node.defaultChecked = !!props.defaultChecked;
|
181 | }
|
182 | }
|
183 | },
|
184 |
|
185 | postMountWrapper: function (inst) {
|
186 | var props = inst._currentElement.props;
|
187 |
|
188 |
|
189 |
|
190 | var node = ReactDOMComponentTree.getNodeFromInstance(inst);
|
191 |
|
192 |
|
193 |
|
194 |
|
195 |
|
196 |
|
197 |
|
198 | switch (props.type) {
|
199 | case 'submit':
|
200 | case 'reset':
|
201 | break;
|
202 | case 'color':
|
203 | case 'date':
|
204 | case 'datetime':
|
205 | case 'datetime-local':
|
206 | case 'month':
|
207 | case 'time':
|
208 | case 'week':
|
209 |
|
210 |
|
211 | node.value = '';
|
212 | node.value = node.defaultValue;
|
213 | break;
|
214 | default:
|
215 | node.value = node.value;
|
216 | break;
|
217 | }
|
218 |
|
219 |
|
220 |
|
221 |
|
222 |
|
223 |
|
224 | var name = node.name;
|
225 | if (name !== '') {
|
226 | node.name = '';
|
227 | }
|
228 | node.defaultChecked = !node.defaultChecked;
|
229 | node.defaultChecked = !node.defaultChecked;
|
230 | if (name !== '') {
|
231 | node.name = name;
|
232 | }
|
233 | }
|
234 | };
|
235 |
|
236 | function _handleChange(event) {
|
237 | var props = this._currentElement.props;
|
238 |
|
239 | var returnValue = LinkedValueUtils.executeOnChange(props, event);
|
240 |
|
241 |
|
242 |
|
243 |
|
244 | ReactUpdates.asap(forceUpdateIfMounted, this);
|
245 |
|
246 | var name = props.name;
|
247 | if (props.type === 'radio' && name != null) {
|
248 | var rootNode = ReactDOMComponentTree.getNodeFromInstance(this);
|
249 | var queryRoot = rootNode;
|
250 |
|
251 | while (queryRoot.parentNode) {
|
252 | queryRoot = queryRoot.parentNode;
|
253 | }
|
254 |
|
255 |
|
256 |
|
257 |
|
258 |
|
259 |
|
260 |
|
261 | var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type="radio"]');
|
262 |
|
263 | for (var i = 0; i < group.length; i++) {
|
264 | var otherNode = group[i];
|
265 | if (otherNode === rootNode || otherNode.form !== rootNode.form) {
|
266 | continue;
|
267 | }
|
268 |
|
269 |
|
270 |
|
271 |
|
272 | var otherInstance = ReactDOMComponentTree.getInstanceFromNode(otherNode);
|
273 | !otherInstance ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.') : _prodInvariant('90') : void 0;
|
274 |
|
275 |
|
276 |
|
277 | ReactUpdates.asap(forceUpdateIfMounted, otherInstance);
|
278 | }
|
279 | }
|
280 |
|
281 | return returnValue;
|
282 | }
|
283 |
|
284 | module.exports = ReactDOMInput; |
\ | No newline at end of file |