The problem with innerHTML
Some like to DOM their way around. Others prefer the simplicity of innerHTML. Julien Lecomte, of Yahoo!, wrote up his thoughts on the problems with innerHTML.
Julien first points out some issues:
- Improper handling of the innerHTML property can enable script-injection attacks on Internet Explorer when the HTML string contains a script tag marked as defered: <script defer>…<script>
- Setting innerHTML will destroy existing HTML elements that have event handlers attached to them, potentially creating a memory leak on some browsers.
- You don’t get back a reference to the element(s) you just created, forcing you to add code to retrieve those references manually (using the DOM APIs…)
- You can’t set the innerHTML property on all HTML elements on all browsers (for instance, Internet Explorer won’t let you set the innerHTML property of a table row element)
He then puts together Douglas Crockfords purge and some code to clean up script tags, arriving at:
JAVASCRIPT:
-
-
YAHOO.util.Dom.setInnerHTML = function (el, html) {
-
el = YAHOO.util.Dom.get(el);
-
if (!el || typeof html !== ’string’) {
-
return null;
-
}
-
-
// Break circular references.
-
(function (o) {
-
-
var a = o.attributes, i, l, n, c;
-
if (a) {
-
l = a.length;
-
for (i = 0; i <l; i += 1) {
-
n = a[i].name;
-
if (typeof o[n] === ‘function’) {
-
o[n] = null;
-
}
-
}
-
}
-
-
a = o.childNodes;
-
-
if (a) {
-
l = a.length;
-
for (i = 0; i <l; i += 1) {
-
c = o.childNodes[i];
-
-
// Purge child nodes.
-
arguments.callee(c);
-
-
// Removes all listeners attached to the element via YUI’s addListener.
-
YAHOO.util.Event.purgeElement(c);
-
}
-
}
-
-
})(el);
-
-
// Remove scripts from HTML string, and set innerHTML property
-
el.innerHTML = html.replace(/<script[^>]*>((.|[\r\n])*?)<\\?\/script>/ig, “”);
-
-
// Return a reference to the first child
-
return el.firstChild;
-
};
-
(Via Ajaxian.)
4 things
1.) although I am against browser sniffing, the purging stuff should only run for IE browsers.
2.) the issue with .innerHTML for tables, thead, tfoot, tr, and select elements is still not addressed.
3.) what if the inner html generates a set of children? e.g. .innerHTML on a UL element? I think I would prefer to return the childNodes, or better yet nothing, since the user already has the top element, let them dig to what they want.
4. the script removal thing needs tweaking, to ONLY do it in IE, and ONLY remove the defer attribute… if I CALL this function, from MY code, I WANT to be able to add scripts.
Wilson
December 14, 2007 at 12:42 pm