Consolidate innerHTML setting logic
See https://github.com/facebook/react/commit/7eb33ef#commitcomment-5447724.
Ben Alpert committed
Feb 25, 2014 at 21:02 UTC
534e7c06e9c2446028a82e2e6c695a130ee7f061
3 files changed
+68
-32
src/browser/ui/ReactComponentBrowserEnvironment.js
+2
-1
@@ -28,6 +28,7 @@ var ReactReconcileTransaction = require('ReactReconcileTransaction');
28
29
var getReactRootElementInContainer = require('getReactRootElementInContainer');
30
var invariant = require('invariant');
31
+var setInnerHTML = require('setInnerHTML');
32
33
34
var ELEMENT_NODE_TYPE = 1;
@@ -113,7 +114,7 @@ var ReactComponentBrowserEnvironment = {
114
'See renderComponentToString() for server rendering.'
115
);
116
116
- container.innerHTML = markup;
117
+ setInnerHTML(container, markup);
118
}
119
)
120
};
src/browser/ui/ReactDOMIDOperations.js
+2
-31
@@ -28,6 +28,7 @@ var ReactMount = require('ReactMount');
28
var ReactPerf = require('ReactPerf');
29
30
var invariant = require('invariant');
31
+var setInnerHTML = require('setInnerHTML');
32
33
/**
34
* Errors for properties that should not be updated with `updatePropertyById()`.
@@ -41,8 +42,6 @@ var INVALID_PROPERTY_ERRORS = {
42
style: '`style` must be set using `updateStylesByID()`.'
43
};
44
44
-var useWhitespaceWorkaround;
45
-
45
/**
46
* Operations used to process updates to DOM nodes. This is made injectable via
47
* `ReactComponent.BackendIDOperations`.
@@ -131,35 +130,7 @@ var ReactDOMIDOperations = {
130
'updateInnerHTMLByID',
131
function(id, html) {
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);
134
}
135
),
136
src/browser/ui/dom/setInnerHTML.js
new
+64
@@ -0,0 +1,64 @@
1
+/**
2
+ * Copyright 2013-2014 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 setInnerHTML
17
+ */
18
+
19
+"use strict";
20
+
21
+var ExecutionEnvironment = require('ExecutionEnvironment');
22
+
23
+/**
24
+ * Set the innerHTML property of a node, ensuring that whitespace is preserved
25
+ * even in IE8.
26
+ *
27
+ * @param {DOMElement} node
28
+ * @param {string} html
29
+ * @internal
30
+ */
31
+var setInnerHTML = function(node, html) {
32
+ node.innerHTML = html;
33
+};
34
+
35
+if (ExecutionEnvironment.canUseDOM) {
36
+ // IE8: When updating a just created node with innerHTML only leading
37
+ // whitespace is removed. When updating an existing node with innerHTML
38
+ // whitespace in root TextNodes is also collapsed.
39
+ // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html
40
+
41
+ // Feature detection; only IE8 is known to behave improperly like this.
42
+ var testElement = document.createElement('div');
43
+ testElement.innerHTML = ' ';
44
+ if (testElement.innerHTML === '') {
45
+ setInnerHTML = function(node, html) {
46
+ // Magic theory: IE8 supposedly differentiates between added and updated
47
+ // nodes when processing innerHTML, innerHTML on updated nodes suffers
48
+ // from worse whitespace behavior. Re-adding a node like this triggers
49
+ // the initial and more favorable whitespace behavior.
50
+ node.parentNode.replaceChild(node, node);
51
+
52
+ if (html.match(/^[ \r\n\t\f]/)) {
53
+ // Recover leading whitespace by temporarily prepending any character.
54
+ // \uFEFF has the potential advantage of being zero-width/invisible.
55
+ node.innerHTML = '\uFEFF' + html;
56
+ node.firstChild.deleteData(0, 1);
57
+ } else {
58
+ node.innerHTML = html;
59
+ }
60
+ };
61
+ }
62
+}
63
+
64
+module.exports = setInnerHTML;