Dealing with <BUTTON>

Hal Pomeranz
Deer Run Associates

At first glance, the <BUTTON> tag seems pretty darn useful as a way to do something different from the plain old boring buttons you get with <INPUT type=submit ...>. All you have to do is insert something like the following into your HTML:

	<BUTTON type=submit name=foo value=bar>
		... wicked cool HTML ...
	</BUTTON>

This is supposed to result in a submit button for your form that looks like whatever "wicked cool HTML" tags you choose to put inside the <BUTTON ...></BUTTON> container. When clicked, the button returns the value "bar" in the parameter "foo".

However, it's been well documented that Microsoft Internet Explorer (MSIE) utterly fails to implement the <BUTTON> tag properly:

  1. MSIE returns the INNERTEXT (the "wicked cool HTML" you put between <BUTTON ...> and </BUTTON>) rather than the value you set with "value=".

  2. Even worse, if the form contains multiple <BUTTON ...></BUTTON> tags, MSIE returns all of the values, rather than just the value for the button that was clicked (actually, this one is apparently fixed in MSIE 7, though I haven't tried it out personally... plus there's still a lot of people out there using MSIE 6 anyway).

Frankly, it's hard to imagine how the MSIE developers could have gotten this more wrong. If they at least only returned the INNERTEXT value of the button that was clicked, you could come up with a hack to infer the correct value by scanning the INNERTEXT. But since there's no way to know which button actually submitted the form, you're pretty much screwed.

Standard Work-Arounds

The normal-work around for this problem is to make use of Javascript combined with the "onclick=" option to the <BUTTON ...> tag:
	<SCRIPT TYPE="text/javascript">
	<!--
	function submitForm(myForm, val)
	{
        	myForm.foo.value = val;
		myForm.submit()
	}
	//-->
	</SCRIPT>

	<BUTTON type=button name=foo onclick="submitForm(this.form, 'bar')">
		... wicked cool HTML ...
	</BUTTON>

When the button is clicked, the Javascript submitForm() routine is invoked which sets the value of "foo" to "bar" and submits the form. If you had multiple <BUTTON></BUTTON> tags on the form, you could generalize the submitForm() routine so you passed it both a variable name and a value to set (see this link for an example of such a routine).

The problem with this approach is that the only way this button submits the form is if the user is running a browser with Javascript enabled. Yes, I know that it's difficult to navigate any web sites these days without Javascript enabled, but some folks feel very strongly about disabling scripting (your humble author included, though I've pretty much given up tilting at that windmill). Wouldn't it be nice if you could have the best of both worlds-- that is, no Javascript required for compliant browsers (pretty much anything except MSIE), and a Javascript work-around for broken browsers like MSIE?

An Alternative Approach

The solution I came up with is just a slight modification of the approach above:
	<input type=hidden name=buttonPressed value=>

	<SCRIPT TYPE="text/javascript">
	<!--
	function submitForm(myForm, button)
	{
        	myForm.foo.buttonPressed = button;
	}
	//-->
	</SCRIPT>

	<BUTTON type=submit name=foo value=bar onclick="submitForm(this.form, 'bar')">
		... wicked cool HTML ...
	</BUTTON>

Take a look at the <BUTTON ...> tag first. Notice that we've gone back to a "submit" type button with the "name=" and "value=" parameters set. This means that for compliant web browsers the right thing will happen without Javascript being turned on.

However, there's also an "onclick=" function defined which sets a hidden variable called "buttonPressed" to the "bar" value that a compliant web browser will also set in the "foo" variable. This means that for users that have Javascript enabled you can always look at "buttonPressed" to figure out which button was activated. Since we're using <BUTTON type=submit ...>, we don't have to call the myForm.submit() routine inside submitForm()-- even MSIE gets that right.

So now you can use the combination of the "foo" and "buttonPressed" variables to figure out what the user wants:

Hey, it's far from perfect, but it's better than nothing.

Hal Pomeranz, 7/14/2007
hal@deer-run.com

Return to: Deer Run Home > Hal's Homepage >