A common solution that I had to implement recently is users on a client's site were double clicking buttons and causing issues. In addition to causing issues users weren't sure if the site was working correctly on long running processes. The JavaScript code I wrote to solve this problem can be divided into two segments. One part handles buttons that make asynchronous calls and another part that handles buttons that cause post-backs. For the buttons that cause post-backs we loop through all buttons and assign the CanSubmitFunction as the click event for that button. In the CanSubmitFunction we keep track of if the user has clicked the button before and if they have we display an alert and prevent the button from submitting. I should mention that I originally tried to disable the button. But doing this prevents the button from submitting and trying to force a submit is difficult to say the least.
// wire up the disable click event
var buttonControls = document.getElementsByTagName("input");
for (i = 0; i < buttonControls.length; i++) {
// if this input type is button, disable
if (buttonControls[i].type == "submit") {
addClickEvent(buttonControls[i], CanSubmitForm);
}
}
function addClickEvent(obj, fn) {
if (obj.addEventListener) {
obj.addEventListener('click', fn, false);
} else
if (obj.attachEvent) {
obj.attachEvent('onclick', fn);
}
}
var isSubmitted = false;
function CanSubmitForm() {
var canSubmit = false;
if (!isSubmitted) {
isSubmitted = true;
canSubmit = true;
}
else {
alert("Please wait for page to load before making another selection.");
}
return canSubmit;
}
For buttons that makes asynchronous calls we can disable the button. In addition to disabling the button we change the cursor so it shows the hourglass. I think the code below is pretty self-explanatory. One issue I do have with this solution is having to different types of behaviors on the buttons throughout the site. I may change the asynchronous code show it also displays an alert when the user clicks on the button twice.
// wire the callbacks for the Ajax events
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
//--------------------------------------
function InitializeRequest(sender, args) {
document.body.style.cursor = "wait";
var buttonControls = document.getElementsByTagName("input");
for (i = 0; i < buttonControls.length; i++) {
// if this input type is button, disable
if (buttonControls[i].type == "submit") {
buttonControls[i].disabled = true;
}
}
}
function EndRequest(sender, args) {
document.body.style.cursor = "default";
var buttonControls = document.getElementsByTagName("input");
for (i = 0; i < buttonControls.length; i++) {
// if this input type is button, enable
if (buttonControls[i].type == "submit") {
buttonControls[i].disabled = false;
}
}
}
The solution is deployed to an existing SharePoint site so it needed to work for all buttons instead of specifying each button by name. You can see above I made use of the unobtrusive JavaScript pattern to make this possible. We also need to put this code in a JavaScript file and add it to the master page that the SharePoint site is using. One more thing to note is I had the JavaScript file reference just above the closing tag to ensure that all the DOM elements have been loaded before the JavaScript code executes.
*Warning - This has not been tested in Firefox. This was a closed intranet and not a requirement for this solution. Though I doubt it would take long to make this code cross-browser compatible.