Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80536 views
1
/**
2
* Copyright 2013-2015, Facebook, Inc.
3
* All rights reserved.
4
*
5
* This source code is licensed under the BSD-style license found in the
6
* LICENSE file in the root directory of this source tree. An additional grant
7
* of patent rights can be found in the PATENTS file in the same directory.
8
*
9
* @providesModule DOMChildrenOperations
10
* @typechecks static-only
11
*/
12
13
'use strict';
14
15
var Danger = require("./Danger");
16
var ReactMultiChildUpdateTypes = require("./ReactMultiChildUpdateTypes");
17
18
var setTextContent = require("./setTextContent");
19
var invariant = require("./invariant");
20
21
/**
22
* Inserts `childNode` as a child of `parentNode` at the `index`.
23
*
24
* @param {DOMElement} parentNode Parent node in which to insert.
25
* @param {DOMElement} childNode Child node to insert.
26
* @param {number} index Index at which to insert the child.
27
* @internal
28
*/
29
function insertChildAt(parentNode, childNode, index) {
30
// By exploiting arrays returning `undefined` for an undefined index, we can
31
// rely exclusively on `insertBefore(node, null)` instead of also using
32
// `appendChild(node)`. However, using `undefined` is not allowed by all
33
// browsers so we must replace it with `null`.
34
parentNode.insertBefore(
35
childNode,
36
parentNode.childNodes[index] || null
37
);
38
}
39
40
/**
41
* Operations for updating with DOM children.
42
*/
43
var DOMChildrenOperations = {
44
45
dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup,
46
47
updateTextContent: setTextContent,
48
49
/**
50
* Updates a component's children by processing a series of updates. The
51
* update configurations are each expected to have a `parentNode` property.
52
*
53
* @param {array<object>} updates List of update configurations.
54
* @param {array<string>} markupList List of markup strings.
55
* @internal
56
*/
57
processUpdates: function(updates, markupList) {
58
var update;
59
// Mapping from parent IDs to initial child orderings.
60
var initialChildren = null;
61
// List of children that will be moved or removed.
62
var updatedChildren = null;
63
64
for (var i = 0; i < updates.length; i++) {
65
update = updates[i];
66
if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING ||
67
update.type === ReactMultiChildUpdateTypes.REMOVE_NODE) {
68
var updatedIndex = update.fromIndex;
69
var updatedChild = update.parentNode.childNodes[updatedIndex];
70
var parentID = update.parentID;
71
72
("production" !== process.env.NODE_ENV ? invariant(
73
updatedChild,
74
'processUpdates(): Unable to find child %s of element. This ' +
75
'probably means the DOM was unexpectedly mutated (e.g., by the ' +
76
'browser), usually due to forgetting a <tbody> when using tables, ' +
77
'nesting tags like <form>, <p>, or <a>, or using non-SVG elements ' +
78
'in an <svg> parent. Try inspecting the child nodes of the element ' +
79
'with React ID `%s`.',
80
updatedIndex,
81
parentID
82
) : invariant(updatedChild));
83
84
initialChildren = initialChildren || {};
85
initialChildren[parentID] = initialChildren[parentID] || [];
86
initialChildren[parentID][updatedIndex] = updatedChild;
87
88
updatedChildren = updatedChildren || [];
89
updatedChildren.push(updatedChild);
90
}
91
}
92
93
var renderedMarkup = Danger.dangerouslyRenderMarkup(markupList);
94
95
// Remove updated children first so that `toIndex` is consistent.
96
if (updatedChildren) {
97
for (var j = 0; j < updatedChildren.length; j++) {
98
updatedChildren[j].parentNode.removeChild(updatedChildren[j]);
99
}
100
}
101
102
for (var k = 0; k < updates.length; k++) {
103
update = updates[k];
104
switch (update.type) {
105
case ReactMultiChildUpdateTypes.INSERT_MARKUP:
106
insertChildAt(
107
update.parentNode,
108
renderedMarkup[update.markupIndex],
109
update.toIndex
110
);
111
break;
112
case ReactMultiChildUpdateTypes.MOVE_EXISTING:
113
insertChildAt(
114
update.parentNode,
115
initialChildren[update.parentID][update.fromIndex],
116
update.toIndex
117
);
118
break;
119
case ReactMultiChildUpdateTypes.TEXT_CONTENT:
120
setTextContent(
121
update.parentNode,
122
update.textContent
123
);
124
break;
125
case ReactMultiChildUpdateTypes.REMOVE_NODE:
126
// Already removed by the for-loop above.
127
break;
128
}
129
}
130
}
131
132
};
133
134
module.exports = DOMChildrenOperations;
135
136