Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Writing Object-Oriented JavaScript Part 3

0.00/5 (No votes)
9 Dec 2003 1  
Using Cfx to develop a JavaScript control class library.

Abstract

Part 1 of this series described the object-oriented features of JavaScript. Part 2 built upon that knowledge and introduced a framework supporting class inheritance. In this final installment, we'll use Cfx to construct a JavaScript control class hierarchy that offers rich client-side behaviors to ASP.NET user controls.

Introduction

A web control represents a portion of the web page that typically provides user interaction such as text boxes, radio buttons, check boxes, etc. Web control can be static as well. Subdividing pages into controls improves abstraction by making pages containers of web controls and enhances reuse and extensibility.

With ASP.NET, you can use conventional HTML elements or ASP.NET controls. You can augment them with defining your own user controls. Eventually ASP.NET renders all controls into HTML and JavaScript interpreted by the client browser. Naturally, you can write your website and use the default ASP.NET behaviors. However this is not feasible in all situations and limits the user experience. Using Cfx you can now achieve greater control and richness to your client-side scripts writing object-oriented JavaScript.

Note - A detail explanation of ASP.NET and web controls is beyond the scope of this article as there are many great books and essays on ASP.NET. The aim of this article is to show how Cfx is used to build classes that take advantage of ASP.NET to build rich clients.

The Strategy

Leveraging ASP.NET Control Names

ASP.NET applies a consistent naming scheme to its controls using the id and name attributes when it renders them as HTML elements. ASP.NET names HTML elements using the element name proceeded by the names of its containers separated by an underscore. For example, in accompanying demo, the ASP.NET CfxText user control encapsulate the ASP.NET textbox control giving it the identifier txtField.

<asp:TextBox id="txtField" runat="server" maxlength="255"></asp:TextBox>

The ASP.NET CfxText user control has the id txtName and is subsequently encapsulated by a CfxWebFormOptions control with the id CfxWebFormOption1. The id generated by ASP.NET for the HTML text element uses the outermost container identifier followed by the separator character continuing with the name of the next container and then finally followed with the control identifier.

<input id="CfxWebFormOptions1_txtName_element" type="text" 
    maxlength="255" class="LgNorm" style="width:224px;" />

By leveraging this naming convention, we can logically group control elements and develop a class hierarchy of ASP.NET control wrappers in JavaScript providing client side behavioral support to the ASP.NET user controls.

Note - ASP.NET 2.0 uses a dollar sign ($) character as the separator character. The dollar sign eliminates ambiguities caused by the underscore separator where it can be used in identifiers. Cfx.Dom.GetElementTerms uses a regular expression that accounts for underscore ambiguities when splitting ASP.NET identifiers into element terms.

The JavaScript Control Class Hierarchy

CfxControl conceptually represents the set of user control classes used on the page. These classes represent a layout description along with its client side behavioral definition. The layout description is defined using ASP.NET and maintained in the accompanying .aspx and .cs files. The client side behaviors are written in JavaScript in corresponding .js files. Thus client behavior is separated from its layout. Notice that we have nearly a one-to-one correspondence between the rendering files and the JavaScript files. The additional JavaScript files contain common base class definition and implementation defined in the CfxControl and CfxInput classes.

At the top level of the JavaScript control class hierarchy is the Object class followed by the CfxControl class and is the root of all JavaScript controls. The CfxWebFormOptions control is the container class for the input controls on the WebForm1 page. There are three input controls deriving specific functionality from the CfxInput class. The CfxText class represents a control for text input. The CfxSelect class represents a single selection dropdown and CfxLabel wraps the ASP.NET Label control. CfxRadioSet represents a group of radio elements. The CfxHistoryOptions class contains the CfxRadioSet and the CfxSelect classes providing a single control for making "historical" selections.

A couple of helper classes that are not part of the CfxControl heirarchy are provided. The CfxError class extends the Error class adding the framework object throwing the exception and the CfxEvent wrapper for JavaScript event objects.

Figure 1. CfxControl class hierarchy.

JavaScript Client-side Controls

CfxControl

The CfxControl class is the base class for all derived controls and encapsulates properties inherited by all controls. The name property is the name of control. Think of controls as document element containers and it is the name of the container the name property represents. The parent property is the parent CfxControl. The items property is an array of document elements that has the control name as part of its id attribute.

Figure 2. ASP.NET control identifier and terms.
For example when the CfxWebFormOptions control named CfxWebFormOptions1 is created, all the elements and images in the document that contains the string CfxWebFormOptions1 in the id attribute are added to the items array of the CfxControl.

CfxInput

The CfxInput class is the base class for input controls. This class defines input controls as having an input element property element and an image property image indicating the error state of the input control. It defines several base methods to manipulate the image property and an Initialize and Validate method. CfxInput is not defined as an abstract class and can be instantiate. This is useful for situations needing a generic input control object.

CfxText

The CfxText control wraps the text input element and validates its input against the regExp regular expression property. The control also provides the ability to sink the onkeypress event inspecting for an the enter key to start validation. Users provide a handler in the event the enter key is pressed via the CfxText control SubmitHandler method.

this.txtName.SubmitHandler( OnEnterKey );
Figure 3. Setting SubmitHandler of txtName control to OnEnterKey handler.

If the submit handler is supplied, during the text input element onkeypress event, execution is transferred to the CfxText control OnEnterKey method. The CfxEvent class wraps the JavaScript event object and inspects for the enter key event. If the enter key event was pressed, the OnEnterKey method calls CfxText submit handler.

function OnEnterKey( evnt )
{
    var cfxEvent = new CfxEvent( evnt );
    if ( cfxEvent.IsEnterKey() )
    {
        // Find the instance from the event source.

        var thisObj = cfxEvent.FindInstance( CfxText );
        
        // Call CfxText control submit handler.

        return thisObj.submit;
    }
    else
        return true;
}
Figure 4. CfxText OnEnterKey event handler.

Fired by the onkeypress event, OnEnterKey method this reference does not refer to a CfxText instance but to the event source element. FindInstance is used to obtain the instance of CfxText associated with the source element. In order for FindInstance to determine the instance, the CfxText.instance flag is set to true in its class definition.

CfxSelect

The CfxSelect control wraps a single selection dropdown input element providing method to add and delete elements to and from the dropdown. CfxSelect also provide accessors methods to obtain the selected text and value as well as the index of the selected element.

CfxLabel

The CfxLabel wraps the ASP.NET Label control providing an interactive way of alterting page text. ASP.NET renders its labels as span elements and CfxLabel locates it through its id attribute constructed by appending together the names of its ancestor controls. The Value accessor updates the inner text of the span element. Rather than using alerts, CfxLabel can be used to enhance the display of error notifications.

CfxRadioSet

The CfxRadioSet control wraps a group of radio input elements. ClickHandler method sets the onclick event handler of the radio button elements. GetElement returns the CfxRadioSet radio button element from the radio button index. GetIndex returns the index of the CfxRadioSet radio button element. The GetItems method inherited from CfxControl is overridden by CfxRadioSet, because radio elements are grouped by the name attribute while the base method uses the id attribute to find elements. The GetSelected method returns the checked radio element, and Length returns the number of radio elements in CfxRadioSet.

CfxHistoryOptions

This control provides the client-side functionality of the set of elements that simulate selecting history criteria. This control provides the functionality for the CfxRadioSet control and the controls associated with the radio buttons.

Figure 5. CfxHistoryOptions user interface.

CfxHistoryOptions groups the control into a CfxRadioSet control containing of a list of the radio elements as well as the radio element affiliations. For example the radioSet property contains the radio elements: radDefault, radByMonth, and radByYear. The radByMonth radio input element affiliate is the CfxSelect control named radByMonth_selByMonth control and radByYear radio input element affiliate is the radByYear_selByYear control. The radDefault radio element has no affiliates. The value attribute of the radio element identifies affiliates thus CfxHistoryOptions class can group elements containing that value. In this case radByMonth radio input affiliation consists of the elements radByMonth radio and radByMonth_selByMonth dropdown.

Figure 6. Grouping radio element affiliate controls.

During initialization, CfxHistoryOptions establishes on an onclick event handler for the radio set. When a radio element is clicked the OnRadioClick handler is called altering the disable state of the radio affiliates. Notice that the handler uses the CfxEvent class FindInstance method to obtain the instance of the CfxHistoryOptions class from the event source element. Finally, the Validate method verifies selections.

Cfx Wrapper Classes

CfxError

This wrapper class augments the JavaScript Error object adding a property that references the instance of the Cfx class throwing the exception. As you will see in the demo, the thrown CfxError object is used identify and change the state of the throwing CfxText object.

CfxEvent

The CfxEvent class is a wrapper for JavaScript event objects. The event object contains the information about JavaScript events and passed along to CfxControl event handlers. CfxEvent hides browser variations of the event object providing a consistent interface. In the demo, CfxControl event handlers are responsible for detecting the enter key event, the radio button check event, and the submit button click event. The handlers create a CfxEvent object to wrap the event object and calls FindInstance to translate the element firing the event into its corresponding CfxControl instance.

Code In Front

The final implementation of the controls occurs in the JavaScript of the WebForm1 page. When WebForm1 loads, the onload event calls the page�s OnLoad function instantiating a new CfxWebFormOptions control and assigns it to formOptions. The SubmitHandler method assigns the OnSubmit event handler that gets called when the control submit button click event occurs or the enter key is pressed from a text control. OnSubmit then calls the Validate method and performs a postback if the validation succeeds.

<script type="text/javascript">
function OnLoad()
{
    formOptions = new CfxWebFormOptions( "CfxWebFormOptions1" );
    formOptions.SubmitHandler( OnSubmit );
}

function OnSubmit()
{
    if ( formOptions.Validate() == true )
        Cfx.Dom.PostBack();
    else
        return false;
}   
<script>
<body topmargin="0" leftmargin="0" marginheight="0" marginwidth="0" 
    onload="OnLoad();">
Figure 7. WebForm1 page code in front are now trivial routines.

Benchmarks

Cfx performs surprisingly well. The demo program includes alerts displaying page load and submission performance. For a 2GHz system, the time for each task was under 35 milliseconds for IE 6.0 and under 50 milliseconds for Mozilla 1.4.

Demo

The ControlDemo demo program, shows how to design and implement a control class heirarchy using Cfx. The approach to this application is to have ASP.NET responsible for the page layout and JavaScript responsible for client-side user interactions.

The URL for this application is http://localhost/JsOOP/ControlDemo/WebForm1.aspx. Copy the source code into the JsOOP/ControlDemo subdirectory of your http://localhost home directory. You can use Visual Studio to create the ASP.NET project or use the IIS management tool found in Administrative Tools of the Control Panel. This demo has been tested on both version 1.0 and 1.1 of the runtime.

Conclusion

This series on object-oriented programming in JavaScript is an attempt to fill in an astonishing gap in the development of client-side scripts. Too often scripts are written as procedural adjuncts rather than as reusable objects. Much of the reason for this, has to do with JavaScript books simply failing to fully explain the language's object-oriented capabilities and no intrinsic support of class inheritance. Another contributing factor is ASP.NET itself where the programming model suggests writing JavaScript as procedural adjuncts for ASP.NET controls.

Cfx, provides an easy to use coding pattern for writing class hierarchies in JavaScript. The result of writing object-oriented scripts is richer client-side functionality by having JavaScript take on greater responsibility of UI management. While ASP.NET defines page layout, the code behind becomes trivial enabling the server-side code to be better focused on the business logic.

On the other hand it may be useful to have the ASP.NET controls emit JavaScript. Using Cfx you can still structure your scripts in an object-oriented fashion. Cfx is quite versitile letting you choose the deployment that works best for you.

Another advantage of Cfx is that it enables you as a web developer to retain greater control of your code. ASP.NET is powerful but too much reliance on any tool from a single vendor can spell trouble when targeting multiple platforms and browsers. Cfx, because it is object-oriented, makes it easy to isolate idiosyncrasies in fa�ades and wrappers. While the demos are written for ASP.NET, Cfx is a JavaScript framework that is not specific to ASP.NET.

I hope that the JavaScript Class Framework elevates the quality of client-side scripts promoting rich web-based interfaces, reduce vendor dependencies, and promote the building of a collection of reusable JavaScript classes.

Revision History

  • Version 1.0 -- Initial Version
  • Version 1.1 -- Fixed content errors.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here