views:

80

answers:

1

I have this code in a js file:

function buildRolePicker() {
    var pnl = $("[id$='staffRoles']");
    $.each(roles["ContactGroupRoles"], function(iteration, item) {
        pnl.append(
                $(document.createElement("input")).attr({
                    id: 'cgr' + item['RoleId'],
                    name: 'cgroles',
                    value: item['RoleId'],
                    title: item['RoleName'],
                    type: 'checkbox'
                })
        );
        pnl.append(
                $(document.createElement('label')).attr({
                    'for': 'cgr' + item['RoleId']
                })
                .text(item['RoleName'])
        );
    });

    alert(document.forms[0].cgroles[8].value);
}

I was wasting some time in other sections of code trying to work out why a call to

alert(document.forms[0].cgroles[8].value);

was returning a value of "on" when it should be returning a long. It turns out the problem is the order in which the attributes are defined. If i change this:

            $(document.createElement("input")).attr({
                id: 'cgr' + item['RoleId'],
                name: 'cgroles',
                value: item['RoleId'],
                title: item['RoleName'],
                type: 'checkbox'
            })

to this:

                $(document.createElement("input")).attr({
                    type: 'checkbox',
                    id: 'cgr' + item['RoleId'],
                    name: 'cgroles',
                    value: item['RoleId'],
                    title: item['RoleName']
                })

everything works fine and I get my long value as expected when i:

alert(document.forms[0].cgroles[8].value);

My question is why?

Test Data:

var roles = {"ContactGroupRoles":[
    {"RoleId":1,"RoleName":"Pending"},
    {"RoleId":2,"RoleName":"CEO"},
    {"RoleId":3,"RoleName":"Financial Controller"},
    {"RoleId":4,"RoleName":"General Manager"},
    {"RoleId":5,"RoleName":"Production Manager"},
    {"RoleId":6,"RoleName":"Sales Manager"},
    {"RoleId":7,"RoleName":"Marketing Manager"},
    {"RoleId":8,"RoleName":"Sales Agent"},
    {"RoleId":9,"RoleName":"Customer Service"},
    {"RoleId":10,"RoleName":"Manager"}
  ]};
+2  A: 

It seems that for whatever reason, IE (IE8 at least) and Opera don't retain the value attribute (though Chrome/Firefox do) through changing the type. Here's a simplified test:

$(document.body).append(
    $("<input />").attr({
        value: 'Test',
        type: 'checkbox'
    })
);
alert($("input").val());
alert(document.body.innerHTML);

You can try it here

IE8/Opera alerts:

  • "on"
  • <input type="checkbox">

Chrome/Firefox alerts:

  • "Test"
  • <input type="checkbox" value="Test">

I'm not sure why Opera in particular is behaving this way, but in any case...just attempting to better demonstrate the issue, the solution of course is to keep the type attribute first. Perhaps a future jQuery release will process type first in the loop, though if the <input> was defined with any attributes earlier this still wouldn't do much good.

However, the $("<input />", { value: 'Test', type: 'checkbox' }); format suffers the same problem, IMO this should be fixed.

Nick Craver