Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

Efficient outerHTML polyfill that doesn't use cloneNode(true)

View outerHTML.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
/*
* 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));
 
}

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

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

Owner

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

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/

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

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.