views:

4572

answers:

4

I have a page that displays a list of records. The user can select the record status using radio buttons, e.g.:

<div id="record_653">
  <label><input type="radio" name="status_653" value="new" checked/>new</label>
  <label><input type="radio" name="status_653" value="skipped" />skipped</label>
  <label><input type="radio" name="status_653" value="downloaded" />downloaded</label>
</div>

I am using JQuery to send the changes made by the user back to the server, where I use them to update the database. This is a simplified version of what I do:

$("#record_653").click( 
function(event) { 
    var url = ...,        
        params = ...;
    post(url,params);                    
});

The problem is that this code will create requests even if the user clicks the same button that was previously checked. What I actually want is the "on change" event, except its behavior in Internet Explorer is not very useful (e.g. here).

So I figure I somehow have to identify if the click event changed the value.

Is the old value stored somewhere (in the DOM? in the event?) so I could compare against it?

If not, how should I store the old value?

+4  A: 

The old value is not stored someplace where you can query it, no. You will need to store the value yourself. You could use a javascript variable, a hidden input element, or jQuery's data() function.

EDIT

The jQuery data function provides access to a key-value-pair data structure as a way to store arbitrary data for a given element. The api looks like:

 // store original value for an element
 $(selector).data('key', value);

 // retrieve original value for an element
 var value = $(selector).data('key');

A more developed thought:

$(document).ready(function() {

    // store original values on document ready
    $(selector).each(function() {
        var value = $(this).val();
        $(this).data('original-value', value);
    })

    // later on, you might attach a click handler to the the option
    // and want to determine if the value has actually changed or not.
    $(selector).click(function() {

        var currentValue = $(this).val();
        var originalValue = $(this).data('original-value');
        if (currentValue != originalValue) {

            // do stuff.

            // you might want to update the original value so future changes
            // can be detected:
            $(this).data('original-value', currentValue);
        }

    });

});
Ken Browning
Thanks for the answer. I wonder which of your solution is better - which one would an experienced developer use for this problem.
Daphna Shezaf
good overview of how to use data, thanks.
Daphna Shezaf
+1  A: 
$('#record_653 input:radio').each(function() {
    $(this).data('isChecked', $(this).is(':checked'));

    $(this).click(function() {
        if ( $(this).is(':checked') !== $(this).data('isChecked') ) {
            // do changed action
        } else {
          $(this).data('isChecked', !$(this).data('isChecked') );
        }
    })

});

This was complicated to do in my head but I think you want something like this.

meder
The code is incorrect beyond the first click (for once, you obviously have to change "isChecked" in the if clause rather than the else clause), but it gave me good clues on how to use the data function and the checked filter. Thanks.
Daphna Shezaf
A: 

As was suggested by meder and Ken Browning, I ended up using JQuery's data() to store the previous value and check against it on every click.

Storing an "is checked" boolean for each input radio is one solution. However you need to maintain this value. So in the click event handler, in addition to changing the "is checked" of the current input, you need to find the input that was previously checked and change its "is checked" data to false.

What I chose to do instead was to store, in the parent element, the currently checked object. So my code looks something like:

$(document).ready(  
    function()  {
        // find the checked input and store it as "currChecked" for the record
        $("#record_653").data("currChecked", 
                             $(this).find("input:radio:checked")[0]);
        // add the click event
        $("#record_653").click( function(event) {
                 if ($(event.target).is("input:radio") && 
                     event.target !== $(this).data("currChecked")) 
                 {
                    $(this).data("currChecked", event.target);
                    handleChangeEvent(event);
                 }
            });

        });
    }
);

Thanks

Daphna Shezaf
A: 

I had the same problem, but with FF I managed to deal with it using the onchange event rather than the onclick.

This is exactly what I was looking for to deal with IE7. Works like a charm! Thanks for the detailed solution!