Site Navigation

Friday, August 24, 2007

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.