May 26, 2017 Webby

Death to bad DOM Implementations

I just encountered a DOM implementation issue in IE which took about three hours to solve (and like a year off my life). The story goes like this:

I could not, for the life of me, figure out why a form submitted in Firefox was coming through perfectly while it was missing fields in IE. The form in question has some normal fields and some dynamically generated ones (if JavaScript is enabled). The normal stuff was coming through fine, but I was getting no values for the dynamically generated fields when the form was submitted in IE. I checked the $_REQUEST variable (I am using PHP) to see what was coming through, just to be sure.

I immediately figured it was missing name attributes, but I was using the proper syntax to create the input elements via the DOM (note: the actual JS is more generic than this)

var inpt = document.createElement('input');
inpt.setAttribute('name', 'company');

Indeed, when I looked at the page through the Web Accessibility Toolbars View Generated Source, it was indeed missing the name attribute:

INPUT id=company maxLength=255
       validatefor=title required=required

After about another hour or two of fruitless Google-ing, I finally typed in the magic phrase (setting the name attribute in Internet Explorer) and ended up on Bennett McElwees blog post of the same name. Suddenly it was all clear and (as I expected) IEs botched implementation of the DOMs createElement function was to blame.

According to the MSDN page on the name attribute (linked and quoted in the blog entry):

The NAME attribute cannot be set at run time on elements dynamically created with the createElement method. To create an element with a name attribute, include the attribute and value when using the createElement method.

It continued with the following example:

var oAnchor =
  document.createElement(A NAME='AnchorName'/A);

The script solution Bennett posted was somewhat of a red herring, however, as Firefox would actually execute the createElement intended for IE and end up with an element named input name=company / which would be rendered on the page as

input name=company /  id=company
        maxlength=255 validatefor=title required=required /

Perhaps you can see why this would be problematic.

I augmented Bennetts script slightly and renamed the function createElementWithName so I wouldnt have to use it on every element I created in the script:

function createElementWithName(type, name) {
  var element;
  // First try the IE way; if this fails then use the standard way
  if (document.all) {
    element =
      document.createElement('< '+type+' name="'+name+'" />');
  } else {
    element = document.createElement(type);
    element.setAttribute('name', name);
  }
  return element;
}

I am not a super fan of the reference to document.all as it feels so much like browser sniffing. I am up for suggestions to improve the function if you have any ideas.

Anyway, I am posting this to hopefully save someone else from the major headache I had today.