Doug's Resume
OO Lexicon
Chat with Doug!
Recent Entries
You may also be interested in...

heaters
hotels boeken in 7 sec
Engagement Rings
Online Dating Australia




SURF'S UP!
You:
Your Web Site:
<< May, 2008 >>
SMTWTFS
123
45678910
11121314151617
18192021222324
25262728293031
Search Blog

ColdFusion Jobs
Recent Comments
Re: The Perfect Alternative to Gas Powered Vehicles (by Thomas Messier at 5/09 12:47 PM)
Re: Promoting Family Unity: Lowering Your Utility Bills! (by Fernando Lopez at 5/07 10:12 PM)
Re: Why I Hate ORMs (a solicited rant) (by Richard at 5/06 10:56 AM)
Re: Why I Hate ORMs (a solicited rant) (by dougboude at 5/06 10:27 AM)
Re: Why I Hate ORMs (a solicited rant) (by Richard at 5/06 6:50 AM)
Re: Why I Hate ORMs (a solicited rant) (by Sean Corfield at 5/06 1:40 AM)
Re: Why I Hate ORMs (a solicited rant) (by Steve Bryant at 5/05 5:07 PM)
Re: Why I Hate ORMs (a solicited rant) (by dougboude at 5/05 4:36 PM)
Re: Why I Hate ORMs (a solicited rant) (by Mark Mandel at 5/05 3:52 PM)
Re: Why I Hate ORMs (a solicited rant) (by dougboude at 5/05 3:42 PM)
Categories
Archives
Photo Albums
Funnies (5)
Family (3)
RSS
Reciprocal Links

Powered by
BlogCFM v1.11

18 September 2006
Client-Side Interactivity without Ajax
Keeping response times down and interactivity high has and always will be two important priorities with web interfaces of any kind. For standard html interfaces, Ajax is all the buzz and is great when it’s necessary to maintain interaction with live data. But when a static version of the data will do just fine, there’s at least one other alternative that you may want to consider….

The <CFWDDX> tag provides a way for us to bridge the gap between dynamic data processed on the server side (specifically, queries returned by CFQUERY), and Javascript on the client side. What this does is give us the ability to transform query results into a form that we can manipulate via javascript, opening up some very useful potential for interactive Dynamic HTML.

In a nutshell, the process goes like this:
  • A CFQUERY tag is run;
  • The result is fed to CFWDDX with the ACTION attribute set to CFML2JS, which produces a Javascript-ready recordset;
  • The JS function that works with the recordset is created
That’s it. Now, for some of the nitty gritty details

In my example, I’m displaying a list of employees for the user to select from. What I want though is that whenever an employee is selected from the list, their detailed information is displayed to the side so that the user can determine if this is the right person or not. Like so:

(go 'head! click it!)

 

Ajax would work for this! Everytime an employee’s name is clicked on, we could make a call back to the server and grab that employee’s detailed information, then, using Javascript, output it to the designated portions of the template without ever reloading the page (yet still executing an HTTP call over the web). Or, we could just go ahead and retrieve the employees’ details during our initial query, since we had to retrieve their names and IDs anyway in order to produce the select list.
<!--- Using QuerySim to create the cfquery... --->
<cf_querysim>
    UserInfo
    userid,fname,lname,ext,title,dept,email
    200|Joe|Blow|2235|Supervisor|Reporting|jblow@nowhere.com
    300|Doug|Boude|2112|WaterBoy|Recreation|dboude@nowhere.com
    100|Stan|Cox|1225|Developer|IT|scox@nowhere.com
    400|Jim|Pickering|1513|Designer|IT|jpickering@nowhere.com
    500|John|Smith|1112|CEO|Management|JASmith@nowhere.com
    600|John|Smith|1123|Janitor|Building Maintenance|JLSmith@nowhere.com
</cf_querysim>

We could then take that query and create a Javascript-friendly version of it like so:
<script>
    <cfwddx action="cfml2js" input="#UserInfo#" toplevelvariable="users">
....
</script>
(Note that the attribute “TopLevelVariable” contains the value that will be used to name our recordset; that is the name it will be referenced as within our JS function.)

Within the body of our page, we’ll go ahead and create the select list just like we always do, only let’s add a function call to the onClick event that we can use to dynamically populate the targeted portions of our template:
<select onClick="getUserInfo(this.value);" size="8">
    <option value="" selected></option>
    <cfoutput query="userInfo">
        <option value="#userid#">#lname#, #fname#</option>
    </cfoutput>
</select> 

Additionally, let’s create the placeholders for our employee details:
<table>
    <tr>
        <td><STRONG>First Name:</STRONG></td><td><span id="fname"></span></td>
    </tr>
    <tr>
        <td><STRONG>Last Name:</STRONG></td><td><span id="lname"></span></td>
    </tr>
    <tr>
        <td><STRONG>Title:</STRONG></td><td><span id="title"></span></td>
    </tr>
    <tr>
        <td><STRONG>Department:</STRONG></td><td><span id="dept"></span></td>
    </tr>
    <tr>
        <td><STRONG>Extension:</STRONG></td><td><span id="ext"></span></td>
    </tr>
    <tr>
        <td><STRONG>Email:</STRONG></td><td><a id="email" href=""></a></td>
    </tr>
</table>
(Note: In my example, I use SPAN tags as placeholders as well as an Anchor tag, but any valid document object (form fields, div tags, etc.) can be targeted as placeholders, as long as they have a unique ID value)

At this point, our query has been converted into a ‘WDDXRecordset’ object. Behind the scenes, it’s a complex Javascript array, but the nice folks at Adobe wrapped it up for us with a set of functions that make it easy to get at the data using JS.  For example, to retrieve the first name from the first row, the call would look something like
Var thisName = getField(0,’fname’);
....
(Note that our first row is referenced with zero instead of one.)

Now all we need is a function to retrieve the employee details. It’s as simple as a Javascript FOR loop, leveraging the functions provided by the WDDXRecordset object:
function getUserInfo(userid){
    var i = 0;
    for (i=0; i < users.getRowCount(); i++){// loop through our wddx recordset...
        if(users.getField(i,'userid') == userid){//if the current record matches the ID passed in...
            document.getElementById('fname').innerHTML = users.getField(i,'fname');
            document.getElementById('lname').innerHTML = users.getField(i,'lname');
            document.getElementById('title').innerHTML = users.getField(i,'TITLE');
            document.getElementById('dept').innerHTML = users.getField(i,'dept');
            document.getElementById('ext').innerHTML = users.getField(i,'ext');
            document.getElementById('email').href = 'mailto:' + users.getField(i,'email');
            document.getElementById('email').innerHTML = users.getField(i,'email');
            return false; //ends this function call
        }
    }
    //if we made it here, then we found no match in our loop above; just blank everything out.
    document.getElementById('fname').innerHTML = "";
    document.getElementById('lname').innerHTML = "";
    document.getElementById('title').innerHTML = "";
    document.getElementById('dept').innerHTML = "";
    document.getElementById('ext').innerHTML = "";
    document.getElementById('email').href = "";
    document.getElementById('email').innerHTML = "";
}  
(Note: Although our function only utilized the getField() and getRecordCount() methods,  several more are available to us. You can take a gander at what else the WDDXRecordset provides at this LiveDocs link)

You can grab the entire template here if you'd like to see it all together.

Gotchas/things to remember:
  • some web hosts don't provide access to the CFIDE/Scripts directory. If this is the case, then you'll need to grab a copy of wddx.js and put it in your webroot, then reference it within a script tag prior to creating any wddx-powered functions, like so:
<script src="wddx.js"></script>//< - - - making sure wddx.js is loaded...
<script>
    <cfwddx action="cfml2js" input="#UserInfo#" toplevelvariable="users">
    function getUserInfo(userid){
        ...(remainder of js)
   
  • When referencing query fields, the js is not case sensitive (a getField(1,'title') will work as well as getField(1,'TITLE') ); However, javascript itself IS case sensitive, so referencing the target span tag you must use the exact case of the ID (getElementById('title') is NOT the same as getElementById('TITLE') )
  • The WDDXRecordset object contains a zero-based array, meaning that the index number of the first row will actually be referenced as zero rather than one (getField(0,’fname’) retrieves the value for first name from the first record)
That's it!

Doug out 



Posted by dougboude at 7:49 PM | PRINT THIS POST! |Link | 3 comments
Subscription Options

You are not logged in, so your subscription status for this entry is unknown. You can login or register here.

Re: Client-Side Interactivity without Ajax
If you are willing to give up the convience methods such as getField() or getRecordCount(), you can replace WDDXRecordset with Object and completely removing any dependancy to the wddx.js library. For example:





The resulting object (in CF terminology) is a structure of arrays, each key in the struct represents a column and the array within represents the different rows, so to determine the record count you might say the following:

if( newJSVariable['MYCOLNAME'].length > 0 )
alert('We have records!');
Posted by JAlpino on September 19, 2006 at 10:04 AM

Re: Client-Side Interactivity without Ajax
The code didn't show up, let me try again:

<cfwddx action="CFML2JS" input="#attributes.var#" output="variables.retJSobj" toplevelvariable="newJSVariable" />

<cfset variables.retJSobj = replaceNoCase(variables.retJSobj,"wddxrecordset","Object","ALL")>
Posted by JAlpino on September 19, 2006 at 10:06 AM

Re: Client-Side Interactivity without Ajax
nice
very nice....!!!
Posted by aajay on April 12, 2007 at 5:08 AM

Name:   Required
Email:   Required your email address will not be publicly displayed.

Want to receive notifications when new comments are added? Login/Register for an account.

Time to take the Turing Test!!!

What letter comes one place(s) before the letter L?
Type your answer exactly four time(s) in the designated box.

Type in the answer to the question you see above:

Your comment:

Sorry, no HTML allowed!