May 26, 2017 Webby

A better createElementWithName()

Back in 2005, I wrote a piece about IEs abysmal generation of NAMEd elements via the DOM (which, interestingly enough, has proven to be one of the most popular posts on the blog, pointing to the fact that this is an obvious pain point for many DOM scripters out there). The the time, I wrote

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;
}

It was a complete hack, but it worked. More importantly, however, it began a discussion of a better way to fix the problem in a cross-browser way. The best solution offered was Anthony Lieuallens very efficient one-time function definition:

function createElementWithName(){}
(function(){
  try {
    var el=document.createElement( 'div name="foo"' );
    if( 'DIV'!=el.tagName ||
        'foo'!=el.name ){
      throw 'create element error';
    }
    createElementWithName = function( tag, name ){
      return document.createElement( '' + tag + ' name="' +
        name + '"/' + tag + '' );
    }
  }catch( e ){
    createElementWithName = function( tag, name ){
      var el = document.createElement( tag );
      // setAttribute might be better here ?
      el.name = name;
      return el;
    }
  }
})();

And now Brian Adkins has refactored the script to be even fewer lines of code:

var createElementWithName = ( function(){
  try {
    var el = document.createElement( 'div name="foo"' );
    if( el.tagName !== 'DIV' || el.name !== 'foo' ){
      throw 'create failed';
    }
    return function( tag, name ){
      return document.createElement( '' + tag + ' name="' +
        name + '"/' + tag + '' );
    };
  }catch( e ){
    return function( tag, name ){
      var el = document.createElement( tag );
      el.setAttribute( 'name', name );
      return el;
    };
  }
})();

Geat job Brian, thanks for sharing.