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