I have recently needed to write code that uses JavaScript to add elements dynamically to a web page on the client. I read the relevant W3C documents and wrote the code, and it seemed to work fine. Until I tried it on Internet Explorer. After some digging, I found an explanation in the MSDN DHTML reference, on the page describing the NAME Attribute.
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.
The trouble is that including attributes in calls to createElement
is a Microsoft-only extension. If you try to do this (e.g. document.createElement("<input name='brian'>")
), there are at least three possible outcomes:
- The browser throws an exception because “<input name=’brian’>” is not a valid element type. This is the correct behaviour.
- The browser creates an element with type = “input” and name = “brian”. This is what IE 6 does.
- The browser creates an element with the invalid type = “<input name=’brian’>”. This is what Netscape 7.1 and Opera 8.5 do. Thanks to Kristof for pointing this out.
So if you want to create named elements dynamically, you have to be a bit crafty. It’s no good trying the correct approach first, because this will fail on IE6 with no way for your code to check. Therefore, I first attempt to create the element by including the name attribute in the call to createElement, and check the result. If it checks out OK, then I’m probably running on IE6 and all is well. Otherwise, I just try again using the correct method of creating the element and then setting the name.
Here’s the function I came up with that allows you to create named elements on any browser. Pass it the name and type of the element you want to create. I have tested this on various Windows browsers: IE5, 5.5 and 6; Firefox 1 and 1.5; Mozilla 1.7; Netscape 7.1 and 8; and Opera 7.23 and 8.5. Please let me know if you notice problems on these or any other browser.
function createNamedElement(type, name) {
var element = null;
// Try the IE way; this fails on standards-compliant browsers
try {
element = document.createElement('<'+type+' name="'+name+'">');
} catch (e) {
}
if (!element || element.nodeName != type.toUpperCase()) {
// Non-IE browser; use canonical method to create named element
element = document.createElement(type);
element.name = name;
}
return element;
}
This code doesn’t use browser-sniffing techniques. Instead it simply tries to create the element using the Internet Explorer method first; if this fails it uses the standard method.
Note also that there are problems setting the name attribute even on static elements:
Microsoft JScript allows the name to be changed at run time. This does not cause the name in the programming model to change in the collection of elements, but it does change the name used for submitting elements.
Be sure to test thoroughly — don’t just assume it will work (as I did).
Here’s Simon Willison‘s
createElement()
function.I found that the same problem applies to the class attribute of an element. So possibly even more attributes can’t be set with the W3C setAttribute method.
I have no problems setting the class of an element. Use this:
element.className = 'someClass';
This works in IE6, at least.
The createElement function seems not to work properly in Opera 8.51 (tested on Windows XP SP2). It won’t throw an error with the IE way and instead, selectEl.nodeName will gives you back the whole string you used as the argument for document.createElement. This problem seems to be solved in the Opera 9 technology preview.
To make it work with Opera
My previous reply seems to have been stripped.
So, to make it work with Opera 8.51, you can do this:
if (!element || element.nodeName != type.toUpperCase())
{
element = document.createElement( type );
element.name = name;
}
Thanks, Kristof. I had long been meaning to test this on other browsers, and you spurred me into action. I have incorporated your change, and the function now works in Opera 8.5 and Netscape 7.1. I appreciate the time you took to share your discoveries.
Simon’s
createElement()
function could indeed be useful for some users. (It solves an IE6 problem when creating elements in XML documents.) It still doesn’t allow you to create named elements, but you could combine the two functions to solve both problems at once!Newer versions of opera browser will try to create element with try and catch method, and they will also managed to do it, so try and catch method is not useful for opera, because it can not properly set up attributes for element, so the created elements actually doesn’t have atributes previously set up with IE create Element method, but the element itself does exist. FF behave normally. So for Opera you will have to find out it’s really opera if (window.opera) object detection method, that is really effecive way to find out it’s opera and you will have to addapt your script also for opera.
if (!element || element.nodeName != type.toUpperCase())
{
element = document.createElement( type );
element.name = name;
}
This is a problem with IE/Mac as element.nodeName returns the whole string used in the argument for document.createElement and type.toUpperCase() returns the element type.
Annette, it sounds as if Mac IE is thoroughly broken. I didn’t think Mac IE was still supported these days — what version of IE do you refer to? One day I’ll fire up my ancient PowerBook (Mac OS 9) and give it a try.
tag-strategia.com » IE DOM Bugs,
It’s recommended to avoid the use of innerHTML because it does not adjust to the W3 standards, also I’ve found some cases where it does not works properly.
There are some cases where it seems that the code is not parsed when innerHTML is used.
The name issue discused here is due to a bad DOM implementation from Microsoft (oh my god! how can this be possible! lol).
Read this page also:
http://www.easy-reader.net/archives/2005/09/02/death-to-bad-dom-implementations/
@Ernesto
Yeah, the other problem with .innerHTML is that IE will not register any inline events you set properly, worse yet, you can’t create any DOM event handlers either.
I am trying to set an onclick event with setAttribute and it works in FF, but it does not with IE6. I solved the problem doing something as it is said here with ‘name’; but I would appreciate any other method, if it is possible.
First off, great article, I found it very helpful and I think it explains my problem….
I think the same problem applies to copied elements. I’m creating an input table with an add row function. I copy the previous row, modify some attributes for each cell/column(name, value) that contains an input field and add the row to the end of the table.
Works great in FF, but in IE7 if I click a radio button in the newly created row, it affects the previous row (the one that was copied).
But, when I submit the form it saves the data correctly.
So I assume you can’t modify the name value at all in IE. Any thoughts on this?
Mataichi, I believe that this will happen in IE6, since you can’t modify the name attribute even on a ciopied element. But it’s interesting that it happens in IE7 too. I haven’t yet tested IE7, but it’s a bit sad if Microsoft still haven’t fixed this.
Bennett –
Indeed this, along with number of other long-standing bugs / issues with the DOM, have not been fixed in IE7. See the third message on this blog post from Dave Massy, program manager at Microsoft from another irate developer ;-). He details all of the ones he knows about that haven’t been fixed yet:
http://blogs.msdn.com/dmassy/archive/2006/11/30/vpc-to-run-ie6-and-ie7-on-the-same-machine.aspx
Cheers,
– Bill