IE DOM Bugs

Posted by Tom on February 7th, 2006

I’ve been working on a Javascript project where it’s necessary to create input elements (radio buttons and checkboxes) dynamically. With a functional DOM, it takes only a couple of lines of code, and works fine in Firefox and Safari. Too bad IE isn’t as DOM compatible as it claims to be.

After several searches, I discovered IE doesn’t allow the name attribute to be changed after the element is created—and it can’t be set in a DOM compatible way during creation.

Bennett McElwee suggested a solution in his blog that is nicely cross-browser; anything other than IE throws an exception and gets created properly. (I suspect modifying the parent node’s innerHTML would work as well.)

function createElement(type, name) {
   var element = null;

   try {
      // First try the IE way; if this fails then use the standard way
      element = document.createElement('<'+type+' name="'+name+'">');
   } catch (e) {
      // Probably failed because we're not running on IE
   }
   if (!element) {
      element = document.createElement(type);
      element.name = name;
   }
   return element;
}

And your type attribute too

Another part of the project requires we transform checkboxes to radio buttons and hidden fields. This could be accomplished through a page reload, but it’s overkill for such a small change. Once again, in truly DOM-compliant browsers, this requires only a couple of lines of code:

element.setAttribute("type", "radio");

The MSDN reference for the type attribute says:

As of Microsoft Internet Explorer 5, the type property is read/write-once, but only when an input element is created with the createElement method and before it is added to the document.

QuirksMode has a bug report for this, complete with test page and workaround submitted by Stijn Peeters. Stijn admits the workaround needs a little bit of cleanup.

Essentially, his solution is to always remove the element, and recreate a modified one. (See the bug above!) Here’s my solution:

try {
   element.setAttribute("type", "radio");
} catch (e) {
   var newElement = null;
   var tempStr = element.getAttribute("name");
   try {
      newElement = document.createElement("<input type=\"" +typeStr+ "\" name=\"" +tempStr+ "\">");
   } catch (e) {}
   if (!newElement) {
      newElement = document.createElement("input");
      newElement.setAttribute("type", "radio");
      newElement.setAttribute("name", tempStr);
   }
   if (tempStr = element.getAttribute("value")) {
      newElement.setAttribute("value", tempStr);
   }
   element.parentNode.replaceChild(newElement, element);
}

Update:

Aaron over at easy-reader.net encountered the same problem a few months before I did. His solution is similar, and the comments there are good. If only I had found it sooner!

  • Google Bookmarks
  • del.icio.us
  • LinkedIn
  • Digg
  • Facebook
  • Reddit
  • StumbleUpon
  • Twitter

13 Responses to “IE DOM Bugs”

Been trying something similar… it all works but I can’t seem to get the focus back on the input field. Any workarounds?

function CC_changetype(target, wrde) {
if(document.getElementById(target.id).value == wrde)
{
replace = document.getElementById(target.name);
var val = replace.value;
var id = replace.id
var parent = replace.parentNode;
var sibling = replace.nextSibling;
var newel = document.createElement(’input’);
newel.setAttribute(’type’, ‘password’);
newel.setAttribute(’value’, ”);
newel.setAttribute(’id’, id);
newel.setAttribute(’maxLength’, ‘8′);
parent.removeChild(replace);
parent.insertBefore(newel, sibling);
//settimeout(’document.getElementById(newel.getAttribute(”id”)).focus();’,1000);
}
}

With IE/Win, it does seem odd that the new element does not get focus, although it does for Firefox and Safari (both on OS X). Calling select() seems to solve the problem:

// ...
newel.focus();
newel.select();

Hey Tom,

It solved the problem very nicely thanx!

Another problem popped up though… I want to copy the style of the old element to the new one. But this doesn’t work. I’m a novice to javascript and can’t find a way to solve this. I can work around with var styleheight = replace.style.height; etc but then I always need to know in advance what styles are set for the element. I guess there should be a way to copy and paste a style into the new element.

if(document.getElementById(target.id).value == wrde)
{
replace = document.getElementById(target.name);
var val = replace.value;
var id = replace.id;
var style = replace.style;

var parent = replace.parentNode;
var sibling = replace.nextSibling;
var newel = document.createElement(’input’);
newel.setAttribute(’type’, ‘password’);
newel.setAttribute(’value’, ”);
newel.setAttribute(’id’, id);
newel.setAttribute(’style’, style);
newel.setAttribute(’maxLength’, ‘8′);
parent.removeChild(replace);
parent.insertBefore(newel, sibling);
newel.focus();
newel.select();

}

Finished…

I finally got it all to work the way I want it. The next script has been tested in: IE6.0, NS7.1, MFirefox1.5, and Mozilla 1.6 on XP service pack 1. Don’t know about any Mac browsers or other compatibilities…

Again thanx for the help!

function CC_changetype(target, wrde)
{

var inp = document.createElement(”input”);
inp.name = inp.id = target.id;
inp.style.cssText = target.style.cssText;
var parent = target.parentNode;

if(target.value == wrde) {
inp.type = “password”;
inp.value = “”;
inp.maxLength = 8;
inp.setAttribute(’onblur’, target.getAttribute(’onfocus’));
inp.setAttribute(’onfocus’, “this.select();”);
var fcs = true;
}
else if (target.value == ”) {
inp.type = “text”;
inp.maxLength = 99;
inp.value = wrde;
inp.setAttribute(’onfocus’, target.getAttribute(’onblur’));
}
if(target.value == wrde || target.value == ”) {
parent.insertBefore(inp, target);
parent.removeChild(target);
}
if(fcs) {
inp.focus();
inp.select();
}
}

Oops… old copy :)

replace

inp.setAttribute(’onfocus’, “this.select();”);

with

inp.setAttribute(’onfocus’, function(){this.select();});

Finished…

I finally got it all to work the way I want it. The next script has been tested in: IE6.0, NS7.1, MFirefox1.5, and Mozilla 1.6 on XP service pack 1. Don’t know about any Mac browsers or other compatibilities…

thanx for the help!

but if u have more rows coming dynamically u ll get prob again. so just follow this code so that u ll get perfect result.

replace

inp.setAttribute(’onfocus’, “this.select();”);

&&&

inp.setAttribute(’onfocus’, function(){this.select();});

with following code

inputTag3.setAttribute(’onblur’, function(){convertToUpperCase(this);});

and in fucntion convertToUpperCase() write as follows.

function convertToUpperCase(fieldId)
{
fieldId.value = fieldId.value.toUpperCase();
}

[...] 参考:1、http://www.thunderguy.com/semicolon/2005/05/23/setting-the-name-attribute-in-internet-explorer/2、http://alt-tag.com/blog/archives/2006/02/ie-dom-bugs/ [...]

This function works in FF and IE. The main difference with the other scripts on this page is that all of the elements attributes are preserved.

Usage:

oElement = document.getElementById(’myElement’);
setInputAttribute(oElement, ‘type’, ‘radio’);

The code:

function setInputAttribute(oInputElement, sAttributeName, sAttributeValue)
{
/* first try the DOM-compliant way
*/
try
{
oInputElement.setAttribute(sAttributeName, sAttributeValue);
}
catch (e)
{
/* then try it another way
*/

/* build HTML string for clone input */

//get all attributes
var aoAttributes = oInputElement.attributes;
var iLength = aoAttributes.length;

//create html string for new input element
var sHTML = “‘;

/* create new element using the HTML string */
oNewElement = document.createElement(sHTML);

/* replace old element with new one */
oInputElement.parentNode.replaceChild(oNewElement, oInputElement);
}
}

Good luck!

For IE 6 at least, setAttribute does not work, period. I have resorted to using the node proeprties (onClick, className, colSpan, id, etc.) and yes they are case-sensitive so for example, colspan onclick doesn’t work. I have the following function:

function setIEAttribute(node,property,value) {
eval(”node.” + property + ” = value”);
}

that seem to do the trick. So in my code I have, for example,

cell.setAttribute(”colspan”,”2″);
if (isIE) setIEAttribute(cell,”colSpan”,”2″);

It’s not pretty but I’d rather have the constant reminder that it’s IE that causing this grief, not the DOM.

Hi Don,

your fix worked for me. thanks

Fixes for all of these IE bugs can be found here:
http://webbugtrack.blogspot.com/2007/08/bug-242-setattribute-doesnt-always-work.html

Hope this helps

I created a similar workaround that uses three functions. A global createElement() function which has a try-catch block in it, and two other functions that cater to Internet Explorer and standards browsers. The try-catch only executes once, as the createElement function is overwritten at run time to be the createElement variation supported by the current browser.

It might run a tad faster than other variations of this bug fix because the try-catch block is only used once.

http://fundamentaldisaster.blogspot.com/2008/10/cross-browser-javascript-creating-dom.html

can any one help the onblur event is not working

var element3 = document.createElement(”input”);
element3.type = “text”;
element3.id = “txt_discountAmount”;
element3.size = “8″;
//element3.onblur = fun1(this.value);
//inp.setAttribute(’onfocus’, function(){this.select();});
element3.setAttribute(”onblur”,function(){getValue(this);});
//element3.onblur = “fun(this)”;

cell6.appendChild(element3);

function getValues(value)
{
alert(value);
}

Add Your Comment