As detailed in Chapter 2, the prototype property provides limited support for class inheritance in JavaScript. ASP.NET AJAX provides more abstraction. Theprototypemechanism is supported for namespace classes that were registered usingClass name.registerClass(). As a second parameter forregisterClass(), you can specify a base class. Here is where you specify from which class the current class derives.
Derived classes
Let’s create a class that inherits from Software. One very specific type of software is a web browser, so let’s create aBrowser class. In addition to the features of the genericSoftware class, a browser would benefit from some extra properties. AnisJavaScriptSupportedproperty can provide information about whether a particular browser is capable of running JavaScript.
Of course, it would be possible to create getter and setter methods fornameandvendoronce again, and to write the constructor code as well. However, one of the benefits of class inheritance (actually, the major benefit) is that you can reuse functionality. BecauseOReilly.Browserinherits fromOReilly.Software, you can use the getter and setter methods (i.e., the properties) that are already there, as well as the_nameand_vendor“private” members. You do, however, need to add getter and setter methods and private members for the newisJavaScriptSupportedproperty, as shown here:
var _isJavaScriptSupported = (isJavaScriptSupported != null)? isJavaScriptSupported : false;
All that remains is for us to write the constructor. But instead of writing it again from scratch, you can reuse the base class constructor. To do so, ASP.NET AJAX provides theinitializeBase()method. The first parameter is the instance of which the base class will be initialized; usually, you providethisas the value. The second parameter is an array of arguments to be passed to the base constructor (the base constructor defines which arguments it expects). In our case, this array consists of the browser name and vendor.
OReilly.Browser.initializeBase(this, new Array(name, vendor));
You can save a few characters and use JSON to create the array:
When we talk about class inheritance, a logical question is whether methods can be overridden in derived classes. The answer is yes. The next question: is there any way to access the equivalent method of the base class, (i.e., the overridden method)? Even better, the answer is again yes, ASP.NET AJAX allows you to do so. To demonstrate this, let’s add a toString() method to OReilly.Softwarethat outputs the product and vendor names stored by the class. Theprototypeproperty ensures automated inheritance and also helps demonstrate access to the base method later on.
You could also directly access the properties_nameand_vendoras variables. Using the getter methods is just a personal preference. There is no functional difference in doing so.
In theOReilly.Browserclass, you could write a similartoString()method:
However, it is once again advisable to reuse existing code, in this case, the base class’stoString()method. ASP.NET AJAX provides you withcallBaseMethod(), a helper method to call a method from the parent class that can take up to three parameters:
instance The instance whose parent’s method to call (usually this)
methodName The name of the method (as a string)
baseArguments Parameters for the method, if any (as an array)
In this case, thetoString()method ofOReilly.Browsercan be implemented as the following code demonstrates:
The final OOP-like feature made available to JavaScript by ASP.NET AJAX is interfaces. An interface does not contain any implementation at all but instead specifies the members that subclasses must implement. Even if you inherit from an interface, there is no implementation you can use. Instead, you must create the methods that are defined in the interface. This is a good way for developers to keep class structure and implementation details separated in their code.
As you have probably already guessed, the method for creating an interface isType.registerInterface(). The interface name you just created is provided as the third (optional) parameter ofregisterClass(). So, starting with the interface itself, we will use the following code:
Here,OReilly.Productis an abstract class. Unfortunately, the final version of ASP.NET AJAX does not support abstract classes (pre-release versions did). Therefore, there is no technical difference between abstract classes and regular classes.
In the following example, theOReilly.Productclass introduces and implements the propertiesnameandvendor.
OReilly.Product = function(name, vendor) { var _name = (name != null) ? name : "unknown"; var _vendor = (vendor != null) ? vendor : "unknown";
The next class to be implemented isOReilly.Software. Since we do not want to instantiate this class directly (we have subclasses likeOReilly.Browserfor that), this can now also be turned into an abstract class. It derives fromOReilly.Product(to getnameandvendor), but it also implementsOReilly.IProduct(for thetoString()method). After declaring the class, we register it with the following call toType.registerClass():
The rest of the code remains unchanged. It is quite long, so you might consider putting it into an external .js file for legibility of the .aspx file. Example 4-4 shows the complete listing.
Example 4-4. Using interfaces to structure code
ClientInterface.aspx
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
In addition to adding OOP-like features for JavaScript coding, ASP.NET AJAX achieves two goals through client class implementions that are analogs of some .NET classes:
Functionality missing in JavaScript is provided as part of ASP.NET AJAX.
.NET developers with little JavaScript experience can use some familiar elements in their code.
In my opinion, this is one of the areas where upcoming ASP.NET AJAX versions will most certainly add more features, so the following list of classes is neither exhaustive nor final. Two useful features that are already available areSys.StringBuilderand enumerations.
Sys.StringBuilder
One of the new features introduced in .NET 1.0 that really improved performance was the introduction of the StringBuilder class. The downside, however, is that applications are usually full of code such as that illustrated below:
string s = "", t; while (){ t = <value>; s += t; }
The problem lies in the statements += t, which is equivalent tos = s + t. Whenever this code is executed, a copy ofsand a copy oftare created in memory, concatenated, then saved back intos. However, it’s inefficient to create a copy ofsto achieve these results. Therefore,StringBuilderuses an optimized algorithm for string concatenation.
In JavaScript, this approach does not have any measurable effect on memory (in fact, the implementation seems to be a tick slower than the standard approach). Then again, performance is not as critical an issue for client script as it is for server code. Nevertheless, for consistency with your server coding techniques, you can rely on your knowledge of .NET coding techniques and useStringBuilder on the client. Example 4-5 puts the StringBuilder class to work. It concatenates some strings to build an HTML chessboard.
Example 4-5. Using an ASP.NET AJAX StringBuilder
ClientStringBuilder.aspx
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>ASP.NET AJAX</title>
The built-in JavaScript functionString.fromCharCode()converts an ASCII code to its associated character, so the innerforloop runs from"a"through"h". As Figure 4-3 reveals, the code in Example 4-7 creates a simple chessboard.
Another .NET type that is emulated by ASP.NET AJAX for JavaScript is Enum. You can create a custom enumeration using the createEnum() method. The API for this changed quite a bit during the Atlas and ASP.NET AJAX development cycle. In its current form, you can create an enumeration as shown in the following listing, but you cannot iterate over it. You can create a namespace, if you wish to use one:
Type.registerNamespace("ORA.MyEnums");
Then, create the enum object, assigning it an (empty) function:
ORA.MyEnums.Ajax = function() {};
Next, define all values in the enumeration, using the syntax below:
This code outputs the string"0 1 2 3 "(the keys for the enumeration entries) in the<div>element.
Enumerations are also used internally by ASP.NET AJAX to define mouse button values (the following code snippet has been edited and reformatted for clarity).
The ASP.NET AJAX client script library implements several convenient features not present in standard JavaScript, including OOP-like functionality and client-side equivalents of .NET Framework features. These features can be used by any JavaScript programmer, without repercussions to ASP.NET or the server-side features of ASP.NET AJAX.
For Further Reading
http://www.kevlindev.com/tutorials/javascript/inheritance Online tutorial for JavaScript’s OOP capabilities
http://aspnetresources.com/blog/ms_ajax_cheat_sheets_batch2.aspx “Cheat sheets” for ASP.NET AJAX’s JavaScript extensions
http://ajax.asp.net/docs/ClientReference/Global/default.aspx Documentation for helper functions and JavaScript base type extensions
http://quickstarts.asp.net/Futures/ajax/doc/cssselectors.aspx The ASP.NET AJAX Futures provides JavaScript helper functions to select elements based on CSS rules