JavaScript Journal

Subscribe to JavaScript Journal: eMailAlertsEmail Alerts newslettersWeekly Newsletters
Get JavaScript Journal: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


JavaScript Authors: Sematext Blog, Klaus Enzenhofer, Mehdi Daoudi, Yakov Fain, AppDynamics Blog

Related Topics: ColdFusion on Ulitzer, XML Magazine, JavaScript

CFDJ: Article

WDDX with JavaScript

WDDX with JavaScript

This article demonstrates how to use Allaire's XML serialization technique, Web Distributed Data eXchange (WDDX [described at www.wddx.org]), to transfer CFML data structures from the server to the client, and into JavaScript and back. Generally WDDX's approach is to interchange data of all types (including complex data types such as nested structures, n-dimensional arrays, record sets, or even binary data) between different programming platforms.

Overview of WDDX
WDDX is simply a way of describing data in a text-based form. Technically it's an XML DTD (Document Type Definition) of XML tags that describes simple and complex data types, such as the contents of a nested structure. Many major Web programming platforms are adopting WDDX; it's currently available in CFML, Java, ASP, PHP, and Perl for the server-sided, platform-independent exchange of data. In addition to transferring data between different server platforms, WDDX is also available in client-sided programming environments such as JavaScript. This article focuses on the latter, but first I'd like to continue with the WDDX overview.

You can use WDDX to serialize some ColdFusion data into a WDDX package:

The result: a WDDX package that represents the content of #myComplexArray# as an XML string is stored in #my- WddxPackage#. It's possible to deliver this WDDX package over the Web using text-based protocols, such as HTTP or SMTP, since the WDDX string is XML and therefore plain vanilla text. This is even true when serializing binary data, which automatically escapes and unescapes to a BinHex64 text representation.

This mechanism allows us to interchange (syndicate) data between different Web applications (even when they're written in different languages). Basically the CFML developer doesn't need to think about the XML stuff, since serialization and deserialization are encapsulated into the tag (or the WDDX-SDK on other language platforms). Deserialization from a WDDX package (obtained from a or access, for example) back into a CFML data type is as easy as this:

The WDDX package that's held in #myWddxPackage# is now deserialized into the CFML variable #myNewData#.

Transferring WDDX Between Server and Client
To provide you with a nice example of how to use WDDX on the client with JavaScript and how to transfer data back to the server, I decided to implement an offline browser for ini files. ini files are simply text files that contain sections and entry-value pairs of configuration settings for some applications. To learn more about the ini style see the CF Studio Help on ColdFusion's SetProfileString() and GetProfileString() functions. I also describe how to grab such a file into WDDX and transfer it as an array of structures to the client where it can be viewed, edited, and extended offline, as well as how to commit these changes back to the server in one step for the whole data set. This example enables us to do offline browsing and editing of ini files residing on the server.

Note that this functionality can also be implemented on a stateful online connection with a step-based editing process involving several action pages (such as loading all the sections, the entries of a specific section, and its value, and writing each one back in its own step). However, the goal of this article is to introduce client-sided usage of WDDX using the ini file as an example of structured data that can be transferred at once to the client and back.

Let's look at what our example does. After entering a server-sided path in an ini file (you can also use the demo ini file provided with this example), you'll see two list boxes and an input field (see Figure 1). In the first list box choose a section within that ini file; in the second, a specific entry within that section while the text field shows the value of the selected entry. Also, you can change the values using the button "Update Value" or add entries or even whole new sections using the "New Entry" and "New Section" buttons (see Figure 2). This is all done on the client using JavaScript. There's no backprocessing to the server, not even for adding new sections and entries. Selecting the "Store data back into ini file on server" button immediately sends all data, including the changes and additions, to the server. WDDX serializes the data (see Figure 3), which results in an update of the ini file.

Theoretically you could connect to your server, open an ini file within the offline browser, close the online connection (go offline), change and/or add data to the ini file browser, and finally go online again and commit all changes at once to your server. This is the concept of a simple offline data browser. Note that we're not dealing with concurrent updates, deletes, commits, and rollback statements here, since the goal of this article is to show you how to use WDDX to transfer complex data types between the server and client (and back), not how to implement a perfect offline data browser, which is clearly out of this article's scope. For a nice offline data browser with single-record updating and other interesting features, I recommend Ben Forta's ( www.forta.com) book Advanced Cold-Fusion Application Development (Que).

Looking at the Code Details
So far I've explained the concept of using WDDX on the client, but to make this article worth reading it's time to introduce and explain the code behind it. First I'd like to demonstrate how to transfer a CFML array to JavaScript with only a few lines of code:


Before using all the WDDX objects (for example, the WddxRecordSet or WddxSerializer object) within JavaScript, you have to include the above line to import the WDDX SDK for JavaScript in your page. If you use "/" CF mapping, you don't have to worry about which path ColdFusion used to place the wddx.js file. After the WDDX-JavaScript SDK is imported to your page, you can transfer any CFML variables directly into JavaScript. Theoretically this is done with two invocations of the tag, as you first have to serialize the CFML data with to WDDX, and then deserialize it with into a client-sided JavaScript variable. However, as Allaire's intention is to minimize any coding overhead and to make things as nice and easy as possible, they created a shortcut to this process that resulted in only a single invocation of

These few lines transfer a complex CFML array (held in #myCfArray#) into a JavaScript array (stored in myJsArray) for client-side usage. To test the code, the length of the JavaScript array is shown in an alert popup box. You can now access all the array elements within JavaScript using myJsArray[index]. But be aware that in JavaScript array elements start at index 0, whereas in CFML they start at index 1. It's also possible to transfer other complex data types, such as record sets or structures, to the client that way. As we're using an array of structures to hold the ini file's sections, note that when accessing structures within JavaScript (coming through WDDX) all keys have to be written in lowercase:

After this basic WDDX-JavaScript introduction, let's look at the source files for this article. (They can be found on the CFDJ Web site, www.sys-con.com/coldfusion/sourcec.cfm.) Although the example consists of four files (index.cfm, top.cfm, main.cfm, and update.cfm), I'll explain only two of them (main.cfm and update.cfm) since the other two open up only the frame set (Listing 1: index.cfm) and the filename entering form (Listing 2: top.cfm).

The file main.cfm (see Listing 3) is invoked after entering the path and filename of the ini file, which is submitted as FORM.filename. After checking if the file really exists on the server, its content is read completely and transferred into an array of structures through some string-parsing code. This code only reads the ini file structure into a data type that represents the sections and entries of the ini file and has nothing to do with the actual topic of this article. The code is necessary to dynamically read the ini file content and can also be encapsulated into a custom tag, so you don't have to worry about it when you're working with WDDX and JavaScript. I won't discuss this parsing code here but will continue the in-depth analysis of the actual WDDX and JavaScript code in main.cfm.

After the ini file has been parsed, its content is available as an array of structures that holds each section, its name, a nested array of structures for each entry, and its corresponding value within the section. This is all stored in the CFML #Profiles# variable, which is transferred through WDDX to the JavaScript ProfilesArray variable. Next you'll see eight JavaScript functions that handle the data on the client side, including the dynamic representation logic and the adding and/or changing of the values, entries, and sections, which I'll discuss in detail later.

In the HTML code there's a

pointing to the file update.cfm (which handles the updating of the ini file and is also discussed later). This form has two hidden form fields: one holds the filename and path to the ini file so the update.cfm template knows what file to update, and the other, WddxData, is initially kept empty. Note: The hidden form field holding the filename is insecure as it allows evil users to specify other files to overwrite besides the ini file. However, as this example focuses on the WDDX part, I left out the part about security. For the curious, I'd implement security using a SESSION-scoped (and therefore server-sided) storage of the filename, or while still using a hidden form-field employ the Encrypt() and Decrypt() functions to prevent certain modifications. (This is only a side note of this article.)

The other hidden form field I mentioned (WddxData) is empty since upon form submission (after all changes to the ini file data have been made on the client side) it will be filled with the serialized WDDX data that's holding the modified ini file's content. That way the whole WDDX package is submitted back to the server in order to update the ini file.

Let's take a closer look at the JavaScript functions in main.cfm that handle the client-sided data processing of the ini file's content. As the user interface of main.cfm consists of two single select boxes as well as a text input box, we need a way to dynamically add and remove the entries of a select box. This is possible with JavaScript through the creation of Option objects within the select list. I decided to encapsulate this general logic into a small JavaScript function:

// General function to add an

Following are three JavaScript functions - initSections(), initEntries(sectionIndex), and initValue(entryIndex) - that dynamically fill the select boxes and the text box with the sections, entries, and values taken from the transferred variable ProfilesArray (see above for the WDDX transfer from CFML to JavaScript). The nice feature is that initSections() calls initEntries() with the appropriate parameter, and initEntries() calls the necessary initValue() for the current selection. By default all select boxes and the text box are empty; they're filled by the onLoad-eventhandler of the tag called initSections(). Also both select boxes call init-Entries() and initValue() respectively in their onChange eventhandler, which results in the dynamic display of the ini file's sections. That's all for the displaying of the ini file's content on the client. Now the user can browse through all sections of the file and display all the entries without having to go back to the server. This is achieved through the JavaScript ProfilesArray variable that holds all the file's data (here the ini profile) as a model.

How can the user change this data model on the client side by changing values and/or adding new entries or sections? This all happens through the next three JavaScript functions - makeNewSection(), makeNewEntry(), and updateValue(). These functions are called by the "New Section" button, the "New Entry" button, and the "Update Value" button, respectively. Both makeNewSection() and makeNewEntry() prompt the user for the name of the section or entry to add and create the appropriate structure within the client-sided data model, ProfilesArray, and refresh the user interface using the above mentioned init-methods. The update- Value() function simply takes the current value out of the value textbox and stores it in the ProfilesArray using the current selection of the section- and entry-select boxes to reference the position to update. Using these three simple functions it's possible to completely change or add data to the data model on the client without the need for further round-trips to the server. Note that for simplicity reasons, I decided not to introduce the offline deletion of entries or sections, since deleting them from the ProfilesArray doesn't delete them on the server side after submit. To get this feature, each entry in ProfilesArray should get a flag set to "delete me upon server-sided processing" when the user deletes it.

So far we're able to view all the content of the file offline and even add or change data. However, this is only done at the client side! To commit all your changes back to the server (within a single request for all the data), you'll have to push the "Store data back into ini file on server" button that invokes the submitToServer() function. This JavaScript function is responsible for serializing the client-sided data model (Profiles-Array) back into a WDDX package and placing it into the hidden form field, "WddxData", before submitting the form.

// Serializes data and submits it to server
function submitToServer() {
fr = document.formIniBrowser;
// serialize the ProfilesArray into WDDX
myWddxSerializer = new WddxSerializer();
tmpWddxPackage = myWddxSerializer.serialize (ProfilesArray);
// place WDDX package into hidden form field for submission to server
fr.WddxData.value = tmpWddxPackage; // alert(tmpWddxPackage);
alert("The complete data was serialized into WDDX and will be submitted to the server");
fr.submit();
}

As you can see from the code, the WDDX serialization of any JavaScript variable is done by first instantiating a WddxSerializer object, then using its serialize(variableToSerialize) method to get the resulting WDDX package. This object is available in JavaScript after the prior import of the WDDX SDK for JavaScript (see above). After placing the WDDX package into the hidden form field, the form gets submitted to update.cfm, which handles the physical updating of the ini file on the server.

After the form has been submitted to update.cfm, this file simply takes the WDDX package out of FORM.WddxData, deserializes it back into the CFML array of structures, and loops over them to update each individual entry in the ini file using ColdFusion's SetProfileString() function.

Voilà, all data has been updated at once! This technique is very efficient and convenient when dealing with dynamic data on the client. If the developer wasn't using WDDX when dealing with large dynamic data updates on the client side, he or she had to write it as a step-based set of templates with round-trips to the server for each request, or deal with dynamic form fields with dynamic names being submitted, which caused a lot of overhead and confusion when using constructs such as .

More Stories By Christian Schneider

Christian Schneider is an Allaire Certified ColdFusion and Web site developer. He has over four years of intensive experience developing CF-based intranet applications for banks and logistic corporations.

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.