Efficient outerHTML polyfill that doesn't use cloneNode(true)
/* | |
* outerHTML.js | |
* Cross-browser full HTMLElement.outerHTML implementation. | |
* | |
* 2011-11-14 | |
* | |
* By Eli Grey, http://eligrey.com | |
* Public Domain. | |
* NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. | |
*/ | |
if (typeof document !== "undefined" && !("outerHTML" in document.createElementNS("http://www.w3.org/1999/xhtml", "_"))) { | |
(function(view) { | |
"use strict"; | |
var | |
container = document.createElementNS("http://www.w3.org/1999/xhtml", "_") | |
, elem_proto = (view.HTMLElement || view.Element).prototype | |
, xml_serializer = new XMLSerializer | |
, outerHTML_getter = function() { | |
var | |
node = this | |
, html | |
; | |
if (document.xmlVersion) { | |
return xml_serializer.serializeToString(node); | |
} else { | |
container.appendChild(node.cloneNode(false)); | |
html = container.innerHTML.replace("><", ">" + node.innerHTML + "<"); | |
container.innerHTML = ""; | |
return html; | |
} | |
} | |
, outerHTML_setter = function(html) { | |
var | |
node = this | |
, parent = node.parentNode | |
, child | |
; | |
if (parent === null) { | |
DOMException.code = DOMException.NOT_FOUND_ERR; | |
throw DOMException; | |
} | |
container.innerHTML = html; | |
while ((child = container.firstChild)) { | |
parent.insertBefore(child, node); | |
} | |
parent.removeChild(node); | |
} | |
; | |
if (Object.defineProperty) { | |
var outerHTML_prop_desc = { | |
get: outerHTML_getter | |
, set: outerHTML_setter | |
, enumerable: true | |
, configurable: true | |
}; | |
try { | |
Object.defineProperty(elem_proto, "outerHTML", outerHTML_prop_desc); | |
} catch (ex) { // IE 8 doesn't support enumerable:true | |
if (ex.number === -0x7FF5EC54) { | |
outerHTML_prop_desc.enumerable = false; | |
Object.defineProperty(elem_proto, "outerHTML", outerHTML_prop_desc); | |
} | |
} | |
} else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) { | |
elem_proto.__defineGetter__("outerHTML", outerHTML_getter); | |
elem_proto.__defineSetter__("outerHTML", outerHTML_setter); | |
} | |
}(self)); | |
} |
This comment has been minimized.
This comment has been minimized.
LeaVerou
commented
Sep 24, 2011
Wouldn't it be more efficient if you cached container instead of creating a new element every time? |
This comment has been minimized.
This comment has been minimized.
Not every element is in the same document, as you can see by my use of |
This comment has been minimized.
This comment has been minimized.
sashasklar
commented
Nov 14, 2011
Have you tested this in a recent version of Firefox? FF 6.0 on OS X seems to be removing the node without replacing it: http://jsfiddle.net/M27UA/ |
This comment has been minimized.
This comment has been minimized.
Fixed. For some reason I had |
This comment has been minimized.
This comment has been minimized.
sashasklar
commented
Nov 14, 2011
Nice, thanks for the quick fix! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
mathiasbynens commentedJun 24, 2011
T-shirt idea: “
0x7FF5EC54
is just a fancy way of saying2146823252
.”