Instantly share code, notes, and snippets.

Embed
What would you like to do?
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));
}
@mathiasbynens

This comment has been minimized.

Show comment
Hide comment
@mathiasbynens

mathiasbynens Jun 24, 2011

T-shirt idea: “0x7FF5EC54 is just a fancy way of saying 2146823252.”

mathiasbynens commented Jun 24, 2011

T-shirt idea: “0x7FF5EC54 is just a fancy way of saying 2146823252.”

@LeaVerou

This comment has been minimized.

Show comment
Hide comment
@LeaVerou

LeaVerou Sep 24, 2011

Wouldn't it be more efficient if you cached container instead of creating a new element every time?

LeaVerou commented Sep 24, 2011

Wouldn't it be more efficient if you cached container instead of creating a new element every time?

@eligrey

This comment has been minimized.

Show comment
Hide comment
@eligrey

eligrey Sep 24, 2011

Not every element is in the same document, as you can see by my use of node.ownerDocument.createElement.

Owner

eligrey commented Sep 24, 2011

Not every element is in the same document, as you can see by my use of node.ownerDocument.createElement.

@sashasklar

This comment has been minimized.

Show comment
Hide comment
@sashasklar

sashasklar 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/

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/

@eligrey

This comment has been minimized.

Show comment
Hide comment
@eligrey

eligrey Nov 14, 2011

Fixed. For some reason I had parent.removeChild(child); in there, and I probably should have at least tested the script once I added the setter :P

Owner

eligrey commented Nov 14, 2011

Fixed. For some reason I had parent.removeChild(child); in there, and I probably should have at least tested the script once I added the setter :P

@sashasklar

This comment has been minimized.

Show comment
Hide comment
@sashasklar

sashasklar Nov 14, 2011

Nice, thanks for the quick fix!

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