Welcome!

ColdFusion Authors: Yakov Fain, Pat Romanski, Liz McMillan, Maureen O'Gara, Greg Ness

Related Topics: ColdFusion

ColdFusion: Article

Out-Moding Modular Presentation with XML

Manage your application's presentation and provide a rich user experience

In my experience, the majority of client change requests for any given application have to do with the presentation layer. This makes sense if you're a client, because the presentation layer is the only part of the application you see.

Thus, it's the one part of the application you can judge and comment on. By and large, clients wouldn't even know how to comment on other parts of the application, except by proxy in seeing how those parts of the application influence the presentation layer. For instance, if a form submission performs an update of data, the client only knows that the functionality performing the update works if the presentation layer indicates the change. If the presentation layer doesn't reflect the change, the client will wonder if anything actually happened. This is because many clients don't have the luxury or know-how to open the database in another IDE, such as Enterprise Manager, to view the data. Even if clients did have this ability, most wouldn't know how or why they should use it.

Unfortunately, despite the fact that it is the most crucial tool for communicating with clients, the presentation layer of an application is often not thoroughly planned, or, worse, simply neglected. I can think of many times I've seen a presentation of a framework, architecture, or other application and asked, "How does X handle the display?" only to hear, "It's very dynamic: you just place your templates in this directory!" This is as though the best answer to versatility in presentation is simply to have no plan at all. How is the application branded (for different clients using an ASP application)? How is localized content presented for multilingual sites and applications? How is presentation filtered for different users and roles? With a little finesse, it's possible to take the presentation layer even further: you can reduce your workload while integrating the interfaces of disparate applications, with little if any impact on their code.

A Magic Trick
These are bold claims, so I don't blame you for being skeptical. Until I faced the same challenge while designing the onTap framework, I too was a skeptic. The onTap framework meets this challenge by using its HTML library and its suite of XML parsing functions to build HTML library presentation. Here is a brief example. To test it, you will need to install the onTap framework from www.fusiontap.com (see Listing 1). All listings for this article can be downloaded from www.sys.con.com/coldfusion/sourcec.cfm.

Looking at the code in Listing 1, you might not think it looks very different from the display templates of most applications. You would be correct in that assessment. The primary difference is the addition of the CFMODULE tag calling the onTap framework's HTML custom tag. This tag is tasked with converting your XHTML template into HTML library structures to be used later. By itself, this example isn't very impressive: it simply takes a string of XHTML with an XML namespace and displays HTML or XHTML. The impressive part is that the converted XML can now be modified ad hoc to become whatever you need. The possibilities even include simplifying some complex DHTML, which would be difficult to accomplish using XSL transformations.

Let me start with something easy. Insert the following line of code between the closing CFMODULE tag and the opening CFOUTPUT tag:

<cfset htlib.childSort(view.mainmenu)>

You should notice that the order of the links in the menu is altered so that the links appear in alphabetical order. Now, for something a bit more involved, add these lines:

<cfset htlib.style(view.mainmenu,"float","left")>
<cfset htlib.addChildContainers(view.mainmenu,"div",true)>

Figures 1 and 2 are before-and-after screen shots depicting the changes you should see in the display after adding these lines of code. You should notice that the menu previously distributed horizontally across the top is now distributed vertically on the left side - a change resulting from just these two additional lines of code.

Indulge me while I offer one more example. Comment out the previous two lines and add the code below:


<cfloop index="x" from="1" to="#htlib.children(view.mainmenu)#">
   <cfset mychild = htlib.childGet(view.mainmenu,x)>
   <cfset mychild = htlib.clone(mychild)>
   <cfset htlib.childAdd(view.pagefooter,mychild)>
</cfloop>

The HTML library offers many alternative ways to accomplish this task. This is certainly not the most sophisticated or elegant method, but it's an easy example that shows how these modular display elements can be easily reused. When these lines of code have been added to the example, the footer menu at the bottom of the page is populated with the same links used in the main menu at the top. The HTML library offers many other tools for display, including rich interface elements such as trees and tabsets (see Figure 3).

A Look Behind the Curtain
I've shown you how easy it can be to get the display of a Web site to roll over and go fetch. Now I'll explain how this functions.

In a nutshell, the HTML library works because HTML and XHTML are structured documents. As with any standardized format, the structure of the document lends itself to being managed because its syntax is predictable. When you know the structure of the language syntax, you can create routines to handle or manage that structure. In essence, this is very similar to writing routines to import or export tab-delimited files or CSVs. The format of the file provides all the information needed to manage the import/export process. In the case of our HTML or XHTML, the process is made a little easier because many of the low-level formatting concerns (e.g., converting escaped characters) are handled for us by the ColdFusion Native XMLParse() function. But in other ways it is more complex. Instead of a linear series of records to insert into a database, the XML document is a nested hierarchy of elements, like a tree. Each has a collection of many disparate properties needing unique handling.

As previously mentioned, reading an XML document is a reasonably easy task because an XML document is consistently structured. Once read-in using the ColdFusion native XMLParse() function, the series of structures and arrays that represent an XML document can be used in many ways. The custom tag used in these examples chooses to convert them further, from XML documents into native ColdFusion structures and arrays specially formatted to work with the HTML library. This extra conversion is done for two reasons. First, although using an existing XML document within ColdFusion isn't very hard, modifying XML documents can be surprisingly difficult. This is particularly true with regard to the addition of child nodes. The native structures and arrays don't have this limitation. Second, an HTML or XHTML document is actually a much more complex document than an "ordinary" XML document, having both CSS and JavaScript features. Although XSLT provides support for CSS, it has no mechanisms for managing JavaScript and can be a daunting shift in thinking for traditional ColdFusion developers. In comparison to structures and arrays, XSLT can also require a significant amount of server resources when making small changes to a document. So XSLT isn't necessarily the most efficient mechanism to use for subtle changes such as adding or removing a single link from a menu in a large HTML document.

When the HTML library was first released, many developers found it to be rather intimidating. Full pages of pure CFSCRIPT to generate the presentation elements looked very different from the traditional template-driven displays most of us are used to seeing. The new HTML custom tag helps to bridge this gap by allowing existing templates to be converted so that they can use the HTML library with little or no modification. Older templates must be formatted as valid XML (no unclosed tags, no unquoted attributes, no valueless attributes, and proper use of XML entities), however this is far less work than converting to pure CFSCRIPT. The XML syntax is only half the story. Many of the more powerful features of the library require an understanding of library's underpinnings, which support the XML syntax.

The good news is that the underlying architecture of the HTML library is not as complicated as it might appear at first glance. In truth, it is quite simple because it is based on the standards of HTML, the format that made Web technology accessible to everyone. In an HTML document, each tag (aka, node or element) has several features:

  • Element: This is the name of the HTML element type being created, such as "div," "span," or "input." An element must have both an opening tag (<div>) and a closing tag (</div>), or it must be closed in the opening tag (<div />).
  • Children: This is the array of HTML tags between a tag or node opening and the closing tag. The children of a given HTML element may be manipulated using the html.childX functions in the HTML library, such as html.children(), html.childAdd(), html.childMove(), and html.childRemove.
  • Attributes: These are the name/value pairs found within the opening tag of a node, such as the name attribute of an input element or the src attribute of an image tag. Every HTML element may have an ID attribute, class attribute, and style attribute. Using the HTML library of the onTap frameworks, these values can be managed with the collection of html.attributeX functions in the HTML library, such as html.attribute(), html.attributeAppend(), and html.attributeRemove().
  • Style: CSS style sheets control the display of HTML elements once the browser receives the document. They can be applied to HTML elements in three ways: (a) using external style sheets (attached to the document using a <LINK> tag), (b) using the <STYLE> tag, or (c) using in-line style elements that are applied as a "style" attribute in the target HTML element. With an HTML library, in-line style elements for a given HTML element can be managed using the collection of html.styleX functions in the HTML library, such as html.style(), html.styleAppend(), and html.styleRemove().
  • Events: The Document Object Model (DOM) for HTML offers a host of event handlers. These include special attributes, which are applied to HTML nodes to provide dynamic presentation within the browser, such as "onclick," "onmouseover," and "onchange." JavaScript is the most common client-scripting language used to implement these event handlers. Unfortunately, JavaScript has no XML syntax and must therefore exist as plain text, outside of our wonderfully structured XML. The HTML library and the new XML syntax for creating HTML library elements seek to provide better management for client-side JavaScript. Events can be managed using the collection of html.eventX functions, such as html.event(), html.eventsShow(), and html.eventRemove().
Beyond the Document
In addition to managing client DOM events, the HTML library also includes a number of additional "server events" that allow the presentation of these elements to be modified at different stages during a ColdFusion page request. Most of the library's server events are triggered when the html.show() function is used to convert the series of structures and arrays representing the HTML into a string of HTML. The following events are available to all elements.
  • Pre: Occurs prior to the opening tag of the HTML node.
  • Post: Occurs after the closing tag of the HTML node.
  • Open: Occurs inside the opening tag of the HTML node, before any children or prechild events are displayed.
  • Close: Occurs inside the closing tag of the HTML node, after all children and all postchild events.
  • Prechild: Occurs prior to the display of each child element.
  • Postchild: Occurs after the display of each child element.
  • Childdelimiter: Occurs between multiple children (after the postchild event of the previous child and prior to the prechild event of the next child). If an element has less than two children, this event will not execute.
These server events can be populated with a variety of elements: functions that can modify the tag and/or return content to the display, plaintext strings that are injected directly into the HTML output, or other HTML elements. This article has already shown an example using a plaintext value. If you examine the XML syntax in Listing 1, you'll notice that the pagefooter node of the XML contains the attribute tap:childdelimiter="|". This inserts the pipe character between each of the child nodes when the footer is displayed. Thus, it prevents repeated instances of the value in the code that might need to be updated if you decide to change the character used to delimit the menu.

Smart Upgrades Through Extensibility
As Web application developers, the most significant portion of our time is likely spent developing forms to allow our users to manage their databases: create/read/update/delete (CRUD). Particularly with regard to updates, this can often be a tedious task. When an update form is presented, it must be prepopulated with existing data. One must determine where the data is gathered from and how it's used to populate the form. Especially when working with applications inherited from previous developers, we often find that the data used to populate forms hasn't been properly escaped with the HTMLEditFormat() function.

Fortunately, with the HTML library's XML syntax, many of these issues are handled automatically. By default, forms are populated with data from the attributes scope. Values from the database can be easily used by setting defaults in the attributes scope with the CFPARAM tag. Thus, much of the work of creating forms is eliminated. Consider Listings 2 and 3, both of which produce the same display. You might notice that, although the second example requires an XML namespace and two new attributes in the select tag, there is no need to replace the HTML input tag with either CFINPUT or a custom tag. This is because the HTML custom tag around the second example uses a series of functions to convert the structured XML document into comparable HTML elements. In the process, it is able to set defaults for commonly forgotten attributes. Or, it may convert deprecated nodes or attributes into a newer format. The CENTER tag, for instance, is converted into a DIV tag with the in-line CSS text-align property set to "center," without any effort on the part of the developer. Because this task is automated by the onTap framework's XML syntax for HTML library presentation, once an application has been converted to use this syntax it becomes very easy to migrate away from deprecated presentation code.

Beyond avoiding deprecated code, this structure and automation also makes presentation for multiple mediums quite simple. For instance, it becomes very easy to send multipart e-mail in both HTML and plaintext formats using the same presentation components. You can use the html.show() function to display an HTML version and the html.showText() function to display the text part of the e-mail.

Although nothing has been implemented at the time of this writing, there are also plans to use the HTML library structure to provide a convenient means of creating G11N globalized applications. In theory, your XHTML templates would be populated with the names of variables in your localized resource bundles and then, at time of display, converted to the appropriate localized values by the html.show() or html.showText() function.

The Last Word
As the author of the onTap framework, I have a bias towards the use of the HTML library. Hopefully this article has helped you understand why I believe so strongly in it. I also hope to have shown you a few of the ways it can help you manage your application's presentation and provide a rich user experience. Feel free to contact me if you have any questions or comment.

More Stories By Isaac Dealey

Isaac Dealey has worked with ColdFusion since 1997 (version 3) for clients from small businesses to large enterprises, including MCI and AT&T Wireless. He evangelizes ColdFusion as a volunteer member of Team Macromedia, is working toward becoming a technical instructor, and is available for speaking engagements.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.