views:

36

answers:

1

I have a button that performs an ajax post -- I want to disable the button, then perform my work, then upon completion -- I want to re-enable the button. My interaction includes swapping out the image button (to a grayed out image button), and presenting a spinner. When complete, I hide the spinner and restore the original button image.

My approach includes unbinding, then rebinding the click event.

Here's my code -- it works great -- but, I want to know if this is a proper/efficient/acceptable strategy?

// Update club name
$j('#btnUpdateClubName').bind('click', updateClubName);

function updateClubName() {
    var $this = $j(this);
    var $spinner = $this.next('.spinner');
    var renderURL = RES.BuildClubUpdateURL("UpdateClubName");

    $this.ajaxStart(function() {
        $this.attr("src", imgPathSaveAndUpdateBtnDisabled).unbind('click').addClass('wait-cursor');
        $spinner.show();
    });

    $j.ajax({ type: "POST", data: $j('#hidStandingOrderId, #txtClubName, #clubOrderIdEditClubName').serialize(), url: renderURL, dataType: 'html', contentType: 'application/x-www-form-urlencoded',
        success: function(data) {
            // do some stuff
            }
        }
    });

    $this.ajaxComplete(function() {
        $spinner.hide();
        $this.attr("src", imgPathSaveAndUpdateBtn).bind('click', updateClubName).removeClass('wait-cursor');
        $j("#cbEditClubName").colorbox.close();
    });
}
+3  A: 

What you have works but it is a bit wasteful, as it adds a new ajaxStart and ajaxComplete handler each time the function runs, I would make one suggestion though, change your .unbind() call to be more specific since you have the information. If you change this:

.unbind('click')

To this:

.unbind('click', updateClubName)

You can have other click events without the .unbind() interfering, it'll only unbind that one handler.


An overall better alternative (to me, you can debate whether it's "better") without rebinding would be to store a variable to know you're currently posting using $.data() and .data(), for example:

$j('#btnUpdateClubName').bind('click', updateClubName);

function updateClubName() {
    if($.data(this, "posting")) return false;   //are we posting? abort!
    $.data(this, "posting", true);              //set variable
    var $this = $j(this);
    var $spinner = $this.next('.spinner');
    var renderURL = RES.BuildClubUpdateURL("UpdateClubName");

    $this.attr("src", imgPathSaveAndUpdateBtnDisabled).addClass('wait-cursor');
    $spinner.show();

    $j.ajax({ type: "POST", data: $j('#hidStandingOrderId, #txtClubName, #clubOrderIdEditClubName').serialize(), url: renderURL, dataType: 'html', contentType: 'application/x-www-form-urlencoded',
        success: function(data) {
            // do some stuff
            $spinner.hide();
            $this.attr("src", imgPathSaveAndUpdateBtn).removeClass('wait-cursor')
                 .data("posting", false);   //clear it out, ready to post again
            $j("#cbEditClubName").colorbox.close();
        }
    });
}

With this approach if you're doing a POST the data for "posting" is true, and future clicks just abandon out...not until the response comes back and your success code runs is the button re-enabled. It's the same effect but no duplicate handlers and no re/un-binding.

Nick Craver
the second solution is much better
KARASZI István
thanks Nick ... nice approach!
rsturim