Introduction
There are times when our applications might take an extra few seconds to respond to a click event. Some users might get impatient and click on the button more than once. We can easily avoid this type of situation by disabling the submit button during postback on the page by using a client-side script. In this article, I will share with everyone how to:
- Disable a button during postback with or without a validation control.
- Change button text value during postback.
- Include an AJAX loading background image during postback.
- How to avoid the 'Page_IsValid is undefined' JavaScript error.
Using the Code
Before we begin, allow me to show you the structure of my project. You are welcome to download this demo.
Demo 1 – Without Validation Control
Here is the content of Jscript.js:
function disableBtn(btnID, newText) {
var btn = document.getElementById(btnID);
setTimeout("setImage('"+btnID+"')", 10);
btn.disabled = true;
btn.value = newText;
}
function setImage(btnID) {
var btn = document.getElementById(btnID);
btn.style.background = 'url(12501270608.gif)';
}
Here is part of the Default.aspx page content:
<table>
<tr>
<td>
<td>
<asp:button id="btnOne" tabIndex="0"
Runat="server" Text="Submit"
onclick="btnOne_Click"
OnClientClick="disableBtn(this.id, 'Submitting...')"
UseSubmitBehavior="false" />
</td>
</tr>
<tr>
<td colspan="2">
<asp:Label ID="Label3"
runat="server" Text=""></td>
</tr>
</table>
<script type="text/javascript" src="JScript.js"></script>
In the Default.aspx page, I have a Button
and a Label
control. Let's take a closer look at the button attributes.
OnClientClick="disableBtn(this.id, 'Submitting...')"
- Calls the JavaScript function by passing in the button ID and the new text value that I want it to display on click.UseSubmitBehavior="false"
- Indicates that the button control should use the ASP.NET postback mechanism instead of the client browser's submit mechanism (UseSubmitBehavior
property).
For testing, I included these lines in default.aspx.cs:
protected void btnOne_Click(object sender, EventArgs e)
{
Thread.Sleep(2000);
Label3.Text = DateTime.Now.ToLongTimeString();
}
Here is how the button will look like when someone clicks on it:
Demo 2 – With Validation Control
Here is the output from Default2.aspx:
Oops... The button is still disabled after it failed the validation process. Let's modify the JavaScript to fix this problem.
Here is the content of the new JavaScript file with comments – Jscript2.js:
function ResetToDefault(btn, oldValue) {
btn.disabled = false;
btn.value = oldValue;
}
var Browser = {
Version: function() {
var version = 999;
if (navigator.appVersion.indexOf("MSIE") != -1) {
version = parseFloat(navigator.appVersion.split("MSIE")[1]);
return version;
}
},
Name: navigator.appName,
isIE: function() {
if (navigator.appVersion.indexOf("MSIE") != -1) {
return true;
}
return false;
}
};
function HasPageValidators() {
var hasValidators = false;
try {
if (Page_Validators.length > 0) {
hasValidators = true;
}
}
catch (error) { }
return hasValidators;
}
function SetImage(btn) {
if (btn.type == "image") {
btn.src = null;
btn.style.width = '100px';
btn.style.height = '20px';
btn.style.backgroundImage = 'url(http://images.ysatech.com/ajax-loader.gif)';
}
else {
if (Browser.isIE() && Browser.Version() === 7) {
btn.style.background = 'url(http://images.ysatech.com/ajax-loader.gif)';
}
else {
btn.style.backgroundImage = 'url(http://images.ysatech.com/ajax-loader.gif)';
}
}
}
function EnableOnUnload(btn, btnText) {
if (!Browser.isIE()) {
window.onunload = function() {
ResetToDefault(btn, btnText);
};
}
}
function EnableValidator(validator) {
var controlToValidate = document.getElementById(validator.controltovalidate);
if (controlToValidate !== null) {
ValidatorEnable(validator);
return true;
}
ValidatorEnable(validator, false);
return false;
}
function disableBtn(btnID, newText) {
var btn = document.getElementById(btnID);
var oldValue = btn.value;
btn.disabled = true;
btn.value = newText;
if (HasPageValidators()) {
Page_IsValid = null;
if (Page_Validators !== 'undefined' && Page_Validators !== null) {
for (var i = 0; i < Page_Validators.length; i++) {
var validator = Page_Validators[i];
if (EnableValidator(validator)) {
if (!Page_Validators[i].isvalid) {
ResetToDefault(btn, oldValue);
}
}
}
var isValidationOk = Page_IsValid;
alert('isValidationOk ' + isValidationOk);
EnableOnUnload(btn, btn.value);
if (isValidationOk !== null) {
if (isValidationOk) {
SetImage(btn);
__doPostBack(btnID, '');
}
else {
btn.disabled = false;
}
}
}
}
else {
SetImage(btn);
btn.disabled = true; btn.value = newText;
EnableOnUnload(btn, btn.value);
}
}
function DisableValidators() {
if (typeof (Page_Validators) === 'undefined')
return;
if (Page_Validators !== 'undefined' && Page_Validators !== null) {
for (var i = 0; i < Page_Validators.length; i++) {
var validator2 = Page_Validators[i];
var controlToValidate2 = document.getElementById(validator2.controltovalidate);
if (controlToValidate2 === null) {
ValidatorEnable(validator2, false);
}
}
}
return false;
}
window.onload = DisableValidators;
Output from using the new JavaScript (JScript2.js):
Conclusion
The main items in this project were the JavaScript (Jscript2) and the button attributes (OnClientClick
, UseSubmitBehavior
). I hope someone will find this tutorial useful. If you think I can improve this code, please leave me a feedback and share your thoughts.
Tested on IE 6.0/7.0 and Firefox 3.0.13.
History
- 08/14/2009 - I found out that, in Firefox, if we hit the button and continue to the next page, and then hit the Back button (or
javascript:history(-1);
)... the button control is still disabled. I have updated the JavaScript (JScript2). I have not fully tested the new implementation. Please leave me a feedback and share your thoughts. - 10/19/2009 - Modified the JavaScript (JScript2) to fix the double validation problem.
- 11/14/2009 - Fixed the bug mentioned by CodeProject user, prodriguez13. The JavaScript will throw an error when the control to validate is not visible. To remedy this, in the
onload
event, I have added the DisableValidators
function. This function is responsible to disable all the validators with controltovalidate === null
. I have received a few requests on getting this script to work with the Image
button. I managed to put together a solution for it. Let me know if you find any bugs. Tested on IE 7.0/8.0, FireFox, image would not show on Google Chrome, maybe someone can shed some light on this.