react 0.7.1 → 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.
- package/README.md +15 -228
- package/ReactJSErrors.js +40 -0
- package/addons.js +4 -0
- package/lib/$.js +46 -0
- package/lib/CSSCore.js +114 -0
- package/lib/CSSProperty.js +90 -0
- package/lib/CSSPropertyOperations.js +97 -0
- package/lib/CallbackRegistry.js +91 -0
- package/lib/ChangeEventPlugin.js +365 -0
- package/lib/CompositionEventPlugin.js +212 -0
- package/lib/DOMChildrenOperations.js +135 -0
- package/lib/DOMProperty.js +266 -0
- package/lib/DOMPropertyOperations.js +168 -0
- package/lib/Danger.js +186 -0
- package/lib/DefaultDOMPropertyConfig.js +187 -0
- package/lib/DefaultEventPluginOrder.js +44 -0
- package/lib/EnterLeaveEventPlugin.js +112 -0
- package/lib/EventConstants.js +73 -0
- package/lib/EventListener.js +61 -0
- package/lib/EventPluginHub.js +190 -0
- package/lib/EventPluginRegistry.js +237 -0
- package/lib/EventPluginUtils.js +185 -0
- package/lib/EventPropagators.js +179 -0
- package/lib/ExecutionEnvironment.js +41 -0
- package/lib/LinkedStateMixin.js +46 -0
- package/lib/LinkedValueMixin.js +68 -0
- package/lib/MobileSafariClickEventPlugin.js +63 -0
- package/lib/PooledClass.js +113 -0
- package/lib/React.js +71 -0
- package/lib/ReactChildren.js +132 -0
- package/lib/ReactComponent.js +515 -0
- package/lib/ReactComponentBrowserEnvironment.js +140 -0
- package/lib/ReactComponentEnvironment.js +24 -0
- package/lib/ReactCompositeComponent.js +1020 -0
- package/lib/ReactCurrentOwner.js +39 -0
- package/lib/ReactDOM.js +194 -0
- package/lib/ReactDOMButton.js +64 -0
- package/lib/ReactDOMComponent.js +374 -0
- package/lib/ReactDOMForm.js +52 -0
- package/lib/ReactDOMIDOperations.js +173 -0
- package/lib/ReactDOMInput.js +169 -0
- package/lib/ReactDOMOption.js +50 -0
- package/lib/ReactDOMSelect.js +160 -0
- package/lib/ReactDOMSelection.js +189 -0
- package/lib/ReactDOMTextarea.js +136 -0
- package/lib/ReactDefaultBatchingStrategy.js +75 -0
- package/lib/ReactDefaultInjection.js +91 -0
- package/lib/ReactDefaultPerf.js +407 -0
- package/lib/ReactErrorUtils.js +46 -0
- package/lib/ReactEventEmitter.js +341 -0
- package/lib/ReactEventEmitterMixin.js +89 -0
- package/lib/ReactEventTopLevelCallback.js +89 -0
- package/lib/ReactInputSelection.js +140 -0
- package/lib/ReactInstanceHandles.js +322 -0
- package/lib/ReactLink.js +54 -0
- package/lib/ReactMarkupChecksum.js +53 -0
- package/lib/ReactMount.js +617 -0
- package/lib/ReactMountReady.js +95 -0
- package/lib/ReactMultiChild.js +441 -0
- package/lib/ReactMultiChildUpdateTypes.js +36 -0
- package/lib/ReactOwner.js +146 -0
- package/lib/ReactPerf.js +88 -0
- package/lib/ReactPropTransferer.js +128 -0
- package/lib/ReactPropTypes.js +158 -0
- package/lib/ReactReconcileTransaction.js +161 -0
- package/lib/ReactServerRendering.js +62 -0
- package/lib/ReactStateSetters.js +111 -0
- package/lib/ReactTextComponent.js +94 -0
- package/lib/ReactTransitionEvents.js +97 -0
- package/lib/ReactTransitionGroup.js +112 -0
- package/lib/ReactTransitionKeySet.js +111 -0
- package/lib/ReactTransitionableChild.js +152 -0
- package/lib/ReactUpdates.js +145 -0
- package/lib/ReactWithAddons.js +41 -0
- package/lib/SelectEventPlugin.js +217 -0
- package/lib/SimpleEventPlugin.js +365 -0
- package/lib/SyntheticClipboardEvent.js +45 -0
- package/lib/SyntheticCompositionEvent.js +51 -0
- package/lib/SyntheticEvent.js +163 -0
- package/lib/SyntheticFocusEvent.js +44 -0
- package/lib/SyntheticKeyboardEvent.js +56 -0
- package/lib/SyntheticMouseEvent.js +85 -0
- package/lib/SyntheticTouchEvent.js +50 -0
- package/lib/SyntheticUIEvent.js +45 -0
- package/lib/SyntheticWheelEvent.js +63 -0
- package/lib/Transaction.js +251 -0
- package/lib/ViewportMetrics.js +37 -0
- package/lib/accumulate.js +54 -0
- package/lib/adler32.js +39 -0
- package/lib/containsNode.js +49 -0
- package/lib/copyProperties.js +54 -0
- package/lib/createArrayFrom.js +94 -0
- package/lib/createNodesFromMarkup.js +93 -0
- package/lib/createObjectFrom.js +61 -0
- package/lib/cx.js +44 -0
- package/lib/dangerousStyleValue.js +57 -0
- package/lib/emptyFunction.js +43 -0
- package/lib/escapeTextForBrowser.js +47 -0
- package/lib/ex.js +49 -0
- package/lib/filterAttributes.js +45 -0
- package/lib/flattenChildren.js +54 -0
- package/lib/forEachAccumulated.js +36 -0
- package/lib/ge.js +76 -0
- package/lib/getActiveElement.js +33 -0
- package/lib/getEventTarget.js +36 -0
- package/lib/getMarkupWrap.js +108 -0
- package/lib/getNodeForCharacterOffset.js +80 -0
- package/lib/getReactRootElementInContainer.js +40 -0
- package/lib/getTextContentAccessor.js +40 -0
- package/lib/getUnboundedScrollPosition.js +45 -0
- package/lib/hyphenate.js +35 -0
- package/lib/invariant.js +54 -0
- package/lib/isEventSupported.js +74 -0
- package/lib/isNode.js +33 -0
- package/lib/isTextInputElement.js +49 -0
- package/lib/isTextNode.js +30 -0
- package/lib/joinClasses.js +44 -0
- package/lib/keyMirror.js +58 -0
- package/lib/keyOf.js +41 -0
- package/lib/memoizeStringOnly.js +39 -0
- package/lib/merge.js +37 -0
- package/lib/mergeHelpers.js +137 -0
- package/lib/mergeInto.js +45 -0
- package/lib/mixInto.js +34 -0
- package/lib/mutateHTMLNodeWithMarkup.js +100 -0
- package/lib/objMap.js +47 -0
- package/lib/objMapKeyVal.js +47 -0
- package/lib/performanceNow.js +42 -0
- package/lib/shallowEqual.js +49 -0
- package/lib/traverseAllChildren.js +127 -0
- package/package.json +33 -31
- package/react.js +4 -0
- package/.npmignore +0 -7
- package/.travis.yml +0 -7
- package/Jakefile.js +0 -39
- package/LICENSE +0 -19
- package/browser-test/dist.html +0 -90
- package/browser-test/index.html +0 -86
- package/browser-test/min.html +0 -90
- package/dist/react.js +0 -3141
- package/dist/react.min.js +0 -22
- package/doc/advanced.md +0 -175
- package/doc/color-def.graffle +0 -938
- package/doc/color-def.png +0 -0
- package/doc/simple.dot +0 -25
- package/doc/simple.png +0 -0
- package/examples/longer-example.js +0 -41
- package/examples/simple.js +0 -45
- package/examples/using-ast-directly.js +0 -30
- package/examples/using-events1.js +0 -79
- package/examples/using-log-events.js +0 -43
- package/lib/base-task.js +0 -120
- package/lib/cb-task.js +0 -84
- package/lib/core.js +0 -138
- package/lib/dsl.js +0 -138
- package/lib/error.js +0 -55
- package/lib/event-collector.js +0 -81
- package/lib/event-manager.js +0 -89
- package/lib/eventemitter.js +0 -20
- package/lib/finalcb-first-task.js +0 -68
- package/lib/finalcb-task.js +0 -65
- package/lib/id.js +0 -22
- package/lib/input-parser.js +0 -56
- package/lib/log-events.js +0 -101
- package/lib/parse.js +0 -41
- package/lib/promise-resolve.js +0 -50
- package/lib/promise-task.js +0 -93
- package/lib/react.js +0 -59
- package/lib/ret-task.js +0 -71
- package/lib/sprintf.js +0 -18
- package/lib/status.js +0 -14
- package/lib/task.js +0 -251
- package/lib/track-tasks.js +0 -74
- package/lib/validate.js +0 -159
- package/lib/vcon.js +0 -113
- package/lib/when-task.js +0 -84
- package/src/dist.build.requirejs +0 -20
- package/test/ast.mocha.js +0 -136
- package/test/cb-task.mocha.js +0 -220
- package/test/core-deferred.mocha.js +0 -143
- package/test/core-when.mocha.js +0 -96
- package/test/core.mocha.js +0 -589
- package/test/dsl.mocha.js +0 -352
- package/test/event-manager.mocha.js +0 -119
- package/test/exec-options.mocha.js +0 -48
- package/test/finalcb-task.mocha.js +0 -58
- package/test/input-parser.mocha.js +0 -86
- package/test/log-events.mocha.js +0 -88
- package/test/mocha.opts +0 -2
- package/test/module-use.mocha.js +0 -164
- package/test/promise-auto-resolve.mocha.js +0 -68
- package/test/ret-task.mocha.js +0 -220
- package/test/task.mocha.js +0 -42
- package/test/validate-cb-task.mocha.js +0 -100
- package/test/validate-ret-task.mocha.js +0 -110
- package/test/validate.mocha.js +0 -324
- package/test/vcon.mocha.js +0 -193
- package/vendor/chai/chai.js +0 -4251
- package/vendor/jquery/jquery-1.7.1.js +0 -9266
- package/vendor/jquery/jquery-1.7.1.min.js +0 -4
- package/vendor/node/util.js +0 -531
- package/vendor/requirejs/require.js +0 -2045
- package/vendor/requirejs/require.min.js +0 -36
|
@@ -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, ' ');
|
|
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;
|