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 | ;
|
10 |
|
11 | var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
|
12 | var DOMNamespaces = require('./DOMNamespaces');
|
13 |
|
14 | var WHITESPACE_TEST = /^[ \r\n\t\f]/;
|
15 | var NONVISIBLE_TEST = /<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/;
|
16 |
|
17 | var createMicrosoftUnsafeLocalFunction = require('./createMicrosoftUnsafeLocalFunction');
|
18 |
|
19 | // SVG temp container for IE lacking innerHTML
|
20 | var 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 | */
|
30 | var 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 |
|
46 | if (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 |
|
95 | module.exports = setInnerHTML; |
\ | No newline at end of file |