views:

635

answers:

2

Hi all,

I have an issue with a jQuery script I wrote that is driving me a bit nuts. As usual it works perfectly in Firefox but falls over in all IE versions.

I have the following HTML. It is generated using Velocity so it should be part of the DOM:

<select name="groups" id="groups" type="select">
<option value="group1">group1</option>
<option value="group2">group2</option>
<option value="group3">group3</option>
</select>

My jQuery script looks like this:

jQuery(document).ready(function() {
    jQuery("#groups option").click(function () {
     alert(group);
     var group = jQuery(this).attr("value");
     AJS.safe.ajax({
      url: "/plugins/userlookup/userlookup.action",
      type: "POST",
      dataType: "json",
      data: {
       group: group
      },
      success: function(data) {
       alert(data);
       jQuery("#users").empty();
       for(var i=0; i < data.userList.length; i++) {
        var userstr = "<option value=\""+data.userList[i]+"\">"+data.userList[i]+"</option>";
        jQuery("#users").append(userstr);
       }
      }
     });
    });
});

Basically there is a drop down list of "groups" and upon selecting a group an AJAX call is made to fetch users from that group and populate another field. In IE, selecting groups does nothing, nor does it give any Javascript errors. I have tried to step through it but looks like the "click" function is not binding at all to any of the elements as none of those alerts are called and breakpoints are never hit in the debugger. I've tried calling the AJAX URL directly in the browser, but unlike Firefox I don't get the JSON output, IE tries the download the action and fails.

I have stepped through all the code in Firefox and the backend code and that is all working.

Can anyone see what could be wrong with what I've done?

+4  A: 

Try using the change event instead of the click event. That is, when the selection is changed, then update your user select with the related data. Note, also, the change to get the selected option from the groups select (this will be the select instead of the option).

jQuery(document).ready(function() {
    jQuery("#groups").change(function () {
        var group = jQuery(this).find(':selected').attr('value');
        AJS.safe.ajax({
                url: "/plugins/userlookup/userlookup.action",
                type: "POST",
                dataType: "json",
                data: {
                        group: group
                },
                success: function(data) {
                        alert(data);
                        jQuery("#users").empty();
                        for(var i=0; i < data.userList.length; i++) {
                                var userstr = "<option value=\""+data.userList[i]+"\">"+data.userList[i]+"</option>";
                                jQuery("#users").append(userstr);
                        }
                }
        });
    });
});

I believe that the click event isn't actually generated in IE for the option elements, it's generated on the select itself. This may be different, though, if you are using a multiselect, though it doesn't appear that you are.

tvanfosson
Thanks so much, this worked a treat!
jenny
`select-many` doesn't have scriptable `option`​s either. Both selects are indivisble widgets in IE, so you have minimal opportunities to script them. In any case the HTML and DOM standards say nothing about the internals of form fields, so it's not advisable to rely on them.
bobince
A: 

Incidentally, in addition to using the change event... if a username may have a & or < character in, you've got an error and potential cross-site-scripting security hole, from where you've stuck the strings together with HTML without proper escaping.

The string-based method is also rather inefficient, as jQuery has to create and discard a select wrapper every time you call it. Avoid creating dynamic HTML with content from strings; use DOM methods as well as jQuery ones where appropriate. For example:

var options= $('#users')[0].options;
options.length= 0;
for(var i= 0; i<data.userList.length; i++)
    options[i]= new Option(data.userList[i]);

...is shorter, faster, easier to read and safer than the string-hacking variant.

bobince