Site Navigation

Showing posts with label DOM Methods. Show all posts
Showing posts with label DOM Methods. Show all posts

Tuesday, July 15, 2008

bug 149 - no DOM Level 2 Mutation Events in IE

Issue: #149
Affects: IE6, IE7, IE8

The W3C specs for (W3C DOM2 Mutation Events) (Nov 2000) specify events that allow developers to listen for changes in the DOM, so that they can apply JavaScript on-demand, as needed.

In particular, noting when a DOM element has children added or changed are the key moments developers would like to be able to apply a sprinkle of JS.

Being able to use these events would be fantastic, but support for them in IE is non-existent at the moment.



Known Workarounds: None.



Related Issues: None.


Bug/Site Feedback |
Submit a bug

Tuesday, April 8, 2008

Will IE8 fix IE's DOM Support issues - Poll Results

Will IE8 fix their DOM Support:

In our last poll, we asked if you felt that IE8 would fix their DOM Support? The poll was live long before the IE8 Beta 1 came out and thus nothing was known about the new version since Microsoft isn't very forthcoming with sharing a road map with developers.

Regardless, the mood of the development community was reflected in the results that came in before the beta release, and was only slightly different after developers got some first hand experiences.



Results:
Yes Completely - 4%
Not A Thing - 16%
Minor Fixes Only - 15%
Mostly Fixed - 3%
Fix Some, Break Some - 30%
I Don't Care Anymore - 5%
Don't Make Me Laugh - 27%


To be honest, most were taken back by Microsoft's commitment towards standards, and actually taking the (correct) brave step to render in Standards Mode by default.

Many of the long standing bugs DOM Bugs were fixed, although there were many that didn't see any attention at all. New features were added, but the overall UI was hardly improved upon at all (from legacy chrome/usability bugs, to the un-movable toolbar issues).

If history of IE7 development is to repeat itself, expect a few more betas for IE8, then an RC (Release Candidate), and a final RTM (Release To Market) date sometime late in Q4, 2008 or Q1, 2009 if they continue to fix ignored issues.

As noted here day 1, we promised to link into the public bug tracking systems for each browser, when and where they became available (and we certainly have done so - if you find a bug listed here that doesn't reference the IE Feedback bug number, please let us know!). When IE8 Beta 1 was released, Microsoft re-opened their "IE Feedback" site at Microsoft Connect, so that developers could view and track bugs with input from Microsoft. It isn't a full public bug tracking site, but it has been dearly missed since it was dismantled after the IE7 release, in fact one of the reasons that this Blog started! ;-)

We hope that the IE Feedback site will stay open forever (or some similar site) so that developers can continue to benefit from its presence, however when directly questioned, the response was less than an absolute yes on the IE Blog.

We wish the IE Team the best of luck on shipping IE8 with great DOM Support to an eager developer base, lets just hope we can close a bunch more issues before it is shipped out the door!



Bug/Site Feedback |
Submit a bug

Saturday, March 22, 2008

bug 199 - can't clone a form element in IE using .cloneNode

Issue: #199
Affects: IE6, IE7, IE8

Well, yes you can clone a form element in IE using .cloneNode() but it won't work the way you need it to work.

It seems that the readonly bugs (bug 235, bug 237) for form elements affects more than just the .createElement() and .setAttribute() methods.

When you clone a node (e.g. a Form Input Element), it will obviously have a name. However that cloned element will have the same name, and it too will be readonly.

Example:

<script type="text/javascript">
function cloneEmail(quantity){
var emailAddr = document.getElementById('emailAddressTemplate');
//clone it!
var newInput = null;
var myForm = document.getElementsByTagName('form')[0];
for(var i=0;i<quantity;i++){
newInput = emailAddr.cloneNode(false);
newInput.setAttribute('name', 'emailAddr' + (i + 1));
myForm.appendChild(newInput);
}
}
</script>


Attempting to change the name in this manner will fail in IE. Calling the following will change the name for the HTTP Get/Post param name, but it won't be accessible to JavaScript by name.


newInput.name = 'emailAddr' + (i + 1);



Known Workarounds: None.



Related Issues: (bug 235, bug 237).

Bug/Site Feedback |
Submit a bug

Tuesday, March 18, 2008

bug 126 - no W3C DOM Level 2 Event Listeners

Issue: #126
Affects: IE6, IE7, IE8
Partially Fixed in: IE9 RC 1 (events are still not possible on option/optgroup elements (bug 280))
Status: Microsoft has confirmed this will NOT be fixed in IE8 RTM


MSIE Feedback ID: 333958



The W3C published the specs for (W3C DOM2 Event Listeners) on or before November 13th, 2000. This means that the spec has been available for over seven years. When it wasn't present in IE6, the development community couldn't complain. When it was omitted from IE7 (they were still too busy trying to catch up) it was unfortunate, but accepted. However we are now at the dawn of IE8 (currently in Beta) and there is still no sign of DOM2 Event Listeners. Therefore this is no longer just a "we haven't had the time yet" or "we have higher priorities" issue, this is now a genuine bug!

Example:

<script type="text/javascript">
var obj = document.getElementById('foo');
obj.addEventListener('click', myClickHandler, false );
</script>



Known Workarounds: One. Create your own "addEvent" function that attempts to best handle IE's missing implementation by wrapping "attachEvent" in a cross-browser implementation.

Example Workaround Code:

//soon



Related Issues: (bug 186).

Bug/Site Feedback |
Submit a bug

Thursday, November 15, 2007

bug 171 - dynamic table DOM gotcha in IE

Issue: #171
Affects: IE6, IE7, IE8

When HTML first came out, the HTML Table was a simple element consisting of a <table> tag, with n <tr> tags, each with n <th> or <td> tags in it.

The specification grew, to include a tag called <tbody> (among others) to help group sets of rows within a table.

Browsers allowed for both implementations, either with the optional tbody section or not.

However Internet Explorer did something strange... they actually started to follow the spec (even though they miss the mark almost everywhere else).

In IE using the DOM, if you try to add <tr> elements to a <table> using the .appendChild() method, you MUST add a <tbody> section first. IE will not throw any errors if you do not, but it will also not render any rows/cells in your table either.


Known Workarounds: One. Always add the tbody section, and be sure to expect it when navigating this table in the DOM later on.


Related Issues: None.

Saturday, October 27, 2007

bug 245 - setAttribute "style" does not work in IE

Issue: #245
Affects: IE6, IE7

As discussed in bug 242, IE does not allow using the DOM Method .setAttribute( name, value ); for many attributes. Some just don't work, other throw errors. For the style attribute IE just ignores the request.

Example:

<script type="text/javascript">
var myObj = docuement.getElementById('myDiv');
myObj.setAttribute('style', 'border:1px dashed #663399;font-weight:bold;');
</script>


You can access each individual style property and set them seperately using DOM 0 techniques (Basically the IE4 way), or you can use the workaround listed below.


Known Workarounds: One. Set the style property's .cssText value when dealing with IE.

Example Workaround Code:

<script type="text/javascript">
var myObj = docuement.getElementById('myDiv');
//use browser sniffing to determine if IE or Opera (ugly, but required)
var isOpera, isIE = false;
if(typeof(window.opera) != 'undefined'){isOpera = true;}
if(!isOpera && navigator.userAgent.indexOf('Internet Explorer')){isIE = true);

var styleData = 'border:1px dashed #663399;font-weight:bold;';
if(!isIE){
//use the correct DOM Method
myObj.setAttribute('style', styleData);
} else {
//use the .cssText hack
myObj.style.setAttribute('cssText', styleData);
}
</script>



Related Issues: bug 242.

Wednesday, October 24, 2007

bug 235 - createElement is broken in IE

Issue: #235
Affects: IE6, IE7

According to the DOM specs for ECMAScript, adding an input field should be as easy as the code snippet below.

Example:

<script type="text/javascript">
var myNewField = document.createElement('input');
myNewField.setAttribute('name', 'tags');
//set any other attributes...
//add to the DOM
document.getElementsByTagName('form')[0].appendChild( myNewField );
</script>


However, if you try this in IE, it will "appear" to work, until you submit the page, or attempt to query the field by name.

IE (for reasons unknown) did not set the name attribute. (seriously, try it!)

The solution is exposed in this MSDN article, whereby IE allows a (horribly) invalid parameter to the createElement() method to get around this bug.


Known Workarounds: One.

You will need to determine if the current browser is IE, then, execute the applicable createElement call.

Example Workaround Code:

<script type="text/javascript">
//use browser sniffing to determine if IE or Opera (ugly, but required)
var isOpera, isIE = false;
if(typeof(window.opera) != 'undefined'){isOpera = true;}
if(!isOpera && navigator.userAgent.indexOf('Internet Explorer')){isIE = true);

var myNewField = null;
if(!isIE){
myNewField = document.createElement('input');
myNewField.setAttribute('name', 'tags');
} else {
myNewField = document.createElement('<input name="tags"/>');
}
//set any other attributes...
//add to the DOM
document.getElementsByTagName('form')[0].appendChild( myNewField );
</script>




Related Issues: bug 242, bug 237.

Tuesday, October 16, 2007

What If? - DOM Method Improvements

What If?

"Missing Methods" in the ECMAScript specification.

Having a complete specification for ECMAScript's DOM manipulation is great, however in time (as with any API) you yearn for some additional features.

IMHO, these methods would be great additions to the current spec.

Additions:

Object Element
getElementsByTagName(name, depth)
This method returns a NodeList.
The name parameter is of type DOMString.
The depth parameter is of type unsigned long.

With the optional depth parameter, developers can request what level of nesting they specifically wish to return.
If omitted, zero or negative, the default behavior of all matching child nodes is returned.

If requested, only elements at the requested level would be returned.

Example:
var allChildCells = myTable.getElementsByTagName('td');
var directCells = myTable.getElementsByTagName('td', 1);
var grandChildCells = myTable.getElementsByTagName('td', 2);

getElementsByClassName(class)
It is already on the way in HTML 5 (Web Applications 1.0)!
Better yet, it is real! Firefox 3 already has it!
And so does Opera 9.5!
And so does WebKit!

Object Node
insertAfter(newChild,refChild)
This method returns a Node.
The newChild parameter is of type Node.
The refChild parameter is of type Node.

Similar to the insertBefore method, except the newChild is inserted
after the refChild in the DOM tree.


Object NodeList
remove(index)
This method returns a NodeList.
The index parameter is of type unsigned long.

When a NodeList is returned from a method like .getElementsByTagName(name) it is
often desired to "filter" out undesired items.
Currently this is only possible by "casting" to an Array (a.k.a. iterate over the
NodeList and copy to an Array)



Ok, so not exactly a browser bug... but some interesting ideas.

What do you think? What methods would you add/modify?


Have your say!

Thursday, October 4, 2007

bug 142 - appendChild doesn't work on a script tag in IE

Issue: #142
Affects: IE6, IE7, IE8 Beta 1, IE8 Beta 2, IE8 PR1, IE8 RC1

Using the DOM to generate elements is ideal, but when you want to generate a script tag, you can't use the DOM in IE.

Example:

<script type="text/javascript">
var scriptTag = document.createElement('script');
scriptTag.appendChild( document.createTextNode('var now = new Date();alert(now.getTime());') );
var bodyTag = document.getElementsByTagName('body')[0];
bodyTag.appendChild( scriptTag );
</script>


In all browsers except IE, this will append a script element to the page, with code as the content.


Known Workarounds: One. For IE, we have to divert from the spec., and use the .text property instead.

Example Workaround Code:

<script type="text/javascript">
var scriptTag = document.createElement('script');
scriptTag.text = 'var now = new Date();alert(now.getTime());';
var bodyTag = document.getElementsByTagName('body')[0];
bodyTag.appendChild( scriptTag );
</script>



Related Issues: None.

Tuesday, September 25, 2007

bug 204 - getElementsByTagName doesn't always work in IE

Issue: #204
Affects: (IE6 unconfirmed), IE7, IE8 Beta 1, IE8 Beta 2, IE8 PR1, IE8 RC1

{element}.getElementsByTagName('*');

Should return all child elements, regardless of nodeName, however it fails under the following scenarios.

Example:

<object id="myObj">
<param name="foo" value="37"/>
<param name="bar" value="75"/>
<param name="baz" value="99"/>
</object>
<script type="text/javascript">
var objTag = document.getElementById('myObj');
alert(objTag.getElementsByTagName('*').length);
</script>


The alert, should indicate a length of 3 child elements, but in IE7 it returns 0 (zero). This bug only occurs with an object element, and child param elements.


Known Workarounds: One. You will need to query specifically for 'param' tag elements.

Example Workaround Code:

<object id="myObj">
<param name="foo" value="37"/>
<param name="bar" value="75"/>
<param name="baz" value="99"/>
</object>
<script type="text/javascript">
var objTag = document.getElementById('myObj');
alert(objTag.getElementsByTagName('param').length);
</script>



Related Issues: None.

bug 237 - type is a readonly attribute in IE

Issue: #237
Affects: IE5, IE5.5, IE6, IE7, IE8, IE9 PP4
MSIE Feedback ID: 332453
Status: Microsoft has confirmed this will NOT be fixed in IE8 RTM
Partially Fixed In: IE9 Platform Preview 6 (only when rendering in IE9 Standards Document Mode)

Update: There are partial fixes for this in IE9 Platform Preview 4. For example you can change an input element from text to hidden and back to text and it works. However changing any input type to a password, then back to any other type deletes the value attribute contents (e.g. erases the set value)

In a world of Web 2.0 shininess, being able to work your JavaScript-Foo on the DOM is critical. A typical, yet simple example of this, would be to change an input type="text" element on a form, to a type="hidden" field, or visa versa.

Example:

<input type="text" id="userid" value=""/>
<script type="text/javascript">
var userIDField = document.getElementById('userid');
var userID = userIDField .value;
//do some fancy ajax stuff...
userIDField.setAttribute('type', 'hidden');
</script>


In a DOM compliant browser, this is a piece of cake. However in IE (msdn article), the type attribute is read-only... except for a small window of time before you add an element to the DOM (e.g. if you are using createElement() )


Known Workarounds: None. If you copy all the information for a given node, into JS variables, then remove the existing element, and create a brand new one in its place, then you are set.

However the sheer complexity of this task makes it rather troublesome even to attempt. Keep in mind, any workaround should handle all attributes set on the element, including custom attributes and attributes in specialized namespaces. Also remember that any event handlers attached to the element need to be copied over to the new element. If you think you have an ideal workaround, drop us a line!


Related Issues: (bug 242).

bug 154 - getElementById is NOT case sensitive in IE

Issue: #154
Affects: IE6, IE7
Fixed In: IE8

MSIE Feedback ID: 333979

"Just when you thought it was safe to go back in the water"! (credit to JAWS the movie) IE's getElementById( id ) throws another curve ball!

Although it should be according to the (spec), IE performs a case-insensitive search for IDs. This isn't likely as bad as (bug 152), but still a concern, if you have 2 IDs with different cases.

Example:

<form id="userInfo">
<input id="userid" value="grovermonster"/>
<input id="userfirst" value="Grover"/>
<input id="userlast" value="Monster"/>
<textarea id="userinfo">
Cute and cuddly and Blue!
</textarea>
<form>
<script type="text/javascript">
var infoForUser = document.getElementById('userinfo').value;
alert('Info for this user:\n\n' + infoForUser);
</script>


In IE, this won't return the "Cute and cuddly and Blue!" line you would expect. Instead, IE tries to return the value of the form itself.


Known Workarounds: One. Use the fix for (bug 152)


Related Issues: (bug 152).

Friday, August 24, 2007

bug 217 - getAttribute doesn't always work in IE

Issue: #217
Affects: IE5, IE5.5, IE6, IE7, IE8 Beta 1, IE8 Beta2, IE8 PR1
Fixed In: IE8 RC 1

Certain attributes can not be retrieved properly in IE. The first example, is the "for" attribute, which is used by <label> tags to link to input fields.

Example:
<script type="text/javascript">
var myLabel = document.getElementById( 'test' );
alert( 'myLabel is for: ' + myLabel.getAttribute( 'for' ) );
</script>

There is a workaround for this (see below)


Known Workarounds: Some.

Example Workaround Code:
<script type="text/javascript">
var myLabel = document.getElementById( 'test' );
alert( 'myLabel is for: ' + myLabel.attributes['for'].nodeValue );
</script>



Related Issues: None.

bug 268 - hasAttributes not supported in IE

Issue: #268
Affects: IE5, IE5.5, IE6, IE7, IE8 Beta 1, IE8 Beta 2
Fixed In: IE8 RC 1

Example:
<script type="text/javascript">
var foo = document.getElementById( 'content' );
alert( foo.hasAttributes() );
</script>



Known Workarounds: Yes.
Example Workaround Code:
<script type="text/javascript">
var foo = document.getElementById( 'content' );
alert( (foo.attributes.length > 0) );
</script>



Related Issues: None.

bug 152 - getElementById returns incorrect objects in IE and Opera

Issue: #152
Affects: IE5, IE5.5, IE6, IE7, Opera 8.2, Opera 9.2
Fixed in: Opera 9.50 alpha 1 build 9500
Almost Fixed in: IE8 Beta 1
Fixed in: IE8 Beta 2

MSIE Feedback ID: 333979

Example:
<script type="text/javascript">
var descField = document.getElementById( 'description' );
alert( descField.nodeName );
</script>

The above code works perfectly, in all browsers returning the element with the id "description". Well almost. IE will return the element with that id, but it will also return any element with a name set to "description". At first glance this may not seem such an issue, but consider this; Do you have a meta tag on any of your pages? Do any of them have a name attribute with the value description? If so, you will get a reference to the meta tag, not the form element (or whatever you thought you were getting, as indicated in the spec for getElementById).

When you think for a moment, about where the name attribute is set, this becomes rather scary. Any named anchor, can now conflict with your well defined element ids.

Notes:
So you might ask, why is this broken in Opera? Opera is usually pretty good at supporting the specs! Well, it seems that for maximum compatibility with IE, even though it is implemented wrong, they mimicked the broken behavior.


Known Workarounds: No direct methods, using Option #3 below is suggested.

Workaround Option: 1
If you rely heavily on getElementById, and you suspect that you may have name conflicts, or that user specific content added to a page may cause conflicts you can use getElementsByTagName( tagName ) then iterate over the results and compare the value returned by getAttribute( 'id' ).

Example Workaround Code:
var inputs = document.getElementsByTagName( 'textarea' );
var descField = null;
for(var i=0;i<inputs.length;i++){
if(inputs.item(i).getAttribute( 'id' ) == 'description' ){
descField = inputs.item(i);
break;
}
}




Workaround Option: 2
If you have the ability to globally apply fixes for IE and Opera, the following code will make both of them follow the spec to a 'T', with a very tiny performance hit.

In this example, we redifine the getElementById method, to work as it was intended.
Example Workaround Code:
//use browser sniffing to determine if IE or Opera (ugly, but required)
var isOpera, isIE = false;
if(typeof(window.opera) != 'undefined'){isOpera = true;}
if(!isOpera && navigator.userAgent.indexOf('Internet Explorer')){isIE = true;}

//fix both IE and Opera (adjust when they implement this method properly)
if(isOpera || isIE){
document.nativeGetElementById = document.getElementById;
//redefine it!
document.getElementById = function(id){
var elem = document.nativeGetElementById(id);
if(elem){
//verify it is a valid match!
if(elem.id == id){
//valid match!
return elem;
} else {
//not a valid match!
//the non-standard, document.all array has keys for all name'd, and id'd elements
//start at one, because we know the first match, is wrong!
for(var i=1;i<document.all[id].length;i++){
if(document.all[id][i].id == id){
return document.all[id][i];
}
}
}
}
return null;
};
}



Oh my! this just gets better and better! (after posting and using this I noted (as did J. Max Wilson) that the second workaround, actually exposes another bug in IE!

Third time's a charm (we hope!)

Workaround Option: 3

Same as workaround 2 above, but rather than test elem.id or elem.getAttribute('id') we'll use the much safer elem.attributes collection. Unfortunately if the element you are looking for, in turn has a child element with a name or id attribute, that is set to "id", it will not test the attribute, but rather the child element. (bug 162 - global namespace pollution)

Example Workaround Code:
//use browser sniffing to determine if IE or Opera (ugly, but required)
var isOpera, isIE = false;
if(typeof(window.opera) != 'undefined'){isOpera = true;}
if(!isOpera && navigator.userAgent.indexOf('Internet Explorer')){isIE = true;}

//fix both IE and Opera (adjust when they implement this method properly)
if(isOpera || isIE){
document.nativeGetElementById = document.getElementById;
//redefine it!
document.getElementById = function(id){
var elem = document.nativeGetElementById(id);
if(elem){
//verify it is a valid match!
if(elem.attributes['id'] && elem.attributes['id'].value == id){
//valid match!
return elem;
} else {
//not a valid match!
//the non-standard, document.all array has keys for all name'd, and id'd elements
//start at one, because we know the first match, is wrong!
for(var i=1;i<document.all[id].length;i++){
if(document.all[id][i].attributes['id'] && document.all[id][i].attributes['id'].value == id){
return document.all[id][i];
}
}
}
}
return null;
};
}




Related Issues: (bug 154), (bug 411), (bug 162).

bug 411 - getElementsByName doesn't work in IE

Issue: #411
Affects: IE5, IE5.5, IE6, IE7, IE8
Status: Microsoft has confirmed this will NOT be fixed in IE8 RTM

MSIE Feedback ID: 334336

Example:
<script type="text/javascript">
var checkboxOptions = document.getElementsByName( 'preferences' );
alert( 'There are ' + checkboxOptions.length + ' preference options.' );
</script>



Known Workarounds: No direct methods.

Example 1 Workaround Code:
Developers must iterate over all potential tag matches with a call to getElementsByTagName(), then for each NodeList returned, check for a match against the name attribute with getAttribute( 'name' ). Alternatively, if retrieving elements from a form by name, formObj.elements[name]; will return a form element array that will suffice.

Example Workaround Code:
<script type="text/javascript">
//option 1
var inputs = document.getElementsByTagName( 'input' );
var checkboxOptions = [];
for(var i=0;i<inputs.length;i++){
if(inputs.item(i).getAttribute( 'name' ) == 'preferences' ){
checkboxOptions.push( inputs.item(i) );
}
}
var checkboxOptions = document.getElementsByName( 'preferences' );
//option 2
var checkboxOptions = document.forms[formIndex].elements['preferences'];

alert( 'There are ' + checkboxOptions.length + ' preference options.' );
</script>

(Note: If there is only one checkbox, using option 2, the length will be undefined, since browsers treat a single checkbox as an atomic item, but multiple as an array)



Example 2 Workaround Code:
Since IE keeps an associative array in the proprietary document.all object, we can carefully iterate over it to solve this issue. (in theory, code below is untested)

<script type="text/javascript">
//use browser sniffing to determine if IE or Opera (ugly, but required)
var isOpera, isIE = false;
if(typeof(window.opera) != 'undefined'){isOpera = true;}
if(!isOpera && navigator.userAgent.indexOf('Internet Explorer')){isIE = true);

if(isIE){
var document._getElementsByName = document.getElementsByName;
document.getElementsByName = function(name){
var temp = document.all[name];
var matches = [];
for(var i=0;i<temp.length;i++){
if(temp[i].name == name){
matches.push(temp[i]);
}
}
return matches;
};
}
</script>


In theory, this should work, but it might need adjusting, if there is only 1 item with the name, and that item, has a length property (e.g. a form, a select list, a radio button or checkbox set.) If you find the perfect solution, please advise.


Related Issues: None.

Tuesday, August 7, 2007

bug 274 - DOM Methods on Select Lists don't work in IE

Issue: #274
Affects: IE6, IE7, IE8, IE9 PP4, IE9 RC 1
Trackers:
MSKB Tracker: 276228

MSIE Feedback ID: 336252
Status: Microsoft has confirmed this will NOT be fixed in IE8 RTM

There is actually several issues with select list elements in Internet Explorer. See the Related Issues section for other issues.

This issue, is the fact that setting the .innerHTML on a select element does not work, and actually appears to render NO options in the list. Some will argue that the .innerHTML property isn't a DOM Method (true), but it has been adopted as a standard method to quickly populate the DOM Fragment inside of an element.

Example:

<script type="text/javascript">
var myOpts = '';
for(var i=1;i<32;i++){
myOpts += '<option value="' + i + '">April ' + i + '</option>';
}
var myDaysSelect = document.getElementById('daySelect');
myDaysSelect.innerHTML = myOpts;
</script>


Select Day:

(the select should populate with options for the days in April - including the bonus April 31st! - In IE any original options are wiped out and none of the new ones are added)


Known Workarounds: One. Apparently you can add the actual select element content to your string (pre and post) then set the .outerHTML value. NOTE: This will trash any event handlers you have on the original element.

Example Workaround Code:

Not going to post. Most advise against this workaround.



Related Issues: (bug 116).

Monday, August 6, 2007

bug 242 - setAttribute doesn't always work in IE

Issue: #242
Affects: IE5, IE5.5, IE6, IE7
MSIE Feedback ID(s): 332453 (events)
332237 (type)
336253 (object, not a string)

336256 (cellpadding, cellspacing)
Partially Fixed in: IE8 Beta 2 (Still does not handle inline events and some developers have reported issues with certain style/class attributes not taking effect right away)


Description: When calling the DOM method .setAttribute( attName, attValue ); in IE, there are several circumstances where it will not work.
Setting the "name" attribute as mentioned (bug 235),(bug 240) does not work, the "colspan" & "rowspan" attributes for th and td tags does not work, the "frameborder" attribute on iframes does not work, nor the "cellpadding" or "cellspacing" attributes on table tags.

Setting any of the inline event attributes does not work either! therefore ALL of the following will not work:
obj.setAttribute( 'onbeforeunload', doSomething );
obj.setAttribute( 'onblur', doSomething );
obj.setAttribute( 'onclick', doSomething );
obj.setAttribute( 'onchange', doSomething );
obj.setAttribute( 'ondblclick', doSomething );
obj.setAttribute( 'onerror', doSomething );
obj.setAttribute( 'onfocus', doSomething );
obj.setAttribute( 'onmousedown', doSomething );
obj.setAttribute( 'onmouseover', doSomething );
obj.setAttribute( 'onmouseout', doSomething );
obj.setAttribute( 'onmouseup', doSomething );
obj.setAttribute( 'onkeydown', doSomething );
obj.setAttribute( 'onkeyup', doSomething );
obj.setAttribute( 'onkeypress', doSomething );
obj.setAttribute( 'onload', doSomething );
obj.setAttribute( 'onsubmit', doSomething );
obj.setAttribute( 'onreset', doSomething );
obj.setAttribute( 'onunload', doSomething );
obj.setAttribute( 'on*', doSomething );

You also can not set the "class" attribute, nor the "for" attribute, or even the "style" attribute.

Example: ...


Known Workarounds: Well there are several, and each depends on which attribute you are trying to set. The following table indicates what you can use to workaround these bugs.



  • Attribute: Workaround

  • acceptcharset: Use "acceptCharset"

  • accesskey: Use "accessKey"

  • allowtransparency: Use "allowTransparency"

  • bgcolor: Use "bgColor"

  • cellpadding: Use "cellPadding"

  • cellspacing: Use "cellSpacing"

  • checked: See note (bug 299)

  • class: Use "className"

  • colspan: Use "colSpan"

  • defaultchecked: Use "defaultChecked"

  • defaultselected: Use "defaultSelected"

  • defaultvalue: Use "defaultValue"

  • for: Use "htmlFor" (also note potential side issue: bug 116)

  • name: None - see (bug 235),(bug 240)

  • type: See note (bug 237) "type" is readonly in IE

  • frameborder: Use "frameBorder"

  • hspace: Use "hSpace"

  • longdesc: Use "longDesc"

  • maxlength: Use "maxLength"

  • marginwidth: Use "marginWidth"

  • marginheight: Use "marginHeight"

  • noresize: Use "noResize"

  • noshade: Use "noShade"

  • on*: Inline events can not be set in IE, attach event handlers instead

  • readonly: Use "readOnly"

  • rowspan: Use "rowSpan"

  • selected: When setting multiple selected items in a "select multiple" this will fail. {bug ref#TBD}

  • style: None - see (bug 245), (bug 329)

  • tabindex: Use "tabIndex"

  • valign: Use "vAlign"

  • vspace: Use "vSpace"




Example Workaround Code:

//set variable IE=true when User Agent known to be IE.
if(!IE){
obj.setAttribute( 'class', 'special' );
} else {
obj.setAttribute( 'className', 'special' );
}

Saturday, August 4, 2007

DOM Method Support - What dreams are made of...

In the ideal world, each and every browser would support these properly, and development would be a breeze... but alas, that is not the case.

For each method listed below, I'll link to the various bugs in terms of their implementation.

getElementById( id )

What seems like the most simplistic method available, yet also one of the most powerful, is unfortunately broken. (bug 152) describes how Internet Explorer, will return an element, if it matches by the id attribute as designed, but will also return a match based on the name attribute. It will also disregard your case-sensitive searches and return elements with IDs with non-matching case (bug 154).

createElement( type )

Another super simple, but super useful method, is again plagued with issues. The correct syntax is:


var myDiv = document.createElement( 'div' );
//or
var myHeader = document.createElement( 'h2' );
//or
var myTextBox = document.createElement( 'input' );


Well, lets say you are building up some form elements on-the-fly (very common in today's Web 2.0 world). Say you want to add a hidden field named "showOption" that you will pre-populate with the value "messages", just before the form is submitted to take the user directly to a certain screen.

The code would look something like this:
development would be a breeze... but alas, that is not the case.


var hiddenOption = document.createElement( 'input' );
hiddenOption.setAttribute('name', 'showOption');
hiddenOption.setAttribute('value', 'messages');
hiddenOption.setAttribute('type', 'hidden');
var myForm = document.forms[0];
document.appendChild(hiddenOption, myForm);
myForm.submit();


So as long as you have a form, this should work! Well, not in Internet Explorer!

As it turns out, in (bug 235) Internet Explorer, you can't set the name attribute on an Element... any Element! To overcome this, there is a hack, which explains why the createElement method is broken (bug 124) in IE. To make the above code snippet work in IE, you need to do this:


var hiddenOption = document.createElement( '<input name="showOption">' );
hiddenOption.setAttribute('type', 'hidden');
hiddenOption.setAttribute('value', 'messages');
var myForm = document.forms[0];
document.appendChild(hiddenOption, myForm);
myForm.submit();


Did you spot the changes?

Change#1.) The Element we create is a string that is the HTML tag, with the name attribute. This is not only quite ugly (mixing tags in strings), but also completely against the spec! document.createElement Spec Reference.

Change#2.) We moved the "type" attribute up to be the first attribute set. The reason for this, is that in IE you can't change the type attribute (bug 237) after the node is added to the DOM, and the default type is always "text". In this code snippet, it didn't matter, but if we had added this to the DOM, before setting the type, we would have been stuck.