従来の Web プログラミングでは、クライアント側機能は Web ページ開発者が管理するものであるため、サーバー コンポーネントではカプセル化されていません。ASP.NET では、このパラダイムから離れ、サーバー コントロールからクライアント側スクリプトに出力するときに、クライアント側処理とサーバー側処理を組み合わせたサーバー コンロトールが使用できるようになりました。
クライアント側機能の最も単純なケースは、Web サーバー コントロールがコントロールの Attributes プロパティによってクライアント側イベントのイベント ハンドラをレンダリングするときに見られます。System.Web.UI.WebControls.Button Web サーバー コントロールから派生し、クライアント側のクリック イベントのイベント ハンドラを提供するコントロール (ClientClickButton
) のサンプルを次に示します。
メモ ページ開発者は、Web サーバー コントロールの Attributes コレクションを使用すると、クライアント側のイベント ハンドラを簡単に提供できます。このサンプルの目的は、コントロール自身がクライアント側のイベント ハンドラを提供する機能をどのようにカプセル化するかを示すことにあります。このサンプルをビルドする方法については、「サーバー コントロールのサンプル」の手順を参照してください。
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CustomControls
{
public class ClientClickButton : Button
{
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
writer.AddAttribute("onclick", "alert('Thanks');");
}
}
}
[Visual Basic]
Option Explicit
Option Strict
Imports System
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Namespace CustomControls
Public Class ClientClickButton
Inherits Button
Protected Overrides Sub AddAttributesToRender(writer As HtmlTextWriter)
MyBase.AddAttributesToRender(writer)
writer.AddAttribute("onClick", "alert('Thanks');")
End Sub
End Class
End Namespace
ClientClickButton
カスタム コントロールを使用するページを次に示します。ClientClickButton
の onClick
属性がクライアント上でレンダリングされることをチェックするには、ブラウザでページを要求し、ソースを表示します。
<%@ Register TagPrefix="Custom" Namespace="CustomControls" Assembly = "CustomControls" %>
<html>
<body>
<form runat=server>
This button handles a client-side click event.
<Custom:ClientClickButton Id = "Button" BackColor = "Red" runat=server/> <br> <br>
</form>
</body>
</html>
前出の例は、クライアント側機能のシンプルな例です。ASP.NET を使用すると、コントロールは、次のリストに示すような、より複雑なクライアント側のシナリオを使用できるようになります。
- クライアント側スクリプト ライブラリの提供。
- ページの上または下でのスクリプトの出力。
- ページ上に複数のコントロール インスタンスが存在する場合でも、ページにはスクリプト ブロックを一度しか表示しないことの確認。
- コントロールによるイベント ハンドラとフォームのクライアント側送信イベントとの関連付けの有効化 (ページにフォームが含まれている場合)。
- コントロールによってレンダリングされたクライアント側要素のクライアントで宣言された配列変数への追加。
これらのシナリオは、System.Web.UI.Page クラスによって公開されたメソッドをとおして有効になり、Page プロパティを使用して ASP.NET サーバー コントロールにアクセスできます。クライアント側機能を提供する Page クラスのメソッドを次の表に示します。
メソッド | 説明 | 使用時期 |
---|---|---|
Page.RegisterClientScriptBlock | コントロールによるスクリプト ブロックの出力を有効にします。このスクリプト ブロックには、インライン スクリプトを格納するか、またはスクリプト ファイルの場所を指定します。スクリプト ブロックはページの先端部分にレンダリングされ、キーを使用してページに登録します。これにより、ページ上に複数のコントロール インスタンスが存在する場合でも、スクリプト ブロックの出力は一度だけになります。
メモ ページの先端部分で出力されるスクリプト ブロックは、ASP.NET ページでは、クライアント スクリプト ブロックと呼ばれます。 |
スクリプト ファイルをインクルードする、またはページの後ろで呼び出される一般的な機能を格納するスクリプト ブロックをレンダリングするときに使用します。特に、レンダリング フェーズで呼び出される機能は、ページの先端部分に存在する必要があります。 |
Page.RegisterStartupScript | コントロールによるスクリプト ブロックの出力を有効にします。このスクリプト ブロックには、インライン スクリプトを格納するか、またはスクリプト ファイルの場所を指定します。スクリプト ブロックはページの下端にレンダリングされ、キーを使用してページに登録します。これにより、ページ上に複数のコントロール インスタンスが存在する場合でも、スクリプト ブロックの出力は一度だけになります。
メモ ページの下端で出力されるスクリプト ブロックは、ASP.NET ページではスタートアップ スクリプト ブロックと呼ばれます。 |
ページ上の要素を呼び出すスクリプトまたはスタートアップで実行する必要のあるスクリプトを出力するときに使用します。このスクリプトはページの下端で出力されるため、参照先の要素がスクリプトの実行前に終了することが保証されます。 |
Page.RegisterArrayDeclaration | コントロールによる、指定した名前を持つクライアント側配列変数へのコントロール自身の追加を有効にします。配列名は、キーを使用して格納するページに登録されます。これにより、ページのクライアント側スクリプトにその名前を持つ配列が 1 つしかレンダリングされないようになります。 | コントロールでレンダリングした要素をクライアント スクリプトの配列変数に属する要素にする場合に使用します。配列を使用すると、同じタイプの要素をグループ化してクライアント スクリプトによるアクセスを簡単にできます。たとえば、検証コントロールは、Page_Validators という名前の配列に自分自身を追加します。 |
Page.RegisterOnSubmitStatement | イベント ハンドラをフォームのクライアント側送信イベントと関連付け、キーを使用して格納するページに登録します。ハンドラは、フォーム要素の onSubmit 属性としてレンダリングされます。ハンドラを登録すると、複数のコントロール インスタンスによる複数のハンドラの送信を防止できます。 | フォームの送信時にクライアント側ハンドラを呼び出す場合に使用します。
メモ インライン スクリプトを引数としてこのメソッドに渡したり、呼び出しをイベント ハンドラに渡したりできます。呼び出しをイベント ハンドラに渡す場合は、ハンドラをスクリプト ブロックまたはスクリプト ライブラリで独立して定義する必要があります。 |
Page.IsClientScriptBlockRegistered | 指定したキーを備えたクライアント スクリプト ブロックが、格納するページに登録されているかどうかを判定します。 | このメソッドの戻り値は、Page.RegisterClientScriptBlock を呼び出す必要があるかどうかを判定するために使用します。 |
Page.IsStartupScriptRegistered | 指定したキーを備えたスタートアップ スクリプト ブロックが、格納するページに登録されているかどうかを判定します。 | このメソッドの戻り値は、Page.RegisterStartupScript を呼び出す必要があるかどうかを判定するために使用します。 |
Page.RegisterHiddenField | サーバー コントロールによって、ページのレンダリング時に出力されるページに隠しフィールドを登録できるようになります。このフィールドは、クライアント スクリプトを使用してアクセスできます。したがって、フォームがサーバーにポストバックされるときにサーバーの隠しフィールドは、ポストバック データとして有効になります。 | サーバー コントロールがクライアント側スクリプトでアクセス可能な隠し変数を送る必要がある場合に使用します。これは、変数をコントロールの属性としてレンダリングできない場合、または、クライアント側処理で必要とするのがコントロールに依存しない変数である場合に役立ちます。例については、「非フォーム コントロールにおけるクライアント側の変更の永続化」を参照してください。 |
検証コントロールとは、ASP.NET によって提供されるクライアント側機能を充分に活用する ASP.NET サーバー コントロールです。サポートされているドキュメント オブジェクト モデルはブラウザごとに異なるため、.NET Framework SDK と共に出荷されるほとんどのサーバー コントロールはクライアント側スクリプトの使用を最小限に抑えており、ほとんどの場合、自動ポストバックに使用されています。ポストバックにスクリプトを使用する方法の詳細については、「ポストバックのためのクライアント側スクリプトの生成」を参照してください。ただし、特定のブラウザをターゲットにする場合、または特定のドキュメント オブジェクト モデルに準拠するブラウザをターゲットにする場合は、コントロール内でクライアント側スクリプトを使用することによって、できるだけクライアント側での処理を増やし、サーバーとの通信を減らすことができます。
ページによって公開されたスクリプト メソッドの使用方法
「基本検証コントロールのサンプル」の次のコードでは、Page クラスによって公開されたクライアント側スクリプト メソッドを使用しています。コードでは、クライアント側スクリプト メソッドの呼び出しが太字フォントで表示されています。コードの最初のコードは、ページの先端部分に含むスクリプト ファイルの名前を格納する文字列定数、ページにスクリプト ブロックを登録するキー、ページの下端に含むスクリプト ブロック、書式情報を提供する文字列を定義しています。
private const string ValidatorFileName = "DomValidation.js";
// The key to register a script key. In this example, the same key
// is used for registering both the script at the top of the
// page (called the client-side script block) and the script
// that is rendered at the bottom of the page (called startup
// script).
private const string ValidatorIncludeScriptKey = "DomValidatorIncludeScript";
// The script block that is rendered at the bottom of the page.
private const string ValidatorStartupScript = @"
<script language=""javascript"">
<!--
var Page_ValidationActive = false;
if (typeof(Page_DomValidationVer) == ""undefined"")
alert(""{0}"");
else
ValidatorOnLoad();
function ValidatorOnSubmit() {{
if (Page_ValidationActive) {{
return ValidatorCommonOnSubmit();
}}
}}
// -->
</script>
";
// Provides formatting information for emitting the script
// block at the top of the page.
private const string IncludeScriptFormat = @"
<script language=""{0}"" src=""{1}{2}""></script>";
// This method is called from OnPrerender in the
// Base Validator Control Sample.
protected void RegisterValidatorCommonScript() {
string ___location = null;
if (!Page.IsClientScriptBlockRegistered(ValidatorIncludeScriptKey)) {
// Provide the ___location of the script file.
___location = Page.Request.ApplicationPath + "/script/";
// Create client script block.
string includeScript = String.Format(IncludeScriptFormat, "javascript", ___location, ValidatorFileName);
Page.RegisterClientScriptBlock(ValidatorIncludeScriptKey, includeScript);
}
if (!Page.IsStartupScriptRegistered(ValidatorIncludeScriptKey)) {
if (___location == null) ___location = Page.Request.ApplicationPath + "/script/";
// Provide error message, which is localized.
string missingScriptMessage = "Validation script is missing '" + ___location + ValidatorFileName + "'";
// Create startup script block.
string startupScript = String.Format(ValidatorStartupScript, new object [] {missingScriptMessage,});
Page.RegisterStartupScript(ValidatorIncludeScriptKey, startupScript);
}
Page.RegisterOnSubmitStatement("ValidatorOnSubmit", "return ValidatorOnSubmit();");
}
[Visual Basic]
Private Const ValidatorFileName As String = "DomValidation.js"
' The key to register a script key. In this example, the same key
' is used for registering both the script at the top of the
' page (called the client-side script block) and the script
' that is rendered at the bottom of the page (called startup
' script).
Private Const ValidatorIncludeScriptKey As String = "DomValidatorIncludeScript"
' The script block that is rendered at the bottom of the page.
Private Const ValidatorStartupScript As String = ControlChars.CrLf & _
"<script language=""javascript"">" & ControlChars.CrLf & _
"<!--" & ControlChars.CrLf & _
"var Page_ValidationActive = false;" & ControlChars.CrLf & _
"if (typeof(Page_DomValidationVer) == ""undefined"")" & ControlChars.CrLf & _
" alert(""{0}"");" & ControlChars.CrLf & _
"else" & ControlChars.CrLf & _
" ValidatorOnLoad();" & ControlChars.CrLf & ControlChars.CrLf & _
"function ValidatorOnSubmit() {{" & ControlChars.CrLf & _
" if (Page_ValidationActive) {{" & ControlChars.CrLf & _
" return ValidatorCommonOnSubmit();" & ControlChars.CrLf & _
" }}" & ControlChars.CrLf & _
"}}" & ControlChars.CrLf & _
"// -->" & ControlChars.CrLf & _
"</script>"
' Provides formatting information for emitting the script
' block at the top of the page.
Private Const IncludeScriptFormat As String = ControlChars.CrLf & _
"<script language=""{0}"" src=""{1}{2}""></script>"
' This method is called from OnPrerender in the
' Base Validator Control Sample.
Protected Sub RegisterValidatorCommonScript()
Dim ___location As String = Nothing
If Not Page.IsClientScriptBlockRegistered(ValidatorIncludeScriptKey) Then
' Provide the ___location of the script file.
' When using a script library, deployment can be
' a problem because the runtime is
' tied to a specific version of the script file.
' This sample takes the easy way out and insists that
' the file be placed in the /script subdirectory
' of the application.
' In other cases, you should place it where it
' can be shared by multiple applications and is placed
' in a separate directory so that different versions
' of a control library can run side by side.
' The recommended pattern is to put script files in the
' path /aspnet_client/<assembly name>/<assembly version>/".
___location = Page.Request.ApplicationPath + "/script/"
' Create the client script block.
Dim includeScript As String = [String].Format(IncludeScriptFormat, "javascript", ___location, ValidatorFileName)
Page.RegisterClientScriptBlock(ValidatorIncludeScriptKey, includeScript)
End If
If Not Page.IsStartupScriptRegistered(ValidatorIncludeScriptKey) Then
If ___location Is Nothing Then
___location = Page.Request.ApplicationPath + "/script/"
End If
' Provide an error message, which is localized.
Dim missingScriptMessage As String = "Validation script is missing '" & ___location & ValidatorFileName & "'"
' Create the startup script block.
Dim startupScript As String = [String].Format(ValidatorStartupScript, New Object() {missingScriptMessage})
Page.RegisterStartupScript(ValidatorIncludeScriptKey, startupScript)
End If
Page.RegisterOnSubmitStatement("ValidatorOnSubmit", "return ValidatorOnSubmit();")
End Sub
「基本検証コントロールのサンプル」の次のコードは、クライアント スクリプトでレンダリングされた配列変数 (Page_Validators
) にコントロールによってレンダリングされた要素を追加する Page.RegisterArrayDeclaration メソッド (コードでは、太字フォントで表示) を呼び出す方法を示しています。Page_Validators
キーを使用してページに配列変数を登録することによって、この名前を持つ変数が 1 つだけページに作成されます。
// This method is called from Render in the
// Base Validator Control Sample.
protected virtual void RegisterValidatorDeclaration() {
string element = "document.getElementById(\"" + ClientID + "\")";
Page.RegisterArrayDeclaration("Page_Validators", element);
}
[Visual Basic]
' This method is called from Render in the
' Base Validator Control Sample.
Protected Overridable Sub RegisterValidatorDeclaration()
Dim element As String = "document.getElementById(""" & ClientID & """)"
Page.RegisterArrayDeclaration("Page_Validators", element)
End Sub
クライアント スクリプト中のコントロールへのアクセス
基本 Control クラスは、レンダリングされた要素の ID 属性として HTML でレンダリングする、ClientID という名前のプロパティを公開します。ASP.NET はコントロールの ClientID を動的に生成し、ページ上のそれぞれのコントロールの ClientID は一意であることが保証されます。したがって、コントロール (つまり、コントロールによってレンダリングされた要素) には、ドキュメント オブジェクト モデルの ID を使用してクライアント上でアクセスできます。コントロールは、ClientID を使用して、隠しフィールドなど、コントロールがレンダリングする追加要素の一意の名前を生成することもできます。
インライン スクリプト (または、スクリプト ライブラリのコード) で ClientID の値を使用するときは、ClientID を文字列変数の正しい位置に挿入するために工夫が必要です。エスケープ文字を使用して、インライン スクリプトを構成する文字列に ClientID を挿入する例を次に示します。
string element = "document.getElementById(\"" + ClientID + "\")";
Page.RegisterArrayDeclaration("Page_Validators", element);
[Visual Basic]
Dim element As String = "document.getElementById(""" & ClientID & """)"
Page.RegisterArrayDeclaration("Page_Validators", element)
String クラスのオーバーロードされた Format メソッドを使用して、ClientID を使用するクライアント側スクリプトを作成することもできます。書式指定の詳細については、「型の書式設定」を参照してください。
スクリプト ファイルの配置
スクリプト対応のコントロールによって出力されたスクリプト ブロックは、インライン スクリプトを格納したり、スクリプト ファイルの場所を提供したりできます。このトピックの前出のサンプルに、両方のケースを示しています。ブロックがスクリプト ファイルの場所を提供する場合は、他のアプリケーションからのスクリプト ファイルを使用できるようにし、同時にスクリプト ファイルがバージョン競合を引き起こさないようにスクリプト ファイルを配置する必要があります。サンプルでは、スクリプト ファイルは、Web アプリケーションの仮想ルート ディレクトリの script
という名前のサブディレクトリに配置されています。
// Provides the ___location of the script file.
___location = Page.Request.ApplicationPath + "/script/";
[Visual Basic]
' Provides the ___location of the script file.
___location = Page.Request.ApplicationPath & "/script/"
サンプルではこの場所になっていますが、他のアプリケーションで使用するスクリプト ファイルの推奨配置場所は次のとおりです。
/aspnet_client/<your assembly name>/<your assembly version>/
aspnet_client ディレクトリは、.NET Framework SDK または Visual Studio .NET をインストールするときにコンピュータ上に作成される仮想ルート Web アプリケーション ディレクトリです。たとえば、ASP.NET と共に出荷されるスクリプト ファイルは、次の場所にあります。
/aspnet_client/system_web/<version of SDK installed>
複数のバージョンの SDK をインストールしている場合は、aspnet_client/system_web の下に複数のサブディレクトリが生成されます。コントロール ライブラリはスクリプト ファイルの特定のバージョンに結び付けられているため、推奨配置パターンを使用するとコントロール ライブラリの異なるバージョンを side-by-side 実行できます。
なお、コンピュータ上で管理される Web サイトごとに aspnet_client が 1 つ作成されます。通常、1 つのサーバーが管理するのは 1 つの Web サイトだけです。ただし、複数サイトの管理も可能であり、複数のサイトの場合は aspnet_client ディレクトリのコピーを複数使用します。
スクリプト レンダリングのチェック
スクリプト対応コントロールは、クライアント側スクリプトのレンダリング行うかどうかを切り替える選択肢をコンシューマに提供する必要があります。ASP.NET の検証 Web サーバー コントロールは、コントロールがスクリプトをクライアントにレンダリングするかどうかを判定する EnableClientScript と命名された Boolean プロパティを公開します。この機能を提供するプロパティは、次のように定義します。
public bool EnableClientScript {
get {
object o = ViewState["EnableClientScript"];
return((o == null) ? true : (bool)o);
}
set {
ViewState["EnableClientScript"] = value;
}
}
[Visual Basic]
Public Property EnableClientScript() As Boolean
Get
Dim o As Object = ViewState("EnableClientScript")
If o Is Nothing Then
Return True
Else
Return CBool(o)
End If
End Get
Set
ViewState("EnableClientScript") = value
End Set
End Property
レンダリングの前に、スクリプト対応のコントロールは、クライアントの能力をチェックし、ユーザー (ページ開発者) がスクリプトをオフにしているかどうかもチェックします。これらのチェックは、通常、レンダリングの前段階およびレンダリング フェーズで実行します。「基本検証コントロールのサンプル」の次のコードでは、レンダリングの前段階でチェックを実行します。
private boolean renderUplevel;
protected override void OnPreRender(EventArgs e) {
base.OnPreRender(e);
...
// Work out uplevelness now.
renderUplevel = DetermineRenderUplevel();
if (renderUplevel) {
// Helper method that creates script blocks
// and registers them with the page.
RegisterValidatorCommonScript();
}
}
// Helper method to check whether script should be rendered.
protected virtual bool DetermineRenderUplevel() {
// Must be on a page.
Page page = Page;
if (page == null || page.Request == null) {
return false;
}
// Check whether the user has turned off scripting and
// check browser capabilities. This custom control
// needs the W3C DOM level 1 for control manipulation
// and at least ECMAScript 1.2.
return (EnableClientScript
&& page.Request.Browser.W3CDomVersion.Major >= 1
&& page.Request.Browser.EcmaScriptVersion.CompareTo(new Version(1, 2)) >= 0);
}
[Visual Basic]
Private _renderUplevel As Boolean
Protected Overrides Sub OnPreRender(e As EventArgs)
MyBase.OnPreRender(e)
_preRenderCalled = True
' Force a re-query of properties for render.
_propertiesChecked = False
' Work out uplevelness now.
_renderUplevel = DetermineRenderUplevel()
If _renderUplevel Then
RegisterValidatorCommonScript()
End If
End Sub
' Helper method to check whether script should be rendered.
Protected Overridable Function DetermineRenderUplevel() As Boolean
' Must be on a page.
Dim page As Page = Page
If page Is Nothing Or page.Request Is Nothing Then
Return False
End If
' Check the browser capabilities.
' This is how you can get automatic fallback to server-side
' behavior. These validation controls need
' the W3C DOM level 1 for control manipulation
' and need at least ECMAScript 1.2 for the
' regular expressions.
Return EnableClientScript AndAlso _
page.Request.Browser.W3CDomVersion.Major >= 1 AndAlso _
page.Request.Browser.EcmaScriptVersion.CompareTo(New Version(1, 2)) >= 0
End Function
レンダリング フェーズでのチェックの実行については、「基本検証コントロールのサンプル」の Render メソッドを参照してください。
クライアントでレンダリングされるスクリプト
コントロールによってカプセル化されたスクリプトがクライアントでどのようにレンダリングされるかを参照するには、「検証コントロールのサンプル」で提供されているサンプルをコンパイルおよび配置し、「検証コントロールのテスト ページのサンプル」で提供されているページを要求してブラウザでページのソースを参照します。表示される HTML とスクリプトを次の例に示します。コントロールによって出力されたスクリプトは、ここでは太字フォントで表示されています。ページは、スクリプトを出力するコントロールをいくつか備えており、それらのすべてが「基本検証コントロールのサンプル」で説明する基本コントロールから派生しています。結果的に、ソースにはこのトピックで説明していないスクリプトがいくつか含まれています。なお、ブラウザでソースを参照する場合、アプリケーションのディレクトリ名 (サンプルでは、samples
) は、アプリケーションの仮想ディレクトリの名前に置き換わります。
<HTML>
<HEAD>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<meta content="Microsoft Visual Studio .NET" name=GENERATOR>
<meta content=C# name=CODE_LANGUAGE>
<meta content="JavaScript (ECMAScript)" name=vs_defaultClientScript>
<meta content="Internet Explorer 3.02 / Navigator 3.0" name=vs_targetSchema>
<title>DOM Validators Test</title>
</HEAD>
<body>
<form name="ValTest" method="post" action="valtest.aspx" language="javascript" onsubmit="return ValidatorOnSubmit();" id="ValTest">
<input type="hidden" name="__VIEWSTATE" value="dDwxOTkwOTM1MDA5O3Q8O2w8aTwxPjs+O2w8dDw7bDxpPDEzPjs+O2w8dDw7bDxpPDE+O2k8Mz47aTw1PjtpPDc+Oz47bDx0PHA8cDxsPFRleHQ7PjtsPElFOz4+Oz47Oz47dDxwPHA8bDxUZXh0Oz47bDw1LjU7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPDEuMjs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8MS4wOz4+Oz47Oz47Pj47Pj47Pj47Pg==" />
<script language="javascript" src="/samples/script/DomValidation.js"></script>
<P><FONT face=Verdana size=5>DOM Validators Test</FONT></P>
<P>
<TABLE cellSpacing=1 cellPadding=1 width=602 border=0 height=131>
<TR>
<TD style="WIDTH: 82px">Name:</TD>
<TD style="WIDTH: 164px"><input name="txtName" type="text" id="txtName" /></TD>
<TD><span id="valRequired" controltovalidate="txtName" errormessage="Required." evaluationfunction="RequiredFieldValidatorEvaluateIsValid" initialvalue="" style="color:Red;visibility:hidden;">Required.</span></TD>
</TR>
<TR>
<TD style="WIDTH: 82px">Postal Code:</TD>
<TD style="WIDTH: 164px"><input name="txtPostcode" type="text" id="txtPostcode" /></TD>
<TD><span id="valRegex" controltovalidate="txtPostcode" errormessage="Postcode must be 9999." evaluationfunction="RegularExpressionValidatorEvaluateIsValid" validationexpression="\d{4}" style="color:Red;visibility:hidden;">Postcode must be 9999.</span></TD>
</TR>
</TABLE></P>
<P>
<input type="submit" name="cmdSubmit" value="Submit" onclick="if (typeof(Page_ClientValidate) == 'function') Page_ClientValidate(); " language="javascript" id="cmdSubmit" />
<input type="submit" name="cmdCancel" value="Cancel" id="cmdCancel" />
</P>
<div id="Panel1" style="border-color:#00C000;border-width:2px;border-style:Solid;height:55px;width:197px;">
<P>
Browser: <span id="lblBrowserName">IE</span><br>
Version: <span id="lblBrowserVersion">5.5</span><br>
Script Version: <span id="lblScriptVersion">1.2</span><br>
DOM Version: <span id="lblDomVersion">1.0</span><br>
Submit clicks: <span id="lblSubmitCount"> 0 </span><br>
Cancel clicks: <span id="lblCancelCount"> 0 </span><br>
</P>
</div>
<script language="javascript"><!-- var Page_Validators = new Array(document.getElementById("valRequired"), document.getElementById("valRegex")); // --></script><script language="javascript"><!--var Page_ValidationActive = false;if (typeof(Page_DomValidationVer) == "undefined") alert("Validation script is missing '/samples/script/DomValidation.js'");else ValidatorOnLoad();function ValidatorOnSubmit() { if (Page_ValidationActive) { return ValidatorCommonOnSubmit(); }}// --></script>
</form>
</body>
</HTML>