react 0.10.0 → 0.11.2
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 +3 -0
- package/dist/JSXTransformer.js +20344 -0
- package/dist/react-with-addons.js +20276 -0
- package/dist/react-with-addons.min.js +22 -0
- package/dist/react.js +18484 -0
- package/dist/react.min.js +21 -0
- package/lib/BeforeInputEventPlugin.js +222 -0
- package/lib/CSSPropertyOperations.js +3 -3
- package/lib/{ReactMountReady.js → CallbackQueue.js} +32 -24
- package/lib/ChangeEventPlugin.js +1 -1
- package/lib/CompositionEventPlugin.js +5 -1
- package/lib/DOMChildrenOperations.js +21 -14
- package/lib/DOMProperty.js +45 -17
- package/lib/DOMPropertyOperations.js +22 -10
- package/lib/DefaultEventPluginOrder.js +1 -0
- package/lib/EventConstants.js +1 -0
- package/lib/EventListener.js +5 -2
- package/lib/EventPluginHub.js +0 -5
- package/lib/EventPluginRegistry.js +6 -4
- package/lib/EventPluginUtils.js +11 -1
- package/lib/ExecutionEnvironment.js +8 -2
- package/lib/{DefaultDOMPropertyConfig.js → HTMLDOMPropertyConfig.js} +42 -49
- package/lib/LinkedValueUtils.js +21 -22
- package/lib/LocalEventTrapMixin.js +52 -0
- package/lib/React.js +57 -3
- package/lib/ReactBrowserComponentMixin.js +4 -0
- package/lib/{ReactEventEmitter.js → ReactBrowserEventEmitter.js} +115 -94
- package/lib/ReactCSSTransitionGroup.js +2 -0
- package/lib/ReactCSSTransitionGroupChild.js +2 -5
- package/lib/ReactChildren.js +31 -10
- package/lib/ReactComponent.js +88 -237
- package/lib/ReactComponentBrowserEnvironment.js +3 -2
- package/lib/ReactComponentWithPureRenderMixin.js +54 -0
- package/lib/ReactCompositeComponent.js +222 -384
- package/lib/ReactDOM.js +22 -18
- package/lib/ReactDOMComponent.js +26 -24
- package/lib/ReactDOMForm.js +5 -13
- package/lib/ReactDOMIDOperations.js +2 -31
- package/lib/ReactDOMImg.js +5 -14
- package/lib/ReactDOMSelect.js +16 -15
- package/lib/ReactDOMSelection.js +35 -10
- package/lib/ReactDOMTextarea.js +2 -4
- package/lib/ReactDefaultBatchingStrategy.js +3 -3
- package/lib/ReactDefaultInjection.js +18 -15
- package/lib/ReactDefaultPerf.js +28 -11
- package/lib/ReactDefaultPerfAnalysis.js +4 -0
- package/lib/ReactDescriptor.js +251 -0
- package/lib/ReactDescriptorValidator.js +283 -0
- package/lib/ReactEmptyComponent.js +78 -0
- package/lib/ReactEventEmitterMixin.js +1 -3
- package/lib/ReactEventListener.js +189 -0
- package/lib/ReactInjection.js +4 -2
- package/lib/ReactLink.js +24 -0
- package/lib/ReactMount.js +51 -19
- package/lib/ReactMultiChild.js +9 -11
- package/lib/ReactPropTransferer.js +44 -29
- package/lib/ReactPropTypes.js +226 -242
- package/lib/ReactPutListenerQueue.js +2 -2
- package/lib/ReactReconcileTransaction.js +14 -14
- package/lib/ReactServerRendering.js +5 -5
- package/lib/ReactServerRenderingTransaction.js +4 -5
- package/lib/ReactTestUtils.js +39 -21
- package/lib/ReactTextComponent.js +8 -22
- package/lib/ReactTransitionChildMapping.js +2 -2
- package/lib/ReactTransitionEvents.js +19 -0
- package/lib/ReactTransitionGroup.js +9 -6
- package/lib/ReactUpdates.js +139 -22
- package/lib/ReactWithAddons.js +5 -2
- package/lib/SVGDOMPropertyConfig.js +97 -0
- package/lib/SimpleEventPlugin.js +7 -1
- package/lib/SyntheticInputEvent.js +52 -0
- package/lib/SyntheticKeyboardEvent.js +33 -4
- package/lib/SyntheticMouseEvent.js +3 -0
- package/lib/SyntheticTouchEvent.js +4 -1
- package/lib/SyntheticUIEvent.js +24 -2
- package/lib/Transaction.js +0 -32
- package/lib/cloneWithProps.js +3 -1
- package/lib/createFullPageComponent.js +1 -1
- package/lib/dangerousStyleValue.js +11 -5
- package/lib/escapeTextForBrowser.js +2 -3
- package/lib/flattenChildren.js +9 -7
- package/lib/getEventKey.js +35 -5
- package/lib/getEventModifierState.js +52 -0
- package/lib/getMarkupWrap.js +2 -0
- package/lib/getTextContentAccessor.js +1 -1
- package/lib/hyphenate.js +3 -0
- package/lib/hyphenateStyleName.js +46 -0
- package/lib/instantiateReactComponent.js +13 -21
- package/lib/invariant.js +17 -19
- package/lib/{objMap.js → mapObject.js} +8 -3
- package/lib/mergeHelpers.js +11 -0
- package/lib/mergeInto.js +3 -2
- package/lib/onlyChild.js +3 -3
- package/lib/performance.js +33 -0
- package/lib/performanceNow.js +5 -14
- package/lib/setInnerHTML.js +85 -0
- package/lib/shouldUpdateReactComponent.js +12 -29
- package/lib/toArray.js +1 -1
- package/lib/traverseAllChildren.js +7 -4
- package/lib/update.js +57 -45
- package/package.json +4 -3
- package/lib/ReactEventTopLevelCallback.js +0 -149
- package/lib/createObjectFrom.js +0 -61
- package/lib/objMapKeyVal.js +0 -47
package/lib/ReactDOM.js
CHANGED
|
@@ -19,10 +19,12 @@
|
|
|
19
19
|
|
|
20
20
|
"use strict";
|
|
21
21
|
|
|
22
|
+
var ReactDescriptor = require("./ReactDescriptor");
|
|
23
|
+
var ReactDescriptorValidator = require("./ReactDescriptorValidator");
|
|
22
24
|
var ReactDOMComponent = require("./ReactDOMComponent");
|
|
23
25
|
|
|
24
26
|
var mergeInto = require("./mergeInto");
|
|
25
|
-
var
|
|
27
|
+
var mapObject = require("./mapObject");
|
|
26
28
|
|
|
27
29
|
/**
|
|
28
30
|
* Creates a new React class that is idempotent and capable of containing other
|
|
@@ -35,30 +37,26 @@ var objMapKeyVal = require("./objMapKeyVal");
|
|
|
35
37
|
* The `style` property functions differently from the DOM API. It accepts an
|
|
36
38
|
* object mapping of style properties to values.
|
|
37
39
|
*
|
|
38
|
-
* @param {string} tag Tag name (e.g. `div`).
|
|
39
40
|
* @param {boolean} omitClose True if the close tag should be omitted.
|
|
41
|
+
* @param {string} tag Tag name (e.g. `div`).
|
|
40
42
|
* @private
|
|
41
43
|
*/
|
|
42
|
-
function createDOMComponentClass(
|
|
43
|
-
var Constructor = function() {
|
|
44
|
+
function createDOMComponentClass(omitClose, tag) {
|
|
45
|
+
var Constructor = function(descriptor) {
|
|
46
|
+
this.construct(descriptor);
|
|
47
|
+
};
|
|
44
48
|
Constructor.prototype = new ReactDOMComponent(tag, omitClose);
|
|
45
49
|
Constructor.prototype.constructor = Constructor;
|
|
46
50
|
Constructor.displayName = tag;
|
|
47
51
|
|
|
48
|
-
var ConvenienceConstructor =
|
|
49
|
-
var instance = new Constructor();
|
|
50
|
-
instance.construct.apply(instance, arguments);
|
|
51
|
-
return instance;
|
|
52
|
-
};
|
|
52
|
+
var ConvenienceConstructor = ReactDescriptor.createFactory(Constructor);
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
55
|
+
return ReactDescriptorValidator.createFactory(
|
|
56
|
+
ConvenienceConstructor
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
59
|
|
|
60
|
-
Constructor.ConvenienceConstructor = ConvenienceConstructor;
|
|
61
|
-
ConvenienceConstructor.componentConstructor = Constructor;
|
|
62
60
|
return ConvenienceConstructor;
|
|
63
61
|
}
|
|
64
62
|
|
|
@@ -68,7 +66,7 @@ function createDOMComponentClass(tag, omitClose) {
|
|
|
68
66
|
*
|
|
69
67
|
* @public
|
|
70
68
|
*/
|
|
71
|
-
var ReactDOM =
|
|
69
|
+
var ReactDOM = mapObject({
|
|
72
70
|
a: false,
|
|
73
71
|
abbr: false,
|
|
74
72
|
address: false,
|
|
@@ -97,6 +95,7 @@ var ReactDOM = objMapKeyVal({
|
|
|
97
95
|
del: false,
|
|
98
96
|
details: false,
|
|
99
97
|
dfn: false,
|
|
98
|
+
dialog: false,
|
|
100
99
|
div: false,
|
|
101
100
|
dl: false,
|
|
102
101
|
dt: false,
|
|
@@ -144,6 +143,7 @@ var ReactDOM = objMapKeyVal({
|
|
|
144
143
|
output: false,
|
|
145
144
|
p: false,
|
|
146
145
|
param: true,
|
|
146
|
+
picture: false,
|
|
147
147
|
pre: false,
|
|
148
148
|
progress: false,
|
|
149
149
|
q: false,
|
|
@@ -183,17 +183,21 @@ var ReactDOM = objMapKeyVal({
|
|
|
183
183
|
// SVG
|
|
184
184
|
circle: false,
|
|
185
185
|
defs: false,
|
|
186
|
+
ellipse: false,
|
|
186
187
|
g: false,
|
|
187
188
|
line: false,
|
|
188
189
|
linearGradient: false,
|
|
190
|
+
mask: false,
|
|
189
191
|
path: false,
|
|
192
|
+
pattern: false,
|
|
190
193
|
polygon: false,
|
|
191
194
|
polyline: false,
|
|
192
195
|
radialGradient: false,
|
|
193
196
|
rect: false,
|
|
194
197
|
stop: false,
|
|
195
198
|
svg: false,
|
|
196
|
-
text: false
|
|
199
|
+
text: false,
|
|
200
|
+
tspan: false
|
|
197
201
|
}, createDOMComponentClass);
|
|
198
202
|
|
|
199
203
|
var injection = {
|
package/lib/ReactDOMComponent.js
CHANGED
|
@@ -24,7 +24,7 @@ var DOMProperty = require("./DOMProperty");
|
|
|
24
24
|
var DOMPropertyOperations = require("./DOMPropertyOperations");
|
|
25
25
|
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
|
|
26
26
|
var ReactComponent = require("./ReactComponent");
|
|
27
|
-
var
|
|
27
|
+
var ReactBrowserEventEmitter = require("./ReactBrowserEventEmitter");
|
|
28
28
|
var ReactMount = require("./ReactMount");
|
|
29
29
|
var ReactMultiChild = require("./ReactMultiChild");
|
|
30
30
|
var ReactPerf = require("./ReactPerf");
|
|
@@ -35,9 +35,9 @@ var keyOf = require("./keyOf");
|
|
|
35
35
|
var merge = require("./merge");
|
|
36
36
|
var mixInto = require("./mixInto");
|
|
37
37
|
|
|
38
|
-
var deleteListener =
|
|
39
|
-
var listenTo =
|
|
40
|
-
var registrationNameModules =
|
|
38
|
+
var deleteListener = ReactBrowserEventEmitter.deleteListener;
|
|
39
|
+
var listenTo = ReactBrowserEventEmitter.listenTo;
|
|
40
|
+
var registrationNameModules = ReactBrowserEventEmitter.registrationNameModules;
|
|
41
41
|
|
|
42
42
|
// For quickly matching children type, to test if can be treated as content.
|
|
43
43
|
var CONTENT_TYPES = {'string': true, 'number': true};
|
|
@@ -147,7 +147,7 @@ ReactDOMComponent.Mixin = {
|
|
|
147
147
|
if (propValue == null) {
|
|
148
148
|
continue;
|
|
149
149
|
}
|
|
150
|
-
if (registrationNameModules
|
|
150
|
+
if (registrationNameModules.hasOwnProperty(propKey)) {
|
|
151
151
|
putListener(this._rootNodeID, propKey, propValue, transaction);
|
|
152
152
|
} else {
|
|
153
153
|
if (propKey === STYLE) {
|
|
@@ -205,20 +205,22 @@ ReactDOMComponent.Mixin = {
|
|
|
205
205
|
return '';
|
|
206
206
|
},
|
|
207
207
|
|
|
208
|
-
receiveComponent: function(
|
|
209
|
-
if (
|
|
210
|
-
|
|
211
|
-
//
|
|
212
|
-
// if this is a
|
|
213
|
-
|
|
214
|
-
//
|
|
208
|
+
receiveComponent: function(nextDescriptor, transaction) {
|
|
209
|
+
if (nextDescriptor === this._descriptor &&
|
|
210
|
+
nextDescriptor._owner != null) {
|
|
211
|
+
// Since descriptors are immutable after the owner is rendered,
|
|
212
|
+
// we can do a cheap identity compare here to determine if this is a
|
|
213
|
+
// superfluous reconcile. It's possible for state to be mutable but such
|
|
214
|
+
// change should trigger an update of the owner which would recreate
|
|
215
|
+
// the descriptor. We explicitly check for the existence of an owner since
|
|
216
|
+
// it's possible for a descriptor created outside a composite to be
|
|
217
|
+
// deeply mutated and reused.
|
|
215
218
|
return;
|
|
216
219
|
}
|
|
217
220
|
|
|
218
|
-
assertValidProps(nextComponent.props);
|
|
219
221
|
ReactComponent.Mixin.receiveComponent.call(
|
|
220
222
|
this,
|
|
221
|
-
|
|
223
|
+
nextDescriptor,
|
|
222
224
|
transaction
|
|
223
225
|
);
|
|
224
226
|
},
|
|
@@ -228,22 +230,22 @@ ReactDOMComponent.Mixin = {
|
|
|
228
230
|
* attached to the DOM. Reconciles the root DOM node, then recurses.
|
|
229
231
|
*
|
|
230
232
|
* @param {ReactReconcileTransaction} transaction
|
|
231
|
-
* @param {
|
|
233
|
+
* @param {ReactDescriptor} prevDescriptor
|
|
232
234
|
* @internal
|
|
233
235
|
* @overridable
|
|
234
236
|
*/
|
|
235
237
|
updateComponent: ReactPerf.measure(
|
|
236
238
|
'ReactDOMComponent',
|
|
237
239
|
'updateComponent',
|
|
238
|
-
function(transaction,
|
|
240
|
+
function(transaction, prevDescriptor) {
|
|
241
|
+
assertValidProps(this._descriptor.props);
|
|
239
242
|
ReactComponent.Mixin.updateComponent.call(
|
|
240
243
|
this,
|
|
241
244
|
transaction,
|
|
242
|
-
|
|
243
|
-
prevOwner
|
|
245
|
+
prevDescriptor
|
|
244
246
|
);
|
|
245
|
-
this._updateDOMProperties(
|
|
246
|
-
this._updateDOMChildren(
|
|
247
|
+
this._updateDOMProperties(prevDescriptor.props, transaction);
|
|
248
|
+
this._updateDOMChildren(prevDescriptor.props, transaction);
|
|
247
249
|
}
|
|
248
250
|
),
|
|
249
251
|
|
|
@@ -280,7 +282,7 @@ ReactDOMComponent.Mixin = {
|
|
|
280
282
|
styleUpdates[styleName] = '';
|
|
281
283
|
}
|
|
282
284
|
}
|
|
283
|
-
} else if (registrationNameModules
|
|
285
|
+
} else if (registrationNameModules.hasOwnProperty(propKey)) {
|
|
284
286
|
deleteListener(this._rootNodeID, propKey);
|
|
285
287
|
} else if (
|
|
286
288
|
DOMProperty.isStandardName[propKey] ||
|
|
@@ -305,7 +307,7 @@ ReactDOMComponent.Mixin = {
|
|
|
305
307
|
// Unset styles on `lastProp` but not on `nextProp`.
|
|
306
308
|
for (styleName in lastProp) {
|
|
307
309
|
if (lastProp.hasOwnProperty(styleName) &&
|
|
308
|
-
!nextProp.hasOwnProperty(styleName)) {
|
|
310
|
+
(!nextProp || !nextProp.hasOwnProperty(styleName))) {
|
|
309
311
|
styleUpdates = styleUpdates || {};
|
|
310
312
|
styleUpdates[styleName] = '';
|
|
311
313
|
}
|
|
@@ -322,7 +324,7 @@ ReactDOMComponent.Mixin = {
|
|
|
322
324
|
// Relies on `updateStylesByID` not mutating `styleUpdates`.
|
|
323
325
|
styleUpdates = nextProp;
|
|
324
326
|
}
|
|
325
|
-
} else if (registrationNameModules
|
|
327
|
+
} else if (registrationNameModules.hasOwnProperty(propKey)) {
|
|
326
328
|
putListener(this._rootNodeID, propKey, nextProp, transaction);
|
|
327
329
|
} else if (
|
|
328
330
|
DOMProperty.isStandardName[propKey] ||
|
|
@@ -402,7 +404,7 @@ ReactDOMComponent.Mixin = {
|
|
|
402
404
|
*/
|
|
403
405
|
unmountComponent: function() {
|
|
404
406
|
this.unmountChildren();
|
|
405
|
-
|
|
407
|
+
ReactBrowserEventEmitter.deleteAllListeners(this._rootNodeID);
|
|
406
408
|
ReactComponent.Mixin.unmountComponent.call(this);
|
|
407
409
|
}
|
|
408
410
|
|
package/lib/ReactDOMForm.js
CHANGED
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
|
|
19
19
|
"use strict";
|
|
20
20
|
|
|
21
|
+
var EventConstants = require("./EventConstants");
|
|
22
|
+
var LocalEventTrapMixin = require("./LocalEventTrapMixin");
|
|
21
23
|
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
|
|
22
24
|
var ReactCompositeComponent = require("./ReactCompositeComponent");
|
|
23
25
|
var ReactDOM = require("./ReactDOM");
|
|
24
|
-
var ReactEventEmitter = require("./ReactEventEmitter");
|
|
25
|
-
var EventConstants = require("./EventConstants");
|
|
26
26
|
|
|
27
27
|
// Store a reference to the <form> `ReactDOMComponent`.
|
|
28
28
|
var form = ReactDOM.form;
|
|
@@ -36,7 +36,7 @@ var form = ReactDOM.form;
|
|
|
36
36
|
var ReactDOMForm = ReactCompositeComponent.createClass({
|
|
37
37
|
displayName: 'ReactDOMForm',
|
|
38
38
|
|
|
39
|
-
mixins: [ReactBrowserComponentMixin],
|
|
39
|
+
mixins: [ReactBrowserComponentMixin, LocalEventTrapMixin],
|
|
40
40
|
|
|
41
41
|
render: function() {
|
|
42
42
|
// TODO: Instead of using `ReactDOM` directly, we should use JSX. However,
|
|
@@ -46,16 +46,8 @@ var ReactDOMForm = ReactCompositeComponent.createClass({
|
|
|
46
46
|
},
|
|
47
47
|
|
|
48
48
|
componentDidMount: function() {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
'reset',
|
|
52
|
-
this.getDOMNode()
|
|
53
|
-
);
|
|
54
|
-
ReactEventEmitter.trapBubbledEvent(
|
|
55
|
-
EventConstants.topLevelTypes.topSubmit,
|
|
56
|
-
'submit',
|
|
57
|
-
this.getDOMNode()
|
|
58
|
-
);
|
|
49
|
+
this.trapBubbledEvent(EventConstants.topLevelTypes.topReset, 'reset');
|
|
50
|
+
this.trapBubbledEvent(EventConstants.topLevelTypes.topSubmit, 'submit');
|
|
59
51
|
}
|
|
60
52
|
});
|
|
61
53
|
|
|
@@ -28,6 +28,7 @@ var ReactMount = require("./ReactMount");
|
|
|
28
28
|
var ReactPerf = require("./ReactPerf");
|
|
29
29
|
|
|
30
30
|
var invariant = require("./invariant");
|
|
31
|
+
var setInnerHTML = require("./setInnerHTML");
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* Errors for properties that should not be updated with `updatePropertyById()`.
|
|
@@ -41,8 +42,6 @@ var INVALID_PROPERTY_ERRORS = {
|
|
|
41
42
|
style: '`style` must be set using `updateStylesByID()`.'
|
|
42
43
|
};
|
|
43
44
|
|
|
44
|
-
var useWhitespaceWorkaround;
|
|
45
|
-
|
|
46
45
|
/**
|
|
47
46
|
* Operations used to process updates to DOM nodes. This is made injectable via
|
|
48
47
|
* `ReactComponent.BackendIDOperations`.
|
|
@@ -131,35 +130,7 @@ var ReactDOMIDOperations = {
|
|
|
131
130
|
'updateInnerHTMLByID',
|
|
132
131
|
function(id, html) {
|
|
133
132
|
var node = ReactMount.getNode(id);
|
|
134
|
-
|
|
135
|
-
// IE8: When updating a just created node with innerHTML only leading
|
|
136
|
-
// whitespace is removed. When updating an existing node with innerHTML
|
|
137
|
-
// whitespace in root TextNodes is also collapsed.
|
|
138
|
-
// @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html
|
|
139
|
-
|
|
140
|
-
if (useWhitespaceWorkaround === undefined) {
|
|
141
|
-
// Feature detection; only IE8 is known to behave improperly like this.
|
|
142
|
-
var temp = document.createElement('div');
|
|
143
|
-
temp.innerHTML = ' ';
|
|
144
|
-
useWhitespaceWorkaround = temp.innerHTML === '';
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (useWhitespaceWorkaround) {
|
|
148
|
-
// Magic theory: IE8 supposedly differentiates between added and updated
|
|
149
|
-
// nodes when processing innerHTML, innerHTML on updated nodes suffers
|
|
150
|
-
// from worse whitespace behavior. Re-adding a node like this triggers
|
|
151
|
-
// the initial and more favorable whitespace behavior.
|
|
152
|
-
node.parentNode.replaceChild(node, node);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (useWhitespaceWorkaround && html.match(/^[ \r\n\t\f]/)) {
|
|
156
|
-
// Recover leading whitespace by temporarily prepending any character.
|
|
157
|
-
// \uFEFF has the potential advantage of being zero-width/invisible.
|
|
158
|
-
node.innerHTML = '\uFEFF' + html;
|
|
159
|
-
node.firstChild.deleteData(0, 1);
|
|
160
|
-
} else {
|
|
161
|
-
node.innerHTML = html;
|
|
162
|
-
}
|
|
133
|
+
setInnerHTML(node, html);
|
|
163
134
|
}
|
|
164
135
|
),
|
|
165
136
|
|
package/lib/ReactDOMImg.js
CHANGED
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
|
|
19
19
|
"use strict";
|
|
20
20
|
|
|
21
|
+
var EventConstants = require("./EventConstants");
|
|
22
|
+
var LocalEventTrapMixin = require("./LocalEventTrapMixin");
|
|
21
23
|
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
|
|
22
24
|
var ReactCompositeComponent = require("./ReactCompositeComponent");
|
|
23
25
|
var ReactDOM = require("./ReactDOM");
|
|
24
|
-
var ReactEventEmitter = require("./ReactEventEmitter");
|
|
25
|
-
var EventConstants = require("./EventConstants");
|
|
26
26
|
|
|
27
27
|
// Store a reference to the <img> `ReactDOMComponent`.
|
|
28
28
|
var img = ReactDOM.img;
|
|
@@ -37,24 +37,15 @@ var ReactDOMImg = ReactCompositeComponent.createClass({
|
|
|
37
37
|
displayName: 'ReactDOMImg',
|
|
38
38
|
tagName: 'IMG',
|
|
39
39
|
|
|
40
|
-
mixins: [ReactBrowserComponentMixin],
|
|
40
|
+
mixins: [ReactBrowserComponentMixin, LocalEventTrapMixin],
|
|
41
41
|
|
|
42
42
|
render: function() {
|
|
43
43
|
return img(this.props);
|
|
44
44
|
},
|
|
45
45
|
|
|
46
46
|
componentDidMount: function() {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
EventConstants.topLevelTypes.topLoad,
|
|
50
|
-
'load',
|
|
51
|
-
node
|
|
52
|
-
);
|
|
53
|
-
ReactEventEmitter.trapBubbledEvent(
|
|
54
|
-
EventConstants.topLevelTypes.topError,
|
|
55
|
-
'error',
|
|
56
|
-
node
|
|
57
|
-
);
|
|
47
|
+
this.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load');
|
|
48
|
+
this.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error');
|
|
58
49
|
}
|
|
59
50
|
});
|
|
60
51
|
|
package/lib/ReactDOMSelect.js
CHANGED
|
@@ -24,7 +24,6 @@ var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
|
|
|
24
24
|
var ReactCompositeComponent = require("./ReactCompositeComponent");
|
|
25
25
|
var ReactDOM = require("./ReactDOM");
|
|
26
26
|
|
|
27
|
-
var invariant = require("./invariant");
|
|
28
27
|
var merge = require("./merge");
|
|
29
28
|
|
|
30
29
|
// Store a reference to the <select> `ReactDOMComponent`.
|
|
@@ -39,19 +38,19 @@ function selectValueType(props, propName, componentName) {
|
|
|
39
38
|
return;
|
|
40
39
|
}
|
|
41
40
|
if (props.multiple) {
|
|
42
|
-
(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
if (!Array.isArray(props[propName])) {
|
|
42
|
+
return new Error(
|
|
43
|
+
("The `" + propName + "` prop supplied to <select> must be an array if ") +
|
|
44
|
+
("`multiple` is true.")
|
|
45
|
+
);
|
|
46
|
+
}
|
|
48
47
|
} else {
|
|
49
|
-
(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
if (Array.isArray(props[propName])) {
|
|
49
|
+
return new Error(
|
|
50
|
+
("The `" + propName + "` prop supplied to <select> must be a scalar ") +
|
|
51
|
+
("value if `multiple` is false.")
|
|
52
|
+
);
|
|
53
|
+
}
|
|
55
54
|
}
|
|
56
55
|
}
|
|
57
56
|
|
|
@@ -142,9 +141,11 @@ var ReactDOMSelect = ReactCompositeComponent.createClass({
|
|
|
142
141
|
updateOptions(this, LinkedValueUtils.getValue(this));
|
|
143
142
|
},
|
|
144
143
|
|
|
145
|
-
componentDidUpdate: function() {
|
|
144
|
+
componentDidUpdate: function(prevProps) {
|
|
146
145
|
var value = LinkedValueUtils.getValue(this);
|
|
147
|
-
|
|
146
|
+
var prevMultiple = !!prevProps.multiple;
|
|
147
|
+
var multiple = !!this.props.multiple;
|
|
148
|
+
if (value != null || prevMultiple !== multiple) {
|
|
148
149
|
updateOptions(this, value);
|
|
149
150
|
}
|
|
150
151
|
},
|
package/lib/ReactDOMSelection.js
CHANGED
|
@@ -18,9 +18,20 @@
|
|
|
18
18
|
|
|
19
19
|
"use strict";
|
|
20
20
|
|
|
21
|
+
var ExecutionEnvironment = require("./ExecutionEnvironment");
|
|
22
|
+
|
|
21
23
|
var getNodeForCharacterOffset = require("./getNodeForCharacterOffset");
|
|
22
24
|
var getTextContentAccessor = require("./getTextContentAccessor");
|
|
23
25
|
|
|
26
|
+
/**
|
|
27
|
+
* While `isCollapsed` is available on the Selection object and `collapsed`
|
|
28
|
+
* is available on the Range object, IE11 sometimes gets them wrong.
|
|
29
|
+
* If the anchor/focus nodes and offsets are the same, the range is collapsed.
|
|
30
|
+
*/
|
|
31
|
+
function isCollapsed(anchorNode, anchorOffset, focusNode, focusOffset) {
|
|
32
|
+
return anchorNode === focusNode && anchorOffset === focusOffset;
|
|
33
|
+
}
|
|
34
|
+
|
|
24
35
|
/**
|
|
25
36
|
* Get the appropriate anchor and focus node/offset pairs for IE.
|
|
26
37
|
*
|
|
@@ -71,13 +82,31 @@ function getModernOffsets(node) {
|
|
|
71
82
|
var focusOffset = selection.focusOffset;
|
|
72
83
|
|
|
73
84
|
var currentRange = selection.getRangeAt(0);
|
|
74
|
-
|
|
85
|
+
|
|
86
|
+
// If the node and offset values are the same, the selection is collapsed.
|
|
87
|
+
// `Selection.isCollapsed` is available natively, but IE sometimes gets
|
|
88
|
+
// this value wrong.
|
|
89
|
+
var isSelectionCollapsed = isCollapsed(
|
|
90
|
+
selection.anchorNode,
|
|
91
|
+
selection.anchorOffset,
|
|
92
|
+
selection.focusNode,
|
|
93
|
+
selection.focusOffset
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
var rangeLength = isSelectionCollapsed ? 0 : currentRange.toString().length;
|
|
75
97
|
|
|
76
98
|
var tempRange = currentRange.cloneRange();
|
|
77
99
|
tempRange.selectNodeContents(node);
|
|
78
100
|
tempRange.setEnd(currentRange.startContainer, currentRange.startOffset);
|
|
79
101
|
|
|
80
|
-
var
|
|
102
|
+
var isTempRangeCollapsed = isCollapsed(
|
|
103
|
+
tempRange.startContainer,
|
|
104
|
+
tempRange.startOffset,
|
|
105
|
+
tempRange.endContainer,
|
|
106
|
+
tempRange.endOffset
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
var start = isTempRangeCollapsed ? 0 : tempRange.toString().length;
|
|
81
110
|
var end = start + rangeLength;
|
|
82
111
|
|
|
83
112
|
// Detect whether the selection is backward.
|
|
@@ -167,23 +196,19 @@ function setModernOffsets(node, offsets) {
|
|
|
167
196
|
}
|
|
168
197
|
}
|
|
169
198
|
|
|
199
|
+
var useIEOffsets = ExecutionEnvironment.canUseDOM && document.selection;
|
|
200
|
+
|
|
170
201
|
var ReactDOMSelection = {
|
|
171
202
|
/**
|
|
172
203
|
* @param {DOMElement} node
|
|
173
204
|
*/
|
|
174
|
-
getOffsets:
|
|
175
|
-
var getOffsets = document.selection ? getIEOffsets : getModernOffsets;
|
|
176
|
-
return getOffsets(node);
|
|
177
|
-
},
|
|
205
|
+
getOffsets: useIEOffsets ? getIEOffsets : getModernOffsets,
|
|
178
206
|
|
|
179
207
|
/**
|
|
180
208
|
* @param {DOMElement|DOMTextNode} node
|
|
181
209
|
* @param {object} offsets
|
|
182
210
|
*/
|
|
183
|
-
setOffsets:
|
|
184
|
-
var setOffsets = document.selection ? setIEOffsets : setModernOffsets;
|
|
185
|
-
setOffsets(node, offsets);
|
|
186
|
-
}
|
|
211
|
+
setOffsets: useIEOffsets ? setIEOffsets : setModernOffsets
|
|
187
212
|
};
|
|
188
213
|
|
|
189
214
|
module.exports = ReactDOMSelection;
|