Using WDDX with ColdFusion and JavaScript ColdFusion Help

Now that you’ve seen an example of server-to-server communication using WDDX, let’s see how WDDX can be used in server-to-browser communication to enhance the user experience. As an added bonus, you’ll use WDDX to replace a server-side database that might otherwise have been implemented in MS Access.

We will use a simple example to highlight how to use WDDX with ColdFusion and JavaScript. This example will retrieve and display random quotes from a hidden frame using WDDX, effectively eliminating the need for a database of quotes on the server.

The Setup

This random quotation example uses JavaScript and DHTML to retrieve random quotes from a hidden frame. It requires Internet Explorer 4 or above, but could be written to accommodate Netscape 4 and above with some extra work. At no time is the entire database
of more than 1500 quotes downloaded to the browser but the quotes are updated at a specified interval without ever reloading the current page. The quotes are not in a database but in a text file that contains a WDDX recordset. This is a relatively simple demonstration of behind- the-scenes data retrieval, yet this technique is potentially useful in a number of areas including form validation and multi-step wizards utilizing DHMTL.

The Code

This application consists of three templates: quotes. cfm, quote_ ’01box. cfm, and quotes. cfm. Quotes. cfm is the page that displays the quotes. It co ‘ains almost allthe JavaScript code required to retrieve the quote from a hidden frame and display it to the user. Quote_toolbox. cfm handles all the WDDX parsing, selects a random quote, and .outputs it to the browser as a JavaScript object that is read by quotes. cfm. Finally a’l l ;..quotes. cfm displays all the quotes at once, arid enables the user to edit delete and add new quotes by way of a CFGRID Java applet. The quotes themselves are stored in the file quotes. wddx, which is included on the CD-ROM

Let’s begin with Listing 33.2 which shows quote_tool box. cfm. Throughout this section code lines are numbered for reference purposes.

In the first block of code (lines 2 to 23), you’re reading the WDDX recordset from a text file (quotes wddx) parsing it into a CFML recordset and storing that recordset in an application variable for future reference.

Note the use of the CFLOCK tag to prevent potential trouble caused by concurrent writes to the Quotes application variable. This technique provides better performance

than reading in the text file and parsing it once every page request. It could however become impractical with much larger recordsets because of the amount of memory consumed by storing the recordset in an application variable.

The next step is to select a random row from this recordset in lines 24 to 32. First, you seed the random number generator using the always-changing number returned by GetT ek Count. Then using the Rad Range function you select a random row number. Creating a new structure, you insert the quote and attribution from the current row in your recordset into the structure

,Now that you have your quote you need only output it as a JavaScript object in lines 39 to 49. The ; n; t function is a simple means of notifying any scripts running in quotes. efm that this page is finished loading and the new quote is available for reading. This will be discussed further when you look at quotes. efm

One of the lesser-known features of the CFWDOX tagje–p.pability to l nvert CFML objects to JavaScript code that, when run in the browser creates JavaScript objects that behave the same as their CFML equivalents. Although this does not directly use WODX, it does take advantage of the objects provided in the JavaScript WOOX module wdd)!:.j s. In the following code you’re simply taking the CFML structure created earlier and outputting it as JavaScript code which looks something like this:

objQuote-new Objeet():
objQuote.attribution-‘Steven Wright’:
objQuote.quote-‘If you’re not part of the solution, you’re part of the
precipitate.’ :

Next, consider quotes. efm, which displays the quotes and loads new ones. The template is shown in Listing 33.3.

1: <CFSETTING ENABLECFOUTPUTONLY-‘No’ SHOWDEBUGOUTPUT-‘No’>
2: <IDOCTYPE HTML PUBLIC ‘-//W3C//DTD HTML 4.0 Transitional//EN’>
3: <HTML>
4: <HEAD>
5: <TITLE>Quotes WOOX Demo</TITLE>
6: <STYLE TYPE-‘text/ess’>
7: body {
8: font-fallily: ‘Arial’. ‘Helvetica’, ‘sans-serif’;
9: font-size: lOpt;
10:’ }
11: .hotkey {
12: text-decoration: underline:
13: {

First you create a hidden frame with quote_tool box. cfm as its source in Lines 98 to 111: Note that if you were targeting Netscape Navigator with this sample you would be unable to use the I FRAME tag, but instead would have to make quotes. cfm and quote_too 1box. cfm part of the same frameset.

The remainder of the important code on this page is all client-side JavaScript. First you set up the global variables and the page initialization in lines 20 to 28. The first variable that you set is the bLoaded variable you set it equal to false. Whenever the quote_too 1box. cfm page finishes loading, it sets this variable to true so that the scripts on this page know that it’s okay to access objects in the toolbox frame. You set a variable with the number of seconds between quote reloads.

The; ni t function uses the after Load function in lines 27 to 29 to wait until the toolbox frame has finished loading before it sets up a global reference to this frame and kicks off the display-quote,load-new-quote sequence. The after Load command simply checks whether b Loaded is t rue; if not it waits 100 milliseconds and calls itself again. If b Loaded is true after Load executes the command passed in as its argument.

The time Refresh function in lines 39 to 49 updates the display of the New Quote button every second. When the countdown reaches zero, it calls the get Quote function which is in lines 50 to 61. The g”etQuote function reloads the toolbox frcuw with a unique value on the URL to ensure that the page is not cached. It uses the afterLoad
function to call display Quote (lines 62 to 75) after the toolbox frame is fully loaded. The display Quote function reads the current quote object from the toolbox frame and Inserts it into the quoteBox DIV.

The a”_quotes . cfm template began life as a quick and dirty wayof displaying all the quotes in the database at once so that people could more easily browse through them. As with all potentially interesting and or challenging techniques however it demanded to be made into something more and eventually ballooned into a full-featured quote management tool. It uses the CFGRIDJava applet to display the quotes and to allow adding editing and deleting of said quotes.

Let’s take a closer look, because this template is the first in this sample to modify the WDDX data  and along the way you’ll discover a limitation in the ColdFusion implementation of record sets as well as a way to work around this limitation. See Listing 33.4 for the complete template. Explanations of each pari will follow. This source code also uses the WDDX file (quotes. wddx)that contains all the quotes. This file is on the CD-ROM.

1: <CFSETTING ENABLECFOUTPUTONLY·’Yes’ SHOWD~BUGOUTPUT-‘No’>
2: <CFIF Not IsDefined(‘Application.Quotes’»
3: <!—
4: Read WDOX data from a file,
5: parse it into a recordset, and cache
6: the recordset in an application v«riable.
7:
8: Be aware that this takes up slightly more
9: than lOOK of RAM on the server.
10: —>
11: <CFLOCK TIMEOUT-‘S’ THROWONTIMEOUT-‘ Yes , NAME-‘QuotesVar’>
12: <CFFILE ACTION-‘ READ’ . .
13: FILE-“GetDirectoryFromPath(GetTemplatePath())’quotes.wddx’
14: VARIABLE-‘ strWDDX’>
15: <CFWDDX ACTION-‘WODX2CFML’ INPUT-“strWDDX” OUTPUT-‘Quotes’>
16: <CFSET Application.Quotes – Quotes>
17: </CFLOCK> .
18: <CFELSE>
19: <1—
20: Copy the cached recordset to a local variable.
21:. —>
22: <CFSET Quotes – Application.Quotes>
23: </CFIF>
24: <CFIF IsoefinedC’Form”;’Save’» ~1′;
25: <CFLOCK ~EOUT-‘5’ THROWONTIMEOUT-‘Yes’ NAME-‘QuotesVar’)
26: <CFSCRIPT>
27: RedoIos • false;
28: deleteList ~ “;
29: saveWQOX – false;
30: if (ArrayLenCForm.QuoteGrid.RowStatus.Action) GT 0) (
31: for.(i-1; i LTE ArrayLen(Fonn:QuoteGrid.RowStatOs’.Action); 1-i+1)
~~.••”32: “sw1″tch (Form.QuoteGrid.RowStatus .Action[i]) ‘1’ ” ,
33: ‘case ‘I,’,: ,( ‘-~.I’ ‘~••. , ‘
-34: II Insert a new row, and make ..the Quote 10 one greater ”
35: II than the ‘previous Quote 10. ~ote that this technique
36: II should not be used in place of a database in production
37: II systems, as concurrent users could quickly make your life
38: II very,difficult with this scheme.
39: QueryAddRowCQuotes);
40: QuerySetCellCQuotes, ‘Quote_Io’,
Quotes.Quote_Io[Quotes.RecordCount – 1] + 1);
41: Qu~rySetCellCQuotes, ‘Quote’, Form.QuoteGrid.Quote[i]);
42: QuerySetCellCQuotes, ‘Attribution’,
Form.QuoteGrid.Attributlon[i]);
43: saveWOoX – true;
44: break;
45: }
46: case ‘U’: (
47: II The Quote 10 is equal to the row number, so we can look up
48: II a particular row to modify without scanning the entire
recordset.
49: – QuerySetCellCQuotes, ‘Quote”, Form.QuoteGrid.Quote[i],
Form.QuoteGrid.Original.Quote_Io[i]);
50: QuerySetCellCQuotes, ‘Attribution”,
Form.QuoteGrid,Attribution[i], Form.QuoteGrid.Original,Quote_Io[i]);
. 51: saveWOoX – true;
52: break;
53: }
54: case ‘0″: (
55: II CF has no function to delete a row from a recordset.
56: II Assemble a,list of rows to be deleted, and build a new
,57: II recordset without them later.
58: deleteList – ListAppendCdeleteList,
Form.QuoteGrid.Original.Quote_Io[i]);
59: RedoIos – true;
60: saveWOoX • true;
61: break;
110: </STYLE)
Ill: </HEAD>
Ill: <BODY BGCOLOR-‘#FFFFFF’)
112: <H3>Quote Manager</H3)
113: <DIV ALIGN-‘center’) ,.
114: <CFFORM ACTION-‘all_quotes.cfm’ METHoD-‘POST’ ENABLECAB-‘Yes’
NAME-‘QuotesForm’)
115: <CFGRID NAME-‘QuoteGrid’ HEIGHT-‘370’ WIDTH-‘600′ QUERYa’Quotes’
INSERT-‘Yes’ DELETE-‘Yes’ SORT-‘ Yes , FONT-‘Arial’ BOLD-‘No’ ITALIC-‘No’
APPENDKEY-‘No’ HIGHLIGHTHREF-‘No’ GRIDDATAALIGN-‘LEFT’ GRIDLINES-‘Yes’
ROWHEADERS-‘ No’ ROWHEADERALIGN-‘ LEFT’ ROWHEADERITALIC-‘ No’ ROWHEADERBOLD-‘ No’
COLHEADERS-‘ Yes , COLHEADERALIGN-‘ LEFT’ COLHEADERITALIC-‘No~ COLHEADERBOLD-‘ No’-
SELECTMODE-‘EDI1’ PICTUREBAR-‘Yes’)
116: <CFGRIDCOLUMN NAME-‘Quote_ID’ HEADERALIGN-‘LEFT’ DATAALIGN-‘LEF-T’ .
BOLD-‘No’ ITALIC-‘No’ SELECT-‘No’ DISPLAY-‘ No , HEADERBOLD-‘No’ HEADERITALIC-‘No’)
117: <CFGRIDCOLUMN NAME-‘Quote’ HEADERALIGN-‘LEFT’ DATAALIGN-‘LEFT’
WIDTH-‘470’ _BOLD-‘No’ ITALIC-‘No’ SELECT-‘Yes’ DISPLAY-‘ Yes , HEADERBOLD-‘ No ,
HEADERITALIC-‘ No’)
118: <CFGRIDCOLUMN NAME-‘Attribution’ HEADERALIGNm’LEFT’ DATAALIGN-‘LEFT’
BOLD-‘No’ ITALIC-‘No’ SELECT-‘Yes’ DISPLAY-‘Yes’ HEADERBOLD-‘No’ HEADERITALIC-‘No’)
119: </CFGRID)
120: <BR)
121: <INPUT TYPE-‘submit’ NAME-‘ save , VALUE-‘Save Changes’) <INPUT
TYPE-‘button’ NAME-‘cancel’ VALUE-‘Back’
onClick-‘document.location.href-‘quotes.cfm”)
122:-</CFFORM>
123: </DIV>
124: </BODY>
125: </HTML)

The first part of this template is the same as quote_tool box. cfm. If Application . Quotes does not exist you read in the WDOX file parse it and store the resulting record set in your application variable. To be brief we’ll skip to the interesting parts.

Documenting the CFGRIDtag is beyond the scope of this chapter. Well assume you can find CFGRID documentation elsewhere, and just tell you what is different about this implementation. The main problem you encounter is that because there is no actual database behind this tag, not only can you not use the CF GRIDUP DATEtag, but you cannot even run a manual SQL query that says, “Update the row that has the ID of x.” You must modify your in-memory record set directly and here’s where you run into that limitation in ColdFusion’s record set functions: You can use the Query Set Cell function to modify the contents of a particular row in the record set provided you know the row number. However, there is no way to look up a particular row by the value of, say, a primary key field without scanning the entire record set until you find the one you’re looking for. You run into a problem that is similar but worse, when you need to delete a particular row. ColdFusion has no function to delete a row from a record set. Instead you must build a new record set that doesn’t contain the rows you want to eliminate and then replace the original recordset with the new one

The are two ways to get around” these limitations: You ~ modify the data s’tnicture or modify the data content. If you ~ere to re arrange the record set so that it is no longer a record set you’ve solved nearly all your problems. You set up the data as.a structure that has your primary key field as the name arid an array containing all the other data in the row as the value. This contains all the same data enables you to quickly look up and.modify rows based on an ID and will even enable you to delete a particular row. So what’s the problem? CFGRID doesn’t know what to do with a structure full of arrays. It understands only record sets. You can manually fill in a CFGRIO’ by using loops and CFGRIOROW but you would also have to rewrite the other pages to accommodate this new data structure and that’s a lot of work.What then is the solution? You’ already know that you can modify a particular row of a recordset if you know its row’riumber. Your first thought might be to simply . include Reco rdset .Cur rentRow as one of the hidden fields in the CFGRIOtag. Unfortunately, CFGRIOdoesn’t like that, because CurrentRow is a reserved word. You’re left with no viable alternative but to make the QUQte_IDin the recordset equal to the row number. It’s okay to modify the ID in this way because you don’t have to reconcile .> this data ‘with a back-end database at any point (if you. were using a database, this whole problem would be a non-issue). In any case, the ID that is returned by CFGRIO I now correct}y maps to the row number for quick and easy editing of existing rows.
Now that you’ve got insert and edit done, what about delete? There’s still no way to delete a row from a recordset. Because CFGRID enables you to delete multiple rows in one operation, you must assemble a list of rows to be deleted, then later create a new record set that doesn’t contain any ~( the records you don’t want. After this is done, you need to loop through the neW recorCiset and reset all the Quote_IO’s back to their row • .number; because the removal of rows will throw this off. After this is done, you’ve successfully implemented add, edit, and delete functionality for your in-memory record sel Allithat’s left is to update your application variable and save the modified record set as WOOx to your text file

Where Do We Go from Here?

For more information on WOOX, your first source should be http://’ItVNI. wddx. org. There, you will find the WOOX SOK, put together by Team Allaire member Nate Weiss as well as public discussion forums where you can ask questions or share your ideas. In the next chapter you willl~am about the CFREGISTRY tag, which enables your ColdFusion templates to access a configuration stored in the Windows registry, as ~eli’\s to createltS entries in the registry. In this way your ColdFusion applications, just like regular Windows applications can leverage the power of the registry as a central repository for configuration information in the Windows environment.

Posted on November 16, 2015 in WDDX

Share the Story

Back to Top
Share This