YOUR FEEDBACK
ASP.NET
mark bosley wrote: Good article. Please post the code or send it to me. It ...
AJAXWorld RIA Conference
$300 Savings Expire July 25
Register Today and SAVE!


2007 West
GOLD SPONSORS:
Active Endpoints
Your SOA Needs BPEL for Orchestration
BEA
Virtualized SOA: Adaptive Infrastructure for Demanding Applications
Nexaweb
Overcoming Bandwidth Challenges with Nexaweb
TIBCO
What is Service Virtualization?
SILVER SPONSORS:
WSO2
Using Web Services Technologies and FOSS Solutions
Click For 2007 East
Event Webcasts

2008 East
PLATINUM SPONSORS:
Appcelerator
Think Fast: Accelerate AJAX Development with Appcelerator
GOLD SPONSORS:
DreamFace Interactive
The Ultimate Framework for Creating Personalized Web 2.0 Mashups
ICEsoft
AJAX and Social Computing for the Enterprise
Kaazing
Enterprise Comet: Real–Time, Real–Time, or Real–Time Web 2.0?
Nexaweb
Now Playing: Desktop Apps in the Browser!
Sun
jMaki as an AJAX Mashup Framework
POWER PANELS:
The Business Value
of RIAs
What Lies Beyond AJAX?
KEYNOTES:
Douglas Crockford
Can We Fix the Web?
Anthony Franco
2008: The Year of the RIA
Click For 2007 Event Webcasts
SYS-CON.TV
TOP COLDFUSION LINKS


JavaScript Remote Scripting with ColdFusion MX
Build Win32-like functionality into your Web forms without resorting to Flash

Digg This!

Have you ever wanted to write an HTML-based form that would behave more like a Win-32 "fat client" application than a Web page? Something like a combo box-like control where the user can type in a text field and have a list-box containing matching records auto-filter based on what was typed?

Maybe you're not thinking of anything that fancy. What about simple drill-down selectors where a user chooses a manufacturer, and, based on that selection, a second drop-down list instantly populates, containing just the products offered by that chosen manufacturer? What's more, you want to accomplish this without having to refresh the browser page and you aren't planning on implementing Flash Remoting.

Enter JavaScript Remote Scripting (JSRS). JSRS is a client-side JavaScript library that uses dynamic HTML elements to make hidden remote procedure calls back to the Web server. JSRS was written by Brent Ashley in 2000 (www.ashleyit.com/rs/). It is open source and free of charge to anyone who wants to use it. It is no longer supported by Brent, but there is a community of active developers who use the library, and help is often available from these folks on Brent's forums. JSRS works asynchronously and, according to Brent, is known to work on Win9x, WinNT/2000, WinXP, Unix/Linux/BSD, and Mac with IE4+, NS4.x, NS6.x, Mozilla, Opera7, and Galeon. There are server-side implementations for ASP, ASP.NET, ColdFusion, PerlCGI, PHP, Python, and JSP (servlet).

This article will provide concrete steps on how to implement JSRS with ColdFusion MX so you can begin taking advantage of this great tool in your ColdFusion projects.

I've targeted this article for intermediate to advanced ColdFusion developers who have intermediate skills with JavaScript and DHTML. If you haven't done a ton of work with JavaScript or DHTML, don't sweat it. There should be enough code here to help you get your first JSRS script working even without that knowledge. Working on a JSRS implementation will help you develop these skills and you'll have fun at the same time!

Examples on the Web
First, let's start with some examples so you can see this technology in action before you start implementing it. Every bit of JSRS code that I've implemented has been for corporate intranets or secure extranet applications, so unfortunately I can't show you anything running in production. I've got a couple of examples on my home page for you to check out, though.

Navigate to www.quagmire.com/whiteboard.aspx to see the examples.

  • Drill-Down Example: Choose "Northwind v2" from the tree view. In this example, you'll see two drop-down lists. The first list contains employees. The second list contains regions. Pull down the first list and start randomly selecting employees. You'll see that regions belonging to that employee automatically appear without refresh in the second drop-down list.
  • List Filtering Example: Choose "Autofilter" from the tree view. This is a working example of an auto-filtering select box. The select box content changes dynamically, and without refresh, based on the criteria typed into the text box. Select a product in the list box and click Submit. Product details display. No refresh occurs. This is a pretty dramatic use of JSRS technology and should get you pumped up to do your first JSRS implementation!

    Getting Started
    The first thing you'll need to do is download the JSRS package for ColdFusion MX and review the source code. It's important to understand the concept of how JSRS works before attempting to implement anything. There are a few moving parts to get familiar with.

    Download the JSRS source code example from www.sys-con.com/coldfusion/sourcec.cfm. The CFMX package is available without the Autofilter example at www.quagmire.com/cfm/jsrsCFMX.zip" .

    The following core files are included in the distribution. Let's get familiar with what they are and what they do:

    • jsrsClient.cfm: The jsrsClient.cfm file is where everything starts and finishes. The critical elements that you must include in this CF template are:
      - Two JavaScript functions: a calling function and a callback function for each JSRS call
      - At least one HTML form element that uses a JavaScript event to fire your calling function
      - A <DIV> tag to which you will write the results of your server-side call
    • jsrsSvr.cfm: This template processes your server-side call. This script executes in a different thread than jsrsClient.cfm.
    • jsrsServer.cfc: This ColdFusion component is used to write the results of jsrsSvr.cfm to your callback function in jsrsClient.cfm. You instantiate this object and invoke the jsrsDispatch() method to do this.
    • jsrsClient.js: This is the core JavaScript library written by Brent Ashley and must be included for any of this to work. You include this file in the <head> section of jsrsClient.cfm.
    • License.txt: Brent Ashley's No Nonsense Copyright and License for JSRS.
    How JSRS Works
    1.  Within jsrsClient.cfm, an HTML form element, such as a text box is wired to a JavaScript event, such as an onKeyUp() event. This onKeyUp() event fires when the user types something in the text box. The contents of the text box are passed to the JavaScript function that is executed when the onKeyUp() event fires.

    2.  The JavaScript function executes a method in Brent Ashley's jsrsClient.js JSRS library named jsrsExecute(). One of the parameters passed into jsrsExecute is the name of the JavaScript callback function. You'll write your callback function in JavaScript and place that function directly beneath the function you used to call jsrsExecute(). Both of these functions will reside in jsrsClient.cfm.

    3.  jsrsClient.js is a blackbox. It processes the information passed in via jsrsExecute(), then does an HTTP Get or Post (depending on the client browser) to the jsrsSvr.cfm file. jsrsClient.js exists on the client (it's sitting in the browser cache). It does a post to the server. This is key to understanding what is happening with JSRS. This post is a new thread that the user executed without even knowing it.

    4.  jsrsSvr.cfm is a server-side processing form that you write to handle the event. jsrsSvr.cfm is a standard CFML template with some special code for handling the information it receives from jsrsClient.js. Here's where you can make a database call, execute a stored procedure, or call into one of your business objects (a CFC, for example) to do something, like return a recordset. You then need to convert this recordset into a delimited list. Once you have this list constructed, you invoke the jsrsDispatch() method of the jsrsSvr.cfc object.

    5.  jsrsSvr.cfc is a CFC that I wrote that takes your delimited list and writes it back to your callback function (see step 2). The process flow is now back where it all started - on jsrsClient.cfm, but now it's in your callback function.

    6.  jsrsClient.cfm callback function uses the JavaScript split function to split your list into a JavaScript array. You then take these values from the array and write them into an HTML string. A little secret about JavaScript that you should know - JavaScript processes arrays about 10x faster than it processes lists. Thus, you should use arrays wherever possible. It's easy to take the array and convert it into a string by using the join method of the array object. See the jsrsClient.cfm code you downloaded for how to do this in the callback function.

    7.  Once you have your HTML string ready for display, simply write this to a <DIV> tag using the innerHTML property.

    Putting It All Together
    First, place jsrsClient.js somewhere on your Web site. I usually create a folder named "javascript" off of my webroot and place all .js files in there. That's a great place to put jsrsClient.js.

    Next, place jsrsSvr.cfc in your components directory - the directory where you are storing all of your CFCs for your application.

    jsrsClient.cfm
    Now, start working on your jsrsClient.cfm page (you don't need to name it jsrsClient.cfm - name it whatever you want). First, set an include reference in the <HEAD></HEAD> section of your template like so:

    <html>
    <head>
    <title>jsrsClient</title>
    <script language="javascript" src="/javascript/jsrsClient.js"></script>
    </head>

    Next, build your Web form. Here is the HTML from the Autofilter jsrsClient.cfm file:

    <form>
    <table>
    <tr>
    <td class="font1Bold">Product Name: </td>
    <td><input type="text" size="15" name="productNameTextBox" class="font1"
    onKeyUp="fcnGetProduct(this)"></td>
    </tr>
    <tr>
    <td></td>
    <td><div id="divListBox">
    <select name="ProductId" size="5" class="font1">
    <cfoutput query="RS">
    <option value="#ProductId#">#ProductName#</option>
    </cfoutput>
    </select>
    </div></td>
    </tr>
    </table>
    <div id="divDetail"></div>
    </form>

    Next, you'll write your calling and callback functions (nest these inside <script language="javascript"></script> tags). The Autofilter example makes two JSRS calls so there are two calling functions and two callback functions. The first RPC call fires with the onKeyUp() event of the text box. The second RPC call fires when the user selects a product in the list box.

    //autofilter JSRS Calling Function (Fires from onKeyUp() event)
    function fcnGetProduct(obj) {
    var aParams = new Array(1);
    aParams[0] = obj.value;
    jsrsExecute( '/jsrs/jsrsSvrMX.cfm', fcnCallbackGetProduct,
    'getProduct', aParams, 0); }

    Note the parameters being passed to jsrsExecute. These parameters are:

    1. '/jsrs/jsrsSvrMX.cfm': This is the template that will handle the server-side processing for JSRS.
    2. 'fcnCallbackGetProduct': This is the name of the callback function.
    3. 'getProduct': This is the <cfcase> action argument that will be used in jsrsSvr.cfm.
    4. 'aParams': jsrsExecute() requires that parameters be passed in via a JavaScript array.
    5. '0': This is a bit field set to either 0 or 1. If you set it to 1, JSRS will make an iFrame visible that it places on jsrsClient.cfm, providing a "window" to execute your jsrsSvr.cfm template. When you are debugging your jsrsSvr.cfm page, you'll set this value to 1 so that you can see any errors that your jsrsSvr.cfm page might be throwing. Once you have everything debugged, set this value back to 0 and effectively hide all the back-end processing under the blanket.
    Now you can start putting together your callback function. You'll probably need to spend some time in jsrsSvr.cfm at this point as well to build your server-side logic, as your callback function will receive its data from there. There is no right order to this process - just work the way that makes the most sense to you.

    //autofilter JSRS Callback Function
    function fcnCallbackGetProduct(optsStr) {
    aCallback = optsStr.split(delim); //split takes the string/list
    //returned from the RPC and converts it into an array
    var strHTMLArr = new Array(); //instantiate array to hold HTML
    var strHTML = ""; //initialize strHTML
    strHTMLArr[0] = '<select id="ProductId" name="ProductId" size="5"
    class="font1">';
    for (i=1; i<=aCallback.length; i++) {
    if(i % 2 == 0) {
    //value of loop is even
    strHTMLArr[i] = aCallback[i-1] + '</option>';
    }
    else {
    //value of loop is odd
    if (i == 1) {
    //highlight the first item in the array
    strHTMLArr[i] = '<option value="' + aCallback[i- 1] + '" SELECTED>';
    }
    else{
    strHTMLArr[i] = '<option value="' + aCallback[i-1] + '">';
    }
    }
    }
    strHTMLArr[i++] = '</select>';
    strHTMLArr[i++] = '<input type="button" value="View Detail" class="submit"
    onClick="fcnGetProductDetail()">';
    strHTML = strHTMLArr.join(""); //join() is the opposite of split().
    //It converts an array to a list using a delimiter, in this case ""
    //(no delimiter)
    document.getElementById("divListBox").innerHTML = strHTML;
    //write
    //out the completed html string to the div tag
    }

    Let's walk through the callback function. The first line is receiving our delimited list back from jsrsDispatch() (see jsrsSvr.cfc). We take that value, which I call "optsStr", and use the JavaScript split method to convert the list to a JavaScript array. Next, I initialize two JavaScript vars, strHTMLArr, and strHTML. strHTMLArr is a JavaScript array that will be used to hold HTML strings.

    Now, use a JavaScript FOR LOOP to iterate through the callback array, writing out HTML along the way. Once the loop is finished, I write in an HTML button (that will call the next JSRS calling function) and then use the join method of the callback array object. By specifying "" as the parameter of the join method, I am effectively concatenating the JavaScript Array into a string as opposed to a list.

    The remaining JavaScript functions are not presented here, but are available for download from www.sys-con.com/coldfusion/sourcec.cfm.

    jsrsSvr.cfm
    Now you'll write your jsrsSvr.cfm file. You can put this file in the same directory as your jsrsClient.cfm file or you can place it out in some global directory where you will place all of your JSRS methods (such as /jsrs located off of your webroot). If you use the latter method, you can use just this one single jsrsSvr.cfm file to handle requests from all of your jsrsClient.cfm files used throughout your application - you just include a new <cfcase></cfcase> statement for each JSRS RPC.

    I would suggest that you simply use the jsrsSvr.cfm file included in the package you downloaded and modify the code inside the <case></case> statements. Everything else can be left alone - and should be left alone unless you really know what you're doing. I've optimized the code in this file to run as fast as possible - using CF arrays.

    Here's the <cfcase> for getProduct. Remember "getProduct" was a parameter that was passed into jsrsExecute() in the calling function.

    <cfcase value="getProduct">

    <cfscript>
    //get recordset
    objNorthwind = CreateObject('component', 'quagmireV3.components.northwind');
    RS = objNorthwind.getProduct(aParams[1]);

    //build return string
    for(i=1; i LTE RS.RecordCount; i=i+1) {
    request.rStr = request.rStr & RS.ProductId[i] & variables.delim &
    RS.ProductName[i] & variables.delim;
    }

    //remove trailing delimiter
    variables.rStrLen = Len(request.rStr);
    if(variables.rStrLen GT 0)
    request.rStr = RemoveChars(#request.rStr#, #variables.rStrLen#, 1);
    </cfscript>

    </cfcase>

    There is no requirement to use CFScript. If you're not comfortable with CFScript, use regular CFML. I prefer CFScript syntax over regular CFML so I tend to use it a lot in my ColdFusion development.

    Walking through this code, I'm first getting a recordset of matching products using the "getProduct" method of my northwind.cfc. Here's that function:

    <cffunction name="getProduct" access="public" returntype="query">
    <cfargument name="ProductName" type="string" required="yes">
    <cfstoredproc procedure="spNW_Sel_Products_findByProductName"
    datasource="#this.DSN#">
    <cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" variable="@ProductName"
    value="#arguments.productName#" null="No">
    <cfprocresult name="RS1">
    </cfstoredproc>
    <cfreturn RS1>
    </cffunction>

    Next, I build a return string by using a FOR loop (you may use <cfoutput></cfoutput> instead if you wish). What's important is that you concatenate the delimited list.

    Last, I whack off the trailing delimiter. The variable request.rStr is now ready to be handed off to jsrsSvr.cfc so that it can be posted back to our callback function.

    Conclusion
    I hope that this concise overview of implementing JavaScript Remote Scripting will help advance your ability to develop UIs for the Web using ColdFusion. JSRS is a very powerful and effective tool for building Win32-like functionality into your Web forms without resorting to Flash.

  • About Grant Szabo
    Grant Szabo is a senior application developer for Global Cloud, Ltd. (www.globalcloud.net) where he delivers Microsoft .NET and ColdFusion solutions for Global Cloud's clients. Grant worked for Allaire (later Macromedia), as director, worldwide professional services for nearly two years in 2000-2001. He is certified in CF5 and CFMX and holds numerous Microsoft certifications including MCSD, MCDBA, MCSE, and MCSA.

    CFDJ LATEST STORIES . . .
    Adobe's Kevin Lynch and Microsoft's Scott Guthrie to Keynote AJAX World RIA Conference & Expo
    Two of the biggest launches in Rich Internet Application history took place in 2007/2008 when Adobe launched AIR 1.0 in February '08 and Microsoft launched Silverlight (September '07). At the 6th International AJAXWorld RIA Conference & Expo in October SYS-CON Events is delighted to be
    Voyager Offers Android, .NET CF, Java Runtime Support
    Recursion Software released a private beta version of their Voyager mobile platform, with powerful interoperability for Android, Microsoft .NET and Compact Framework (CF), all Java editions (JME CDC, JSE and JEE), and more than 15 embedded operating systems. The Voyager platform is a p
    AJAX and Enterprise RIA Tools - JSF, Flex, and JavaFX
    2008 is going to be an important year for Rich Internet Applications. Most organizations are delivering or planning to deliver Rich Internet Applications; however, at the same time, most IT managers are facing a dilemma: which Rich Internet Application technology and platform to use? T
    CFDynamics Announces Renewed Agreement with SmarterTools
    CFDynamics, a ColdFusion web host, has renewed an agreement with SmarterTools that will allow them to pass on immediate value to their customers. When a customers signs up for a dedicated hosting account they will now receive $750 worth of features including SmarterMail, SmarterStats a
    Microsoft's Virtualization Chief Mike Neil To Keynote SYS-CON's Virtualization Conference & Expo
    Mike Neil is general manager for virtualization strategy in the Windows Server Division at Microsoft. Mike is focused on the delivery of the Windows virtualization technology, including Windows Server 2008 Hyper-V, Microsoft Hyper-V Server and Virtual PC 2007. Mike also directs the tec
    SYS-CON's Virtualization Conference & Expo: Themes & Topics
    From Application Virtualization to Xen, a round-up of the virtualization themes & topics being discussed in NYC June 23-24, 2008 by the world-class speaker faculty at the 3rd International Virtualization Conference & Expo being held by SYS-CON Events in The Roosevelt Hotel, in midtown
    SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS
    SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
    Click to Add our RSS Feeds to the Service of Your Choice:
    Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
    myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
    Publish Your Article! Please send it to editorial(at)sys-con.com!

    Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021

    SYS-CON FEATURED WHITEPAPERS

    ADS BY GOOGLE