views:

606

answers:

4

Now I could be going about this the wrong way so if there is a better solution please post that as well. What I am trying to do is disable a button once it is clicked to prevent double clicks. In the past I have done my just disabling the button onclick but with webforms I am running into a little bit of a snag because there is validation on the page so I need that to fire and I need to post back.

So I have the following JQuery function to make a button disable itself on click. Here is the JQuery:

jQuery.fn.disableOnClick =
    function()
    {
        return this.each(function()
        {
            $(this).click(function()
            {
                $(this).attr('disabled', 'disabled');
                return true;
            })
        })
    };

Intended usage would be:

$(document).ready(function()
{
    $("#<%= btnSomeButton.ClientID %>").disableOnClick ();
});

This doesn't work... the button always disables, the validation is ignored and the postback doesn't even happen. I would assume because I am overwrittin the click handler. Suggestions?

UPDATE: I have tried just a basic function that is connected to the 'OnClientClick' of the button to do:

// In my Page_Load
btnSomeButton.OnClientClick = "return DisableButton('" + btnSomeButton.ClientID + "');";

// Javascript function
function DisableButton(id)
{
    var bButton = $("#" + id);
    if (Page_ClientValidate())
    {
        $("#" + id).attr('disabled', 'disabled');
        __doPostBack(id, '');
    }
}

This works as expected in a non master page setup but when I try to use it with a page that has a master page, the postback occurs and the Page_Load fires but the button click handler never gets called. It's like the __doPostBack is not sending which control event to fire correctly.

Any suggestions for changes or even a whole different approach?

+1  A: 

One idea for a different approach (disclaimer: this is not a fully baked solution) is to go from the submit action of the form instead of the click handler of the button.

The validation all happens through the submit handler of the form. If everything checks out, the form is allowed to submit. If you could hook into that process, then when the form started to submit for real, you could find all buttons with the class DisableOnSubmit and disable them.

Validation could take some time, however, and some people (annoyingly) seem to like to double-click on web forms, so it might be best to blend the approaches. Disable the button immediately with a click handler, then if validation fails, re-enable the buttons that were disabled.

EDIT In response to comments

This description could be turned to be more like the signature in the question (where any button could be made to be click-once regardless of its CSS classes).

Create a jQuery extender where the buttons that fit the selector are given an onClick handler and (if not already done) the hook is added to the validation being complete. The onClick handler adds the clicked button to a collection of "currently in click evaluation" buttons. If validation succeeds, the form submits normally. If validation fails, the buttons in the collection are re-enabled and removed from the collection.

For the evil update panels, you might want to look into specifying these events with live bindings (used to be a plugin, but I think it's now part of the jQuery core depending on which version you're using) so that the event handlers are reregistered when the partial postbacks complete.

David
The solution could be applied to multiple buttons on a given form though as there could be many buttons that do postbacks. Also, I am trying to do something generic that will work on any button by just adding the basic javascript call as in my usage example.
Kelsey
Also keep in mind there are evil UpdatePanels in use as well.
Kelsey
+1  A: 

I get the feeling you can use GetPostBackEventReference to do the actual postback once you've done your validation dance.

Edit Oops, forgot the other half of the answer :-)

As for the double postback, I've used Postback Ritalin by Dave Ward in the past to curtail those pesky hyperactive users.

Dan F
A: 

Add this to your startup code (ready event handler):

var elemButton = $('#<%= Button1.ClientID %>');
var fnExistingHandler = elemButton[0].onclick;
elemButton[0].onclick = function() 
{ 
  fnExistingHandler(); 
  if (!Page_BlockSubmit) 
  {
    $(this)
      .hide()
      .after('<input type="button" value="Please Wait..." disabled="disabled" />');
  }
};

Basically you append new code to existing click handler. Note checking global variable Page_BlockSubmit.

Instead of disabling submit button you can hide it and immediately insert disabled button in its place. Because this happens very quickly it will look as button becoming disabled to the user. Details are at the blog of Josh Stodola.

Edit: fixed client validation.

Pavel Chuchuva
This has the same problems as disabling in that the validation doesn't fire first so I could be left with a invalid button state and the postback is eaten up I think.
Kelsey
Yes, you're right. I've updated my answer to address this issue.
Pavel Chuchuva
A: 

Haven't tried it but what about something like this:

$("input[type=submit]").live("click", function() {
$(this).hide().clone().insertAfter(this).show().attr("disabled", "disabled").val("Please wait...");
    return true;
});

This will ensure a submit button isn't disabled which ASP.NET doesn't like.

Peter Theill