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.
- package/README.md +10 -222
- package/addons.js +1 -0
- package/lib/AutoFocusMixin.js +30 -0
- package/lib/CSSCore.js +115 -0
- package/lib/CSSProperty.js +121 -0
- package/lib/CSSPropertyOperations.js +97 -0
- package/lib/ChangeEventPlugin.js +387 -0
- package/lib/ClientReactRootIndex.js +30 -0
- package/lib/CompositionEventPlugin.js +260 -0
- package/lib/DOMChildrenOperations.js +165 -0
- package/lib/DOMProperty.js +268 -0
- package/lib/DOMPropertyOperations.js +181 -0
- package/lib/Danger.js +187 -0
- package/lib/DefaultDOMPropertyConfig.js +197 -0
- package/lib/DefaultEventPluginOrder.js +44 -0
- package/lib/EnterLeaveEventPlugin.js +145 -0
- package/lib/EventConstants.js +76 -0
- package/lib/EventListener.js +69 -0
- package/lib/EventPluginHub.js +291 -0
- package/lib/EventPluginRegistry.js +260 -0
- package/lib/EventPluginUtils.js +214 -0
- package/lib/EventPropagators.js +143 -0
- package/lib/ExecutionEnvironment.js +44 -0
- package/lib/LinkedStateMixin.js +46 -0
- package/lib/LinkedValueUtils.js +161 -0
- package/lib/MobileSafariClickEventPlugin.js +63 -0
- package/lib/PooledClass.js +119 -0
- package/lib/React.js +95 -0
- package/lib/ReactCSSTransitionGroup.js +65 -0
- package/lib/ReactCSSTransitionGroupChild.js +138 -0
- package/lib/ReactChildren.js +132 -0
- package/lib/ReactComponent.js +550 -0
- package/lib/ReactComponentBrowserEnvironment.js +158 -0
- package/lib/ReactComponentEnvironment.js +26 -0
- package/lib/ReactCompositeComponent.js +1455 -0
- package/lib/ReactContext.js +67 -0
- package/lib/ReactCurrentOwner.js +39 -0
- package/lib/ReactDOM.js +207 -0
- package/lib/ReactDOMButton.js +68 -0
- package/lib/ReactDOMComponent.js +399 -0
- package/lib/ReactDOMForm.js +59 -0
- package/lib/ReactDOMIDOperations.js +218 -0
- package/lib/ReactDOMImg.js +58 -0
- package/lib/ReactDOMInput.js +181 -0
- package/lib/ReactDOMOption.js +51 -0
- package/lib/ReactDOMSelect.js +179 -0
- package/lib/ReactDOMSelection.js +189 -0
- package/lib/ReactDOMTextarea.js +140 -0
- package/lib/ReactDefaultBatchingStrategy.js +75 -0
- package/lib/ReactDefaultInjection.js +115 -0
- package/lib/ReactDefaultPerf.js +244 -0
- package/lib/ReactDefaultPerfAnalysis.js +199 -0
- package/lib/ReactErrorUtils.js +37 -0
- package/lib/ReactEventEmitter.js +337 -0
- package/lib/ReactEventEmitterMixin.js +57 -0
- package/lib/ReactEventTopLevelCallback.js +109 -0
- package/lib/ReactInjection.js +39 -0
- package/lib/ReactInputSelection.js +140 -0
- package/lib/ReactInstanceHandles.js +338 -0
- package/lib/ReactLink.js +54 -0
- package/lib/ReactMarkupChecksum.js +53 -0
- package/lib/ReactMount.js +641 -0
- package/lib/ReactMountReady.js +95 -0
- package/lib/ReactMultiChild.js +425 -0
- package/lib/ReactMultiChildUpdateTypes.js +38 -0
- package/lib/ReactOwner.js +154 -0
- package/lib/ReactPerf.js +85 -0
- package/lib/ReactPropTransferer.js +147 -0
- package/lib/ReactPropTypeLocationNames.js +31 -0
- package/lib/ReactPropTypeLocations.js +29 -0
- package/lib/ReactPropTypes.js +359 -0
- package/lib/ReactPutListenerQueue.js +61 -0
- package/lib/ReactReconcileTransaction.js +181 -0
- package/lib/ReactRootIndex.js +36 -0
- package/lib/ReactServerRendering.js +59 -0
- package/lib/ReactStateSetters.js +111 -0
- package/lib/ReactTextComponent.js +99 -0
- package/lib/ReactTransitionChildMapping.js +106 -0
- package/lib/ReactTransitionEvents.js +97 -0
- package/lib/ReactTransitionGroup.js +187 -0
- package/lib/ReactUpdates.js +148 -0
- package/lib/ReactWithAddons.js +46 -0
- package/lib/SelectEventPlugin.js +200 -0
- package/lib/ServerReactRootIndex.js +36 -0
- package/lib/SimpleEventPlugin.js +413 -0
- package/lib/SyntheticClipboardEvent.js +51 -0
- package/lib/SyntheticCompositionEvent.js +51 -0
- package/lib/SyntheticDragEvent.js +44 -0
- package/lib/SyntheticEvent.js +164 -0
- package/lib/SyntheticFocusEvent.js +44 -0
- package/lib/SyntheticKeyboardEvent.js +58 -0
- package/lib/SyntheticMouseEvent.js +85 -0
- package/lib/SyntheticTouchEvent.js +50 -0
- package/lib/SyntheticUIEvent.js +45 -0
- package/lib/SyntheticWheelEvent.js +66 -0
- package/lib/Transaction.js +276 -0
- package/lib/ViewportMetrics.js +37 -0
- package/lib/accumulate.js +54 -0
- package/lib/adler32.js +39 -0
- package/lib/cloneWithProps.js +59 -0
- package/lib/containsNode.js +49 -0
- package/lib/copyProperties.js +54 -0
- package/lib/createArrayFrom.js +91 -0
- package/lib/createFullPageComponent.js +63 -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/flattenChildren.js +57 -0
- package/lib/forEachAccumulated.js +36 -0
- package/lib/getActiveElement.js +34 -0
- package/lib/getEventKey.js +85 -0
- package/lib/getEventTarget.js +36 -0
- package/lib/getMarkupWrap.js +118 -0
- package/lib/getNodeForCharacterOffset.js +80 -0
- package/lib/getReactRootElementInContainer.js +40 -0
- package/lib/getTextContentAccessor.js +42 -0
- package/lib/getUnboundedScrollPosition.js +45 -0
- package/lib/hyphenate.js +35 -0
- package/lib/invariant.js +62 -0
- package/lib/isEventSupported.js +70 -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 +136 -0
- package/lib/mergeInto.js +45 -0
- package/lib/mixInto.js +34 -0
- package/lib/objMap.js +47 -0
- package/lib/objMapKeyVal.js +47 -0
- package/lib/onlyChild.js +43 -0
- package/lib/performanceNow.js +42 -0
- package/lib/shallowEqual.js +49 -0
- package/lib/shouldUpdateReactComponent.js +58 -0
- package/lib/toArray.js +75 -0
- package/lib/traverseAllChildren.js +189 -0
- package/lib/warning.js +40 -0
- package/package.json +32 -21
- package/react.js +1 -0
- package/.npmignore +0 -7
- package/.travis.yml +0 -5
- 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 -3107
- package/dist/react.min.js +0 -22
- package/doc/advanced.md +0 -174
- 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 -123
- 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 -90
- package/lib/when-task.js +0 -85
- 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 -350
- 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 -147
- 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 -2038
- package/vendor/jquery/jquery-1.7.1.js +0 -9266
- package/vendor/jquery/jquery-1.7.1.min.js +0 -4
- package/vendor/mocha/mocha.css +0 -135
- package/vendor/mocha/mocha.js +0 -3589
- package/vendor/node/util.js +0 -531
- package/vendor/requirejs/require.js +0 -2053
- package/vendor/requirejs/require.min.js +0 -33
|
@@ -0,0 +1,39 @@
|
|
|
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 ReactInjection
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
"use strict";
|
|
20
|
+
|
|
21
|
+
var DOMProperty = require("./DOMProperty");
|
|
22
|
+
var EventPluginHub = require("./EventPluginHub");
|
|
23
|
+
var ReactDOM = require("./ReactDOM");
|
|
24
|
+
var ReactEventEmitter = require("./ReactEventEmitter");
|
|
25
|
+
var ReactPerf = require("./ReactPerf");
|
|
26
|
+
var ReactRootIndex = require("./ReactRootIndex");
|
|
27
|
+
var ReactUpdates = require("./ReactUpdates");
|
|
28
|
+
|
|
29
|
+
var ReactInjection = {
|
|
30
|
+
DOMProperty: DOMProperty.injection,
|
|
31
|
+
EventPluginHub: EventPluginHub.injection,
|
|
32
|
+
DOM: ReactDOM.injection,
|
|
33
|
+
EventEmitter: ReactEventEmitter.injection,
|
|
34
|
+
Perf: ReactPerf.injection,
|
|
35
|
+
RootIndex: ReactRootIndex.injection,
|
|
36
|
+
Updates: ReactUpdates.injection
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
module.exports = ReactInjection;
|
|
@@ -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 ReactInputSelection
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
"use strict";
|
|
20
|
+
|
|
21
|
+
var ReactDOMSelection = require("./ReactDOMSelection");
|
|
22
|
+
|
|
23
|
+
var containsNode = require("./containsNode");
|
|
24
|
+
var getActiveElement = require("./getActiveElement");
|
|
25
|
+
|
|
26
|
+
function isInDocument(node) {
|
|
27
|
+
return containsNode(document.documentElement, node);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @ReactInputSelection: React input selection module. Based on Selection.js,
|
|
32
|
+
* but modified to be suitable for react and has a couple of bug fixes (doesn't
|
|
33
|
+
* assume buttons have range selections allowed).
|
|
34
|
+
* Input selection module for React.
|
|
35
|
+
*/
|
|
36
|
+
var ReactInputSelection = {
|
|
37
|
+
|
|
38
|
+
hasSelectionCapabilities: function(elem) {
|
|
39
|
+
return elem && (
|
|
40
|
+
(elem.nodeName === 'INPUT' && elem.type === 'text') ||
|
|
41
|
+
elem.nodeName === 'TEXTAREA' ||
|
|
42
|
+
elem.contentEditable === 'true'
|
|
43
|
+
);
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
getSelectionInformation: function() {
|
|
47
|
+
var focusedElem = getActiveElement();
|
|
48
|
+
return {
|
|
49
|
+
focusedElem: focusedElem,
|
|
50
|
+
selectionRange:
|
|
51
|
+
ReactInputSelection.hasSelectionCapabilities(focusedElem) ?
|
|
52
|
+
ReactInputSelection.getSelection(focusedElem) :
|
|
53
|
+
null
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @restoreSelection: If any selection information was potentially lost,
|
|
59
|
+
* restore it. This is useful when performing operations that could remove dom
|
|
60
|
+
* nodes and place them back in, resulting in focus being lost.
|
|
61
|
+
*/
|
|
62
|
+
restoreSelection: function(priorSelectionInformation) {
|
|
63
|
+
var curFocusedElem = getActiveElement();
|
|
64
|
+
var priorFocusedElem = priorSelectionInformation.focusedElem;
|
|
65
|
+
var priorSelectionRange = priorSelectionInformation.selectionRange;
|
|
66
|
+
if (curFocusedElem !== priorFocusedElem &&
|
|
67
|
+
isInDocument(priorFocusedElem)) {
|
|
68
|
+
if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) {
|
|
69
|
+
ReactInputSelection.setSelection(
|
|
70
|
+
priorFocusedElem,
|
|
71
|
+
priorSelectionRange
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
priorFocusedElem.focus();
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @getSelection: Gets the selection bounds of a focused textarea, input or
|
|
80
|
+
* contentEditable node.
|
|
81
|
+
* -@input: Look up selection bounds of this input
|
|
82
|
+
* -@return {start: selectionStart, end: selectionEnd}
|
|
83
|
+
*/
|
|
84
|
+
getSelection: function(input) {
|
|
85
|
+
var selection;
|
|
86
|
+
|
|
87
|
+
if ('selectionStart' in input) {
|
|
88
|
+
// Modern browser with input or textarea.
|
|
89
|
+
selection = {
|
|
90
|
+
start: input.selectionStart,
|
|
91
|
+
end: input.selectionEnd
|
|
92
|
+
};
|
|
93
|
+
} else if (document.selection && input.nodeName === 'INPUT') {
|
|
94
|
+
// IE8 input.
|
|
95
|
+
var range = document.selection.createRange();
|
|
96
|
+
// There can only be one selection per document in IE, so it must
|
|
97
|
+
// be in our element.
|
|
98
|
+
if (range.parentElement() === input) {
|
|
99
|
+
selection = {
|
|
100
|
+
start: -range.moveStart('character', -input.value.length),
|
|
101
|
+
end: -range.moveEnd('character', -input.value.length)
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
// Content editable or old IE textarea.
|
|
106
|
+
selection = ReactDOMSelection.getOffsets(input);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return selection || {start: 0, end: 0};
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @setSelection: Sets the selection bounds of a textarea or input and focuses
|
|
114
|
+
* the input.
|
|
115
|
+
* -@input Set selection bounds of this input or textarea
|
|
116
|
+
* -@offsets Object of same form that is returned from get*
|
|
117
|
+
*/
|
|
118
|
+
setSelection: function(input, offsets) {
|
|
119
|
+
var start = offsets.start;
|
|
120
|
+
var end = offsets.end;
|
|
121
|
+
if (typeof end === 'undefined') {
|
|
122
|
+
end = start;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if ('selectionStart' in input) {
|
|
126
|
+
input.selectionStart = start;
|
|
127
|
+
input.selectionEnd = Math.min(end, input.value.length);
|
|
128
|
+
} else if (document.selection && input.nodeName === 'INPUT') {
|
|
129
|
+
var range = input.createTextRange();
|
|
130
|
+
range.collapse(true);
|
|
131
|
+
range.moveStart('character', start);
|
|
132
|
+
range.moveEnd('character', end - start);
|
|
133
|
+
range.select();
|
|
134
|
+
} else {
|
|
135
|
+
ReactDOMSelection.setOffsets(input, offsets);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
module.exports = ReactInputSelection;
|
|
@@ -0,0 +1,338 @@
|
|
|
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 ReactInstanceHandles
|
|
17
|
+
* @typechecks static-only
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
"use strict";
|
|
21
|
+
|
|
22
|
+
var ReactRootIndex = require("./ReactRootIndex");
|
|
23
|
+
|
|
24
|
+
var invariant = require("./invariant");
|
|
25
|
+
|
|
26
|
+
var SEPARATOR = '.';
|
|
27
|
+
var SEPARATOR_LENGTH = SEPARATOR.length;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Maximum depth of traversals before we consider the possibility of a bad ID.
|
|
31
|
+
*/
|
|
32
|
+
var MAX_TREE_DEPTH = 100;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Creates a DOM ID prefix to use when mounting React components.
|
|
36
|
+
*
|
|
37
|
+
* @param {number} index A unique integer
|
|
38
|
+
* @return {string} React root ID.
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
function getReactRootIDString(index) {
|
|
42
|
+
return SEPARATOR + index.toString(36);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Checks if a character in the supplied ID is a separator or the end.
|
|
47
|
+
*
|
|
48
|
+
* @param {string} id A React DOM ID.
|
|
49
|
+
* @param {number} index Index of the character to check.
|
|
50
|
+
* @return {boolean} True if the character is a separator or end of the ID.
|
|
51
|
+
* @private
|
|
52
|
+
*/
|
|
53
|
+
function isBoundary(id, index) {
|
|
54
|
+
return id.charAt(index) === SEPARATOR || index === id.length;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Checks if the supplied string is a valid React DOM ID.
|
|
59
|
+
*
|
|
60
|
+
* @param {string} id A React DOM ID, maybe.
|
|
61
|
+
* @return {boolean} True if the string is a valid React DOM ID.
|
|
62
|
+
* @private
|
|
63
|
+
*/
|
|
64
|
+
function isValidID(id) {
|
|
65
|
+
return id === '' || (
|
|
66
|
+
id.charAt(0) === SEPARATOR && id.charAt(id.length - 1) !== SEPARATOR
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Checks if the first ID is an ancestor of or equal to the second ID.
|
|
72
|
+
*
|
|
73
|
+
* @param {string} ancestorID
|
|
74
|
+
* @param {string} descendantID
|
|
75
|
+
* @return {boolean} True if `ancestorID` is an ancestor of `descendantID`.
|
|
76
|
+
* @internal
|
|
77
|
+
*/
|
|
78
|
+
function isAncestorIDOf(ancestorID, descendantID) {
|
|
79
|
+
return (
|
|
80
|
+
descendantID.indexOf(ancestorID) === 0 &&
|
|
81
|
+
isBoundary(descendantID, ancestorID.length)
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Gets the parent ID of the supplied React DOM ID, `id`.
|
|
87
|
+
*
|
|
88
|
+
* @param {string} id ID of a component.
|
|
89
|
+
* @return {string} ID of the parent, or an empty string.
|
|
90
|
+
* @private
|
|
91
|
+
*/
|
|
92
|
+
function getParentID(id) {
|
|
93
|
+
return id ? id.substr(0, id.lastIndexOf(SEPARATOR)) : '';
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Gets the next DOM ID on the tree path from the supplied `ancestorID` to the
|
|
98
|
+
* supplied `destinationID`. If they are equal, the ID is returned.
|
|
99
|
+
*
|
|
100
|
+
* @param {string} ancestorID ID of an ancestor node of `destinationID`.
|
|
101
|
+
* @param {string} destinationID ID of the destination node.
|
|
102
|
+
* @return {string} Next ID on the path from `ancestorID` to `destinationID`.
|
|
103
|
+
* @private
|
|
104
|
+
*/
|
|
105
|
+
function getNextDescendantID(ancestorID, destinationID) {
|
|
106
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
107
|
+
isValidID(ancestorID) && isValidID(destinationID),
|
|
108
|
+
'getNextDescendantID(%s, %s): Received an invalid React DOM ID.',
|
|
109
|
+
ancestorID,
|
|
110
|
+
destinationID
|
|
111
|
+
) : invariant(isValidID(ancestorID) && isValidID(destinationID)));
|
|
112
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
113
|
+
isAncestorIDOf(ancestorID, destinationID),
|
|
114
|
+
'getNextDescendantID(...): React has made an invalid assumption about ' +
|
|
115
|
+
'the DOM hierarchy. Expected `%s` to be an ancestor of `%s`.',
|
|
116
|
+
ancestorID,
|
|
117
|
+
destinationID
|
|
118
|
+
) : invariant(isAncestorIDOf(ancestorID, destinationID)));
|
|
119
|
+
if (ancestorID === destinationID) {
|
|
120
|
+
return ancestorID;
|
|
121
|
+
}
|
|
122
|
+
// Skip over the ancestor and the immediate separator. Traverse until we hit
|
|
123
|
+
// another separator or we reach the end of `destinationID`.
|
|
124
|
+
var start = ancestorID.length + SEPARATOR_LENGTH;
|
|
125
|
+
for (var i = start; i < destinationID.length; i++) {
|
|
126
|
+
if (isBoundary(destinationID, i)) {
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return destinationID.substr(0, i);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Gets the nearest common ancestor ID of two IDs.
|
|
135
|
+
*
|
|
136
|
+
* Using this ID scheme, the nearest common ancestor ID is the longest common
|
|
137
|
+
* prefix of the two IDs that immediately preceded a "marker" in both strings.
|
|
138
|
+
*
|
|
139
|
+
* @param {string} oneID
|
|
140
|
+
* @param {string} twoID
|
|
141
|
+
* @return {string} Nearest common ancestor ID, or the empty string if none.
|
|
142
|
+
* @private
|
|
143
|
+
*/
|
|
144
|
+
function getFirstCommonAncestorID(oneID, twoID) {
|
|
145
|
+
var minLength = Math.min(oneID.length, twoID.length);
|
|
146
|
+
if (minLength === 0) {
|
|
147
|
+
return '';
|
|
148
|
+
}
|
|
149
|
+
var lastCommonMarkerIndex = 0;
|
|
150
|
+
// Use `<=` to traverse until the "EOL" of the shorter string.
|
|
151
|
+
for (var i = 0; i <= minLength; i++) {
|
|
152
|
+
if (isBoundary(oneID, i) && isBoundary(twoID, i)) {
|
|
153
|
+
lastCommonMarkerIndex = i;
|
|
154
|
+
} else if (oneID.charAt(i) !== twoID.charAt(i)) {
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
var longestCommonID = oneID.substr(0, lastCommonMarkerIndex);
|
|
159
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
160
|
+
isValidID(longestCommonID),
|
|
161
|
+
'getFirstCommonAncestorID(%s, %s): Expected a valid React DOM ID: %s',
|
|
162
|
+
oneID,
|
|
163
|
+
twoID,
|
|
164
|
+
longestCommonID
|
|
165
|
+
) : invariant(isValidID(longestCommonID)));
|
|
166
|
+
return longestCommonID;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Traverses the parent path between two IDs (either up or down). The IDs must
|
|
171
|
+
* not be the same, and there must exist a parent path between them. If the
|
|
172
|
+
* callback returns `false`, traversal is stopped.
|
|
173
|
+
*
|
|
174
|
+
* @param {?string} start ID at which to start traversal.
|
|
175
|
+
* @param {?string} stop ID at which to end traversal.
|
|
176
|
+
* @param {function} cb Callback to invoke each ID with.
|
|
177
|
+
* @param {?boolean} skipFirst Whether or not to skip the first node.
|
|
178
|
+
* @param {?boolean} skipLast Whether or not to skip the last node.
|
|
179
|
+
* @private
|
|
180
|
+
*/
|
|
181
|
+
function traverseParentPath(start, stop, cb, arg, skipFirst, skipLast) {
|
|
182
|
+
start = start || '';
|
|
183
|
+
stop = stop || '';
|
|
184
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
185
|
+
start !== stop,
|
|
186
|
+
'traverseParentPath(...): Cannot traverse from and to the same ID, `%s`.',
|
|
187
|
+
start
|
|
188
|
+
) : invariant(start !== stop));
|
|
189
|
+
var traverseUp = isAncestorIDOf(stop, start);
|
|
190
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
191
|
+
traverseUp || isAncestorIDOf(start, stop),
|
|
192
|
+
'traverseParentPath(%s, %s, ...): Cannot traverse from two IDs that do ' +
|
|
193
|
+
'not have a parent path.',
|
|
194
|
+
start,
|
|
195
|
+
stop
|
|
196
|
+
) : invariant(traverseUp || isAncestorIDOf(start, stop)));
|
|
197
|
+
// Traverse from `start` to `stop` one depth at a time.
|
|
198
|
+
var depth = 0;
|
|
199
|
+
var traverse = traverseUp ? getParentID : getNextDescendantID;
|
|
200
|
+
for (var id = start; /* until break */; id = traverse(id, stop)) {
|
|
201
|
+
var ret;
|
|
202
|
+
if ((!skipFirst || id !== start) && (!skipLast || id !== stop)) {
|
|
203
|
+
ret = cb(id, traverseUp, arg);
|
|
204
|
+
}
|
|
205
|
+
if (ret === false || id === stop) {
|
|
206
|
+
// Only break //after// visiting `stop`.
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
210
|
+
depth++ < MAX_TREE_DEPTH,
|
|
211
|
+
'traverseParentPath(%s, %s, ...): Detected an infinite loop while ' +
|
|
212
|
+
'traversing the React DOM ID tree. This may be due to malformed IDs: %s',
|
|
213
|
+
start, stop
|
|
214
|
+
) : invariant(depth++ < MAX_TREE_DEPTH));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Manages the IDs assigned to DOM representations of React components. This
|
|
220
|
+
* uses a specific scheme in order to traverse the DOM efficiently (e.g. in
|
|
221
|
+
* order to simulate events).
|
|
222
|
+
*
|
|
223
|
+
* @internal
|
|
224
|
+
*/
|
|
225
|
+
var ReactInstanceHandles = {
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Constructs a React root ID
|
|
229
|
+
* @return {string} A React root ID.
|
|
230
|
+
*/
|
|
231
|
+
createReactRootID: function() {
|
|
232
|
+
return getReactRootIDString(ReactRootIndex.createReactRootIndex());
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Constructs a React ID by joining a root ID with a name.
|
|
237
|
+
*
|
|
238
|
+
* @param {string} rootID Root ID of a parent component.
|
|
239
|
+
* @param {string} name A component's name (as flattened children).
|
|
240
|
+
* @return {string} A React ID.
|
|
241
|
+
* @internal
|
|
242
|
+
*/
|
|
243
|
+
createReactID: function(rootID, name) {
|
|
244
|
+
return rootID + name;
|
|
245
|
+
},
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Gets the DOM ID of the React component that is the root of the tree that
|
|
249
|
+
* contains the React component with the supplied DOM ID.
|
|
250
|
+
*
|
|
251
|
+
* @param {string} id DOM ID of a React component.
|
|
252
|
+
* @return {?string} DOM ID of the React component that is the root.
|
|
253
|
+
* @internal
|
|
254
|
+
*/
|
|
255
|
+
getReactRootIDFromNodeID: function(id) {
|
|
256
|
+
if (id && id.charAt(0) === SEPARATOR && id.length > 1) {
|
|
257
|
+
var index = id.indexOf(SEPARATOR, 1);
|
|
258
|
+
return index > -1 ? id.substr(0, index) : id;
|
|
259
|
+
}
|
|
260
|
+
return null;
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that
|
|
265
|
+
* should would receive a `mouseEnter` or `mouseLeave` event.
|
|
266
|
+
*
|
|
267
|
+
* NOTE: Does not invoke the callback on the nearest common ancestor because
|
|
268
|
+
* nothing "entered" or "left" that element.
|
|
269
|
+
*
|
|
270
|
+
* @param {string} leaveID ID being left.
|
|
271
|
+
* @param {string} enterID ID being entered.
|
|
272
|
+
* @param {function} cb Callback to invoke on each entered/left ID.
|
|
273
|
+
* @param {*} upArg Argument to invoke the callback with on left IDs.
|
|
274
|
+
* @param {*} downArg Argument to invoke the callback with on entered IDs.
|
|
275
|
+
* @internal
|
|
276
|
+
*/
|
|
277
|
+
traverseEnterLeave: function(leaveID, enterID, cb, upArg, downArg) {
|
|
278
|
+
var ancestorID = getFirstCommonAncestorID(leaveID, enterID);
|
|
279
|
+
if (ancestorID !== leaveID) {
|
|
280
|
+
traverseParentPath(leaveID, ancestorID, cb, upArg, false, true);
|
|
281
|
+
}
|
|
282
|
+
if (ancestorID !== enterID) {
|
|
283
|
+
traverseParentPath(ancestorID, enterID, cb, downArg, true, false);
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Simulates the traversal of a two-phase, capture/bubble event dispatch.
|
|
289
|
+
*
|
|
290
|
+
* NOTE: This traversal happens on IDs without touching the DOM.
|
|
291
|
+
*
|
|
292
|
+
* @param {string} targetID ID of the target node.
|
|
293
|
+
* @param {function} cb Callback to invoke.
|
|
294
|
+
* @param {*} arg Argument to invoke the callback with.
|
|
295
|
+
* @internal
|
|
296
|
+
*/
|
|
297
|
+
traverseTwoPhase: function(targetID, cb, arg) {
|
|
298
|
+
if (targetID) {
|
|
299
|
+
traverseParentPath('', targetID, cb, arg, true, false);
|
|
300
|
+
traverseParentPath(targetID, '', cb, arg, false, true);
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Traverse a node ID, calling the supplied `cb` for each ancestor ID. For
|
|
306
|
+
* example, passing `.0.$row-0.1` would result in `cb` getting called
|
|
307
|
+
* with `.0`, `.0.$row-0`, and `.0.$row-0.1`.
|
|
308
|
+
*
|
|
309
|
+
* NOTE: This traversal happens on IDs without touching the DOM.
|
|
310
|
+
*
|
|
311
|
+
* @param {string} targetID ID of the target node.
|
|
312
|
+
* @param {function} cb Callback to invoke.
|
|
313
|
+
* @param {*} arg Argument to invoke the callback with.
|
|
314
|
+
* @internal
|
|
315
|
+
*/
|
|
316
|
+
traverseAncestors: function(targetID, cb, arg) {
|
|
317
|
+
traverseParentPath('', targetID, cb, arg, true, false);
|
|
318
|
+
},
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Exposed for unit testing.
|
|
322
|
+
* @private
|
|
323
|
+
*/
|
|
324
|
+
_getFirstCommonAncestorID: getFirstCommonAncestorID,
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Exposed for unit testing.
|
|
328
|
+
* @private
|
|
329
|
+
*/
|
|
330
|
+
_getNextDescendantID: getNextDescendantID,
|
|
331
|
+
|
|
332
|
+
isAncestorIDOf: isAncestorIDOf,
|
|
333
|
+
|
|
334
|
+
SEPARATOR: SEPARATOR
|
|
335
|
+
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
module.exports = ReactInstanceHandles;
|