08 October 2004
Please Wait... buttons
Picture this;
You are a normal web user. By this I mean that you are not a web developer, and you are not amazingly web savvy. You are trying to find some information on the Internet about fishing, so you go onto your local fishing web forums, and spend quite a bit of time filling out a form to post a new message. When you have finished you scroll to the bottom of the page and click the ‘Post Message' button. After a couple of seconds nothing seems to happen, so you click it again. Still no immediate response, so you click is a few more times. Eventually the page submits, and you have either posted the same message 20 times, or generated an error of quite seriousness. Either way, to some web developer in the world, you have just become the bane of his day!
It's time to fight back at our impatient click-happy enemy! Or at least try and help them.
Back to reality
It's not their fault, but users like the one above can be a real pain. Impatient and ‘click happy' is the way a lot of people interact with the web. You may or may not have had to deal with someone who has done this, but inevitably you will have to. Unless…
Pro-active buttons
The solution as I see it is either to stop people from clicking the buttons more than once, or to let them know that they only need to click it once.
My idea came when I notice what Alex Haneng had done on his website forums ( www.haneng.com/forums.asp ). In his forms, he has buttons coded with an OnClick event:
OnClick="ButtonName.disabled=true;submit();"
It was a good idea I thought, even if it was implemented in a bad way. Basically, as soon as someone clicks the button, it will disable the button so that they can't go click happy and click again.
I thought that with a little bit of improving, that the idea could be taken to new levels.
Introducing the DOM version
I wanted to use the same idea as Alex, but without introducing any javascript into my buttons. My DOM scripting has been getting a bit better polished, so I decided to give it a go with DOM based Javascript.
In the system that I wanted to implement this onto, all my buttons (INPUT tags with type=”sumit”) also have the class of ‘button'. This is for my style sheet, but can also be used in my javascript.
The plan is to loop through all the INPUT tags on the page, find the ones with a ‘button' class, and add an onclick event to them.
pleaseWaitButtons = function(){
//find all the INPUT tags
var navRoot = document.getElementsByTagName("input");
//loop through all the tags and find the ones with class=”button”
for (var i = 0; i < navRoot.length ; i++) {
if (navRoot[i].className=='button'){
//add the onclick event
navRoot[i].onclick = function(){
this.disabled=true;
}//end onclick function
}// end if
}// end for loop
}// end function
window.onload=pleaseWaitButtons;
Now, when someone clicks one of my buttons, they can't possibly click it again.
But wait, it's not perfect; If a user decides straight away that they didn't want to click the button, and they hit the browsers ‘stop' button, then the disabled button because useless to them. Not accessibility.
Another problem; the system that I want to implement this into is an ASP.NET system. ASP.NET commonly uses multiple buttons on one form; if you disable the button the ASP.NET code behind page cannot work out what has been clicked and wont trigger off the correct server side ‘click' event. So, disabling the buttons isn't a good idea after all!
Please Wait…
After discovering the little ASP.NET incompatibility, I decided that what would be best is to leave the button enables, but to change it so that the user would see that something was happening. Wouldn't it be great I thought if I was to tell the use to ‘Please Wait…' by actually changing the text of the button to say just that! So I did;
pleaseWaitButtons = function(){
//find all the INPUT tags
var navRoot = document.getElementsByTagName("input");
//loop through all the tags and find the ones with class="button"
for (var i = 0; i < navRoot.length ; i++) {
if (navRoot[i].className=='button'){
//add the onclick event
navRoot[i].onclick = function(){
this.value='Please Wait...';
}//end onclick function
}// end if
}// end for loop
}// end function
window.onload=pleaseWaitButtons;
As you can see, only one line needed to change. I thought to myself that this would do. If for any reason the submission of the form is taking a long time, the button will say ‘please wait…' and the user will know that something is actually happening. No need to keep on clicking. A nice usable, and accessible way of providing extra functionality to help users!
But I forgot something; What if the button doesn't post you to another web page. For example; in my ASP.NET application there is a section where you can request a bunch of XML files to be downloaded in a ZIP file. We have a form that lets you select the files you want in the ZIP, and then a button that will post you to another ASP.NET page that builds the ZIP file on the fly, and streams it to the users browser. This means that you never actually leave the current page; you just get a prompt to download the ZIP file. What's the problem? Well the text of the button just clicked says ‘Please Wait…' even after the desired events has been triggered off. I needed to find a way of setting the button's text value back to the original after a certain amount of time.
Enter SetTimeout()
SetTimeout is a JavaScript function that I have used a little bit in the past. And then I realised my need, I thought of it straight away. What I needed to do was use this function to set a period of time before calling another function that would set the text value of the button back to normal. Easy peasey:
var origValue; //used to hold the value of a button just clicked
var currentButton; //used to hold the DOM ref of the button
//the function used to reset the buttons after the ‘please wait…’ change
function resetValue(obj, value){
obj.value = value;
}
pleaseWaitButtons = function(){
//find all the INPUT tags
var navRoot = document.getElementsByTagName("input");
//loop through all the tags and find the ones with class=”button”
for (var i = 0; i < navRoot.length ; i++) {
if (navRoot[i].className=='button'){
//add the onclick event
navRoot[i].onclick = function(){
//set origValue to remember the original text value
origValue = this.value;
currentButton = this;
this.value='Please Wait...';
//set the timeout for 10 seconds
setTimeout("resetValue(currentButton, origValue)", 10000)
}//end onclick function
}// end if
}// end for loop
}// end function
window.onload=pleaseWaitButtons;
There you have it, my ‘please wait…' buttons! The most important parts in the code above is the resetValue function, which expects the values ‘obj' and ‘value', the first being the DOM path to the button, and the second being the original text value of the button (saved in the origValue variable – before changing the text to ‘please wait…'). I could have called the two variables (origValue and currentButton) from the function, without asking for them like above, but I felt it would be best to do it this way in case I ever added anything else to this JavaScript that might make use of the resetValue function.
I hope that you find this useful, happy wubbing!
- Time: 18:44
- Wubb Development
Comments ( 5 )
Malarkey
Phil Baines
I'm sure that it could be improved on, and if anyone has any improvements I would be more than happy to hear about them!
Chris Neale
Are you sure about `bain` ?
The bane of my day/hour/'time unit of choice' is usually those that misspell or mispunctuate : )
Phil Baines
Thanks
James White
Great Article
Sorry, commenting has been disabled for a while. I am getting a stupid amount of comment spam, and need to find a new way of doing things.
I will not publish your email address, but I may use it to get in contact with you.
HTML tags and entities display as source; they do not render. To create a live link, simply type the URL (including http://).