views:

2348

answers:

4

Consider this sample code:

<div class="containter" id="ControlGroupDiv">
  <input onbeforeupdate="alert('bingo 0'); return false;" onclick="alert('click 0');return false;" id="Radio1" type="radio" value="0" name="test" checked="checked" />  
  <input onbeforeupdate="alert('bingo 1'); return false;" onclick="alert('click 1');return false;"  id="Radio2" type="radio" value="1" name="test" />   
  <input onbeforeupdate="alert('bingo 2'); return false;" onclick="alert('click 2');return false;"  id="Radio3" type="radio" value="2" name="test" />   
  <input onbeforeupdate="alert('bingo 3'); return false;" onclick="alert('click 3');return false;"  id="Radio4" type="radio" value="3" name="test" />   
  <input onbeforeupdate="alert('bingo 4'); return false;" onclick="alert('click 4');return false;"  id="Radio5" type="radio" value="4" name="test" />   
  <input onbeforeupdate="alert('bingo 5'); return false;" onclick="alert('click 5');return false;"  id="Radio6" type="radio" value="5" name="test" />   
</div>

On FireFox 2 and 3, putting the return false on the click event of a radio button prevents the value of it and of all the other radio buttons in the group from changing. This effectively makes it read-only without disabling it and turning it gray.

On Internet Explorer, if another radio button is checked and you click on a different one in the group, the checked one clears before the click event fires on the one you clicked. However, the one you clicked on does not get selected because of the 'return false' on the click event.

According to MSDN, the onbeforeupdate event fires on all controls in the control group before the click event fires and I assumed that was where the other radio button was being cleared. But if you try the code above, no alert is ever shown from the onbeforeupdate event - you just get the click event alert. Evidently that event is never getting fired or there isn't a way to trap it.

Is there any event you can trap that allows you to prevent other radio buttons in the group from clearing?

Note that this is a simplified example, we are actually using jQuery to set event handlers and handle this.

Update:

If you add this event to one of the radio buttons:

onmousedown="alert('omd'); return false;"

The alert box pops up, you close it, and the click event never fires. So we thought we had it figured out, but no, it couldn't be that easy. If you remove the alert and change it to this:

onmousedown="return false;"

It doesn't work. The other radio button clears and the click event on the button you clicked on fires. onbeforeupdate still never fires.

We thought it might be timing (that's always a theory even though it's rarely true), so I tried this:

onmousedown="for (i=0; i<100000; i++) {;}; return false;"

You click, it pauses for a while, then the other radio button clears and then the click event fires. Aaargh!

Update:

Internet Explorer sucks. Unless someone comes up with a good idea, we're abandoning this approach and going with the checkbox jQuery extension which does do what we want, but puts a heavier client-side script burden on the page and requires more recoding of the HTML because of the ASP.Net server control rendering and master-page name mangling.

+1  A: 

Yup, that's a strange bug. I did manage to cook up a workaround. I use a bit of Prototype to handle class names here. It works in IE and FF. You can probably shorten it up with a selector instead of a crude loop.

<form name="f1">
<input type=radio onmouseover="recordMe()" onclick="clickCheck();return false" checked value="A" name="r1" id="radio1" />
<input type=radio onmouseover="recordMe()" onclick="clickCheck();return false" value="B" name="r1" id="radio2" />
</form>
<script type="text/javascript">
function recordMe() {
    for(var x=0;x<document.f1.r1.length;x++) {
     if(document.f1.r1[x].checked) {
      $(document.f1.r1[x].id).addClassName('radioChecked')
     }
    }
}
function clickCheck() {
    for(var x=0;x<document.f1.r1.length;x++) {
     if($(document.f1.r1[x].id).hasClassName('radioChecked')) {
      $(document.f1.r1[x].id).checked=true
     }
    }
}
</script>
Diodeus
A: 

What is your goal? If you just want to capture when a change is made, run your logic on the onclick event. (this will get around IE's bug with onchange)

If you are trying to change the expected behavior of radio buttons - I would highly recommend against it.

scunliffe
The only thing we are trying to do is, by customer request, not gray out disabled radio buttons and checkboxes. This was a quick and easy solution for all of the checkboxes on all browsers and all of the radio buttons on everything except for IE (of course).
CMPalmer
hehehe, I love customer requests! - I want the thing I'm not allowed to click to look exactly like the things I can click. - makes no sense! ;-)
scunliffe
Eh, in this case I can't argue too much. Grayed out checked boxes are hard to read and Firefox/IE render the associated labels different ways (including IE's really annoying way of turning the grayed out text into chiseled "3D" that looks like crap against anything but white.
CMPalmer
As someone else in another thread said, substituting a Yes/No True/False text isn't as visually recognizable as a checked box or radio button and the rest of the form is quite obviously read only without being grayed out so why should the check/radio controls be different?
CMPalmer
A: 

None of these approaches worked - we wound up using the checkbox jQuery plug-in that replaces the checkboxes and radio buttons with shiftable images. That means that we can control the view of the disabled controls.

PITA but it works.

CMPalmer
+1  A: 

I had this problem as well. We currently implement jquery, so I used it to just re-check the appropriate one. Obviously you don't need jquery to set the property of the checkboxes.

function something(type){//type can be 1 or 0
     if(confirm("You will lose all unsaved changes. Continue?")){
     //Do stuff
          switch(type){
               case 1:
                break;
               case 0;
                break;
                default:
                //nothing;
                 break;
          }//!End of switch 
      }else{//They clicked canel
      //Reset checkboxes in IE
          if(type==1){$('#IDofCheckbox1').attr('checked', true);}
          else{$('#IDofCheckbox2').attr('checked', true);}
      }//!End of if they clicked cancel