views:

18554

answers:

14

I'm using jQuery to hide and show elements when a radio button group is altered/clicked. It works fine in browsers like Firefox, but in IE 6 and 7, the action only occurs when the user then clicks somewhere else on the page.

To elaborate, when you load the page, everything looks fine. In Firefox, if you click a radio button, one table row is hidden and the other one is shown immediately. However, in IE 6 and 7, you click the radio button and nothing will happen until you click somewhere on the page. Only then does IE redraw the page, hiding and showing the relevant elements.

Here's the jQuery I'm using:

$(document).ready(function(){

    $(".hiddenOnLoad").hide();

    $("#viewByOrg").change(function () {
            $(".visibleOnLoad").show();
            $(".hiddenOnLoad").hide();
    });

    $("#viewByProduct").change(function () {
            $(".visibleOnLoad").hide();
            $(".hiddenOnLoad").show();
    });     
 });

Here's the part of the XHTML that it affects. Apologies if it's not very clean, but the whole page does validate as XHTML 1.0 Strict:

<tr>
    <td>View by:</td>
    <td>
       <p>
         <input type="radio" name="viewBy" id="viewByOrg" value="organisation" checked="checked"/>
         Organisation
       </p>
       <p>
         <input type="radio" name="viewBy" id="viewByProduct" value="product"/> 
         Product
       </p>
    </td>
</tr>

<tr class="visibleOnLoad">
  <td>Organisation:</td>
  <td>
    <select name="organisation" id="organisation" multiple="multiple" size="10">
      <option value="1">Option 1</option>
      <option value="2">Option 2</option>
    </select>
  </td>
</tr>

<tr class="hiddenOnLoad">
  <td>Product:</td>
  <td>
    <select name="product" id="product" multiple="multiple" size="10">
      <option value="1">Option 1</option>
      <option value="2">Option 2</option>
    </select>
  </td>
</tr>

If anyone has any ideas why this is happening and how to fix it, they would be very much appreciated!

+44  A: 

Try using .click instead of .change

Paolo Bergantino
Thank you, this worked perfectly.
Philip Morton
The Click event only works if you change the value using the mouse - if you use the keyboard then click doesn't trigger, but change does.
samjudson
@samjudson, in my testing this is not correct and jquery's click does trigger when i select the next radio button using arrow keys. (vista, ie7)
Pacifika
@Pacifika: Not for me in IE7. At least it gets that right."click" is a totally different event from "change" and there are at least some cases (if not all) where it's an inappropriate substitute.
Bobby Jack
@samjudson: click events on radio buttons and checkboxes also fire when selecting them using the keyboard. Works in all browsers
Philippe Leybaert
I stand corrected - that does appear to be the case, however counter-intuitive it might be!
Bobby Jack
I hate IE 6/7 and love stack overflow
CVertex
I love that this works with keyboard changes as well!
orip
+1  A: 

I'm pretty sure this is a known issue with IE. Adding a handler for the onclick event should fix the problem:

$(document).ready(function(){

    $(".hiddenOnLoad").hide();

    $("#viewByOrg").change(function () {
        $(".visibleOnLoad").show();
        $(".hiddenOnLoad").hide();
    });

    $("#viewByOrg").click(function () {
        $(".visibleOnLoad").show();
        $(".hiddenOnLoad").hide();
    });

    $("#viewByProduct").change(function () {
        $(".visibleOnLoad").hide();
        $(".hiddenOnLoad").show();
    });     

    $("#viewByProduct").click(function () {
        $(".visibleOnLoad").hide();
        $(".hiddenOnLoad").show();
    });     
});
Chris Zwiryk
+4  A: 

In IE you must use the click event, in other browsers onchange. Your function could become

$(document).ready(function(){
   $(".hiddenOnLoad").hide();
   var evt = $.browser.msie ? "click" : "change";
   $("#viewByOrg").bind(evt, function () {
                        $(".visibleOnLoad").show();
                        $(".hiddenOnLoad").hide();
                    });

   $("#viewByProduct").bind(evt, function () {
                        $(".visibleOnLoad").hide();
                        $(".hiddenOnLoad").show();
                    });     
});
Pier Luigi
+9  A: 

This should work too:

$(document).ready(function(){
   $(".hiddenOnLoad").hide();
   $("#viewByOrg, #viewByProduct").bind(($.browser.msie ? "click" : "change"), function () {
                        $(".visibleOnLoad").show();
                        $(".hiddenOnLoad").hide();
                    });
});

Thanks Pier. This was very helpful.

This is, at least, a much better answer than the current accepted/highest-voted one. It 'only' breaks keyboard accessibility under IE, rather than for all the good browsers too.
Bobby Jack
... although, isn't this just a copy of Pier's answer?
Bobby Jack
Agreed, it's a slightly less readable version of Pier's but with both selectors being bound in one call.
TreeUK
+22  A: 

The problem with using the click event instead of change is you get the event if the same radio box is selected (i.e. hasn't actually changed). This can be filtered out if you check that the new value is different than the old. I find this a little annoying.

If you use the change event, you may notice that it will recognize the change after you click on any other element in IE. If you call blur() in the click event, it'll cause the change event to fire (only if the radio boxes actually have a changed).

Here's how I'm doing it:

// This is the hack for IE
if ($.browser.msie) {
  $("#viewByOrg").click(function() {
    this.blur();
    this.focus();
  });
}

$("#viewByOrg").change(function() {
  // Do stuff here
});

Now you can use the change event like normal.

Edit: Added a call to focus() to prevent accessibility issues (see Bobby's comment below).

Mark A. Nicolosi
That's a very evil hack, because it prevents your users from navigating using the keyboard, because the focus disappears after selecting a radio button.
Philippe Leybaert
This is great, but it causes keyboard accessibility problems. Once the blur() event has fired, the radio button is no longer focussed, so moving amongst radio buttons with the keyboard becomes extremely awkward.My current solution is to add a call to "this.focus();" immediately after the blur() statement.
Bobby Jack
Why the downvotes? This is (almost) the best solution here.
Bobby Jack
I think it's the worst solution presented, because of the accessibility problems.
Philippe Leybaert
But the accessibility problem can be resolved with a call to focus(). It's at least as good as using click() for everything.
Bobby Jack
Thanks Bobby, I'll add that to the answer.
Mark A. Nicolosi
I had this problem early today and I'm going to try this tomorrow. This seems better to me than using 'click'. If I used 'click' then I would be basically implementing the 'change' event myself. Thanks IE for wasting more of my time having to work around you.
delux247
It works like a charm for me, thank you.
farzan
A: 

imo using click instead of change makes the ie behaviour be different. I'd rather emulate the change event behaviour using a timer (setTimout).

something like (warning - notepad code):

if ($.browser.msie) {
  var interval = 50;
  var changeHack = 'change-hac';
  var select = $("#viewByOrg");
  select.data(changeHack) = select.val();
  var checkVal=function() {
    var oldVal = select.data(changeHack);
    var newVal = select.val();
    if (oldVal !== newVal) {
      select.data(changeHack, newVal);
      select.trigger('change')
    }
    setTimeout(changeHack, interval);
  }
  setTimeout(changeHack, interval);
}

$("#viewByOrg").change(function() {
  // Do stuff here
});
Ken Egozi
whoah... a little heavy-handed, no?
orip
+5  A: 

Have you tried IE's onpropertychange event? I dont know if it makes a difference but it's probably worth a try. IE does not trigger the change event when values are updated via JS code but perhaps onpropertychange would work in this instance.

$("#viewByOrg").bind($.browser.msie? 'propertychange': 'change', function(e) {
  e.preventDefault(); // Your code here 
});
Kevin
This worked perfect for me thanks!
Wil
A: 

10xs Kevin, work as a charm :)

zetxx
A: 

Nice answer, but how to use the change func n do this?

jaan
+1  A: 

I had the same issue with input text.

I changed:

$("#myinput").change(function() { "alert('I changed')" });

to

$("#myinput").attr("onChange", "alert('I changed')");

and everything is working fine for me!

fabrice
+1  A: 

This is a simple way to tell IE to fire the change event when the element is clicked:

if($.browser.msie) {
    $("#viewByOrg").click(function() {
        $(this).change();
    });
}

You could expand this to something more generic to work with more form elements:

if($.browser.msie) {
    $("input, select").click(function() {
        $(this).change();
    });
    $("input, textarea").keyup(function() {
        $(this).change();
    });
}
paulspringett
A: 

try this, it works for me

$("#viewByOrg")
        .attr('onChange', $.browser.msie ? "$(this).data('onChange').apply(this)" : "")
        .change( function(){if(!$.browser.msie)$(this).data('onChange').apply(this)} )
        .data('onChange',function(){alert('put your codes here')});
A: 

add this plugin

jQuery.fn.radioChange = function(newFn){
    this.bind(jQuery.browser.msie? "click" : "change", newFn);
}

then

$(function(){
    $("radioBtnSelector").radioChange(function(){
        //do stuff
    });
});
wapsee
A: 

In IE, force radio and checkboxes to trigger a "change" event:

if($.browser.msie && $.browser.version < 8)
  $('input[type=radio],[type=checkbox]').live('click', function(){
    $(this).trigger('change');
  });
Jeoff Wilks