Tải bản đầy đủ (.pdf) (26 trang)

ASP.NET AJAX Programmer’s Reference - Chapter 2 ppsx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (423.97 KB, 26 trang )

JavaScript Base Type
Extensions
The main goal of the ASP.NET AJAX client-side framework is to emulate the ASP.NET and .NET
Framework as much as possible to bring similar .NET-style programming to your client-side
scripting. The ASP.NET AJAX JavaScript base type extensions are the first step toward achieving
this goal.
These extensions extend the functionality of the JavaScript base types such as
Array , Boolean ,

Date , Error , Number , Object , and String to add support for .NET-like methods and properties.
As such, the ASP.NET AJAX JavaScript base type extensions make client-side programming
against these JavaScript base types more like server-side programming against their .NET counter-
parts as much as possible .
The code samples presented in this chapter use a new JavaScript function named
pageLoad and a
new server control named
ScriptManager as shown in the boldfaced portion of Listing 2-1 .
Listing 2-1: The ASP . NET Page Used by the Examples
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>
function pageLoad() {
. . .
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>


</body>
</html>
c02.indd 27c02.indd 27 8/20/07 5:42:26 PM8/20/07 5:42:26 PM
Chapter 2: JavaScript Base Type Extensions
28
I’ll discuss the pageLoad JavaScript function and ScriptManager server control in detail in future
chapters. For now, here are two key concepts:
❑ One of the responsibilities of the ScriptManager server control is to download the ASP.NET
AJAX client-side framework to the requesting browser to make it available to the browser’s
JavaScript engine.
❑ The ASP.NET AJAX client-side framework automatically calls the pageLoad JavaScript function
after the page and the related client-side scripts are completely loaded.
ASP . NET AJAX Array Type Extensions
The .NET Array type features methods such as Clone , Add , Clear , Contains , IndexOf , Insert ,

Remove , and RemoveAt . The ASP.NET AJAX client-side framework extends the JavaScript Array type to
add support for similar methods. These extensions allow the JavaScript
Array type to emulate its .NET
counterpart as much as possible to make you feel like you’re programming against the .NET
Array type.
Keep in mind that these new methods are static methods, which means that you must call these methods
directly on the
Array class itself.
add
The add method takes two arguments of type Array and Object , respectively and adds the Object to
the end of the
Array as shown in the following code. Because the second argument is of type Object ,
you can add any type of object to the specified array.
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>

<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var a = [‘m1’,’m2’];
Array.add(a, ‘m3’);
for (var i = 0; i<a.length; i++)
alert(a[i]);
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
c02.indd 28c02.indd 28 8/20/07 5:42:27 PM8/20/07 5:42:27 PM
Chapter 2: JavaScript Base Type Extensions
29
add Range
The addRange method takes two arguments of type Array and adds the contents of the second Array
object to the end of the first
Array object, as shown in the following code:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {

var a1 = [‘m1’,’m2’];
var a2 = [‘m3’,’m4’,’m5’];
Array.addRange(a1, a2);
for (var i = 0; i<a1.length; i++)
alert(a1[i]);
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
clear
The clear method clears the specified Array object and sets its length property to zero, as shown in
the following code fragment:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var a1 = [‘m1’,’m2’];
alert(a1.length);
Array.clear(a1);
alert(a1.length);
}
</script>
</head>

<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
c02.indd 29c02.indd 29 8/20/07 5:42:27 PM8/20/07 5:42:27 PM
Chapter 2: JavaScript Base Type Extensions
30
clone
The clone method clones the specified Array object. This cloning operation is a shallow copy , which
means that the object referenced in the
Array object and its clone reference the same objects. That is, the
references are copied, but the objects being referenced are not copied, as shown in the following code:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var a1 = [‘m1’,’m2’];
var a2 = Array.clone(a1);
alert(“a1[0] = “ + a1[0] + “\n” + “a2[0] = “ + a2[0]);
alert(“a1[1] = “ + a1[1] + “\n” + “a2[1] = “ + a2[1]);
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />

</form>
</body>
</html>
contains
The contains method returns a Boolean value that indicates whether the specified Array object
contains the specified element. For example:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var a1 = [‘m1’,’m2’];
alert(Array.contains(a1,’m2’));
alert(Array.contains(a1,’m4’));
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
c02.indd 30c02.indd 30 8/20/07 5:42:27 PM8/20/07 5:42:27 PM
Chapter 2: JavaScript Base Type Extensions
31
enqueue and dequeue
The JavaScript Array type can be used as a stack. The standard JavaScript Array type exposes two
methods named

push and pop . The push method pushes a specified item onto the top of the stack, and
the
pop method pops up the item at the top of the stack. Here is an example:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var a = [];
a.push(‘m1’);
a.push(‘m2’);
a.push(‘m3’);
alert(a.pop());
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
This example respectively pushes the m1 , m2 , and m3 items onto the top of the stack. Note that the last
pushed item—that is,
m3 —sits on the top of the stack. The call into the pop method pops up the topmost
item—that is,
m3 . Figure 2-1 presents the stack before and after the call into the pop method.
Stack (Before Calling pop) Stack (After Calling pop)
‘m3’

‘m2’
‘m2’
‘m1’
‘m1’
Figure 2-1
The JavaScript
Array type can also be used as a queue. A queue is the opposite of a stack. A queue uses a
FIFO (first in, first out) algorithm where the first item added to the queue is the first item to be served.
The JavaScript
Array type includes a method named shift that allows you to access the first item
c02.indd 31c02.indd 31 8/20/07 5:42:28 PM8/20/07 5:42:28 PM
Chapter 2: JavaScript Base Type Extensions
32
added to the list. Here is an example of a queue in JavaScript:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var a = [];
a[0] = ‘m1’;
a[1] = ‘m2’;
a[2] = ‘m3’;
alert(a.shift());
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>

<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
As you can see, JavaScript already supports the concept of queueing. However, the way this is done in
JavaScript is quite different from the way it’s done in the .NET Framework. The main problem is
that JavaScript uses an unintuitive approach to implement a queue. The ASP.NET AJAX client-side
framework extends the functionality of the JavaScript
Array type to add support for two
convenient .NET-like methods named
enqueue and dequeue , as shown here:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var a = [];
Array.enqueue(a,’m1’);
Array.enqueue(a,’m2’);
Array.enqueue(a,’m3’);
alert(Array.dequeue(a));
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>

</html>
Figure 2-2 presents the queue before and after the call into the dequeue method.
c02.indd 32c02.indd 32 8/20/07 5:42:28 PM8/20/07 5:42:28 PM
Chapter 2: JavaScript Base Type Extensions
33
for Each
The ASP.NET AJAX client-side framework extends the functionality of the JavaScript Array type to add
support for a method named
forEach . The best way to understand what this method does is to look at
the internal implementation of this method as shown in Listing 2-2 .
Listing 2-2: The Internal Implementation of the for Each Method
Array.forEach = function(b, e, d)
{
for(var a = 0, f = b.length; a < f; a ++ )
{
var c = b[a];
if(typeof c !== “undefined”)
e.call(d, c, a, b);
}
}
The forEach method takes the following three parameters:
❑ b : This parameter references a JavaScript Array object.
❑ e : This parameter references a JavaScript function that takes three parameters, which will be dis-
cussed shortly .
❑ d : This parameter references a JavaScript object.
As Listing 2-2 shows, the
forEach function iterates through the elements of the Array object ( b ), calls
the JavaScript function (
e ) once for each enumerated element, and passes the following parameters
into the

call method of this JavaScript function ( e ):
❑ The JavaScript object ( d )
❑ The value of the enumerated element ( c )
❑ The index of the enumerated element ( a )
❑ The JavaScript Array itself ( b )
It’s completely up to the implementation of the JavaScript function (
e ) and the JavaScript object ( d ) what
to do with the enumerated element of the specified
array object ( b ) when the JavaScript function ( e ) is
called. Listing 2-3 shows an example.
Queue (Before Calling dequeue) Queue (After Calling dequeue)
‘m3’
‘m2’
‘m3’
‘m2’
‘m1’
Figure 2-2
c02.indd 33c02.indd 33 8/20/07 5:42:28 PM8/20/07 5:42:28 PM
Chapter 2: JavaScript Base Type Extensions
34
Listing 2-3: Demonstration of the for Each Method
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>
function multiply(val,index,ar)
{
ar[index] = val * this.get_c();
}


function myClass(c)
{
this.c = c;
this.get_c = function ()
{
return this.c;
};
}

function pageLoad() {
var a = [1, 2, 3, 4];
var myObj = new myClass(6);
Array.forEach(a, multiply, myObj);
for (var j = 0; j<a.length; j++)
alert(a[j]);
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
In this case, the forEach function calls the multiply JavaScript function once for each element of the

Array ( a ). Note that Listing 2-3 also defines a class named myClass with a simple field and a getter
method that returns the value of this field. In this case, the
forEach function simply multiplies the value
of each element of the array by the number 6.

index Of
The ASP.NET AJAX client-side framework extends the functionality of the JavaScript Array type
to add support for a method named
indexOf . As the name implies, this method returns the index of a
specified element of a specified array. As such, it takes the following three parameters:
❑ The JavaScript array to be searched
❑ The array element to search for
❑ The index at which to start searching the array
c02.indd 34c02.indd 34 8/20/07 5:42:29 PM8/20/07 5:42:29 PM
Chapter 2: JavaScript Base Type Extensions
35
Here is an example:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var a = [1, 2, 3, 4];
alert (Array.indexOf(a, 3, 1));
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
insert

The ASP.NET AJAX client-side framework extends the JavaScript Array type to add support for a
method named
insert , which inserts a specified object into a specified array at the specified index. The
following code fragment inserts the number
5 into the specified array at position 1 , which means that
after the insertion, the array will contain these elements:
1 , 5 , 2 , 3 , and 4 .
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var a = [1, 2, 3, 4];
Array.insert(a, 1, 5);
for (var i = 0; i<a.length; i++)
alert(a[i]);
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
c02.indd 35c02.indd 35 8/20/07 5:42:29 PM8/20/07 5:42:29 PM
Chapter 2: JavaScript Base Type Extensions
36
parse

The parse extension method allows you to parse the content of a string into an array. The string must
follow this format:
“[m1, m2, m3, m4, m5]” . Here is an example:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var str = “[1, 2, 3, 4]”;
var a = Array.parse(str);
for (var i = 0; i<a.length; i++)
alert(a[i]);
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
remove
The remove extension method allows you to remove a specified item from a specified array. The follow-
ing code fragment removes the number
3 from the specified array:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>


function pageLoad() {
var a = [1, 2, 3, 4];
Array.remove(a,3);
for (var i = 0; i<a.length; i++)
alert(a[i]);
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
c02.indd 36c02.indd 36 8/20/07 5:42:30 PM8/20/07 5:42:30 PM
Chapter 2: JavaScript Base Type Extensions
37
remove At
The removeAt method removes an item with the specified index from the specified array. The following
code listing removes the item with an index of
2 (that is, the number 3 ) from the specified array:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var a = [1, 2, 3, 4];
Array.removeAt(a,2);

for (var i = 0; i<a.length; i++)
alert(a[i]);
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
ASP . NET AJAX Boolean Type Extensions
The ASP.NET AJAX client-side framework extends the JavaScript Boolean type to add support for a
new .NET-like method named
parse that parses the string values of “true” and “false” into a valid
JavaScript Boolean value. Here’s an example:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var b = Boolean.parse(“false”);
alert(b);
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />

</form>
</body>
</html>
c02.indd 37c02.indd 37 8/20/07 5:42:30 PM8/20/07 5:42:30 PM
Chapter 2: JavaScript Base Type Extensions
38
ASP . NET AJAX Date Type Extensions
The ASP.NET AJAX Date type extensions extend the JavaScript Date type to add support for two new
methods named
format and localeFormat , which format a date using the invariant and current cul-
tures, respectively. Here is an example of both methods:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var d = new Date();
var f1 = d.format(“hh:mm:ss”);
alert(f1);
var f2 = d.localeFormat(“d”);
alert(f2);
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>

</html>
ASP . NET AJAX Object Type Extensions
The .NET Object class exposes a method named GetType that you can call on an object to query its type
at runtime. The ASP.NET AJAX client-side framework extends the JavaScript
Object type to add
support for two .NET-like methods named
getType and getTypeName , which return the type of the
object and the fully qualified name of the type, respectively. Here’s an example:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>
function Person (firstName, lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}

function pageLoad() {
var p = new Person(“Shahram”, “Khosravi”);
var b = Object.getType(p);
var name = Object.getTypeName(b);
alert(name);
}
c02.indd 38c02.indd 38 8/20/07 5:42:30 PM8/20/07 5:42:30 PM
Chapter 2: JavaScript Base Type Extensions
39
</script>
</head>
<body>

<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
This code fragment first defines a new class named Person and instantiates an instance of this class.
Next, it calls the
getType method of the Object class, passing in the new Person instance to return a
reference to the type of the instance; that is, the constructor of the
Person class. Then, it calls the

getTypeName method of the Object class to return the name of the instance type.
ASP . NET AJAX String Type Extensions
The ASP.NET AJAX client-side framework extends the functionality of the JavaScript String type
to add support for the .NET-like methods discussed in the following sections. These extensions make
programming against the JavaScript String type more like programming against the .NET
String type.
This is yet another attempt on the part of the ASP.NET AJAX framework to make client-side program-
ming feel more like server-side .NET programming.
ends With
The endsWith .NET-like extension method returns a Boolean value that specifies whether a specified
string ends with the specified substring. Note that any leading or trailing white space of the substring is
considered part of the substring itself. In other words, the
endsWith method does not trim the substring.
For example, the second call to the
endsWith method in the following code fragment returns false ,
because the string passed into the method contains a trailing white space:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>

<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var str = “Programming ASP.NET”;
alert(str.endsWith(“.NET 3.0”));
alert(str.endsWith(“.NET 3.0 “));
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
c02.indd 39c02.indd 39 8/20/07 5:42:30 PM8/20/07 5:42:30 PM
Chapter 2: JavaScript Base Type Extensions
40
starts With
The startsWith method returns a Boolean value that specifies whether a specified string starts with the
specified substring. Again, leading or trailing white space of the substring is considered part of the
substring itself. In this example, just like the previous one, the second call to
startsWith returns false
because the string passed into the method contains extra leading white space:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {

var str = “Programming ASP.NET”;
alert(str.startsWith(“Programming “));
alert(str.startsWith(“ Programming “));
}
</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
trim
The trim method trims the specified string — that is, it removes the leading and trailing white space.
For example, the following code fragment returns
true in both cases even though the second case
contains trailing white space because the call to
trim removes this white space:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var str = “Programming ASP.NET”;
alert(str.startsWith(“Programming “));
alert(str.startsWith(“ Programming “.trim()));
}
</script>
</head>

<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
c02.indd 40c02.indd 40 8/20/07 5:42:31 PM8/20/07 5:42:31 PM
Chapter 2: JavaScript Base Type Extensions
41
The ASP.NET AJAX client-side framework also adds two new methods named trimEnd and trimStart
that respectively remove only the trailing and leading white space from the specified string.
Formatting
The ASP.NET AJAX client-side framework extends the String JavaScript type to add support for
two formatting methods named
format and localeFormat , which use the invariant and current
culture to format the specified string, respectively. The first argument of these two methods contains the
formatting string, very similar to the .NET formatting strings. Here is an example of both methods:
<%@ Page Language = “C#” %>
<html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “JavaScript” type = “text/javascript”>

function pageLoad() {
var a = 5, b = 8;
var str = String.format(“a = {0}\nb = {1}”, a, b);
alert(str);
}
</script>
</head>
<body>

<form id = “form1” runat = “server”>
<asp:ScriptManager ID = “ScriptManager1” runat = “server” />
</form>
</body>
</html>
ASP . NET AJAX Error Type Extensions
One of the highly recommended programming practices is to wrap critical parts of the code in a

try-catch-finally block to trap and handle runtime exceptions. The .NET Framework includes a
set of convenient exception classes such as
ArgumentException , ArgumentNullException , and
ArgumentOutOfRangeException for server-side exception programming. The ASP.NET AJAX Error
type extensions extend the functionality of the JavaScript
Error type to add support for similar
.NET-like exception programming facilities on the client side.
create
The create function is a new static function of the JavaScript Error type that allows you to create a new

Error object with additional error information. This function takes two arguments. The first argument is
the error message. The second argument is an optional object with properties that provide more informa-
tion about the error. This object must contain a property named
name that uniquely identifies the error
type. The rest of the properties can have any name and values that make sense to your application. For
example, you may want to assign a unique integer number to each error type.
c02.indd 41c02.indd 41 8/20/07 5:42:31 PM8/20/07 5:42:31 PM
Chapter 2: JavaScript Base Type Extensions
42
The following page code presents an example where the create function is used:
<%@ Page Language = “C#” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”

“ /><html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “javascript” type = “text/javascript”>
function validateInput(input)
{
var reg = new RegExp(“(\\d\\d)[-/](\\d\\d)[-/](\\d\\d(?:\\d\\d)?)”);
var date = reg.exec(input);
if (date == null)
{
var err = Error.create(“Please enter a valid date!”,
{name : “MyError”, errorNumber : 234});
throw err;
}
}

function clickCallback()
{
var date = document.getElementById(“date”);
try
{
validateInput(date.value);
}
catch (e)
{
alert(“Error Message: “ + e.message +
“\nError Number: “ + e.errorNumber);
date.value = “”;
}
}


</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager runat = “server” ID = “ScriptManager1” />
Enter date: <input type = “text” id = “date” />&nbsp;
<input type = “button” value = “Validate” onclick = “clickCallback()” />
</form>
</body>
</html>
Figure 2-3 shows what you’ll see in your browser when you access this page.
c02.indd 42c02.indd 42 8/20/07 5:42:32 PM8/20/07 5:42:32 PM
Chapter 2: JavaScript Base Type Extensions
43
As you can see, this is a simple page that consists of a text box and a button. When you enter a date in
the text box and click the button, the
clickCallback function is invoked as follows:
function clickCallback()
{
var date = document.getElementById(“date”);
try
{
validateInput(date.value);
}

catch (e)
{
alert(“Error Message: “ + e.message +
“\nError Number: “ + e.errorNumber);
date.value = “”;

}
}
This function first accesses the text box element, like this:
var date = document.getElementById(“date”);
Notice that the clickCallback function wraps the call to a function named validateInput in a try
block and catches the exceptions that the
validateInput function raises in the associated catch block.
As the name implies, the
validateInput function validates the value you entered in the textbox. For
example:
function validateInput(input)
{
var reg = new RegExp(“(\\d\\d)[-/](\\d\\d)[-/](\\d\\d(?:\\d\\d)?)”);
var date = reg.exec(input);
if (date == null)
{
var err = Error.create(“Please enter a valid date!”,
{name : “MyError”, errorNumber : 234});
throw err;
}
}
Figure 2-3
c02.indd 43c02.indd 43 8/20/07 5:42:32 PM8/20/07 5:42:32 PM
Chapter 2: JavaScript Base Type Extensions
44
This function first creates a RegExp JavaScript object, passing in the regular expression pattern that
specifies the valid date formats:
var reg = new RegExp(“(\\d\\d)[-/](\\d\\d)[-/](\\d\\d(?:\\d\\d)?)”);
The validateInput function then calls the exec method on the RegExp object to execute the regular
expression passing in the date you entered in the text box:

var date = reg.exec(input);
If the entered value does not match a valid date format specified in the regular expression pattern, the

exec function returns null, and consequently the validateInput function calls the create static
method of the
Error class to create a new Error object:
var err = Error.create(“Please enter a valid date!”,
{name : “MyError”, errorNumber : 234});
Finally, the validateInput function throws the exception:
throw err;
As discussed earlier, the clickCallback function catches this error in its catch block and calls the

alert function to display the values of the message and errorNumber properties of the error object, as
shown in the following code. Recall that the
errorNumber property was defined in the validateInput
function when the create function was called.
catch (e)
{
alert(“Error Message: “ + e.message +
“\nError Number: “ + e.errorNumber);
date.value = “”;
}
Now take a look at the internal implementation of the create function as shown in the following code
fragment:
Error.create = function(d, b)
{
var a = new Error(d);
a.message = d;
if(b)
for(var c in b)

a[c] = b[c];
a.popStackFrame();
return a
};
As this code shows, the create function creates a new Error object, passing in its first argument:
var a = new Error(d);
c02.indd 44c02.indd 44 8/20/07 5:42:32 PM8/20/07 5:42:32 PM
Chapter 2: JavaScript Base Type Extensions
45
Next, it assigns the properties of the object or array passed in as its second argument to the newly
created
Error object:
for(var c in b)
a[c] = b[c];
Finally, it calls the popStackFrame function, which will be thoroughly discussed in the next section.
pop StackFrame
The JavaScript Error type features two properties named fileName and lineNumber . Some browsers
set the values of these properties to respectively specify the URL of the document and the line number in
the document where the error occurred.
These two properties provide great debugging information for developers. Some browsers set these
properties to the URL of the document and the line number in the document where the error was created
as opposed to the URL of the document and the line number in the document where the error occurred.
To help you understand the difference between these two scenarios, let’s revisit the previous example. In
the previous example, the error is created in the
validateInput function, but it occurs in the

clickCallback function at the point where the validateInput function is invoked. To see how this
works, first you need to modify the clickCallback method to add the highlighted code shown in the
following code fragment. The highlighted code simply displays the values of the
fileName and


lineNumber properties.
function clickCallback()
{
var date = document.getElementById(“date”);
try
{
validateInput(date.value);
}
catch (e)
{
alert(“Error Message: “ + e.message +
“\nError Number: “ + e.errorNumber +
“\nDocument: “ + e.fileName +
“\nLine Number: “ + e.lineNumber);
date.value = “”;
}
}
As mentioned in the previous section, the Error.create method contains a call into the popStack-
Frame
method. You want to see the effect of the popStackFrame method, so you also need to comment
out the line of code in the
Error.create method that calls the popStackFrame method. This means
that you need to use the following implementation instead of the standard implementation.
c02.indd 45c02.indd 45 8/20/07 5:42:33 PM8/20/07 5:42:33 PM
Chapter 2: JavaScript Base Type Extensions
46
To distinguish between the Error.create standard method and the following version, give your
version a different name,
MyErrorCreate :

Function MyErrorCreate(d, b)
{
var a = new Error(d);
a.message = d;
if(b)
for(var c in b)
a[c] = b[c];
//a.popStackFrame();
return a
};
The following code presents a new version of the previous example, which uses your own

MyErrorCreate method:
<%@ Page Language = “C#” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“ /><html xmlns = “ /><head id = “Head1” runat = “server”>
<title>Untitled Page</title>
<script language = “javascript” type = “text/javascript”>
function MyErrorCreate(d, b)
{
var a = new Error(d);
a.message = d;
if(b)
for(var c in b)
a[c] = b[c];
//a.popStackFrame();
return a
};

function validateInput(input)

{
var reg = new RegExp(“(\\d\\d)[-/](\\d\\d)[-/](\\d\\d(?:\\d\\d)?)”);
var date = reg.exec(input);
if (date == null)
{
var err = MyErrorCreate(“Please enter a valid date!”,
{name : “MyError”, errorNumber : 234});
throw err;
}
}

function clickCallback()
{
var date = document.getElementById(“date”);
try
{
validateInput(date.value);
c02.indd 46c02.indd 46 8/20/07 5:42:33 PM8/20/07 5:42:33 PM
Chapter 2: JavaScript Base Type Extensions
47
}
catch (e)
{
alert(“Error Message: “ + e.message +
“\nError Number: “ + e.errorNumber +
“\nDocument: “ + e.fileName +
“\nLine Number: “ + e.lineNumber);
date.value = “”;
}
}


</script>
</head>
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager runat = “server” ID = “ScriptManager1” />
Enter date: <input type = “text” id = “date” />&nbsp;
<input type = “button” value = “Validate” onclick = “clickCallback()” />
</form>
</body>
</html>
Next, you need to run this example in a browser such as Mozilla Firefox that supports the fileName and

lineNumber properties. If you run this example in Mozilla Firefox and enter an invalid value in the text
box, you’ll get the pop-up message shown in Figure 2-4 .
Figure 2-4
According to this message, the error occurred in line number 10. Select the Page Source option from the
browser’s View menu to view the page source. As the page source shows, the line number 10 is the code
line highlighted in the following code fragment:
function MyErrorCreate(d, b)
{
var a = new Error(d);
a.message = d;
if(b)
for(var c in b)
a[c] = b[c];
//a.popStackFrame();
return a
};
c02.indd 47c02.indd 47 8/20/07 5:42:33 PM8/20/07 5:42:33 PM

Chapter 2: JavaScript Base Type Extensions
48
In other words, according the pop-up message shown in Figure 2-4 , the error occurred where the Error
object was created. This isn’t right because the error occurred where the
MyErrorCreate function was
actually called, as shown in the highlighted portion of the following code:
function validateInput(input)
{
var reg = new RegExp(“(\\d\\d)[-/](\\d\\d)[-/](\\d\\d(?:\\d\\d)?)”);
var date = reg.exec(input);
if (date == null)
{
var err = MyErrorCreate(“Please enter a valid date!”,
{name : “MyError”, errorNumber : 234});
throw err;
}
}
As this example shows, browsers such as Mozilla Firefox set the fileName and lineNumber properties
of the
Error object to the URL of the document and the line in the document where the Error object
was created.
To correct this misbehavior of browsers such as Mozilla Firefox, the ASP.NET AJAX client-side
framework extends the functionality of the JavaScript
Error type to add support for a function named

popStackFrame . To illustrate how this function works, uncomment the line of code in MyErrorCreate
that invokes
popStackFrame . Now if you run the example again, you’ll get the pop-up message shown
in Figure 2-5 .
Figure 2-5

According to this message, the error occurred at line 26. Now if you view the page source again, you’ll
notice that line 26 contains the highlighted code shown in the previous code listing. In other words,
thanks to the
popStackFrame function, the pop-up message reports that the error occurred where the

MyCreateError method (which is the Error.create method) was actually called.
Under the Hood of pop StackFrame
You may be wondering how the popStackFrame function manages to fix this problem. To answer this
question, first you need to understand an important property of the JavaScript
Error object named

stack , which is a string that contains a list of substrings separated by “\n” , where each substring con-
tains the information about a particular stack frame. Each stack frame corresponds to a particular func-
tion call. To help you understand what an error stack and a stack frame are, run the page shown in
Listing 2-4 .
c02.indd 48c02.indd 48 8/20/07 5:42:34 PM8/20/07 5:42:34 PM
Chapter 2: JavaScript Base Type Extensions
49
Listing 2-4: A Web Page that Displays an Error Stack
<%@ Page Language = “C#” %>

<!DOCTYPE html PUBLIC
“-//W3C//DTD XHTML 1.0 Transitional//EN”
“ /><html xmlns = “ /><head runat = “server”>
<title>Untitled Page</title>
<script language = “javascript” type = “text/javascript”>
function getStack(err)
{
var a = err.stack.split(“\n”);
Array.forEach(a, function(item, i, array)

{
array[i] = String.format(“a[{0}] = {1}”, i, item);
});
alert(a.join(“\n”));
}

function validateInput(input)
{
var reg = new RegExp(“(\\d\\d)[-/](\\d\\d)[-/](\\d\\d(?:\\d\\d)?)”);
var date = reg.exec(input);
if (date == null)
{
var err = Error.create(“Please enter a valid date!”,
{name : “MyError”, errorNumber : 234});
getStack(e);
err.popStackFrame();
throw err;
}
}

function clickCallback()
{
var date = document.getElementById(“date”);
try
{
validateInput(date.value);
}
catch (e)
{
getStack(err);

date.value = “”;
}
}

</script>
</head>
(continued)
c02.indd 49c02.indd 49 8/20/07 5:42:34 PM8/20/07 5:42:34 PM
Chapter 2: JavaScript Base Type Extensions
50
Listing 2-4 (continued)
<body>
<form id = “form1” runat = “server”>
<asp:ScriptManager runat = “server” ID = “ScriptManager1” />
Enter date: <input type = “text” id = “date” />&nbsp; <input type = “button”
value = “Validate” onclick = “clickCallback()” />
<br /><span id = “span1”></span>
</form>
</body>
</html>
As the first boldfaced portion of Listing 2-4 shows, this page takes these steps:
1. It splits the stack string into its constituent substrings, where each substring represents a stack
frame:
var a = err.stack.split(“\n”);
2. It iterates through the substrings, or stack frames, to display each stack frame on a single line in
the pop-up message shown in Figure 2-6 .
Figure 2-6
As Figure 2-6 shows, this error stack consists of three main stack frames, where each frame represents a
particular function call. For example, the first stack frame represents the call to the
validateInput

function. Also note that each stack frame consists of two main parts, separated by the
@ character, where
the first part is the function call. The second part itself consists of two parts separated by a colon (
: ),
where the first part is the URL of the document that contains the function and the second part is the line
number in the document.
Figure 2-6 displays the contents of the stack before the call into the
popStackFrame function. The second
boldfaced portion of Listing 2-4 displays the contents of the stack after the call into the
popStackFrame
function, as shown in Figure 2-7 . Comparing Figures 2-6 and 2-7 clearly shows that the
popStackFrame
function removes the stack frame that represents the call into the
validateInput function. In other
words, the new stack now reports line 31 of the
clickCallback function as the place where the error
occurred as opposed to the line 15 of the
validateInput function where the error object was created.
c02.indd 50c02.indd 50 8/20/07 5:42:34 PM8/20/07 5:42:34 PM
Chapter 2: JavaScript Base Type Extensions
51
Now let’s look at the internal implementation of the popStackFrame function to see how this function
removes the previously mentioned stack frame. Listing 2-5 presents the internal implementation of the

popStackFrame function.
Listing 2-5: The Internal Implementation of the popStackFrame Function
Error.prototype.popStackFrame = function()
{
if(typeof this.stack === “undefined” || this.stack === null ||
typeof this.fileName === “undefined” || this.fileName === null ||

typeof this.lineNumber === “undefined” || this.lineNumber === null)
return;
var a = this.stack.split(“\n”),
c = a[0],
e = this.fileName + “:” + this.lineNumber;
while(typeof c !== “undefined” && c !== null && c.indexOf(e) === - 1)
{
a.shift();
c = a[0]
}
var d = a[1];
if(typeof d === “undefined” || d === null)
return;
var b = d.match(/@(.*):(\d+)$/);
if(typeof b === “undefined” || b === null)
return;
this.fileName = b[1];
this.lineNumber = parseInt(b[2]);
a.shift();
this.stack = a.join(“\n”)
};
The popStackFrame function first splits the stack string into its constituent substrings as expected
(remember that each substring represents a stack frame):
var a = this.stack.split(“\n”)
Figure 2-7
c02.indd 51c02.indd 51 8/20/07 5:42:35 PM8/20/07 5:42:35 PM

×