The library for web and native user interfaces.
Consolidate ReactDOMNodeCache and getDOMNodeID into ReactID.
When we move away from using the "id" attribute to identify React-generated elements, we will need the cache (formerly ReactDOMNodeCache) to be tied much more closely to the code that looks elements up by ID (getDOMNodeID) and sets element IDs, since the magic of document.getElementById will no longer be available. The priming functions are going to come in handy when we create new DOM fragments in mountComponent. For backwards compatibility, the ReactDOMNodeCache and getDOMNodeID modules still exist, but they are implemented entirely in terms of functions exported from ReactID.
CommitSyncScript committed
Jun 21, 2013 at 16:01 UTC
191c0dec32ee22ec833c2afc0107058f66982a0f
3 files changed
+135
-82
src/core/ReactDOMNodeCache.js
+4
-66
@@ -19,70 +19,8 @@
19
20
"use strict";
21
22
-var ExecutionEnvironment = require('ExecutionEnvironment');
23
-var ReactMount = require('ReactMount');
22
+var ReactID = require('ReactID');
23
25
-var invariant = require('invariant');
26
-
27
-var nodeCache = {};
28
-
29
-/**
30
- * DOM node cache only intended for use by React. Placed into a shared module so
31
- * that both read and write utilities may benefit from a shared cache.
32
- *
33
- * @internal
34
- */
35
-var ReactDOMNodeCache = {
36
-
37
- /**
38
- * Finds the node with the supplied React-generated DOM ID.
39
- *
40
- * @param {string} id A React-generated DOM ID.
41
- * @return {?DOMElement} DOM node with the suppled `id`.
42
- * @internal
43
- */
44
- getNodeByID: function(id) {
45
- invariant(
46
- ExecutionEnvironment.canUseDOM,
47
- 'getDOMNode(): The DOM is not supported in the current environment.'
48
- );
49
- if (!nodeCache[id]) {
50
- nodeCache[id] =
51
- document.getElementById(id) ||
52
- ReactMount.findReactRenderedDOMNodeSlow(id);
53
- }
54
- return nodeCache[id];
55
- },
56
-
57
- /**
58
- * Purges the supplied ID from cache.
59
- *
60
- * @param {string} id A React-generated DOM ID.
61
- * @internal
62
- */
63
- purgeID: function(id) {
64
- nodeCache[id] = null;
65
- },
66
-
67
- /**
68
- * Purges the entire node cache used for fast ID lookups.
69
- *
70
- * This implementation is aggressive with purging because the bookkeeping
71
- * associated with doing fine-grained deletes from the cache may outweight the
72
- * benefits of the cache.
73
- *
74
- * The heuristic used to purge is 'any time anything is deleted'. Typically
75
- * this means that a large amount of content is being replaced and several
76
- * elements would need purging regardless. This is also when applications are
77
- * less likely to be in the middle of "smooth operations" such as animations
78
- * or scrolling.
79
- *
80
- * @internal
81
- */
82
- purgeEntireCache: function() {
83
- nodeCache = {};
84
- }
85
-
86
-};
87
-
88
-module.exports = ReactDOMNodeCache;
24
+exports.getNodeByID = ReactID.getNode;
25
+exports.purgeID = ReactID.purgeID;
26
+exports.purgeEntireCache = ReactID.purgeEntireCache;
src/core/ReactID.js
new
+128
@@ -0,0 +1,128 @@
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 ReactID
17
+ * @typechecks
18
+ */
19
+
20
+"use strict";
21
+
22
+var ReactMount = require('ReactMount');
23
+var ATTR_NAME = 'id';
24
+var nodeCache = {};
25
+
26
+/**
27
+ * Accessing node[ATTR_NAME] or calling getAttribute(ATTR_NAME) on a form
28
+ * element can return its control whose name or ID equals ATTR_NAME. All
29
+ * DOM nodes support `getAttributeNode` but this can also get called on
30
+ * other objects so just return '' if we're given something other than a
31
+ * DOM node (such as window).
32
+ *
33
+ * @param {DOMElement|DOMWindow|DOMDocument} node DOM node.
34
+ * @returns {string} ID of the supplied `domNode`.
35
+ */
36
+function getID(node) {
37
+ if (node && node.getAttributeNode) {
38
+ var attributeNode = node.getAttributeNode(ATTR_NAME);
39
+ return attributeNode && attributeNode.value || '';
40
+ }
41
+
42
+ return '';
43
+}
44
+
45
+/**
46
+ * Sets the React-specific ID of the given node.
47
+ *
48
+ * @param {DOMElement} node The DOM node whose ID will be set.
49
+ * @param {string} id The value of the ID attribute.
50
+ */
51
+function setID(node, id) {
52
+ var oldID = getID(node);
53
+ if (oldID !== id) {
54
+ delete nodeCache[oldID];
55
+ }
56
+ node.setAttribute(ATTR_NAME, id);
57
+ nodeCache[id] = node;
58
+}
59
+
60
+/**
61
+ * Finds the node with the supplied React-generated DOM ID.
62
+ *
63
+ * @param {string} id A React-generated DOM ID.
64
+ * @return {?DOMElement} DOM node with the suppled `id`.
65
+ * @internal
66
+ */
67
+function getNode(id) {
68
+ if (!nodeCache.hasOwnProperty(id)) {
69
+ nodeCache[id] =
70
+ document.getElementById(id) || // TODO Quit using getElementById.
71
+ ReactMount.findReactRenderedDOMNodeSlow(id);
72
+ }
73
+
74
+ var node = nodeCache[id];
75
+ if (getID(node) === id) {
76
+ return node;
77
+ }
78
+
79
+ return null;
80
+}
81
+
82
+/**
83
+ * Efficiently finds all nodes with a React-specific ID and primes the
84
+ * cache so that getNode lookups take constant time.
85
+ *
86
+ * @param {DOMElement} root The root element to scan.
87
+ */
88
+function primeTree(root) {
89
+ var nodes = root.querySelectorAll
90
+ ? root.querySelectorAll('[' + ATTR_NAME + ']')
91
+ : root.getElementsByTagName('*');
92
+
93
+ for (var i = 0; i < nodes.length; ++i) {
94
+ prime(nodes.item(i));
95
+ }
96
+
97
+ prime(root);
98
+}
99
+
100
+function prime(node) {
101
+ var attributeNode = node.getAttributeNode(ATTR_NAME);
102
+ if (attributeNode) {
103
+ nodeCache[attributeNode.value] = node;
104
+ }
105
+}
106
+
107
+/**
108
+ * Causes the cache to forget about one React-specific ID.
109
+ *
110
+ * @param {string} id The ID to forget.
111
+ */
112
+function purgeID(id) {
113
+ delete nodeCache[id];
114
+}
115
+
116
+/**
117
+ * Clears the entire cache.
118
+ */
119
+function purgeEntireCache() {
120
+ nodeCache = {};
121
+}
122
+
123
+exports.getID = getID;
124
+exports.setID = setID;
125
+exports.getNode = getNode;
126
+exports.primeTree = primeTree;
127
+exports.purgeID = purgeID;
128
+exports.purgeEntireCache = purgeEntireCache;
src/dom/getDOMNodeID.js
+3
-16
@@ -19,22 +19,9 @@
19
20
"use strict";
21
22
-/**
23
- * Accessing "id" or calling getAttribute('id') on a form element can return its
24
- * control whose name or ID is "id". All DOM nodes support `getAttributeNode`
25
- * but this can also get called on other objects so just return '' if we're
26
- * given something other than a DOM node (such as window).
27
- *
28
- * @param {DOMElement|DOMWindow|DOMDocument} domNode DOM node.
29
- * @returns {string} ID of the supplied `domNode`.
30
- */
22
+var ReactID = require('ReactID');
23
+
24
function getDOMNodeID(domNode) {
32
- if (domNode.getAttributeNode) {
33
- var attributeNode = domNode.getAttributeNode('id');
34
- return attributeNode && attributeNode.value || '';
35
- } else {
36
- return '';
37
- }
25
+ return ReactID.getID(domNode);
26
}
39
-
27
module.exports = getDOMNodeID;