AJAX Components - Part 2 | Page 2 | WebReference

AJAX Components - Part 2 | Page 2

[previous] [next]

AJAX Components - Part 2

Behavior Component

Another reason that we started by looking at hard-coded HTML to make an AJAX component is that we can make a good start by adding AJAX to our hard-coded HTML using a behavioral approach. This can be a good approach if things such as graceful failure are important because it can easily fall back on the standard HTML markup in cases when users have web browsers that either don't have JavaScript enabled or don't support certain core AJAX functionality such as the XHR object. These are becoming more and more unlikely, particularly in the enterprise where computer software is generally centrally configured and managed. Similarly, behavioral components enable you to incrementally add AJAX features to rendered HTML where the HTML might have come from some existing server-side framework, enhancing the value of your existing web application assets. The Microsoft AJAX Framework (formerly known as Atlas) has a considerable focus on behavioral components. For example, rather than creating an autocomplete component, the Microsoft AJAX Framework has an autocomplete behavior, quintessential AJAX, that can be applied to any existing component such as a standard HTML <input> element. In this case, much like a dynamic <select> element, it adds the ability to allow users to dynamically choose words from a database as they type in the <input> control. For our DataGrid component, adding some grid-like behavior to the standard HTML might entail enabling the end user to edit or sort data in the grid.

Defining behavioral components is often done declaratively by extending the default HTML markup and setting some metadata on a standard HTML element. For the most part, this metadata consists of a CSS class name that generally does not have any actual style information associated with it. To instantiate a behavioral component, the bootstrapper scours the DOM to find elements with recognizable metadata—be it a CSS class name or otherwise. When an element with known metadata is discovered, the standard component instantiation commences. Markup for a sortable HTML table can have an additional class, such as sortable, which would look like this:

The code to actually attach the sorting behavior to the HTML element uses the popular getElementsByClassName() function for which there are several different custom implementations or approaches. Because it is such a popular function, we shortened the name to $$. We can use the $$ function in our bootstrapper along with the makeSortable() function to add the sorting behavior to our HTML table.

For a sortable HTML table, we require the makeSortable() function to do a few things. Each table that we want to have made sortable needs to have an additional class added to each header cell and an event handler function attached to the click event of the table header. To indicate to the end user that they can click on the column header to sort the table by that column, we add the button class that changes the users' mouse cursors to a hand icons; when they click, it causes the global sort() function to be executed in the context of the HTML <table> element. (You remember from Chapter 2 that running the event handler in the context of the HTML element means the this keyword refers to the HTML element that makes writing the sort function a bit easier.)

The sorting of data is something that we should all remember from Computer Science 101. JavaScript is no different from other languages in this regard, and we use the familiar bubble sort algorithm to order our table rows. We can also consider using the JavaScript array sorting functionality; however, it requires a bit more tedious overhead such as copying values between arrays and the like. The sort() function is shown here:

Because the sort() function is executed in the context of the HTML table element, we can access the collection of table rows using the native table rows property and similarly access the collection of cells in each row using the cells property. To get the value that is rendered in each cell of the table, rather than using something such as innerHTML that returns the rendered value of the cell, we instead get the custom VALUE attribute that we created ourselves (this might be an instance where you want to use a custom namespaced attribute) and which contains the raw, unformatted data. This is an important consideration when we deal with things such as prices that might be prepended with a "$" character for rendering but sorted as numbers. Having said that, after we dynamically connect our table to a datasource, this will no longer be necessary. Finally, we use some more native DOM manipulation methods such as element.insert Before(newNode, refNode). The insertBefore() method makes sorting the rows quite simple in that we can use that method with DOM nodes that are already rendered—in this case, the table rows—and it actually moves those nodes and re-renders them.

That is all there is to building a small behavioral AJAX component that can be layered on top of an existing web application. The entire idea behind behavioral components is gaining popularity from the world of semantic markup and other technologies such as Microformats. Strictly speaking, a Microformat is not a new technology but instead a set of simple data formatting standards to provide more richly annotated content in web pages. Microformats use the same CSS class extension approach to give general XHTML content more semantic information. Microformats and other burgeoning standards such as the W3C endorsed RDFa are great places to watch to get an idea of where web technologies are heading and finding the best way to create declarative AJAX components.

At any rate, behavioral AJAX using HTML declarations sprinkled with some additional metadata can be a great approach for AJAX development because it can be achieved in an incremental manner, thus avoiding any large up-front investment in training or technology. It can be a great way to test the AJAX waters before a more large scale deployment. Of course, there are still other ways to use your existing architecture when moving toward AJAXifying your applications.

[previous] [next]