Permalink
Cannot retrieve contributors at this time
Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
| /** | |
| * Copyright 2013-present, Facebook, Inc. | |
| * All rights reserved. | |
| * | |
| * This source code is licensed under the BSD-style license found in the | |
| * LICENSE file in the root directory of this source tree. An additional grant | |
| * of patent rights can be found in the PATENTS file in the same directory. | |
| * | |
| * @providesModule setInnerHTML | |
| */ | |
| 'use strict'; | |
| var ExecutionEnvironment = require('ExecutionEnvironment'); | |
| var DOMNamespaces = require('DOMNamespaces'); | |
| var WHITESPACE_TEST = /^[ \r\n\t\f]/; | |
| var NONVISIBLE_TEST = /<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/; | |
| var createMicrosoftUnsafeLocalFunction = require('createMicrosoftUnsafeLocalFunction'); | |
| // SVG temp container for IE lacking innerHTML | |
| var reusableSVGContainer; | |
| /** | |
| * Set the innerHTML property of a node, ensuring that whitespace is preserved | |
| * even in IE8. | |
| * | |
| * @param {DOMElement} node | |
| * @param {string} html | |
| * @internal | |
| */ | |
| var setInnerHTML = createMicrosoftUnsafeLocalFunction( | |
| function(node, html) { | |
| // IE does not have innerHTML for SVG nodes, so instead we inject the | |
| // new markup in a temp node and then move the child nodes across into | |
| // the target node | |
| if (node.namespaceURI === DOMNamespaces.svg && !('innerHTML' in node)) { | |
| reusableSVGContainer = reusableSVGContainer || document.createElement('div'); | |
| reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>'; | |
| var svgNode = reusableSVGContainer.firstChild; | |
| while (svgNode.firstChild) { | |
| node.appendChild(svgNode.firstChild); | |
| } | |
| } else { | |
| node.innerHTML = html; | |
| } | |
| } | |
| ); | |
| if (ExecutionEnvironment.canUseDOM) { | |
| // IE8: When updating a just created node with innerHTML only leading | |
| // whitespace is removed. When updating an existing node with innerHTML | |
| // whitespace in root TextNodes is also collapsed. | |
| // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html | |
| // Feature detection; only IE8 is known to behave improperly like this. | |
| var testElement = document.createElement('div'); | |
| testElement.innerHTML = ' '; | |
| if (testElement.innerHTML === '') { | |
| setInnerHTML = function(node, html) { | |
| // Magic theory: IE8 supposedly differentiates between added and updated | |
| // nodes when processing innerHTML, innerHTML on updated nodes suffers | |
| // from worse whitespace behavior. Re-adding a node like this triggers | |
| // the initial and more favorable whitespace behavior. | |
| // TODO: What to do on a detached node? | |
| if (node.parentNode) { | |
| node.parentNode.replaceChild(node, node); | |
| } | |
| // We also implement a workaround for non-visible tags disappearing into | |
| // thin air on IE8, this only happens if there is no visible text | |
| // in-front of the non-visible tags. Piggyback on the whitespace fix | |
| // and simply check if any non-visible tags appear in the source. | |
| if (WHITESPACE_TEST.test(html) || | |
| html[0] === '<' && NONVISIBLE_TEST.test(html)) { | |
| // Recover leading whitespace by temporarily prepending any character. | |
| // \uFEFF has the potential advantage of being zero-width/invisible. | |
| // UglifyJS drops U+FEFF chars when parsing, so use String.fromCharCode | |
| // in hopes that this is preserved even if "\uFEFF" is transformed to | |
| // the actual Unicode character (by Babel, for example). | |
| // https://github.com/mishoo/UglifyJS2/blob/v2.4.20/lib/parse.js#L216 | |
| node.innerHTML = String.fromCharCode(0xFEFF) + html; | |
| // deleteData leaves an empty `TextNode` which offsets the index of all | |
| // children. Definitely want to avoid this. | |
| var textNode = node.firstChild; | |
| if (textNode.data.length === 1) { | |
| node.removeChild(textNode); | |
| } else { | |
| textNode.deleteData(0, 1); | |
| } | |
| } else { | |
| node.innerHTML = html; | |
| } | |
| }; | |
| } | |
| testElement = null; | |
| } | |
| module.exports = setInnerHTML; |