Skip to content

@eligrey /outerHTML.js
Created

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
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

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

@LeaVerou

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

@eligrey
Owner

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

@sashasklar

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
Owner

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

Nice, thanks for the quick fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.