outaTiME

at devel days

The problem with innerHTML

with one comment

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:

  1.  
  2. YAHOO.util.Dom.setInnerHTML = function (el, html) {
  3.     el = YAHOO.util.Dom.get(el);
  4.     if (!el || typeof html !== ’string’) {
  5.         return null;
  6.     }
  7.  
  8.     // Break circular references.
  9.     (function (o) {
  10.  
  11.         var a = o.attributes, i, l, n, c;
  12.         if (a) {
  13.             l = a.length;
  14.             for (i = 0; i <l; i += 1) {
  15.                 n = a[i].name;
  16.                 if (typeof o[n] === ‘function’) {
  17.                     o[n] = null;
  18.                 }
  19.             }
  20.         }
  21.  
  22.         a = o.childNodes;
  23.  
  24.         if (a) {
  25.             l = a.length;
  26.             for (i = 0; i <l; i += 1) {
  27.                 c = o.childNodes[i];
  28.  
  29.                 // Purge child nodes.
  30.                 arguments.callee(c);
  31.  
  32.                 // Removes all listeners attached to the element via YUI’s addListener.
  33.                 YAHOO.util.Event.purgeElement(c);
  34.             }
  35.         }
  36.  
  37.     })(el);
  38.  
  39.     // Remove scripts from HTML string, and set innerHTML property
  40.     el.innerHTML = html.replace(/<script[^>]*>((.|[\r\n])*?)<\\?\/script>/ig, “”);
  41.  
  42.     // Return a reference to the first child
  43.     return el.firstChild;
  44. };
  45.  

(Via Ajaxian.)

Written by outaTiME

December 14, 2007 at 11:20 am

Posted in Development, Javascript

One Response

Subscribe to comments with RSS.

  1. 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


Leave a Reply