Ask the DHTML Pro 10-Minute Solutions

Disable a Form Button: The Power of Three
By Shelley Powers

From the title of this article, you might think that the DHTML Pro has tried to solve one too many cross-browser DHTML problems and is feeling the strain. What does "the Power of Three" have to do with DHTML? "The Power of Three" refers to an approach I use for solving any development problem, including finding solutions to cross-browser DHTML problems. I never look for just one solution to the problem—I always look for at least three different solutions. If this sounds a bit silly, consider that "the Power of Three" has helped folks understand Egyptian hieroglyphs, sail the seas, chart stars, and even map our own neighborhoods.

To demonstrate my Power of Three approach, I tried to come up with three solutions to the question: "How can I enable/disable a button using client-side VBScript or JavaScript? If I can't enable/disable it, can I make it visible/invisible?" When reading the question, you might ask, "Why can't you just disable the form button?" Something like this code will work with Internet Explorer 4.x and up:


document.forms[0].elements[5].disabled=true

This code disables the fifth form element in the first page form, which just happens to be a button. In IE, the button takes on a disabled appearance and no action occurs when you click the button, as you can see from this example. However, the problem with this approach is that Netscape Navigator 4.x does not support the disabled attribute (though Navigator 5.0 should support the disabled attribute for form buttons).

Because the disabled attribute doesn't work as a cross-browser solution, we'll need to take a look at alternative solutions. In fact, we'll look at three solutions, starting with the simplest: ignoring the button.

Ignore the Button
When considering solutions, always look at the simplest first. In this case, we'll look at a non-DHTML solution: handling button processing within the JavaScript processing. Normally when a Web page client presses a form button, either the form is submitted for processing or some other activity takes place. However, you don't have to disable the button to prevent the activity from taking place. Instead, you can provide a message to your client that the activity they might be expecting is not taking place because they haven't provided the necessary information, or some other event must take place—whatever message is appropriate.

I created an example (Solution 1) that has a small form and a form button. The page also has two hypertext links—one that calls a function to disable the form button, and one that calls another function to enable the button again:


<a href="javascript:disable()"><h3>Disable button</h3></a>
<a href="javascript:enable()"><h3>Enable button</h3></a>

The functions to enable or disable the buttons do nothing more than set a button state. This button state is checked in the button event handler code and used to deliver a message to the person pressing the button:


<SCRIPT language="javascript">

state = 0;

function someaction() {
  if (state == 0) 
	alert("button is enabled");
  else
	alert("button is 'disabled'");
}
function disable() {
  state = 1;
}
function enable() {
  state = 0;
}
</SCRIPT>

This solution is quick and simple and can work with older browsers as well as new. It is the most commonly applied technique to let users know that they haven't filled out all of the form elements necessary to submit the form.

Hide the Form Button Using DHTML
Another approach could be to use DHTML to hide the form button. Before you can hide or show parts of a form, you have to understand the relationship between a form and a document, and a positioned layer (in this case a DIV block) and a document, for Netscape Navigator. A form is contained entirely in one document object. A CSS-positioned DIV block consists of a new document object. Form elements themselves cannot be hidden or positioned with Navigator 4.x—they must be contained in a positional element such as a DIV block.

Consider placing one form element in a positioned DIV block—so it can be hidden or shown separately from the other form elements—and placing the rest of the form elements in another DIV block or created directly in the main Web page. The form gets divided across two different document objects, which isn't allowed.

Alternatively, you create and place two forms in two DIV blocks: one containing all of the form elements but the button, the other containing just the button, as Solution 2 demonstrates. Then, when the disable link is clicked, the button is hidden, therefore preventing the person from clicking on the button:


function disable() {
   if (navigator.appName == "Microsoft Internet Explorer") 
      document.forms[1].elements[0].style.visibility="hidden";
   else 
      document.btndiv.visibility="hidden";
}

When the button is enabled, it is shown on the form again:


function enable() {
   if (navigator.appName == "Microsoft Internet Explorer") 
      document.forms[1].elements[0].style.visibility="inherit";
   else 
      document.btndiv.visibility="inherit";
}	

For IE 5.x, the form element is hidden directly—an approach that should also work with Navigator 5.0. However, you could have hidden the entire button DIV block with IE also (an approach that works best with IE 4.x and up solutions).

This second solution works fine to disable a form button. However, hiding and showing form buttons can be a bit disconcerting to the Web page client. A cross-browser solution that provides the appearance and behavior of a disabled button would be ideal. You can create a DHTML example to do this as a third solution.

Emulate the Disabled Button
You can't disable a form button and have the solution work with Navigator 4.x, but you can emulate a button using image replacement. This solution works for Navigator 3.x and up, as well as IE 4.x and up. First, create three button images: one that looks like a fully enabled button, one that looks like the enabled button when pressed, and one that looks like a disabled button. Next, create an array of images and add these three buttons to the array:


var img = new Array(3);

for (i = 0; i < 3; i++)
   img[i] = new Image();

img[0].src = "button1.gif";
img[1].src = "button2.gif";
img[2].src = "button3.gif";
 

Add the form to the Web page, and add a positioned DIV block containing the "button" image to the page after the form:


<DIV id="btndiv" style="top: 320; width:100%; visibility:inherit">
<table align="center">
<tr><td colspan=2 align="center">
<a href="" onclick="return false" 
		onMouseDown="switch_state()"
		onMouseUp="switch_state()">
<img src="button1.gif" border=0></a>
</td></tr>
</table>
</DIV>

Add two event handlers to the hypertext link surrounding the image to call functions that switch the image's source between the "button up" image and the "button down" image:


function switch_state() {
   if (state == 3) return;
   if (state == 0) {
      state = 1;
      if (navigator.appName == "Microsoft Internet Explorer") 
         document.images[0].src = img[1].src;
      else 
         document.btndiv.document.images[0].src = img[1].src;
      }
   else {
      state=0;
      if (navigator.appName == "Microsoft Internet Explorer") 
         document.images[0].src = img[0].src;
      else 
         document.btndiv.document.images[0].src = img[0].src;
      }
}

The state global value in the code provides information about the state the button is in: disabled (a state of 3), enabled and in "button up" state (a state of 0), and enabled and in "button down" state (a state of 1).

To disable the button, the state and the image are changed to reflect both the appearance of the disabled button (grayed out button text) and the disabled button behavior (can't push the button). To reenable the button, the image is changed back to the "button up" enabled image, and the state is changed back to enabled:


function disable() {
   state = 3;
   if (navigator.appName == "Microsoft Internet Explorer") 
      document.images[0].src = img[2].src;
   else 
      document.btndiv.document.images[0].src = img[2].src;
}

function enable() {
   state = 0;
   if (navigator.appName == "Microsoft Internet Explorer") 
      document.images[0].src = img[0].src;
   else 
      document.btndiv.document.images[0].src = img[0].src;
}
	

As you can see in Solution 3, the emulated button does a pretty good job of standing in for the form button. This approach works with Navigator 3.x and up, and IE 4.x and up.

The next time you're writing code to solve a problem, step back and ask yourself, "Is this the only approach I can take? Can I find other approaches that would work just as well?" You might find simpler solutions that are more interesting to work with than the first one you tried. And, you don't have to stop at three solutions: the Power of Three also implies the Power of Three, or more. I came up with a Solution 4 for the disabled form button problem—a solution that works equally well, if you don't mind chasing your customers away.

 
Other 10-Minute Solutions
 Understand and Leverage XML
 Transform Your Data With XSL
 Dynamically Change the Color of an Image
 Customizing Style Sheets on the Fly
 Communicate With the Server Using XMLHTTP
 Implement a DHTML Mouseover Effect Using the DOM, HTML 4, and CSS
 Disable a Form Button: The Power of Three
 Get Ready for Navigator 5.0 DHTML
 Implement a Pull-Down Menu
 Handle User Events With DHTML
 Click Anywhere Links
 Displaying XML Data Islands with JavaScript
 Add Persistence to Your XML Data Islands
 Essential JavaScript: 8 Cross-Browser Solutions
 Automate Your Form Validation
 Build an Animation Generator
 Encapsulate Your JavaScript: Keep Private Methods Private
 Create a Tabbed User Interface
 Generate Tabbed Interfaces Automatically With JavaScript OOP
 Integrating News Feeds
 Build A JavaScript Tree Control
 Build an Object-Oriented Tree Control using JavaScript
 Build an XML-based Tree Control with JavaScript
 How To Move Items Between Lists with JavaScript
 Create an Object-Oriented JavaScript Calendar Using the Façade Design Pattern


Ask the DHTML Pro | Who is the Pro? | Usage Policies | Ask a Question | Search | Feedback


Sponsored Links


Advertising Info  |   Member Services  |   Contact Us  |   Help  |   Feedback  |   Site Map
Jupiterweb networks

internet.comearthweb.comDevx.comClickZ

Search Jupiterweb:

Jupitermedia Corporation has four divisions:
JupiterWeb, JupiterResearch, JupiterEvents, and JupiterImages

Copyright 2004 Jupitermedia Corporation All Rights Reserved.
Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Jupitermedia Corporate Info | Newsletters | Tech Jobs | E-mail Offers