UNPKG

3.74 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2013-present, Facebook, Inc.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 */
8
9'use strict';
10
11var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
12var DOMNamespaces = require('./DOMNamespaces');
13
14var WHITESPACE_TEST = /^[ \r\n\t\f]/;
15var NONVISIBLE_TEST = /<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/;
16
17var createMicrosoftUnsafeLocalFunction = require('./createMicrosoftUnsafeLocalFunction');
18
19// SVG temp container for IE lacking innerHTML
20var reusableSVGContainer;
21
22/**
23 * Set the innerHTML property of a node, ensuring that whitespace is preserved
24 * even in IE8.
25 *
26 * @param {DOMElement} node
27 * @param {string} html
28 * @internal
29 */
30var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {
31 // IE does not have innerHTML for SVG nodes, so instead we inject the
32 // new markup in a temp node and then move the child nodes across into
33 // the target node
34 if (node.namespaceURI === DOMNamespaces.svg && !('innerHTML' in node)) {
35 reusableSVGContainer = reusableSVGContainer || document.createElement('div');
36 reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>';
37 var svgNode = reusableSVGContainer.firstChild;
38 while (svgNode.firstChild) {
39 node.appendChild(svgNode.firstChild);
40 }
41 } else {
42 node.innerHTML = html;
43 }
44});
45
46if (ExecutionEnvironment.canUseDOM) {
47 // IE8: When updating a just created node with innerHTML only leading
48 // whitespace is removed. When updating an existing node with innerHTML
49 // whitespace in root TextNodes is also collapsed.
50 // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html
51
52 // Feature detection; only IE8 is known to behave improperly like this.
53 var testElement = document.createElement('div');
54 testElement.innerHTML = ' ';
55 if (testElement.innerHTML === '') {
56 setInnerHTML = function (node, html) {
57 // Magic theory: IE8 supposedly differentiates between added and updated
58 // nodes when processing innerHTML, innerHTML on updated nodes suffers
59 // from worse whitespace behavior. Re-adding a node like this triggers
60 // the initial and more favorable whitespace behavior.
61 // TODO: What to do on a detached node?
62 if (node.parentNode) {
63 node.parentNode.replaceChild(node, node);
64 }
65
66 // We also implement a workaround for non-visible tags disappearing into
67 // thin air on IE8, this only happens if there is no visible text
68 // in-front of the non-visible tags. Piggyback on the whitespace fix
69 // and simply check if any non-visible tags appear in the source.
70 if (WHITESPACE_TEST.test(html) || html[0] === '<' && NONVISIBLE_TEST.test(html)) {
71 // Recover leading whitespace by temporarily prepending any character.
72 // \uFEFF has the potential advantage of being zero-width/invisible.
73 // UglifyJS drops U+FEFF chars when parsing, so use String.fromCharCode
74 // in hopes that this is preserved even if "\uFEFF" is transformed to
75 // the actual Unicode character (by Babel, for example).
76 // https://github.com/mishoo/UglifyJS2/blob/v2.4.20/lib/parse.js#L216
77 node.innerHTML = String.fromCharCode(0xfeff) + html;
78
79 // deleteData leaves an empty `TextNode` which offsets the index of all
80 // children. Definitely want to avoid this.
81 var textNode = node.firstChild;
82 if (textNode.data.length === 1) {
83 node.removeChild(textNode);
84 } else {
85 textNode.deleteData(0, 1);
86 }
87 } else {
88 node.innerHTML = html;
89 }
90 };
91 }
92 testElement = null;
93}
94
95module.exports = setInnerHTML;
\No newline at end of file