UNPKG

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