1

The routine below works perfectly in Mozilla, but not in IE (I'm using 9 but have changed the compatibility mode and it's broken in 7 and 8 too).

I know that it's something to do with the e.type as 'undefined' in IE, and fine in Moz, but don't know what the correct syntax should be to satisfy both.

function changeChartColumns(){
        var myArray = [];
        var k = 1;
        var b = 0;
        myArray[0]=0;
        for (b in document.frm_obj.elements) {
            var e = document.frm_obj.elements[b];
            if ( e.type=="checkbox" ) {
                if(e.checked == true){
                    var at_least_one_checked = true;
                    myArray[k] = parseInt(e.value,10);
                    k = k+1;
                }
            }
        }
        if(at_least_one_checked == true){
            return myArray;
        }else{
            alert("I cannot display zero information. Please select some stuff using the checkboxes.");
            stop_script_running; // horrible hack
        }
}

Here's the HTML:

<form name="frm_obj" id="frm_obj" method="post">
      <table>   
        <tr>
         <td><input type="checkbox" name="list" value="2" checked onClick="changeChartColumns();"></td>
         <td>Option 1</td>
         <td><input type="checkbox" name="list" value="3" checked onClick="changeChartColumns();"></td>
         <td>Option 2</td>
         <td><input type="checkbox" name="list" value="4" checked onClick="changeChartColumns();"></td>

       </table>
     </form>

Thanks in advance. H.

4 Answers 4

1

Use a proper for loop:

    for (var i=0; i < document.frm_obj.elements.length; i++) {

Working demo: http://jsfiddle.net/y7xFz/1

for...in is designed to iterate over all enumerable properties of an object. document.frm_obj.elements returns a HTMLCollection, whose enumerable properties differ between browsers. In general, you shouldn't use for...in on arrays and HTMLCollections - reserve use for object maps with named properties only.

Sign up to request clarification or add additional context in comments.

3 Comments

Just to further this, the reason why it doesn't work is that the for..in loop on a form accesses the each element by name and thus when you request the type of a checkbox and there is a "set" of checkboxes with the same name, it returns undefined. This occurs with both radio or checkbox elements when there is more than one. When there is only 1 radio or checkbox element it will work fine.
@scunliffe: that's not the problem here - he's accessing the elements collection of a named form object, which returns a HTMLCollection. In IE, none of the elements within a HTMLCollection are enumerable, but the properties item, list, length and namedItem are. So with a for...in, you're actually iterating over those properties rather than the elements within the collection.
ah yes, in this case, in IE, that's what is iterated over - silly IE. The original JavaScript docs (v1.0) was a collection of form elements. Quote from the Netscape JavaScript docs: "Each Form object (which itself is an element of the document.forms array) has an elements array that reflects the text boxes, buttons, and other elements in an HTML form..." - oh well, good to know that IE throws in extra content and thus a for..in loop is seriously not the way to iterate over the content.
0

Try with getAttribute() perhaps.

Comments

0

In your code replace the below line

for (b in document.frm_obj.elements) {

with this one

for (b in document.body.getElementsByTagName("input")) { 

This way it will also work in IE.

1 Comment

You shouldn't use for...in loops on arrays and HTMLCollections. See my answer for an explanation. Also, what if there is more than one form in the document?
0

( b.type == "checkbox" )

[Also,] at_least_one_checked is defined in the local if block.

1 Comment

JavaScript only has function scope (except for a few exceptions). if blocks and for loops do not have their own scope, so if a variable is defined in one of those blocks it is available to the entire function.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.