- In an internet driven environment, it is imperative for a company to keep its product or business to the forefront of potential customers' minds. The ...
- A successful enterprise is all about constantly reinventing ways to work more efficiently. In today’s techno age, this translates to testing new too...
- The IT industry plays a pivotal role in providing application development solutions and custom software development to a wide range of industries, i...
- Royal Victorian Eye and Ear Hospital, 2010 Atcomm has been contracted to implement a complex IOP glaucoma management tool which will be distribut...
- We are pleased to announce another implementation of a CMS system for a large Melbourne based fitness center - Star Plate Studio. Atcomm has depl...
The Microsoft Client Library for AJAX
-
font size
decrease font size
increase font size
Overview
Most of the power of AJAX resides on the client and is strictly related to the browser’s and platform’s client-side functionality. Even though a large share of AJAX pages are built using a slightly different set of server controls, they couldn’t work without a powerful environment available on the client and written in JavaScript. Such a script code governs the execution of out-of-band calls and often kicks in and replaces regular postbacks with AJAX postbacks. No AJAX functionality would ever be possible without JavaScript and a standard (and rich) Document Object Model (DOM). The DOM, though, is not enough.
The DOM represents the programming gateway to the page constituent elements, but it is not designed to provide programming facilities such as those you can find in a general-purpose library. Normally, the script tools you can leverage to consume objects and contents from the DOM are those provided by the JavaScript language. Not exactly a powerful toolkit. Enter the Microsoft AJAX Library.
The Microsoft AJAX library is written in JavaScript, although with a strong sense of objectorientation. The JavaScript language does support objects and allow the creation of custom objects. It does not, however, support full object-orientedness since it has no native concept of true object inheritance. Nonetheless, even excluding true object-orientation, JavaScript is still a modern and suitable language that can be used to build a class framework a la the .NET Framework. ASP.NET AJAX takes the JavaScript language to the next level by adding some type-system extensions and the notions of namespace and inheritance. In addition, the ASP.NET AJAX JavaScript supports interfaces and enumerations, and has a number of helper functions to manipulate strings and arrays.
These extensions are coded using the base set of instructions that characterize the core JavaScript language, and they’re persisted to the .js files that form the Microsoft AJAX client runtime environment.
In this chapter, you’ll first learn how to use extensions to JavaScript-such as namespaces, interfaces, and inheritance-and then take the plunge into the namespaces and classes that form the client-side AJAX framework.
JavaScript Language Extensions
Writing a rich and complex framework such as ASP.NET AJAX using only plain old JavaScript is probably beyond human capabilities. On the other hand, using another language would pose serious browser-compatibility issues and eliminate the main reason behind the today’s success of the AJAX paradigm-its broad reach.
Infrastructure for Extensions
The Microsoft AJAX library adds a strong focus on typing to the JavaScript language. Top-level types such as array, Boolean, string, and number are encapsulated in classes and forced into a hierarchical structure that mirrors-to the extent that it is possible-the true .NET Framework. The Microsoft AJAX library exposes a class-oriented type system to the outside world that supports namespaces, inheritance, interfaces, enumerations, reflection, and a good deal of helper methods for strings, arrays, and other base types.
All together, these extensions enable you to code ASP.NET AJAX client functionalities in a more structured way and thereby improve maintenance, extensibility, and ease of development.
The Microsoft AJAX Library Engine
The library is made of a few .js files downloaded to the client browser on demand. At a minimum, the core runtime script file is downloaded. All script files are incorporated as resources in the ASP.NET AJAX assembly-the System.Web.Extensions.dll file-and are extracted and injected in the client page as required by the page itself.
Adding the Microsoft AJAX library to a Web application makes JavaScript programming easier, and it automatically endows the client environment with a set of new and richer objects and object-oriented capabilities.
| Note |
Although the Microsoft AJAX library ships as part of ASP.NET AJAX Extensions, nothing prevents you from using those .js files in non–ASP.NET 2.0 applications. In particular, you are encouraged to download the JavaScript files from the ASP.NET AJAX Web site and link them from, say, a PHP or ASP.NET 1.1 application, obtaining the same pleasant effect-object-oriented features from a script language. You get the files under the Microsoft permissive license agreement and are allowed to use and modify these scripts in your own applications. Find them at http://ajax.asp.net/downloads/default.aspx. |
The Root Object of the Microsoft AJAX Library
Overall, JavaScript is an object-based language. (It’s not truly object-oriented because it doesn’t implement some of the required object-oriented concepts, such as true object inheritance.) The language features a set of built-in objects, including Function, Object, Boolean, Array, Number, and String. All intrinsic objects have a read-only property named prototype. You use the prototype property to provide a base set of functionality shared by any new instance of an object of that class. New functionality can be added to the class prototype inside of an application to extend and improve the capabilities of a given class. This is exactly what the Microsoft AJAX library does.
In the library (precisely, in the MicrosoftAjax.js file), all built-in JavaScript objects feature a richer prototype and incorporate new capabilities. For example, the library extends the JavaScript Function object with a set of methods to provide for delegates and callbacks. Here’s a brief snippet from (the debug version of) MicrosoftAjax.js that illustrates the point:
// Set the type name
Function.__typeName = 'Function';
// Define a callback
Function.createCallback = function Function$createCallback(method, context)
{
var e = Function._validateParams(...);
if (e) throw e;
return function() {
var l = arguments.length;
if (l > 0) {
var args = [];
for (var i = 0; i < l; i++) {
args[i] = arguments[i];
}
args[l] = context;
return method.apply(this, args);
}
return method.call(this, context);
}
}
// Define a delegate (function pointer)
Function.createDelegate = function Function$createDelegate(
instance, method)
{
var e = Function._validateParams(...);
if (e) throw e;
return function() {
return method.apply(instance, arguments);
}
}
The Function type is then associated with the Type property on the window object in the browser DOM:
window.Type = Function;
The window object is the top-level object in the JavaScript hierarchy and represents a browser window. The browser creates one window object when it opens an HTML page and additional window objects for each frame it encounters. You can access all window members by using the member name directly-that is, without prefixing it with a name that evaluates to the current window object. The window object features a number of predefined members, including the popular alert method and event object; in addition, new dynamic members can be defined on the fly.
The native Function object, referred through the nickname of Type, is extended with a number of object-oriented methods. This is accomplished by extending the prototype property that characterizes any JavaScript object. The following code shows how to add the getName method to all Microsoft AJAX library objects:
Type.prototype.getName = function Type$getName()
{
if (arguments.length !== 0)
throw Error.parameterCount();
return (typeof(this.__typeName) === "undefined")
? "" : this.__typeName;
}
In this way, you can ask each JavaScript object to qualify itself in a reliable and precise way. In MicrosoftAjax.js, the Function object works in a way that resembles the following pseudo-class:
public class Function
{
public static Object createCallback(Object method, Object context);
public static Object createDelegate(Object instance, Object method);
public static Object emptyFunction();
public static Object emptyMethod();
public static Object getRootNamespaces();
public static Object isClass(Object type);
public static Object isEnum(Object type);
public static Object isFlags(Object type);
public static Object isInterface(Object type);
public static Object isNamespace(Object object);
public static Object parse(Object typeName, Object ns);
public static Object registerNamespace(Object namespacePath);
public Object callBaseMethod(Object instance, Object name, Object args);
public Object getBaseMethod(Object instance, Object name);
public Object getBaseType();
public Object getInterfaces();
public Object getName();
public Object implementsInterface(Object interfaceType);
public Object inheritsFrom(Object parentType);
public Object initializeBase(Object instance, Object baseArguments);
public Object isImplementedBy(Object instance);
public Object isInstanceOfType(Object instance);
public Object registerClass(Object type, Object base, Object interface);
public Object registerEnum(Object name, Object flags);
public Object registerInterface(Object typeName);
public Object resolveInheritance();
}
All methods added to the prototype will be “inherited” by any other function defined in the context of any library-powered application.
Other Top-Level Types
The Microsoft AJAX library contains code that defines new objects and extends existing JavaScript objects with additional functionality. Table 2-1 lists the main global objects defined in the library.

By simply adding a ScriptManager server control to an ASP.NET page, you gain the right to use any additional methods on native objects that are defined in the Microsoft AJAX library. For example, the following code will work just fine if you add such a control:
var s = "Dino";
alert(s.startsWith('D'));
The native JavaScript String object doesn’t feature either a startsWith or an endsWith method. However, the following code in Microsoft Client library does the trick:
String.prototype.endsWith = function String$endsWith(suffix)
{
var e = Function._validateParams(...);
if (e) throw e;
return (this.substr(this.length - suffix.length) === suffix);
}
String.prototype.startsWith = function String$startsWith(prefix)
{
var e = Function._validateParams(...);
if (e) throw e;
return (this.substr(0, prefix.length) === prefix);
}
Discovering Type Information
JavaScript objects are not truly strongly-typed objects. In particular, there’s no fully reliable mechanism to know the type of the object you’re working with. The toString method and the typeof operator help only partially. The former is designed to provide a string representation of the object, so it merely returns the contents of the object for strings and numbers. The latter always returns object regardless of the name of the custom object you’re manipulating. Consider a class IntroAjax.Person defined as shown here:
Type.registerNamespace("IntroAjax");
// Constructor
IntroAjax.Person = function IntroAjax$Person(firstName, lastName)
{
IntroAjax.Person.initializeBase(this);
this._firstName = firstName;
this._lastName = lastName;
}
// Add a FirstName property to the class prototype
IntroAjax.Person.prototype.get_FirstName =
function IntroAjax$Person$get_FirstName() {
// Raise an error if the number of arguments doesn't match
if (arguments.length !== 0)
throw Error.parameterCount ();
return this._firstName;
}
IntroAjax.Person.prototype.set_FirstName =
function IntroAjax$Person$set_FirstName(value) {
// Automatic arguments validation
var e = Function._validateParams(arguments,
[{name: "value", type: String}]);
if (e)
throw e;
this._firstName = value;
}
// Add a LastName property to the class prototype
IntroAjax.Person.prototype.get_LastName =
function IntroAjax$Person$get_LastName() {
if (arguments.length !== 0)
throw Error.parameterCount();
return this._lastName;
}
IntroAjax.Person.prototype.set_LastName =
function IntroAjax$Person$set_LastName(value) {
var e = Function._validateParams(arguments,
[{name: "value", type: String}]);
if (e)
throw e;
this._lastName = value;
}
IntroAjax.Person.registerClass('IntroAjax.Person');
Imagine that you now create an instance of this class and then need to know about its exact type. A new method added to the Object object provides for exact type recognition. The method to use is Object.getTypeName:
var p = new Person("Dino", "Esposito");
alert(Object.getTypeName(p));
The message box now shows IntroAjax.Person instead of a more generic “object” string. It’s interesting to take a look at the source code of the getTypeName method:
Object.getTypeName = function Object$getTypeName(instance)
{
var e = Function._validateParams( ... );
if (e) throw e;
return Object.getType(instance).getName();
}
Object.getType = function Object$getType(instance)
{
var e = Function._validateParams( ... );
if (e) throw e;
var ctor = instance.constructor;
if (!ctor || (typeof(ctor) !== "function") ||
!ctor.__typeName || (ctor.__typeName === 'Object'))
{
return Object;
}
return ctor;
}
In the end, the getName method on the root Type object is used to resolve the type name. (As mentioned earlier, Type is a global window object that evaluates to the JavaScript Function object.)
Type.prototype.getName = function Type$getName()
{
if (arguments.length !== 0)
throw Error.parameterCount();
return (typeof(this.__typeName) === "undefined")
? "" : this.__typeName;
}
As you can see, the getName method simply returns the value of an internal variable. It turns out that each new object sets the _typeName variable to the string that represents the class name. For example, in the Microsoft AJAX library the type name of the Object class is explicitly set to the string “Object”:
Object._typeName = 'Object';
All built-in JavaScript objects are modified in the Microsoft AJAX library to feature an additional type name property.
| Note |
JavaScript clearly has a number of useful similarities with C-like languages such as C# and Java. Yet it is a script language with a number of shortcuts and special extensions. One is the === (triple =) operator; another is its opposite, the !== operator. The === operator is a variation of the classic == (is-equal-to) operator and checks for both value and type, whereas the classic equality operator is limited to checking values. As an example, consider the following code snippet: var x = 1; var y = "1"; If you compare x == y, you get true-the same value. If you compare x === y, you get false-the same value, but not the same type. |
The bottom line is that the Microsoft AJAX library builds a thick abstraction layer on top of the core JavaScript native objects that transforms a script language in a sort of object-oriented script framework. If you forget for a while about most common JavaScript concepts and syntax elements you know and think of it as a brand new language, you could easily envision the library as a shrink-wrapped version of the .NET Framework and the ASP.NET AJAX JavaScript language as simplified C#.
| Note |
You might have noticed that JavaScript functions used to implement methods on objects are named rather than being plain anonymous functions. This approach is a change in the Microsoft AJAX library that occurred with the Beta stage of ASP.NET AJAX, and it’s also a technique that is not that common among JavaScript writers. In the Microsoft AJAX library, functions are pseudo-named so that you get additional information, such as obtaining context within a stack trace. This change will help Visual Studio “Orcas” to do a great job with debugging and Microsoft IntelliSense. |
Reflection Capabilities
Earlier in the chapter, I showed a pseudoclass named Function to represent the real capabilities of the JavaScript Function type in the Microsoft AJAX library. Table 2-2 provides more information regarding what most of those methods really do. All methods in the table are invoked on library classes to help you discover type information and manage it dynamically. Static methods are invoked from the Type object directly.
.gif)
The $get Alias
Before we take a look at more juicy object-oriented extensions such as namespaces and inheritance, let’s discuss a few shortcuts you can use in your script code to speed up development.
One of the most common mistakes that occurs when writing script code inside of Web pages is to use direct access to HTML elements instead of resorting to the getElementById method of the DOM. Suppose you have a text box element named TextBox1 in your client page. The following script code won’t work on all browsers:
alert(TextBox1.value);
The correct form ratified by the W3C paper for the HTML DOM standards is shown here:
alert(document.getElementById("TextBox1").value);
The correct form is clearly more verbose and bothersome to write over and over again. Microsoft Client library comes to the rescue with the $get global function. Simply put, the $get function is a shortcut for the document.getElementById function. In an ASP.NET AJAX page, the following expression is fully equivalent to the one just shown:
alert($get("TextBox1").value);
More precisely, the $get function is an alias for a piece of code defined as follows:
var $get = Sys.UI.DomElement.getElementById = function
Sys$UI$DomElement$getElementById(id, element)
{
var e = Function._validateParams( ... );
if (e) throw e;
if (!element)
return document.getElementById(id);
if (element.getElementById)
return element.getElementById(id);
var nodeQueue = [];
var childNodes = element.childNodes;
for (var i = 0; i < childNodes.length; i++)
{
var node = childNodes[i];
if (node.nodeType == 1)
nodeQueue[nodeQueue.length] = node;
}
while (nodeQueue.length) {
node = nodeQueue.shift();
if (node.id == id) {
return node;
}
childNodes = node.childNodes;
for (i = 0; i < childNodes.length; i++) {
node = childNodes[i];
if (node.nodeType == 1) {
nodeQueue[nodeQueue.length] = node;
}
}
}
return null;
}
If you simply call $get passing the sole ID, the function falls back into document.getElementById. Alternatively, you can specify a root element. If this element supports the getElementById method, the function returns the output of element.getElementById; otherwise, the $get function uses the DOM interface to explore the contents of the subtree rooted in the element to locate the node with the given name.
| Note |
Before the Beta stage, ASP.NET AJAX defined a global alias named $ that mapped to the document.getElementById function. The $ alias has been changed to $get to avoid conflicts with other AJAX frameworks developers might use along with ASP.NET AJAX. |
Similar shortcuts exist also to look up components in the runtime hierarchy and to create them and add and remove event handlers. We’ll return to this point later in the chapter as we make our way through the library components.
Closures vs. Prototypes
When it comes to JavaScript classes (more exactly, pseudoclasses), there are mainly two models to use when creating them. One is known as a closure; one is based on the prototype. In early builds of the Microsoft AJAX library, the ASP.NET team used the closure model. They switched to the prototype model in the Beta stage.
A closure is a general concept of programming languages. When applied to JavaScript, it can be summarized as follows: A closure is a JavaScript function that can have variables and methods defined together within the same context. In this way, the outermost (anonymous or named) function “closes” the expression. Here’s an example of the closure model for a function that represents a Person type with two properties:
registerNamespace("IntroAjax");
// Closure: Constructor and members
IntroAjax.Person = function()
{
var _firstName;
var _lastName;
this.get_FirstName = function() { return this._firstName; }
this.get_LastName = function() { return this._lastName; }
}
IntroAjax.Person.registerClass('IntroAjax.Person');
As you can see, the closure is nothing more than the constructor of the class. Again, JavaScript classes are not classes in the sense understood in the .NET Framework, but we’ll refer to them as classes for convenience.
In a closure model, the constructor contains the member declarations and members are truly encapsulated and private to the class. In addition, members are instance based, which increases the memory used by the class.
The prototype model entails that you define the “public” structure of the class through the JavaScript prototype object. The following code sample shows how to rewrite the preceding Person class to avoid a closure. The resulting code is nearly identical to the code presented earlier for the IntroAjax.Person class-that is, the recommended way to write classes in the Microsoft AJAX library.
registerNamespace("IntroAjax");
// Prototype: Constructor
IntroAjax.Person = function()
{
// Ctor creates private fields
this._firstName = "";
this._lastName = "";
}
// Prototype: Members
IntroAjax.Person.prototype.get_FirstName = function() {
return this._firstName;
}
IntroAjax.Person.prototype.get_LastName = function() {
return this._lastName;
}
IntroAjax.Person.registerClass("IntroAjax.Person");
In the prototype model, the constructor and members are clearly separated and a constructor is always required. As for private members, the Microsoft AJAX library convention is to name them with a “_” prefix. In the prototype model, members are shared by all instances, which reduces the memory used by each instance and provides for faster object instantiation. Aside from syntax peculiarities, the prototype model makes defining classes much more similar to the classic object-oriented programming (OOP) model than the closure model.
| Note |
The goal of the ASP.NET AJAX team was deliver a model that provided the best quality and performance on the largest number of browsers. Prototypes have a good load time in all browsers; and indeed, they have excellent performance in Firefox. (In contrast, closures have a better load time than prototypes in Internet Explorer.) Prototypes provide better support for IntelliSense, and allow for tool-based statement completion when used in tools that support this feature, such as Visual Studio “Orcas”. Prototypes can also help you obtain type information by simply using reflection. You won’t have to create an instance of the type in order to query for type information, which is unavoidable if closures are used. Finally, prototypes allow you to easily view private class members when debugging. Debugging objects derived using the closure model requires a number of additional steps. |
If you’re simply going to write client script that uses built-in classes in the library, you don’t need to learn about closures and prototypes. If you happen to write a custom JavaScript class to extend the Microsoft AJAX library, you should use the prototype model.
| Note |
If you want to learn more about JavaScript closures, go to the following URL: http:// www.jibbering.com/faq/faq_notes/closures.html. |
Object-Oriented Extensions
In JavaScript, the Function object is the main tool you use to combine code with properties and forge new components. In the Microsoft AJAX library, the Function object is extended to incorporate type information, as well as namespaces, inheritance, interfaces, and enumerations. Let’s see how.
Adding Namespace Support
A namespace provides a way of grouping and classifying types belonging to a library. A namespace is not a type itself, but it adds more information to the definition of each type it contains to better qualify the type. Conceptually, a namespace is related to a directory in much the same way a type is related to a file. The unit of data you work with is ultimately the file, and you identify the file by name. However, files with the same name defined in different directories appear as completely distinct entities to any programming environment.
By default, all custom JavaScript functions belong to the global space of names. In the Microsoft AJAX library, you can associate a custom function with a particular namespace for purely organizational reasons. When declaring a custom type in the Microsoft AJAX library, you can do as follows:
Type.registerNamespace("IntroAjax");
IntroAjax.Person = function IntroAjax$Person(firstName, lastName)
{
this._firstName = firstName;
this._lastName = lastName;
}
// Define the body of members
function IntroAjax$Person$ToString() {
return this._lastName + ", " + this._firstName;
}
...
// Define the prototype of the class
IntroAjax.Person.prototype = {
ToString: IntroAjax$Person$ToString,
get_FirstName: IntroAjax$Person$get_FirstName,
set_FirstName: IntroAjax$Person$set_FirstName,
get_LastName: IntroAjax$Person$get_LastName,
set_LastName: IntroAjax$Person$set_LastName
}
// Register the class
IntroAjax.Person.registerClass("IntroAjax.Person");
The Type.registerNamespace method adds the specified namespace to the runtime environment. In a way, the registerNamespace method is equivalent to using the namespace {…} construct in C# or the Namespace .. End Namespace construct in Microsoft Visual Basic .NET.
| Note |
Because the Microsoft AJAX library expresses the capabilities of a runtime framework rather than the syntax of a programming language, the correspondence between Type.registerNamespace and a C# or Visual Basic .NET language construct is purely logical. Internally, Type.registerNamespace is limited to adding information to the current DOM to track the current namespace. |
The IntroAjax.Person function defined following the namespace declaration describes a type Person in the IntroAjax namespace. Finally, the newly defined function must be registered as a class with the Microsoft AJAX library framework. You use the registerClass method on the current function. The registerClass method is defined in the prototype of the Function object; as such, it is inherited by all functions. Internally, the registerClass method sets the _typeName property of the function to the first parameter of the method-the actual name of the class.
The registerClass method takes a number of parameters. The first parameter is mandatory, and it indicates the public name that will be used to expose the JavaScript function as a class. Additional and optional parameters are the parent class if there is any and any interface implemented by the class.
As mentioned, in the definition of a new class, you can use an anonymous function or a named function. In terms of syntax, both solutions are acceptable. The convention, though, is that you opt for named functions and name each function after its fully qualified name, replacing the dot symbol (.) with a dollar symbol ($).
Adding Inheritance Support
Let’s define a new class Citizen that extends Person by adding a couple of properties: address and a national identification number. Here’s the skeleton of the code you need:
// Declare the class
IntroAjax.Citizen = function IntroAjax$Citizen(firstName, lastName, id)
{
...
}
// Define the prototype of the class
IntroAjax.Citizen.prototype = {
...
}
// Register the class
IntroAjax.Citizen.registerClass("IntroAjax.Citizen", IntroAjax.Person);
Note that the first argument of registerClass is a string, but the second one has to be an object reference. Let’s flesh out this code a bit.
In the constructor, you’ll set some private members and call the base constructor to initialize the members defined on the base class. The initializeBase method (defined on Function) retrieves and invokes the base constructor.
IntroAjax.Citizen = function IntroAjax$Citizen(firstName, lastName, id)
{
IntroAjax.Citizen.initializeBase(this, [firstName, lastName]);
this._id = id;
this._address = "";
}
You pass initializeBase the reference to the current object as well as an array with any parameters that the constructor to call requires. You can use the [...] notation to define an array inline. If you omit the [...] notation, be ready to handle a parameter count exception.
Quite often, developers derive a class because they need to add new members or alter the behavior of an existing method or property. Object-oriented languages define a proper keyword to flag members as overridable. How is that possible in JavaScript? By simply adding a member to the class prototype, you mark it as overridable in derived classes. In addition, if the member already exists on the base class, it is silently overridden in the new one. Here’s the prototype of the Citizen class:
IntroAjax.Citizen.prototype =
{
ToString: IntroAjax$Citizen$ToString,
get_ID: IntroAjax$Citizen$get_ID,
get_Address: IntroAjax$Citizen$get_Address,
set_Address: IntroAjax$Citizen$set_Address
}
The class has a read-only ID property and a read-write Address property. Furthermore, it overrides the ToString method defined in the parent class.
function IntroAjax$Citizen$ToString()
{
var temp = IntroAjax.Citizen.callBaseMethod(this, 'ToString');
temp += " [" + this._id + "]";
return temp;
}
You use callBaseMethod to invoke the same method on the parent class. Defined on the Function class, the callBaseMethod method takes up to three parameters: instance, name of the method, plus an optional array of arguments for the base method.
As mentioned earlier, the ToString method on the Person class returns a LastName, FirstName string. The ToString method on the Citizen class returns a string in the following format: LastName, FirstName [ID].
| Note |
In the prototype model, a derived class has full access to the private members of the parent class. To be precise, in JavaScript the notion of private members is not the same as in classic OOP. As mentioned earlier, in the Microsoft AJAX library private members exist by convention; they’re not enforced by any syntax rules. In other words, the language allows you to access, say, the member _firstName of class Person straight from class Citizen. You should avoid that, though, as base class accessor implementations may provide additional logic over and above simply returning the field value. |
Adding Interface Support
An interface describes a group of related behaviors that are typical of a variety of classes. In general, an interface can include methods, properties, and events; in JavaScript, it contains only methods.
Keeping in mind the constraints of the JavaScript language, to define an interface you create a regular class with a constructor and a prototype. The constructor and each prototyped method, though, will just throw a not-implemented exception. Here’s the code for the sample Sys.IDisposable built-in interface:
Type.registerNamespace("Sys");
Sys.IDisposable = function Sys$IDisposable()
{
throw Error.notImplemented();
}
function Sys$IDisposable$dispose()
{
throw Error.notImplemented();
}
Sys.IDisposable.prototype =
{
dispose: Sys$IDisposable$dispose
}
Sys.IDisposable.registerInterface('Sys.IDisposable');
The following statement registers the Citizen class, makes it derive from Person, and implements the IDisposable interface:
IntroAjax.Citizen.registerClass('IntroAjax.Citizen',
IntroAjax.Person, Sys.IDisposable);
To implement a given interface, a JavaScript class simply provides all methods in the interface and lists the interface while registering the class:
function IntroAjax$Citizen$dispose
{
this._id = "";
this._address = "";
}
IntroAjax.Citizen.prototype =
{
dispose: IntroAjax$Citizen$dispose
...
}
Note, though, that you won’t receive any runtime error if the class that declares to implement a given interface doesn’t really support all the methods.
| Note |
If a class implements multiple interfaces, you simply list all required interfaces in the registerClass method as additional parameters. Here’s an example:
Sys.Component.registerClass('Sys.Component', null,
Sys.IDisposable,
Sys.INotifyPropertyChange,
Sys.INotifyDisposing);
As you can see, in this case you don’t have to group interfaces in an array |
Core Components
The AJAX client library is made up of three main logical layers: JavaScript extensions, core framework classes, and user-interface (UI) framework classes. (See Figure 2-1.)

As mentioned in the previous sections, JavaScript extensions add new methods and capabilities to native JavaScript objects and enable registration methods to simulate object-oriented constructs such as classes, namespaces, inheritance, and interfaces. The UI framework includes base components to define client behaviors, controls, DOM elements, and input devices such as keyboard and mouse buttons. The UI framework also incorporates as private elements classes that provide the client object model for a couple of ASP.NET AJAX server controls, namely Timer and UpdateProgress. We’ll cover these controls in Chapter 4, “Partial Page Rendering.”
The core framework classes form a sort of base library that incorporates a set of commonly used classes for event handling, string manipulation, Web services, debugging, and network operations. As you saw earlier, the Microsoft AJAX library supports namespaces, so classes in the client library belong to a particular namespace. Most classes in the base framework layer of the library belong to the Sys namespace.
In the remainder of this chapter, we’ll take a look at the main functionality implemented in the Microsoft AJAX library, starting with the Application object.
The Sys.Application Object
The execution of each ASP.NET AJAX page is controlled by an application object that is instantiated in the body of the library. The application object is an instance of a private class-the Sys._Application class. As mentioned, JavaScript has no notion of private members; therefore, private members are conventionally indicated by the underscore symbol (_) in their names.
Whenever an ASP.NET AJAX page is loaded in the browser, an instance of the Sys._Application class is promptly created and assigned to the Sys.Application object:
Sys.Application = new Sys._Application();
In addition, each ASP.NET AJAX page is injected with the following script code:
This code is placed immediately after the closing tag of the page’s form, and it commands the loading of any script files registered for loading with the page’s script manager. More details on script loading are unveiled in Chapter 3, “The Pulsing Heart of ASP.NET AJAX.” As a result, the Sys.Application object is the nerve center of the ASP.NET AJAX page.
Generalities of the Sys._Application Class
The Sys._Application class derives from Component and is the entry point in the page hierarchy to locate client-side components either bound to server controls or programmatically added to the application. Table 2-3 lists some of the methods available on the Sys._Application class.

The application object serves two main purposes: providing access to page components, and loading external script files registered with the page script manager. Note that each external script file registered with the script manager needs to place a notifyScriptLoaded call at the bottom of its source to notify the application of success.
Looking Up Components
The findComponent method scrolls the runtime hierarchy of components for the current page until it finds a component with a matching ID. The method has two possible prototypes:
Sys._Application.findComponent(id); Sys._Application.findComponent(id, parent);
The former overload takes the ID of the component and uses it to look up and navigate the hierarchy all the way down from the root. When a non-null parent argument is specified, the search is restricted to the subtree rooted in the context object. The id parameter must be a string; the context parameter must be an Microsoft Client library object. The method returns the object that matches the ID, or it returns null if no such a object is found.
Microsoft Client library also supports a shortcut for retrieving runtime components-the $find method. The $find method is an alias for findComponent.
var $find = Sys.Application.findComponent;
You can use this method to locate all components created by server controls and extenders, as well as by your own JavaScript code and, if supported, by XML-Script declarations.
Events in the Page Lifetime
Table 2-4 lists the events fired by the Sys._Application class. Listeners for these events can be added via script code.

When an ASP.NET AJAX page first loads up, the load event is fired for the client code to perform any required initialization. Note that the event refers to the page lifetime, not the application lifetime. So whenever a classic postback occurs, you receive a new load event. You don’t receive events for any AJAX-style postback. Likewise, the unload event is fired when the page is unloaded.
The load event occurs after an ASP.NET AJAX page has been loaded and initialized completely. For such a page, the load event is preferable to the browser’s onload for initialization purposes. Only when you get the Microsoft AJAX library load event, therefore, can you be sure that the page is ready for user interaction.
The unload event occurs just before the Microsoft AJAX library runtime releases the page and all of its resources. For the sake of the application’s stability, you should use this event instead of the browser’s onunload event for clean-up tasks.
The following code shows how to add handlers to the load and unload events via script:
Sys.Application.add_load(_pageLoadHandler); Sys.Application.add_unload(_pageUnloadHandler);
You add this code to a tag you import in the page. Note that this tag must be placed past the definition of the script manager control, as shown here:
An even easier way to define load and unload handlers is by means of predefined function names: pageLoad and pageUnload. These functions need to be global and parameterless.
Because this piece doesn’t directly call into any of the Microsoft AJAX library objects-including Sys.Application-you can safely place it everywhere, even at the top of the ASP.NET AJAX page.
The Sys.Component Object
Generally, the term component denotes an object that is reusable and can interact with other objects in the context of a framework. The term control, on the other hand, denotes an object that is sort of a specialized component. The main trait that differentiates components and controls is the user interface. Components are non-UI objects; controls are primarily UI-based objects.
In the Microsoft AJAX library, the root component class is Sys.Component. The root class for controls is named Control and, guess what, lives in the Sys.UI namespace. In the Microsoft AJAX library, Sys.UI.Control derives from Sys.Component. Let’s learn more about the common properties of components; we’ll work with controls later in the chapter.
The Sys.Component Class
Derived from the JavaScript native type Object, the Sys.Component class defines a number of properties and events shared by all components. Table 2-5 lists the properties of the Sys.Component class.

The Sys.Component class features an initialize method that is used to start up the component. The base implementation of the method simply sets an internal flag to denote that the component has been initialized. Derived classes can further specialize the method to accomplish additional tasks. Table 2-6 lists the methods of the Sys.Component class.

In addition to the members considered so far, the class fires a couple of events: disposing and propertyChanged. The former event occurs when the component is being disposed of; the latter event occurs when the state of the component is updated. The propertyChanged event is part of the INotifyPropertyChange interface.
Detecting Property Changes
The Sys.Component class features a built-in mechanism to detect ongoing changes to the properties of a component. When this happens, the propertyChanged event is fired. The method raisePropertyChanged on the base class allows derived components to fire the propertyChanged event to notify callers that the value of a given property has been updated. Here’s a sample implementation of a component property:
this.set_MyProperty = function(value) {
_myProperty = value;
this.raisePropertyChanged("MyProperty");
}
Generally, derived components place a call to raisePropertyChanged in the set method of a given property. For a derived component, using the property changes mechanism is optional and not mandatory.
Batched Updates
The Sys.Component class also provides facilities when too many properties are going to be updated at the same time. To minimize screen updates, you can tell the object to perform property updates in a batch. To do so, you group updates in calls to the beginUpdate and endUpdate methods. When a batch update operation is in progress, the value of the isUpdating property is automatically set to true.
Depending on the specific component, batch updates can improve performance and minimize screen updates.
The $create Alias
The $create alias provides a concise syntax for creating an Microsoft AJAX library component. It is mapped to the static method create on the Sys.Component class with the following prototype:
var $create = Sys.Component.create = function Sys$Component$create(
type, properties, events, references, element)
{
...
}
Of all the arguments just shown, only the type argument is mandatory; all others are optional. For example, the following code creates an instance of Samples.UI.Button and assigns it a click event handler, button1_Click, and ties it to the DOM element control sendDataButton:
$create(Samples.UI.Button,
{},
{'click':'button1_Click'},
{}
$get('sendDataButton')
);
The $create method defines the type to create, a list of properties, event handlers, and even an optional DOM element if any exists. The $create alias can also handle scenarios in which components have references to other components. In addition, objects are automatically registered with Sys.Application, thus allowing components to be found through $find.
Component Disposing
The Sys.Component class implements two interfaces that revolve around the disposal of any component instance: the Sys.IDisposable and Sys.INotifyDisposing interfaces. The Sys.Disposable interface features the dispose method; the Sys.INotifyDisposing interface lists the sole disposing event.
Components are required to be disposable so that you can free all of their client resources when used in the context of updatable panels. In addition, you should make sure the dispose method handles being called more than once.
