-
-
Save usmonster/d15e4475e3983bd35dba to your computer and use it in GitHub Desktop.
Updated Node.prototype.textContent shim for IE8 ONLY
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
// inspired by Eli Grey's shim @ http://eligrey.com/blog/post/textcontent-in-ie8 | |
// heavily modified to better match the spec: | |
// http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Node3-textContent | |
if (Object.defineProperty && Object.getOwnPropertyDescriptor && | |
Object.getOwnPropertyDescriptor(Element.prototype, 'textContent') && | |
!Object.getOwnPropertyDescriptor(Element.prototype, 'textContent').get) { | |
// NOTE: Neither of these "drop-in" patterns would work: | |
// Object.defineProperty(..., ..., descriptor); // nope! | |
// Object.defineProperty(..., ..., { get: descriptor.get, set: descriptor.set }); // nope! | |
// So must use function-wrapped descriptor.fn.call pattern. | |
// "Normal" Elements | |
// NOTE: textContent is different from innerText, so its use would be incorrect: | |
//var innerText = Object.getOwnPropertyDescriptor(Element.prototype, "innerText"); // nope! | |
var getTextContent = function(x) { | |
if (this.tagName === 'BR') { return '\n'; } | |
var c = this.firstChild; | |
var tc=[]; | |
// append the textContent of its children | |
while(!!c) { | |
if (c.nodeType !== 8 && c.nodeType !== 7) { // skip comments | |
tc.push(c.textContent); | |
} | |
c = c.nextSibling; | |
} | |
// a <br> Element should show as a newline | |
c = null; | |
tc = tc.join(''); | |
return tc; | |
}; | |
var setTextContent = function(x) { | |
var c; | |
while(!!(c=this.lastChild)) { | |
this.removeChild(c); | |
} | |
if (x!==null) { | |
c=document.createTextNode(x); | |
this.appendChild(c); | |
} | |
}; | |
Object.defineProperty(Element.prototype, 'textContent', { | |
get: function() { | |
// return innerText.get.call(this); // not good enough! | |
return getTextContent.call(this); | |
}, | |
set: function(x) { | |
// return innerText.set.call(this, x); // not good enough! | |
setTextContent.call(this, x); | |
}, | |
configurable: true | |
}); | |
// <script> Elements | |
var scriptText = Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype, 'text'); | |
Object.defineProperty(HTMLScriptElement.prototype, 'textContent', { | |
get: function() { | |
return scriptText.get.call(this); | |
}, | |
set: function(x) { | |
scriptText.set.call(this, x); | |
}, | |
configurable: true | |
}); | |
// <style> Elements | |
var cssText = Object.getOwnPropertyDescriptor(CSSStyleSheet.prototype, 'cssText'); | |
Object.defineProperty(HTMLStyleElement.prototype, 'textContent', { | |
get: function() { | |
return cssText.get.call(this.styleSheet); | |
}, | |
set: function(x) { | |
cssText.set.call(this.styleSheet, x); | |
}, | |
configurable: true | |
}); | |
// <title> Elements | |
var titleText = Object.getOwnPropertyDescriptor(HTMLTitleElement.prototype, 'text'); | |
Object.defineProperty(HTMLTitleElement.prototype, 'textContent', { | |
get: function() { | |
return titleText.get.call(this); | |
}, | |
set: function(x) { | |
titleText.set.call(this, x); | |
}, | |
configurable: true | |
}); | |
// Text nodes | |
var textNodeValue = Object.getOwnPropertyDescriptor(Text.prototype, 'nodeValue'); | |
Object.defineProperty(Text.prototype, 'textContent', { | |
get: function() { | |
return textNodeValue.get.call(this); | |
}, | |
set: function(x) { | |
textNodeValue.set.call(this, x); | |
}, | |
configurable: true | |
}); | |
// Comments (and possibly other weird Node types that are treated as comments in IE) | |
var elementNodeValue = Object.getOwnPropertyDescriptor(Element.prototype, 'nodeValue'); | |
Object.defineProperty(HTMLCommentElement.prototype, 'textContent', { | |
get: function() { | |
return elementNodeValue.get.call(this); | |
}, | |
set: function(x) { | |
elementNodeValue.set.call(this, x); | |
}, | |
configurable: true | |
}); | |
// Document and DocumentFragment Nodes | |
// NOTE: IE8 seems to reuse HTMLDocument for both, so have to check nodeType explicitly | |
var documentNodeValue = Object.getOwnPropertyDescriptor(HTMLDocument.prototype, 'nodeValue'); | |
Object.defineProperty(HTMLDocument.prototype, 'textContent', { | |
get: function() { | |
// document fragments have textContent | |
if (this.nodeType === 11) { | |
return getTextContent.call(this); | |
} | |
// a true Document's textContent is always null | |
return null; // === documentNodeValue.get.call(this); | |
}, | |
set: function(x) { | |
if (this.nodeType === 11) { | |
setTextContent.call(this, x); | |
} | |
// setting a Document's textContent has no side effects | |
// else { documentNodeValue.set.call(this, x); } | |
}, | |
configurable: true | |
}); | |
// other Node types are either deprecated or don't matter in HTML5/IE standards mode | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
TODO:
configurable: true
(apparently neitherconfigurable
norenumerable
are used by IE, thoughconfigurable: true
generates an error)