Ordinarily, a user must click on the Submit button of a form in order to send information entered by a user to a server. You want to use the Enter key for this purpose as well.
Write some code that generates a
client script that captures the
keypress
event of the browser document object and
then checks each keystroke for the Enter key.
In the .aspx
file, add id
and
runat
attributes to the body
element so that the tag’s contents can be accessed
(and modified) in the code-behind:
<body id="pageBody" runat="server"
leftmargin="0" marginheight="0" marginwidth="0" topmargin="0">
In the code-behind class for the page, use the .NET language of your choice to:
Call the Add
method of the
pageBody
object’s Attributes
collection to add the onload
attribute to the
pageBody
control, which causes the
captureKeyPress
(or equivalently named)
client-side script function to be called when the page is first
loaded. Your goal is to have HTML like this sent to the browser:
<body id="pageBody" leftmargin="0" marginheight="0" marginwidth="0" topmargin="0" onload="captureKeyPress( );">
Build a string containing the client-side JavaScript that is to be
executed when the page is loaded and that causes it to be output as
part of the rendered page. The client-side script must capture the
keypress
event in the browser, check to see if the
key pressed is the Enter key, and perform the form submittal, as the
following JavaScript does:
<script language='javascript'> <!-- function captureKeyPress( ) { document.onkeypress = checkForReturn; } function checkForReturn( ) { if (window.event.keyCode==13) { if (window.event.srcElement.id != 'btnCancel') { window.event.keyCode=0; _ _doPostBack('btnSave',''), } } } //--> </script>
Use the RegisterClientScriptBlock
method of the
Page
object to register the script block so that
it is output when the page is rendered.
Example 3-1 through Example 3-3 show the .aspx
and
code-behind files for an application that makes use of this solution.
This code will work only with Internet Explorer. In Netscape, the
client script required to capture the keypress
event and process the key presses is quite different and beyond the
scope of this book; however, Recipe 3.1.4 references a JavaScript book that can help you through the
browser-specific aspects of JavaScript.
The idea behind our solution is to use client script to capture the
keypress
event of the browser document object so
you can check each keystroke for the Enter key. After the Enter key
is detected, the client script calls the client-side method provided
by ASP.NET to perform a postback
of the form to
the server.
In terms of the client script, the solution we advocate involves starting with some skeleton JavaScript and then generating the rest on the fly. The best way to describe how this is done is by turning to our example.
Before we delve into the example, though, you might be wondering why
our solution doesn’t place all of the JavaScript
code directly in the .aspx
file from the start
instead of generating it on the fly. The reason is that such an
approach requires you to hardcode the IDs of the buttons and the name
of the ASP.NET-generated postback
function in the
client script. Our approach has the distinct advantage that it will
not break if the IDs of the buttons are changed or if the name of the
postback
function is changed in a later release of
ASP.NET.
Our explanation of the example begins with the client-side JavaScript that we cause to be generated in the code-behind. We then delve into the code in the code-behind that generates it.
The client-side JavaScript that is to be generated by the code-behind
is shown next. It consists of two functions:
captureKeyPress
and
checkForReturn
.
<script language='javascript'> <!--function captureKeyPress( )
{ document.onkeypress = checkForReturn; }function checkForReturn( )
{ if (window.event.keyCode==13) { if (window.event.srcElement.id != 'btnCancel') { window.event.keyCode=0; _ _doPostBack('btnSave',''), } } } //--> </script>
The captureKeyPress
function sets the
checkForReturn
function to be executed anytime a
key is pressed in the browser.
The checkForReturn
function first
checks to see if the key pressed is the
Enter key (keycode
13). If so, it then checks the
source of the event. The Enter key should cause a form
postback
, with the source of the
postback
set to the Save button in all cases,
except when the Cancel button is the source. This check is important
because without it, hitting the Enter key when the Cancel button is
the selected control results in a postback
with
both the Save and Cancel button click events raised.
If the key pressed is the Enter key and the source of the
keypress
event is not the Cancel button, the event
keycode
is set to 0 to stop further processing of
the keypress
event. Then the ASP.NET
postback
function is called, passing the Save
button as the source of the postback
(first
parameter) and no arguments for the postback
event
(second parameter).
In this example, the body element is modified in the code-behind. To
provide access to the body element in the code-behind, the
id
and runat
attributes are
added:
<body id="pageBody" runat="server"
leftmargin="0" marginheight="0" marginwidth="0" topmargin="0">
All work in the code-behind is done in the
Page_Load
method. The first operation performed is
to call the Add
method of the
pageBody
object’s Attributes
collection to add the onload
attribute to the
pageBody
control, which causes the
captureKeyPress
client-side script function to be
called when the page is first loaded.
This results in the following HTML being sent to the browser:
<body id="pageBody" leftmargin="0" marginheight="0" marginwidth="0"
topmargin="0"
onload="captureKeyPress( );
">
The remainder of the Page_Load
method builds a
string containing the client-side JavaScript and causes it to be
output as part of the rendered page. This code begins by creating a
new StringBuilder
object named
clientScript
and adds the opening script block
code to it. It then adds the code to define the
captureKeyPress
function to the
clientScript
StringBuilder
.
Using the StringBuilder
class makes a lot of sense
here because of all the appending that is being done to the
clientScript
string. If the
String
class had been used instead, ASP.NET would
have returned a new String
every time a
modification was made to clientScript
, slowing
down execution. This is a good example of where using the
StringBuilder
class can really improve
performance. Refer to Recipe 16.2 for
additional information on String performance.
Next, the code adds the checkForReturn
function to
the clientScript
StringBuilder
.
The following highlighted code sections provide the ASCII value of
the Enter keycode
, the name of the Cancel button,
and the name of the method created by ASP.NET to process the page
postback
(_ _doPostBack
). Using
this approach improves the maintainability of your code by allowing
you to change the ID of the Cancel button or the name of the
postback
function without requiring you to modify
this code.
The GetPostBackClientEvent
is passed two
parameters, as highlighted in the following code. The first is a
reference to the control that caused the postback
.
Setting this to the Save button will cause the Save
button’s click event to be raised when the page is
posted back. The second parameter contains the arguments that are
passed to the Save button click event; no arguments are actually
required here.
functionScript = "if (window.event.keyCode==" &Asc(NewLine)
& ") " & _ "{" & NewLine & _ "if (window.event.srcElement.id!='" &btnCancel.ID
& "') " & _ "{" & NewLine & _ "window.event.keyCode=0;" & NewLine & _GetPostBackClientEvent(btnSave,
"") & ";" & NewLine & _ "}" & NewLine & _ "}" & NewLine clientScript.Append("function checkForReturn( )" & NewLine) clientScript.Append("{" & NewLine) clientScript.Append(functionScript) clientScript.Append("}" & NewLine) functionScript = "if (window.event.keyCode==" +System.Convert.ToByte(NEW_LINE).ToString( )
+ ") " + "{" + NEW_LINE + "if (window.event.srcElement.id!='" +btnCancel.ID
+ "') " + "{" + NEW_LINE + "window.event.keyCode=0;" + NEW_LINE +GetPostBackClientEvent(btnSave, "")
+ ";" + NEW_LINE + "}" + NEW_LINE + "}" + NEW_LINE; clientScript.Append("function checkForReturn( )" + NEW_LINE); clientScript.Append("{" + NEW_LINE); clientScript.Append(functionScript); clientScript.Append("}" + NEW_LINE);
Finally, the closing </script>
tag is added
to the clientScript
StringBuilder
.
The code shown here registers the script block to be output when the page is rendered:
Page.RegisterClientScriptBlock("ScriptBlock", _ clientScript.ToString( )) Page.RegisterClientScriptBlock("ScriptBlock", clientScript.ToString( ));
The code shown in the Page_Load
method must be
executed anytime the page is displayed. In this example, this is
accomplished by generating the client script in the
Page_Load
method without checking to see if the
page is initially being displayed or if a postback
is being performed. Although this approach works, it can result in
generating the client script even when the page is not going to be
displayed, such as when a postback
results in
displaying a different page. Refer to Recipe 3.2 for a more efficient example of
generating the client script.
The sidebar Building a JavaScript Library in Recipe 3.5 for information on creating a reusable library of JavaScript functions; Recipe 16.2 for improving String operation performance; JavaScript: The Definitive Guide, by David Flanagan (O’Reilly), for more information on browser-specific JavaScript
Example 3-1. Using the Enter key to submit a form (.aspx)
<%@ Page Language="vb" AutoEventWireup="false"
Codebehind="CH03EnterSubmitVB.aspx.vb"
Inherits="ASPNetCookbook.VBExamples.CH03EnterSubmitVB" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Using Enter To Submit Form</title>
<link rel="stylesheet" href="css/ASPNetCookbook.css">
</head>
<body id="pageBody" runat="server"
leftmargin="0" marginheight="0" marginwidth="0" topmargin="0">
<form id="frmEnterCapture" method="post" runat="server">
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="center">
<img src="images/ASPNETCookbookHeading_blue.gif">
</td>
</tr>
<tr>
<td class="dividerLine">
<img src="images/spacer.gif" height="6" border="0"></td>
</tr>
</table>
<table width="90%" align="center" border="0">
<tr>
<td><img src="images/spacer.gif" height="10" border="0"></td>
</tr>
<tr>
<td align="center" class="PageHeading">
Using Enter To Submit Form (VB)
</td>
</tr>
<tr>
<td><img src="images/spacer.gif" height="10" border="0"></td>
</tr>
<tr>
<td align="center">
<table border="0">
<tr>
<td class="LabelText">Email Address: </td>
<td>
<asp:TextBox ID="txtEmailAddress" Runat="server"
Columns="30" CssClass="LabelText" />
</td>
</tr>
<tr>
<td class="LabelText">Password: </td>
<td>
<asp:TextBox ID="txtPassword" Runat="server"
textmode="Password"
Columns="30" CssClass="LabelText" />
</td>
</tr>
<tr>
<td colspan="2">
<br>
<table align="center" width="50%">
<tr>
<td align="center">
<asp:ImageButton ID="btnLogin" Runat="server"
ImageUrl="images/buttons/button_login.gif" />
</td>
<td align="center">
<asp:ImageButton ID="btnCancel" Runat="server"
ImageUrl="images/buttons/button_cancel.gif" />
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</form>
</body>
</html>
Example 3-2. Using the Enter key to submit a form code-behind (.vb)
Option Explicit On Option Strict On '----------------------------------------------------------------------------- ' ' Module Name: CH03EnterSubmitVB.aspx.vb ' ' Description: This module provides the code behind for ' CH03EnterSubmitVB.aspx ' '***************************************************************************** Imports Microsoft.VisualBasic Imports System.Environment Imports System.Text Namespace ASPNetCookbook.VBExamples Public Class CH03EnterSubmitVB Inherits System.Web.UI.Page 'controls on formProtected pageBody As System.Web.UI.HtmlControls.HtmlGenericControl
Protected WithEvents btnLogin As System.Web.UI.WebControls.ImageButton Protected WithEvents btnCancel As System.Web.UI.WebControls.ImageButton '************************************************************************* ' ' ROUTINE: Page_Load ' ' DESCRIPTION: This routine provides the event handler for the page load ' event. It is responsible for initializing the controls ' on the page. '------------------------------------------------------------------------- Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.LoadDim clientScript As StringBuilder
Dim functionScript As String
'add onload attribute to the page body to add a handler to the
'keypress event for the page
pageBody.Attributes.Add("onload", _
"captureKeyPress( );")
'generate the opening script tag
clientScript = New StringBuilder
clientScript.Append("<script language='javascript'>" & NewLine)
clientScript.Append("<!--" & NewLine)
'add the client script used to capture the keypress event
functionScript = "document.onkeypress = checkForReturn;" & NewLine
clientScript.Append("function captureKeyPress( )" & NewLine)
clientScript.Append("{" & NewLine)
clientScript.Append(functionScript)
clientScript.Append("}" & NewLine)
'add the client script to check the keypress event
functionScript = "if (window.event.keyCode==" & Asc(NewLine) & ") " & _
"{" & NewLine & _
"if (window.event.srcElement.id!='" & btnCancel.ID & "') " & _
"{" & NewLine & _
"window.event.keyCode=0;" & NewLine & _
GetPostBackClientEvent(btnLogin, "") & ";" & NewLine & _
"}" & NewLine & _
"}" & NewLine
clientScript.Append("function checkForReturn( )" & NewLine)
clientScript.Append("{" & NewLine)
clientScript.Append(functionScript)
clientScript.Append("}" & NewLine)
'generate the closing script tag
clientScript.Append("//-->" & NewLine)
clientScript.Append("</script>" & NewLine)
'register the client script to be output when the page is rendered
Page.RegisterClientScriptBlock("ScriptBlock", _
clientScript.ToString( ))
End Sub 'Page_Load '************************************************************************* ' ' ROUTINE: btnLogin_Click ' ' DESCRIPTION: This routine provides the event handler for the login ' button click event. It is responsible for processing ' the form data. '------------------------------------------------------------------------- Private Sub btnLogin_Click(ByVal sender As Object, _ ByVal e As System.Web.UI.ImageClickEventArgs) _ Handles btnLogin.Click 'perform login operations here End Sub 'btnLogin_Click '************************************************************************* ' ' ROUTINE: btnCancel_Click ' ' DESCRIPTION: This routine provides the event handler for the cancel ' button click event. '------------------------------------------------------------------------- Private Sub btnCancel_Click(ByVal sender As Object, _ ByVal e As System.Web.UI.ImageClickEventArgs) _ Handles btnCancel.Click 'perform cancel operations here End Sub 'btnCancel_Click End Class 'CH03EnterSubmitVB End Namespace
Example 3-3. Using the Enter key to submit a form code-behind (.cs)
//---------------------------------------------------------------------------- // // Module Name: CH03EnterSubmitCS.aspx.cs // // Description: This module provides the code behind for // CH03EnterSubmitCS.aspx // //**************************************************************************** using System; using System.Text; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; namespace ASPNetCookbook.CSExamples { public class CH03EnterSubmitCS : System.Web.UI.Page { // controls on formprotected System.Web.UI.HtmlControls.HtmlGenericControl pageBody;
protected System.Web.UI.WebControls.ImageButton btnLogin; protected System.Web.UI.WebControls.ImageButton btnCancel; //************************************************************************ // // ROUTINE: Page_Load // // DESCRIPTION: This routine provides the event handler for the page // load event. It is responsible for initializing the // controls on the page. //------------------------------------------------------------------------ private void Page_Load(object sender, System.EventArgs e) {const char NEW_LINE = ' ';
StringBuilder clientScript = null;
String functionScript = null;
// wire the login and cancel button click events
this.btnLogin.Click += new ImageClickEventHandler(this.btnLogin_Click);
this.btnCancel.Click +=
new ImageClickEventHandler(this.btnCancel_Click);
// add onload attribute to the page body to add a handler to the
// keypress event for the page
pageBody.Attributes.Add("onload",
"captureKeyPress( );");
// generate the opening script tag
clientScript = new StringBuilder( );
clientScript.Append("<script language='javascript'>" + NEW_LINE);
clientScript.Append("<!--" + NEW_LINE);
// add the client script used to capture the keypress event
functionScript = "document.onkeypress = checkForReturn;" + NEW_LINE;
clientScript.Append("function captureKeyPress( )" + NEW_LINE);
clientScript.Append("{" + NEW_LINE);
clientScript.Append(functionScript);
clientScript.Append("}" + NEW_LINE);
// add the client script to check the keypress event
functionScript = "if (window.event.keyCode==" +
System.Convert.ToByte(NEW_LINE).ToString( ) + ") " +
"{" + NEW_LINE +
"if (window.event.srcElement.id!='" + btnCancel.ID + "') " +
"{" + NEW_LINE +
"window.event.keyCode=0;" + NEW_LINE +
GetPostBackClientEvent(btnLogin, "") + ";" + NEW_LINE +
"}" + NEW_LINE +
"}" + NEW_LINE;
clientScript.Append("function checkForReturn( )" + NEW_LINE);
clientScript.Append("{" + NEW_LINE);
clientScript.Append(functionScript);
clientScript.Append("}" + NEW_LINE);
// generate the closing script tag
clientScript.Append("//-->" + NEW_LINE);
clientScript.Append("</script>" + NEW_LINE);
// register the client script to be output when the page is rendered
Page.RegisterClientScriptBlock("ScriptBlock",
clientScript.ToString( ));
} // Page_Load //************************************************************************ // // ROUTINE: btnLogin_Click // // DESCRIPTION: This routine provides the event handler for the login // button click event. It is responsible for processing // the form data. // //------------------------------------------------------------------------ private void btnLogin_Click(Object sender, System.Web.UI.ImageClickEventArgs e) { // perform login operations here } // btnLogin_Click //************************************************************************ // // ROUTINE: btnCancel_Click // // DESCRIPTION: This routine provides the event handler for the cancel // button click event. // //------------------------------------------------------------------------ private void btnCancel_Click(Object sender, System.Web.UI.ImageClickEventArgs e) { // perform cancel operations here } // btnCancel_Click } // CH03EnterSubmitCS }