Passing Simple Variables to ColdFusion


In the "Serializing Packets with WddxSerializer" section of this chapter, you learned about a rather sophisticated way to pass complex, multifaceted data from JavaScript to ColdFusion: by serializing the data into a WDDX packet and posting it to the server. If you only need to pass simple values (such as strings or numbers) to the server, you can use simpler methods.

Passing Variables as URL Parameters

The simplest method of passing variables to ColdFusion is to simply pass them in the URL.

1.

Construct a URL that includes the values you want to pass as URL parameters, using the &name=value format you already know and love. If a value may include spaces, slashes, or any other "funny" characters (basically anything other than numbers and letters), you must use the escape() function to escape the characters; it does the same thing that URLEncodedFormat() does in CFML.

2.

Tell the browser to navigate to the new URL, using the document.location.href property or the document.location.replace() function.

The following snippet would create a function that causes the browser to navigate to a fictitious ColdFusion page called ShowFilms.cfm, passing URL parameters called Name and Rating in the URL:

 function loadPageBasedOnAge(name, age) {  var rating, url;  // Decide on a rating, based on the value  // of the JavaScript age variable  if (age < 13) {  rating = "G";  } else if (age < 18) {  rating = "PG-13";  } else {  rating = "R";  }  // Construct a new URL, passing the rating to ColdFusion  var url = "ShowFilms.cfm?Name=" + escape(name) + "&Rating=" + rating;  // Navigate to the new URL  document.location.href = url; } 

NOTE

This snippet is just meant to demonstrate the syntax you would use; it doesn't necessarily make any real-world sense. If you were simply collecting a name and age from the user, you would probably just use a normal HTML form to collect the information.


Passing Variables as Form Parameters

Another way to pass simple values is to use hidden form fields. To place a simple value (that is, any value that can be straightforwardly expressed as a string) into a form field, just use JavaScript code like the following, where myValue is the JavaScript value that you want to pass to the server:

 document.forms[0].MyHiddenField.value = myValue; 

If you wish, the form can then be submitted programmatically, like so:

 document.forms[0].submit(); 

Listing 17.12 creates a page that subjects the user to a short, three-question quiz about some important dates in his or her life. The user is given only ten seconds to answer each question. The time remaining ticks off visually, at tenth-of-a-second intervals (Figure 17.7).

Figure 17.7. A JavaScript-based timer is used to time the user's response.


If the user provides a valid date in time, the amount of time that they took to answer the question is passed to the server (in milliseconds). If the user fails to provide a valid date in time, the page automatically refreshes, displaying the next question in the sequence. When all three questions have been answered (or not answered), the user gets a summary page that shows their responses and the time it took for them to answer each question (Figure 17.8).

Figure 17.8. A JavaScript-based timer is used to time the user's response.


NOTE

This example is meant to introduce you to a potentially useful idea: passing values to ColdFusion that could, by their nature, only be known to JavaScript. It's not meant to serve as the foundation for a bulletproof quiz or e-learning application. That said, you could adapt this idea to produce a secure testing application that visually displays the time remaining for each section of the test.


Listing 17.12. TimedFormSubmission.cfmPassing JavaScript Variables as URL Parameters
 <!--- Name:        TimedFormSubmission.cfm Author:      Nate Weiss and Ben Forta Description: Demonstrates passing JavaScript              variables to ColdFusion in the URL. Created:     02/01/05 ---> <!--- Filename of the current ColdFusion page ---> <cfset CurrentPage=GetFileFromPath(GetBaseTemplatePath())> <!--- Keep track of the responses on the server ---> <cfparam name="SESSION.TimedResponses"          type="struct"          default="#StructNew()#"> <!--- We'll ask the poor user one of these questions at random ---> <cfset Messages[1]="When is your spouse's or partner's birthday?"> <cfset Messages[2]="When is your anniversary?"> <cfset Messages[3]="When is your ColdFusion application going to be done?"> <!--- Maximum number of milliseconds allowed per answer ---> <cfset MaxMillisecondsPerPage=10000> <!--- If the form is being submitted... ---> <cfif IsDefined("form.TimeElapsed")   AND IsDefined("form.AnswerDate")   AND Val(form.TimeElapsed) GT 0   AND IsDefined("URL.MessageNum")   AND URL.MessageNum GT 0   AND StructCount(SESSION.TimedResponses) EQ (URL.MessageNum - 1)>   <!--- Record the number of seconds elapsed --->   <!--- Don't allow the user to overwrite the number by reloading the page --->   <cfif IsDate(form.AnswerDate) OR (form.TimeElapsed GTE MaxMillisecondsPerPage)>     <cfif StructKeyExists(SESSION.TimedResponses, URL.MessageNum) EQ False>       <!--- Create a structure that holds user's answer and elapsed time --->       <cfset AnswerStruct=StructNew()>       <cfset AnswerStruct.TimeElapsed=form.TimeElapsed>       <cfset AnswerStruct.IsAnswered=IsDate(form.AnswerDate)>       <cfif AnswerStruct.IsAnswered>         <cfset AnswerStruct.AnswerDate=form.AnswerDate>       </cfif>       <!--- Save structure in SESSION.TimedResponses by the message number --->       <cfset SESSION.TimedResponses[URL.MessageNum]=AnswerStruct>     </cfif>   </cfif> </cfif> <html> <head> <title>Surprise Quiz</title> </head> <h2>Surprise Quiz</h2> <!--- If all the messages have been responded to Display the results of the quiz ---> <cfif StructCount(SESSION.TimedResponses) GTE ArrayLen(Messages)>   <body>   <!--- Display message --->   <!--- In a real application, the user would succeed sometimes... :) --->   <p><strong>Wow, you failed the quiz miserably.</strong><br>   Here are the response times for your answers:<br>   <ol>   <!--- For each of the user's answers --->   <cfloop from="1"           to="#ArrayLen(Messages)#"           index="i">     <cfoutput>       <li>         <!--- This is the message user was responding to --->         #Messages[i]#<br>         <!--- If the user provided a response --->         <cfif SESSION.TimedResponses[i].IsAnswered>           Answered "#SESSION.TimedResponses[i].AnswerDate#" in           #NumberFormat(SESSION.TimedResponses[i].TimeElapsed / 1000, "9.99")#           seconds<br><br>         <!--- If the user wasn't able to answer the question --->         <cfelse>           [was not answered in time]         </cfif>       </li>     </cfoutput>   </cfloop>   </ol>   <!---   Erase the SESSION.TimedResponses variable   The quiz will start over if the page is reloaded    --->   <cfset StructDelete(SESSION, "TimedResponses")>   <!--- Display message --->   <p>Dude (or dudette), you are in <strong>so much trouble</strong>.   Like, good luck tonight.<br>   <!--- Link to try again --->   <!--- Because SESSION.TimedResponses was erased, quiz will begin again --->   <p>If you want, you can <a href="TimedFormSubmission.cfm">try again</a>.<br> <!--- If not all the questions have been responded to, Provide a simple form interface for providing an answer ---> <cfelse>   <!--- Determine the message number to display now --->   <cfloop from="1"           to="#ArrayLen(Messages)#"           index="ShowMessageNum">     <cfif NOT StructKeyExists(SESSION.TimedResponses, ShowMessageNum)>       <cfbreak>     </cfif>   </cfloop>   <!--- Get the text for the message --->   <cfset Message=Messages[ShowMessageNum]>   <!--- Custom script functions --->   <script type="text/javascript"           language="JavaScript">     // Because these variables is declared outside of a function block,     // they are maintained by JavaScript at the page level     var msMaxPerQuestion=<cfoutput>#MaxMillisecondsPerPage#</cfoutput>;     var intervalHandle;     var msMomentPageWasLoaded;     // Function to increment the msTimeElapsed variable     // and place its value in the TimeElapsed hidden field     function fillTimeElapsed() {       // Determine how many milliseconds have elapsed so far       msTimeElapsed=new Date().valueOf() - msMomentPageWasLoaded;       // Place the time elapsed (in milliseconds) in the hidden field       document.forms[0].TimeElapsed.value=msTimeElapsed;       // Display the timer value       var msg=((msMaxPerQuestion - msTimeElapsed) / 1000).toFixed(1);       document.getElementById("elSecsElapsed").innerhtml=msg;       // If the time has elapsed       if (msTimeElapsed >= msMaxPerQuestion) {         // Stop the timer         window.clearInterval(intervalHandle);         // Submit the form         document.forms[0].submit();       };     }     // This funciton executes when the page first loads     function initPage() {       // Records the current time (as number of milliseconds since 1/1/1970)       msMomentPageWasLoaded=new Date().valueOf();       // Start the timer       intervalHandle=window.setInterval('fillTimeElapsed()', 100);       // Set focus to the AnswerDate input field       document.forms[0].AnswerDate.focus();     };   </script>   <!--- Call the fillTimeElapsed() function once every 10 milliseconds --->   <body onload="initPage()">   <!--- Self-submitting form --->   <cfform action="#CurrentPage#?MessageNum=#ShowMessageNum#"           method="Post"           onsubmit="window.clearInterval(intervalHandle)">     <!--- Hidden field to pass secondsElapsed variable to ColdFusion --->     <cfinput type="Hidden"              name="TimeElapsed">     <!--- Ordinary form field --->     <p>     <strong><cfoutput>#Message#</cfoutput></strong>     <br>     <cfinput type="Text"              name="AnswerDate"              required="Yes"              validate="date"              message="Um, fill in the date first.">     <br>     <p>Think fast, you're being timed!<br>     (time remaining: <span ></span>&nbsp;seconds)<br>     <!--- Submit button --->     <p>     <cfinput type="Submit"              name="sbmt"              value="Submit Answer">   </cfform> </cfif> </body> </html> 

When this page first appears in the browser, the onload event calls the initPage() function. Within initPage(), a global variable called msMomentPageWasLoaded is set to the current time (according to the browser machine's clock, and expressed as the number of milliseconds since midnight on January 1, 1970). In addition, the window.setInterval() method is used to create a sort of internal timer which executes the fillTimeElapsed() function once every 100 milliseconds (that is, ten times per second).

Within fillTimeElapsed(), a global local variable called msTimeElapsed is incremented by 100 each time the function is calledis calculated by subtracting the value in msMomentPageWasLoaded from the current time (again, in milliseconds). The msTimeElapsed, thus keeping track of the approximate number of milliseconds that have passed since the page first loaded. variable thus holds the number of milliseconds that have elapsed since the initPage() executed, which in turn is the number of milliseconds that have passed since the page first appeared in the browser.

The number of elapsed milliseconds is stored in the hidden form field named TimeElasped; this value will be available to ColdFusion as a normal FORM variable when the form is submitted. In addition, a formatted version of the number is displayed by setting the innerHTML property of the <SPAN> element called elSecsElapsed. The getElementById() syntax used here can be used to get or set the properties of any scriptable HTML element; the exact properties available will vary from browser to browser. The innerHTML property used here is supported by IE 4 and above and Netscape 6 and above (or other Mozilla-based browsers).

If the number of elapsed milliseconds exceeds the maximum number of milliseconds (in this example, 10,0000, or ten seconds), the timer is cleared using window.clearInterval(). The form is then submitted using the form's submit() method.

The rest of the code is relatively straightforward ColdFusion code that uses a structure called SESSION.TimedResponses to remember each user's responses as they encounter the three parts of the quiz. The structure is made up of smaller sub-structures, each containing a TimeElapsed property, an IsAnswered property that indicates whether the user provided an answer in time, and an AnswerDate property which is the user's actual response to the question (if any).

Opening Popup Windows

For better or for worse, one of the things that JavaScript is most used for most is to open popup windows. Much of the time, popup windows are an annoyance, but there are times when you may have a legitimate need to create one for your application. You can find a full discussion about popup windows in a JavaScript reference, but this section will quickly introduce you to the basics, emphasizing the fact that you can easily pass variables to ColdFusion as part of the popup-opening process.

To open a popup window, use the window.open() method, in the following form:

 window.open(popupURL, popupName, popupFeatures); 

The popupURL is the URL of the page to display in the popup window. The popupName is an optional target name for the popup window (if you provide the name of an existing window, the same window will be reused each time the method is called; if not, a new window is opened each time). The popupFeatures argument is an optional comma-separated list of window features, which you can use to control the size and position of the popup window. Table 17.16 lists most of the values you can supply in the popupFeatures string; consult a JavaScript reference for a complete listing.

Table 17.16. Window Features for the window.popup() Method

FEATURE

DESCRIPTION

width

The width of the popup window, in pixels.

height

The height of the popup window, in pixels.

top

The position of the window, in pixels, from the top of the screen.

left

The position of the window from the left edge of the screen.

resizable

Whether the window should be resizable (yes or no).

scrollbars

Whether scrollbars should appear in the window (yes or no). Even when no, the scrollbars only appear when necessary.

status

Whether the status bar should be displayed at the bottom of the popup window (yes or no).

toolbar

Whether the browser toolbar (with the next and back buttons and so on) should appear at the top of the window (yes or no).

menubar

Whether the usual browser menu bar should appear(yes or no).

location

Whether the URL location (the area where you type a new location to browse to) should appear at the top of the window (yes or no).


So, the following would open a popup window that is 300 pixels wide and 200 pixels wide, displaying content from the ShowFilm.cfm page:

 window.open("ShowFilm.cfm", "filmPopup", "width=300,height=200"); 

Of course, you are free to make the values of JavaScript variables available to the page you are displaying in the popup window. For instance, if you have a JavaScript variable called filmID, you can easily pass it as a URL parameter to the ShowFilm.cfm page, like so:

 window.open(  "ShowFilm.cfm?FilmfilmPopup",  "width=300,height=200"); 

If you provide a name in the popupName argument, the popup window will be reused each time a new window.open() method executes that uses the same name. This can help avoid a situation where there are too many popup windows strewn about the user's screen. In such a case, it is often helpful to add an onload="window.focus()" attribute to the <body> tag of the window being opened, so that it moves in front of any other windows each time it is reused, like so:

 <BODY onload="window.focus()"> 

The JSRelatedSelects4Popup.cfm page (included with this chapter's listings) provides a Show Film button that the user can use to display details about the selected film in a popup window, as shown in Figure 17.9. The detail page is provided by ShowFilm.cfm (also included with this chapter's listings), which includes the window.focus() line shown above so that the popup window for the film details always moves to the front as each film's details are loaded.

Figure 17.9. A popup window displays film details when the user clicks the Show Film button.




Advanced Macromedia ColdFusion MX 7 Application Development
Advanced Macromedia ColdFusion MX 7 Application Development
ISBN: 0321292693
EAN: 2147483647
Year: 2006
Pages: 240
Authors: Ben Forta, et al

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net