Introduction
Say you have a web page that has a simple form that, for example, sends feedback to you. Great, that sounds straightforward... so you've now created your form and it all works fine. However, when the end user comes to use the form, he/she enters their "First Name", "Last Name", "Email Address" .... and their "Feedback Message", then hits "Enter" (Return), instead of of getting a lovely thank you message for sending you some feedback, the user gets a new page with lots of search results!?
What has happened? Well... on the same page at the top is a search control, and when the user hits the "Enter" key, it fired the "Search" button and not the "Submit" button on your form.
This article (and code) will show you the best solution to the problem, and will allow you to handle as many forms on one page and still fire the correct button when the "Enter" Key is pressed.
Background
When I first had this problem, my first instinct was to look on the web (as everyone does). I found lots of different solutions out there for this.
The best one I could find was to attach an onkeypress
event to the input fields to catch event.keycode == 13
(event.which
, if using Firefox), P.s.: 13 is the code for the Enter Key.
Although this did work, it meant adding the event to every input field on the page, which also meant having to Attributes.Add()
for every server control.
Then, I found a breakthrough: in ASP.NET 2.0, the standard asp:panel
control has an attribute called "DefaultButton
". All you have to do is wrap your form in a Panel
and set the default button for the form. Now, the Enter Key works a treat.
The End...!?
Well, almost. Sadly, the application I'm developing was not in .NET 2.0; that is why I have written this article. This code is applicable for all .NET 1.1 apps, and even if you are not using ASP.NET at all, you can still use the code in a regular HTML page edited in Notepad!.
The basis of the code is the ASP.NET 2.0 Panel
.
Using the code
The code I have provided is for use in ASP.NET 1.1.
Copy the FormPanel.cs file to your project (you may want to change the namespace), then register the control on your page. Set the default button to the button you wish to be fired when the Enter Key gets pressed inside of the form.
<%@ Page language="c#" Codebehind="Default.aspx.cs"
AutoEventWireup="false" Inherits="FormPanel.Default" %>
<%@ Register TagPrefix="custom"
Namespace="FormPanel.Controls"
Assembly="FormPanel" %>
...
<custom:FPanel DefaultButton="btnSearch" runat="server">
//Your form here
</custom:FPanel>
...
If you are not using ASP.NET, then you can use the JavaScript that this control creates to do the same thing, and use a DIV
as your panel (which is what an asp:panel
renders as in the end!).
<script>
function FormPanel_FireDefaultButton(event, target) {
if ((event.keyCode == 13 || event.which == 13) && !(event.srcElement &&
(event.srcElement.tagName.toLowerCase() == 'textarea')))
{
var defaultButton = document.getElementById(target);
if (defaultButton == 'undefined') defaultButton = document.all[target];
if (defaultButton && typeof(defaultButton.click) != 'undefined')
{
defaultButton.click();
event.cancelBubble = true;
if (event.stopPropagation) event.stopPropagation();
return false;
}
}
return true;
}
</script>
<div onkeypress="javascript:return FormPanel_FireDefaultButton(event,'btnSubmit')">
//Your form here
<div>
Points of interest
All the input fields must be inside of the panel, and the form in question must be "in focus" in order for the correct Enter Key event to fire. However, the actual button can be anywhere on the page.
While I was putting this together, I needed to search the page for the correct button control. Page.FindControl()
is not recursive (i.e., does not find a control within a control within a control etc.). This code also includes a nice little method for searching all controls:
private Control FindControl(Control control, string id)
{
if (_ctl != null) return _ctl;
IEnumerator iEnum = control.Controls.GetEnumerator();
iEnum.Reset();
while (iEnum.MoveNext())
{
if (_ctl != null) break;
if (((Control)iEnum.Current).ID == id)
{
_ctl = ((Control)iEnum.Current);
break;
}
FindControl(((Control)iEnum.Current),id);
}
return _ctl;
}
Hope this is of help.
History
None to date.