ColdFusion 9.0 Resources |
Using Ajax User Interface Components and FeaturesContents [Hide]Use Adobe ColdFusion Ajax-based layout and form controls and other Ajax-based user interface capabilities to create a dynamic application. For information about how ColdFusion uses the Ajax framework in general, or how to use ColdFusion Ajax data and programming capabilities, including binding to form data and managing JavaScript resources, see Using Ajax Data and Development Features. About Ajax and ColdFusion user interface featuresAjax (Asynchronous JavaScript and XML) is a set of web technologies for creating interactive web applications. Ajax applications typically combine:
ColdFusion provides many tools that simplify using Ajax technologies for dynamic applications. By using ColdFusion tags and functions, you can easily create complex Ajax applications. ColdFusion Ajax featuresColdFusion provides two types of Ajax features:
Data and development featuresColdFusion data and development features help you develop effective Ajax applications that use ColdFusion to provide dynamic data. They include many features that you can use with other Ajax frameworks, including Spry. The following data and development features are important for use with form and layout tags:
For more information about the data and development features and how to use them, see Using Ajax Data and Development Features. User Interface tags and featuresSeveral ColdFusion user interface elements incorporate Ajax features. The tags and tag-attribute combinations can be divided into the following categories:
The following table lists the basic tags and attributes that display the Ajax-based features. For information on additional forms-specific features, see Using Ajax form controls and features.
In addition to the tags and attributes, ColdFusion provides many JavaScript functions that let you control and manage the display. Many functions control the display of specific tags. For example, you can use JavaScript functions to dynamically display and hide the window. There are also several utility tags, such as the ColdFusion.getElementValue function that gets the value of a control attribute, or the ColdFusion.navigate function that displays the results of a URL in a container tag. For a complete list of all ColdFusion Ajax JavaScript functions, and detailed function descriptions, see Ajax JavaScript Functions in the CFML Reference. Using ColdFusion Ajax user interface featuresColdFusion Ajax user interface features let you create data-driven pages that update dynamically without requiring multiple HTML pages or page refreshes or non-HTML display tools such as Flash forms. Many user interface features use data binding to dynamically get data based on other data values: form field values, form control selections, and selections in Spry data sets. ColdFusion Ajax user interface controls and features can be divided into two major categories:
Display layout controls include the cflayout, cfpod, and cfwindow controls. Some of the data interaction features include the HTML cfgrid control, the cfmenu control, and dynamic autosuggest lists for text input controls. Most display layout and data interaction features can use data binding to dynamically interact with the user. ColdFusion Ajax user interface features are based on the Yahoo User Interface Library and the Ext JavaScript Library. Also, the cftextarea rich text editor is based on the FCKeditor text editor. In most situations, you require only ColdFusion tags and functions (including JavaScript functions) to create and manage the interface. However, advanced developers can modify the library code, particularly the CSS styles, to customize the controls in more complex ways. Controlling Ajax user interface layoutThe following layout tags let you dynamically control the display:
For information about how you can use these tags to submit form contents asynchronously, see Using Ajax containers for form submission. Using the cfdiv tagThe cfdiv tag is a general-purpose container that lets you use a bind expression to specify its contents. It therefore lets you dynamically refresh any arbitrary region on the page based on bind events. By default, the tag creates an HTML div region, but it can create any HTML tag with body contents. Unlike other ColdFusion Ajax container tags, you can use any type of bind expression to populate contents: CFC or JavaScript function, URL, or a string with bind parameters. As a result, the cfdiv tag provides substantial flexibility in dynamically populating the page contents. The cfdiv tag is also useful if you want a form to submit asynchronously. That is, whether or not you use a bind expression to populate the tag. If you submit a form that is inside a cfdiv tag (including in HTML returned by a bind expression), the form submits asynchronously. The response from the form submission populates the cfdiv region. (The cflayoutarea, cfwindow, and cfpod tags have the same behavior.) For example, you could have a page with a form that includes a list of artists, and lets you add artists. If the form is in a cfdiv tag, when the user submits the form, the entire page is not refreshed, only the region inside the cfdiv tag. For an example of using container controls for asynchronous forms, see Using Ajax containers for form submission. One use case for a cfdiv tag is an application where a cfgrid tag displays an employee list. Details of the selected row in the grid are displayed inside a cfdiv tag with a bind expression that specifies the cfgrid in a bind parameter. As users click through different employees on the grid, they get the employee details in the cfdiv region. The following simple example shows how you can use the cfdiv tag to get data using a bind expression. It uses binding to display the contents of a text input field in an HTML div region. When a user enters text in the input box and tabs out of it, or clicks another region of the application, the div region displays the entered text. The cfdiv tag.cfm file, the main application file, has the following contents. <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>cfdiv Example</title> </head> <body> <cfform> <cfinput name="tinput1" type="text"> </cfform> <h3> using a div</h3> <cfdiv bind="url:divsource.cfm?InputText={tinput1}" ID="theDiv" style="background-color:##CCffFF; color:red; height:350"/> </body> </html> The divsource.cfm file that defines the contents of the div region has the following code: <h3>Echoing main page input:</h3> <cfoutput> <cfif isdefined("url.InputText")> #url.InputText# <cfelse> No input </cfif> </cfoutput> Using layoutsThe cflayout tag controls the appearance and arrangement of one or more child cflayoutarea regions. The cflayoutarea regions contain display elements and can be arranged in one of the following ways:
You can configure a layout area to have scroll bars all the time, only when the area content exceeds the available screen size, or never. You can let layout area contents extend beyond the layout area. You can also nest layouts inside layout areas to create complex displays. You can define the layout area content in the cflayoutarea tag body. But, you can also use a bind expression to dynamically get the content by calling a CFC function, requesting a CFML page, or calling a JavaScript function. ColdFusion provides many JavaScript functions for managing layouts, including functions to collapse, expand, show, and hide border areas; and to create, enable, disable, select, show, and hide tabs. For a complete list of functions, see Ajax JavaScript Functions in the CFML Reference. The following example shows the use of a tabbed layout, including the use of JavaScript functions to enable and disable a tab, and to show and hide a tab. <html xmlns="http://www.w3.org/1999/xhtml"> <head> </head> <body> <!--- The tabheight attribute sets the height of all tab content areas and therefore the layout height. The width style controls the layout width. ---> <cflayout type="tab" name="mainTab" tabheight="300px" style="width:400px"> <!--- Each layoutarea is one tab. ---> <cflayoutarea title="First Tab" name="tab1"> <h2>The First Tab</h2> <p> Here are the contents of the first tab. </p> </cflayoutarea> <cflayoutarea title="Second Tab" name="tab2"> <h2>The Second Tab</h2> <p> This is the content of the second tab. </p> </cflayoutarea> </cflayout> <p> Use these links to test selecting tabs via JavaScript:<br /> <a href="" onClick="ColdFusion.Layout.selectTab('mainTab','tab1');return false;"> Click here to select tab 1.</a><br /> <a href="" onClick="ColdFusion.Layout.selectTab('mainTab','tab2');return false;"> Click here to select tab 2.</a><br /> </p> <p> Use these links to test disabling/enabling via JavaScript. Notice that you cannot disable the currently selected tab.<br /> <a href="" onClick="ColdFusion.Layout.enableTab('mainTab','tab1');return false;"> Click here to enable tab 1.</a><br /> <a href="" onClick="ColdFusion.Layout.disableTab('mainTab','tab1');return false;"> Click here to disable tab 1.</a><br /> </p> </body> </html> For an example that uses a bordered layout with cfpod children, see the next section. For another example of a tab layout, see the cflayoutarea tag in the CFML Reference. For an example of a bordered layout nested inside a layout area of a vertical layout, see cflayout in the CFML Reference. Styling layoutsThe cflayout and cflayoutarea tags have style attributes. The cflayout tag style attribute controls the style of the layout container, and sets default values for many, but not all, styles for the layout areas. For example, the color and background color styles of the cflayout tag set the default text and background colors in the layout areas. But the cflayout tag border style sets only the color of the border around the entire layout, not the layout area borders. The cflayoutarea tag style attribute controls the style of the individual layout area and overrides any corresponding settings in the cflayout tag. As is often the case with complex controls, the effects of layout and layout area styles can vary. For example, do not often specify the height style in the cflayout tag; instead, specify height styles on each of the cflayoutarea tags. The following simple example shows a tab layout with two layout areas. The layout has a light pink background color, and the layout areas have three pixel-wide red borders.: <cflayout name="layout1" type="tab" style="background-color:##FFCCCC"> <cflayoutarea title="area1" style="border:3px solid red"> Layout area 1 </cflayoutarea> <cflayoutarea title="area1" style="border:3px solid red"> Layout area 2 </cflayoutarea> </cflayout> Using podsThe cfpod control creates a content region with a title bar and surrounding border. You can define the pod content in the cfpod tag body, or you can use a bind expression to dynamically get the content from a URL. Pods are frequently used for portlets in a web portal interface and for similar displays that are divided into independent, possibly interactive, regions. You control the pod header style and body style independently by specifying CSS style properties in the headerStyle and bodyStyle attributes. The following example uses multiple pods inside cflayoutarea tags to create a simple portal. The time pod gets the current time from a CFML page. The contents of the other pods is defined in the cfpod bodies for simplicity. Each pod uses the headerStyle and bodyStyle attributes to control the appearance. The cfpodExample.cfm application has the following code: <html> <head> </head> <body> <cflayout name="theLayout" type="border" style="height:300;"> <cflayoutarea position="left" size="300" style="float:right;"> <cfpod width="300" name="theNews" title="All the latest news" headerstyle="background-color:##DDAADD; font-size:large; font-style:italic; color:black" bodyStyle="background-color:##FFCCFF; font-family:sans-serif; font-size:80%"> Contents of a news feed would go here. </cfpod> </cflayoutarea> <cflayoutarea position="center" align="center" > <cfpod name="theSports" width="500" title="What's new in your favorite sports" headerstyle="background-color:##AADDDD; font-size:large; font-style:italic; color:black" bodyStyle="background-color:##CCFFFF; font-family:sans-serif; font-size:90%"> Contents of a sports feed would go here. </cfpod> </cflayoutarea> <cflayoutarea position="right" size="302"> <cfpod width="300" height="20" name="thetime" title="The Weather" source="podweather.cfm" headerstyle="background-color:##DDAADD; font-style:italic; color:black" bodyStyle="background-color:##FFCCFF; font-family:sans-serif; font-size:80%" /> <cfpod width="300" name="thestocks" title="What's new in business" headerstyle="background-color:##DDAADD; font-size:large; color:black; font-style:italic" bodyStyle="background-color:##FFCCFF; font-family:sans-serif; font-size:80%"> Contents of a news feed would go here. </cfpod> </cflayoutarea> </cflayout> </body> </html> In this example, the podweather.cfm page contains only the following line. A more complete example would dynamically get the weather from a feed and format it for display. Partly Cloudy, 76 degrees Using pop-up windowsColdFusion HTML pop-up windows have the following characteristics:
Display and hide windowsYou display a window in the following ways:
You can hide a window that is currently showing by calling the ColdFusion.Window.hide function. You can use the ColdFusion.Window.onShow and ColdFusion.Window.onhide functions to specify JavaScript functions to run when a window shows or hides. The following example shows how you can create, display, and hide a window. It also shows several of the configuration options that you can set, including whether the user can close, drag, or resize the window. When you run the application, the cfwindow tag creates and shows Window 1. You can then hide it and reshow it. To show Window 2, click the Create Window 2 button, followed by the Show Window 2 button. You can then hide and show it. The following example shows the main application page: <html> <head> <script> <!-- //Configuration parameters for window 2. var config = {x:250,y:300,height:300,width:300,modal:false,closable:false, draggable:true,resizable:true,initshow:false,minheight:200,minwidth:200 } --> </script> </head> <body> <!--- Create a window with a title and show it. Don't allow dragging or resizing. ---> <cfwindow name="window1" title="CFML Window" draggable="false" resizable="false" initshow="true" height="250" width="250" x=375 y=0> <p> This content was defined in the cfwindow tag body. </p> </cfwindow> <form> <!--- Use the API to show and hide Window 1. ---> <input type="button" value="Show Window1" onClick="ColdFusion.Window.show('window1')"> <input type="button" value="Hide Window1" onClick="ColdFusion.Window.hide('window1')"><br /> <!--- Use the API to create, show, and hide Window 2 ---> <input type="button" value="Create Window2" onClick="ColdFusion.Window.create('window2', 'JavaScript Window', 'window2.cfm', config)"> <input type="button" value="Show Window2" onClick="ColdFusion.Window.show('window2')"> <input type="button" value="Hide Window2" onClick="ColdFusion.Window.hide('window2')"> </form> </body> </html> The window2.cfm file with the contents of Window 2 has the following contents: <cfoutput> <p> This content was loaded into window 2 from a URL.<br /> </p> </cfoutput> Use the window show and hide eventsYou can use the onShow and onHide events that are triggered each time a window shows and hides to control your application. To do so, call the ColdFusion.Window.onShow and ColdFusion.Window.onHide functions to specify the event handlers. Both functions take the window name and the handler function as parameters. The event handler functions can take a single parameter, the window name. The following example displays an alert message when a window hides or shows. The alert message includes the window name. The alert does not show when the window first appears, because the cfwindow tag uses the initShow attribute to initially display the window. An alert message does appear when the user hides the window by clicking the Toggle Window button or the close button on the window. <html> <head> <script language="javascript"> //Boolean value tacking the window state. var shown=true; //Functions to display an alert box when function onshow(name) { alert("window shown = " + name); } function onhide(name) { alert("window hidden = " + name); } //Initialize the window show/hide behavior. function initWindow() { ColdFusion.Window.onShow("testWindow", onshow); ColdFusion.Window.onHide("testWindow", onhide); } //Show or hide the window, depending on its current state. function toggleWindow() { if (shown) { ColdFusion.Window.hide("testWindow"); shown = false; } else { ColdFusion.Window.show("testWindow"); shown = true; } } </script> </head> <!-- The body tag onLoad event calls the window show/hide initializer function. --> <body onLoad="initWindow()"> <cfwindow name="testWindow" initshow=true title="test window" closable=true> Window contents </cfwindow> <cfform> <cfinput name="button" value="Toggle Window" onclick="javascript:toggleWindow()" type="button"/> </cfform> </body> </html> Control container contentsColdFusion provides a variety of ways to set and change container tag contents:
These different techniques provide you with flexibility in writing your code. For example, the ColdFuson.navigate function and the controlName_body variable provide similar functionality. However, with the controlName_body technique, you make explicit Ajax requests to get markup for the body, and the JavaScript functions in the retrieved markup might not work properly. ColdFusion.navigate takes care of these issues. Therefore, limit use of the controlName_body technique to simpler use cases. The following example shows how you can use various techniques to change container contents. It consists of a main page and a second windowsource.cfm page with text that appears in a main page window when you click a button. The main page has a cfpod control, two cfwindow controls, and the following buttons:
The following example shows the main page: <html> <head> <!--- Callback handler puts text in the window.cfm callback div block. ---> <script language="javascript"> var mycallBack = function(){ document.getElementById("callback").innerHTML = "<br><br> <b>This is printed by the callback handler.</b>"; } <!--- The error handler pops an alert with the error code and message. ---> var myerrorHandler = function(errorCode,errorMessage){ alert("[In Error Handler]" + "\n\n" + "Error Code: " + errorCode + "\n\n" + "Error Message: " + errorMessage); } </script> </head> <body> <cfpod height="50" width="200" title="The Title" name="theTitle"> This is a cfpod control. </cfpod><br> <!--- Clicking the link runs a ColdFusion.navigate function that replaces the second window's contents with windowsource.cfm. The callback handler then updates the window contents further. ---> <cfwindow name="w1" title="CF Window 1" initShow=true x=10 y=200 width="200"> This is a cfwindow control.<br><br> <a href="javascript:ColdFusion.navigate('windowsource.cfm','w2', mycallBack,myerrorHandler);">Click</a> to navigate Window 2</a> </cfwindow> <cfwindow name="w2" title="CF Window 2" initShow=true x=250 y=200 width="200"> This is a second cfwindow control. </cfwindow> <cfform> <!--- This button only replaces the second window body with the body of the windowsrc.cfm page. ---> <cfinput type="button" name="button" value="Simple navigate" onClick="ColdFusion.navigate('windowsource.cfm','w2');"> <!--- This button replaces the second window body and title content. ---> <cfinput type="button" name="button2" value="Change w2 body & title" onClick="w2_body.innerHTML='New body inner HTML';w2_title.innerHTML= 'New Title inner HTML'"> <!--- This button puts the second window title in the pod body. ---> <cfinput type="button" name="button3" value="Change pod body" onClick="theTitle_body.innerHTML=w2_title.innerHTML;"> </cfform> </body> </html> The following example shows the windowsource.cfm page: This is markup from "windowsource.cfm" <!--- The callback handler puts its output in the following div block. ---> <div id="callback"></div> Using menus and toolbarsThe cfmenu and cfmenuitem tags let you create vertical menus and horizontal toolbars. Define menus and toolbars
The following example shows a simple horizontal menu with submenus that uses JavaScript to change the display contents. When the user selects an end item in a menu, the text in the div block below the menu shows the path to the selected menu. <html> <head> </head> <body> <!--- The selected function changes the text in the selectedItemLabel div block to show the selected item. ---> <script type="text/javascript"> function selected(item) { var el = document.getElementById("selectedItemLabel"); el.innerHTML = "You selected: " + item; } </script> <!--- A horizontal menu with nested submenus. Clicking an end item calls the selected function. ---> <cfmenu name="hmenu" bgcolor="##9999ff" selectedfontcolor="##0000dd" selecteditemcolor="##ddddff"> <cfmenuitem display="Home" href="javascript:selected('Home');" /> <cfmenuitem display="File"> <cfmenuitem display="Open..."> <cfmenuitem display="Template" href="javascript:selected('File > Open... > Template');" /> <cfmenuitem divider="true" /> <cfmenuitem display="CSS" href="javascript:selected('File > Open... > CSS');" /> </cfmenuitem> <cfmenuitem display="Close" href="javascript:selected('File > Close');" /> </cfmenuitem> <cfmenuitem display="Help"> <cfmenuitem display="About" href="javascript:selected('Help > About');" /> </cfmenuitem> </cfmenu> <!--- A div with initial text. The selected function changes the text by resetting the innerHTML. ---> <div style=" margin-top: 100; margin-left: 10;"><span id="selectedItemLabel"> Please select an item!</span></div> </body> </html> Styling menusThe cfmenu and cfmenuitem tags have several attributes that let you easily control the menu appearance. These attributes consist of two types: basic and CSS style. Basic attributes, such as the cfmenu tag fontColor attribute, control individual menu characteristics. CSS style attributes let you specify a CSS style specification for a whole menu or part of a menu. The following information describes how the CSS style specifications interact and affect the menu style. For descriptions of all style-related attributes, see the cfmenu and cfmenuitem descriptions in the CFML Reference. The cfmenu and cfmenuitem tags provide a hierarchy of CSS style attributes that affect different parts of the menu. The following table describes these attributes in hierarchical order:
In addition to these styles, consider any style-related attributes, such as bgcolor, that you set on the cfmenu tag. When you design your menu, keep in mind the following issues:
For an application that shows some of the effects of menu style attributes, see the example in the cfmenuitem tag in the CFML Reference. ColdFusion attributes provide most style options that you are likely to require. However, you can, if necessary, modify the basic menu styles for all menus by editing the menu-related styles in the CSS files in the yui.css file. This file is located by default in the web_root/CFID/scripts/ajax/resources/yui directory. For more information about these styles, see the Yahoo! User Interface Library menu documentation. Uploading filesThe cffileupload tag lets you select multiple files and upload them to a server. Working with the cffileuploadThe cffileupload tag displays a dialog
that lets you upload multiple files. The following are the file
upload features:
Sending custom response to the callback and error handlersThe page/URL that handles the upload operation on the server can send back a struct with the keys status and message as shown here: <cffile action = "upload" destination = "#Expandpath('./upload')#" nameconflict="makeunique"> <cfset str.STATUS = 200> <cfset str.MESSAGE = "File Upload Successful"> <cfoutput>#serializeJSON(str)#</cfoutput> The following example illustrates the error handler: <cftry> <cffile action = "upload" destination = "#Expandpath('./upload')#"> <cfcatch type="any"> <cfset str.STATUS = 500> <cfset str.MESSAGE = "Error occurred while uploading the file"> <cfoutput>#serializeJSON(str)#</cfoutput> </cfcatch> </cftry> If the user tries to upload a file already present in the upload directory, it results in an error. The status and message are set to the specifications in the catch block. Using stylesThe attributes headercolor, textcolor, bgcolor, titletextalign, titletextcolor, and rollovercolor lets you style the file upload control. The following example illustrates the styling of file upload control: <cffileupload url="uploadAll.cfm" name="myuploader3" align="right" style="headercolor:silver;textcolor:1569C7;titletextalign:right;titletextcolor:black;bgcolor:74BBFB;"/> The following code shows how the attribute onUploadComplete is used: <!--- upload.cfm ---> <!--- <cffile action = "upload" destination = "#Expandpath('./upload')#" nameconflict="makeunique"> ---> <script language="javascript"> var uploadCompleteHandler = function(obj){ var result = "Upload Details:" + "\n\n"; for(var i=0;i < obj.length; i++){ result = result + "FILENAME: " + obj[i].FILENAME + "\n" + "STATUS: " + obj[i].STATUS + "\n" + "MESSAGE: " + obj[i].MESSAGE + "\n\n"; } } </script> <br> <cffileupload url="uploadall.cfm" name="myuploader" onUploadComplete="uploadCompleteHandler" maxUploadSize=100 stopOnError=false /> Using Ajax form controls and featuresColdFusion HTML forms and controls provide the following Ajax-based features:
Using Ajax form controlsColdFusion Ajax-based form controls let you submit Ajax forms in your applications without refreshing the entire page. Note: When you use Ajax to submit forms asynchronously
from the page, you cannot use cfinput or input tags
to upload files.
Using Ajax containers for form submissionThe ColdFusion Ajax container tags, cfdiv, cflayoutarea, cfpod, and cfwindow, automatically submit any forms that they contain asynchronously. When the form is submitted, the result returned by the action page replaces the contents of the container, but has no effect on the rest of the page. The following example shows this behavior in the submitSimple.cfm page: <html xmlns="http://www.w3.org/1999/xhtml"> <head> </head> <body> <cflayout type="vbox" name="layout1"> <cflayoutarea> <h3>This area is not refreshed when the form is submitted.</h3> <br /> </cflayoutarea> <cflayoutarea> <h3>This form is replaced by the action page</h3> <cfform name="myform" format="html" action="showName.cfm"> <cfinput type = "Text" name = "name"> <cfinput type = "submit" name = "submit" value = "Enter name"> </cfform> </cflayoutarea> </cflayout> </body> </html> In the following example, when you enter a name in the text input and click the Enter name button, the entered text replaces the form on the page, but the rest of the page is not refreshed. This example shows the showName.cfm action page: <cfif IsDefined("Form.name")> <cfoutput>The Name is : <strong>#Form.name#</strong></cfoutput> </cfif> Using the cfajaxproxy SetForm functionThe SetForm function of the proxy object created by the cfajaxproxy tag causes the proxy to pass the form values as arguments to the next CFC function that you call after the SetForm function. This way, you can pass the current values of fields in a form to a CFC function, which can then do the necessary processing and return a result. When you use the SetForm function, the following rules apply to the arguments in the called CFC function:
The following example shows how to use the SetForm tag to submit the contents of a login form. When the user clicks the Login! button, the doLogin function calls the proxy setForm function and then the AuthenticationSystem.cfc validateCredentials method. The validateCredentials method checks the password of the user and if it is valid, returns true to the proxy. Because the proxy is synchronous (the default), the doLogin method gets the returned value. If the value is true, it hides the login window; the user can then access the page contents. If the return value is false, the doLogin function displays a message in the login window title bar. The following example shows the setForm.cfm application: <html> <head> <script type="text/javascript"> function doLogin() { // Create the Ajax proxy instance. var auth = new AuthenticationSystem(); // setForm() implicitly passes the form fields to the CFC function. auth.setForm("loginForm"); //Call the CFC validateCredentials function. if (auth.validateCredentials()) { ColdFusion.Window.hide("loginWindow"); } else { var msg = document.getElementById("loginWindow_title"); msg.innerHTML = "Incorrect username/password. Please try again!"; } } </script> </head> <body> <cfajaxproxy cfc="AuthenticationSystem" /> <cfif structKeyExists(URL,"logout") and URL.logout> <cflogout /> </cfif> <cflogin> <cfwindow name="loginWindow" center="true" closable="false" draggable="false" modal="true" title="Please login to use this system" initshow="true" width="400" height="200"> <!--- Notice that the form does not have a submit button. Submit action is performed by the doLogin function. ---> <cfform name="loginForm" format="xml"> <cfinput type="text" name="username" label="username" /><br /> <cfinput type="password" name="password" label="password" /> <cfinput type="button" name="login" value="Login!" onclick="doLogin();" /> </cfform> </cfwindow> </cflogin> <p> This page is secured by login. You can see the window containing the login form. The window is modal; so the page cannot be accessed until you log in. <ul> <li><a href="setForm.cfm">Continue using the application</a>!</li> <li><a href="setForm.cfm?logout=true">Logout</a>!</li> </ul> </p> </body> </html> The following example shows the AuthenticationSystem.cfc file: <cfcomponent output="false"> <cffunction name="validateCredentials" access="remote" returntype="boolean" output="false"> <cfargument name="username" type="string"/> <cfargument name="password" type="string"/> <cfset var validated = false/> <!--- Ensure that attempts to authenticate start with new credentials. ---> <cflogout/> <cflogin> <cfif arguments.username is "user" and arguments.password is "secret"> <cfloginuser name="#arguments.username#" password="#arguments.password#" roles="admin"/> <cfset validated = true/> </cfif> </cflogin> <cfreturn validated/> </cffunction> </cfcomponent> Using the ColdFusion.Ajax.submitForm functionYou can use the ColdFusion.Ajax.submitForm function to submit form contents to a CFML page (or other active page) at any time. For example, you could use this function to automatically save a partially completed form. This function does not support uploading a file attachment to the form. When you use this function, you pass it the name of the form to submit and the URL of the page that processes the form. You can also specify the following optional parameters:
The following proof of concept example uses the ColdFusion.Ajax.submitForm function to submit two form fields to an asyncFormHandler.cfm page, which simply echoes the form values. The callback handler displays an alert with the returned information. <html> <head> <!--- The cfajaximport tag is required for the submitForm function to work because the page does not have any Ajax-based tags. ---> <cfajaximport> <script> function submitForm() { ColdFusion.Ajax.submitForm('myform', 'asyncFormHandler.cfm', callback, errorHandler); } function callback(text) { alert("Callback: " + text); } function errorHandler(code, msg) { alert("Error!!! " + code + ": " + msg); } </script> </head> <body> <cfform name="myform"> <cfinput name="mytext1"><br /> <cfinput name="mytext2"> </cfform> <a href="javascript:submitForm()">Submit form</a> </body> </html> The asynchFormHandler.cfm page consists of a single line, as follows: <cfoutput>Echo: #form.mytext1# #form.mytext2#</cfoutput> Using the ColdFusion.navigate function to submit a formThe ColdFusion.navigate JavaScript function can submit a form to a URL and have the returned output appear in a specified container control, such as a cfdiv, cflayout, cfpod, or cfwindow tag. This function lets you populate a control other than the one that contains the form when the user submits the data. You can also use the function to submit the form asynchronously when a user performs an action outside the form, such as clicking a menu item. For an example that uses this function, see the ColdFusion.navigate function in the CFML Reference. Using HTML gridsThe ColdFusion HTML cfgrid control lets you use a bind expression to dynamically populate the grid. HTML grids that use bind expressions are paged; as users navigate from page to page of the grid, the grid dynamically gets the data for only the required page from the data source. You also use bind expressions when you let users edit form contents, and other ColdFusion controls can bind to the grid. Also, HTML grids provide several JavaScript functions that you can use to manage and manipulate the grids. You can also create a static HTML grid by specifying a cfgrid tag that does not use a bind expression. With static grids, all data is initially available. In HTML mode, if you move the mouse over a column heading, a down arrow button appears. Clicking the button displays a list with the following options:
If you specify selectMode="edit" for an HTML grid, the grid displays Insert, Save, Cancel, and Delete buttons to the bottom bar. The Insert button opens a new editable row. The Save button commits any changes to the bind source. The Cancel button rolls back any changes that have not been saved. The Delete button deletes a selected row. You need not press the Save button after clicking the Delete button. Dynamically filling form dataHTML grids can dynamically fill the grid data by using a bind attribute with a bind expression that calls a CFC or JavaScript function, or a URL. The bind expression uses bind parameters to specify dynamic information provided by the grid and the values of any other form field attributes. Pass the following bind parameters to the bind expression. If you omit any of the parameters in the function call or URL, you get an error. These parameters send information about the grid and its state to the data provider function. The data for these parameters is provided automatically. You do not set any values manually.
Note: The cfgridsortcolumn and cfgridsortdirection parameters can
be empty if the user or application has not sorted the grid, for
example, by clicking a grid column header.
For more information on binding and bind parameters, see Using Ajax Data and Development Features in the CFML Reference. You can use optional parameters to specify additional information to pass to the called function. These parameters provide data that the called function requires to determine the data to return. For example, if the function returns the cities in a state, you would pass it the state name. Any or all of the optional function parameters can be bind parameters. A state name, for example, could come from the selection in a states cfselect control. If you do not want the grid to refresh automatically when other controls change, you can use the @none specifier on all optional bind parameters. Doing this, prevents automatic updating of the grid based on the bound control values. Use the ColdFusion.Grid.refresh JavaScript function to explicitly refresh the grid contents. For more information on the use of the @none specifier and explicitly refreshing the control, see Specifying bind parameters. If the grid supports user sorting of the data (the sort attribute is true), the function called by the bind expression must return data in the desired sorted order, and must use the values of the cfgridsortcolumn and cfgridsortdirection bind parameters to determine the order. Even if you do not allow user sorting, still pass these parameters to the function; otherwise, you get an error. Also, your function or action page must handle cases where these parameters are empty strings, because their values are not set until the user selects a column header to sort the grid, or you call the JavaScript ColdFusion.Grid.sort function. The format of the returned data depends on how you get the data:
When you specify a CFC in the bind attribute, use the queryConvertForGrid function to convert a query directly into a structure that you can use as your CFC return value. When you specify a CFML page in the bind attribute, use the queryConvertForGrid function to convert a query into a structure, and then use the serializeJSON function to convert the structure into a JSON representation. If you manually create a JavaScript object or its JSON representation, it must have two top-level keys:
Note: If a CFC manually creates a return structure,
the QUERY value can be a ColdFusion query object;
ColdFusion automatically converts it for remote access.
The following example defines an object that a JavaScript bind function can return to provide the data for a cfgrid tag: var myobject = {"TOTALROWCOUNT":6,"QUERY":{"COLUMNS":["EMP_ID","FIRSTNAME", "EMAIL"],"DATA":[[1,"Carolynn","CPETERSON"], [2,"Dave","FHEARTSDALE"], [3,"Linda","LSTEWART"], [4,"Aaron","ASMITH"], [5,"Peter","PBARKEN"], [6,"Linda","LJENNINGS"],]}}; The following example uses a bind expression and a CFC to populate a dynamic, paged, data grid. The CFML page contains the following form: <html xmlns="http://www.w3.org/1999/xhtml"> <head> </head> <body> <cfform name="form01"> <cfgrid format="html" name="grid01" pagesize=5 sort=true bind="cfc:places.getData({cfgridpage},{cfgridpagesize}, {cfgridsortcolumn},{cfgridsortdirection})"> <cfgridcolumn name="Emp_ID" display=true header="eid" /> <cfgridcolumn name="FirstName" display=true header="Name"/> <cfgridcolumn name="Email" display=true header="Email" /> </cfgrid> </cfform> </body> </html> The places.cfc file looks as follows. Notice that the query gets the full data set each time the function gets called. the QueryConvertForGrid function selects and returns only the required page of data: <cfcomponent> <cffunction name="getData" access="remote" output="false"> <cfargument name="page"> <cfargument name="pageSize"> <cfargument name="gridsortcolumn"> <cfargument name="gridsortdirection"> <cfquery name="team" datasource="cfdocexamples"> SELECT Emp_ID, FirstName, EMail FROM Employees <cfif gridsortcolumn neq "" or gridsortdirection neq ""> order by #gridsortcolumn# #gridsortdirection# </cfif> </cfquery> <cfreturn QueryConvertForGrid(team, page, pageSize)> </cffunction> </cfcomponent> The following example is equivalent to the previous one, but uses a URL bind expression in the main page and a CFML page to return the data. The main page contains the following form: <html xmlns="http://www.w3.org/1999/xhtml"> <head> </head> <body> <cfform name="form01"> <cfgrid format="html" name="grid01" pagesize=5 sort=true bind="url:getdata.cfm?page={cfgridpage}&pageSize={cfgridpagesize} &sortCol={cfgridsortcolumn}&sortDir={cfgridsortdirection}"> <cfgridcolumn name="Emp_ID" display=true header="eid" /> <cfgridcolumn name="FirstName" display=true header="Name"/> <cfgridcolumn name="Email" display=true header="Email" /> </cfgrid> </cfform> </body> </html> The following example shows the getdata.cfm page: <!--- Empty string; the default end of the query SQL. ---> <cfset queryEnd=""> <cfquery name="team" datasource="cfdocexamples"> SELECT Emp_ID, FirstName, EMail FROM Employees <cfif sortcol neq "" or sortdir neq ""> order by #sortcol# #sortdir# </cfif> </cfquery> <!--- Format the query so that the bind expression can use it. ---> <cfoutput>#serializeJSON(QueryConvertForGrid(team, page, pageSize))# </cfoutput> If your database lets you specify SQL to retrieve only the required page of data in a query, you can optimize efficiency by using such a query. Do not use the QueryConvertForGrid function. Instead, manually create the return structure and return only the single page of data. Ensure that you set the TotalRowCount field to the number of rows in the entire data set, not the number of rows in the returned page of data. Using the bindOnLoad attributeThe bindOnLoad attribute causes a control to execute its bind expression immediately when it loads, and not wait until the event that normally triggers the bind expression evaluation to occur. This way, the control can be filled with an initial value. This attribute is false by default for all ColdFusion Ajax controls that have the attribute, except cfdiv and cfgrid, for which it is true by default. Having a truebindOnLoad value on these controls ensures that they are populated when they load. When a control with a truebindOnLoad attribute is bound to a control that also binds when the page loads, the first and second control load themselves at the onLoad page event. Then the first control loads itself again in response to a change event from the second control when that control completes loading. So, the first control makes two Ajax calls, whereas it must make only one, when the second control finished loading. Because the cfinput, cfselect, and cftextarea control bindOnLoad attributes are false by default, you do not encounter any problems if a cfgrid or cfdiv tag binds to any of these controls and you do not explicitly set the bindOnLoad attributes. However, if the control does set its bindOnLoad attribute to true, set the cfgrid or cfdiv attribute to false to ensure that the control only fetches data when the control that it is bound to returns. You can also get a double loading if a grid binds to a Spry data set. By default, the grid and data set load data at page load, and then the grid loads data again in response to a selection change event from the data set when it sets focus to its first row. Set bindOnLoad to false to ensure that the grid fetches data only when it receives a selection change event from the data set. Dynamically editing grid contentsWhen you use a bind expression to get cfgrid data dynamically, you can also update the data source dynamically with user input, without requiring the user to submit the form. You can use dynamic updating to update or delete data in the data source. (To edit cfgrid data, select the contents of a field and type the new value; to delete a row, select a field in the row and click the delete button at the bottom of the grid.) You cannot insert new rows directly in a grid that uses a bind expression. To add rows, enter the data in a form, and make sure that the grid refreshes after the form has been submitted. To update or delete data dynamically, do the following:
When you update data dynamically, you can also use the onError attribute to specify the name of a JavaScript function to handle any errors that result in a CFC or URL returning an HTTP error status. The method must take two parameters: the HTTP error code and a text message that describes the error. The following example shows an onError handler function: <script type="text/javascript"> function errorhandler(id,message) { alert("Error while updating \n Error code: "+id+" \nMessage: "+message);} </script> The following example displays the members of a department and lets users edit the data in the fields. When the focus leaves the edited field an onChange event triggers and the form calls the editData CFC function to update the data source. <html xmlns="http://www.w3.org/1999/xhtml"> <head> <script type="text/javascript"> function errorhandler(id,message) { alert("Error while updating\n Error code: "+id+"\n Message: "+message); } </script> </head> <body> <cfform name="form01"> <cfgrid format="html" name="grid01" pagesize=11 stripeRows=true stripeRowColor="gray" bind="cfc:places.getData({cfgridpage},{cfgridpagesize}, {cfgridsortcolumn},{cfgridsortdirection})" delete="yes" selectmode="edit" onchange="cfc:places.editData({cfgridaction},{cfgridrow},{cfgridchanged})"> <cfgridcolumn name="Emp_ID" display=true header="Employee ID"/> <cfgridcolumn name="FirstName" display=true header="Name"/> <cfgridcolumn name="Email" display=true header="Email"/> </cfgrid> </cfform> </body> </html> The getData function is identical to the getData function in Dynamically filling form data. This example shows the editData function in the CFC: <cffunction name="editData" access="remote" output="false"> <cfargument name="gridaction"> <cfargument name="gridrow"> <cfargument name="gridchanged"> <cfif isStruct(gridrow) and isStruct(gridchanged)> <cfif gridaction eq "U"> <cfset colname=structkeylist(gridchanged)> <cfset value=structfind(gridchanged,#colname#)> <cfquery name="team" datasource="cfdocexamples"> update employees set <cfoutput>#colname#</cfoutput> = '<cfoutput>#value#</cfoutput>' where Emp_ID = <cfoutput>#gridrow.Emp_ID#</cfoutput> </cfquery> <cfelse> <cfquery name="team" datasource="cfdocexamples"> delete from employees where emp_id = <cfoutput>#gridrow.Emp_ID# </cfoutput> </cfquery> </cfif> </cfif> </cffunction> Binding controls to grid contentsYou can bind the contents of a form control to the data in a grid field by specifying a bind parameter as the form control bind attribute value. To do so, use the following syntax: <cfinput name="name" type="text" bind="{gridName.columnName}"> By default, each time the selected row in the grid changes, the bind parameter is re-evaluated, and the control value changes to the value of the specified column of selected grid cell. Grid JavaScript functionsYou can use the following JavaScript functions to manage an HTML format grid:
For more information, see the ColdFusion.Grid.getGridObject, ColdFusion.Grid.refresh, and ColdFusion.Grid.sort functions in the CFML Reference. Using the Boolean column and groupingThe example in this section shows how to use the Boolean column. The code also illustrates how to group data in a grid on a selected grid column. This example uses all types of Boolean representations. For grouping, groupField is set to active and the grid data is grouped accordingly. <cfset emps = querynew("firstname,department, salary,active")> <cfset queryaddrow(emps,10)> <cfset querysetcell(emps,"firstname","Debra",1)> <cfset querysetcell(emps,"department","Accounting",1)> <cfset querysetcell(emps,"salary","100000",1)> <cfset querysetcell(emps,"active","Y",1)> <cfset querysetcell(emps,"firstname","Doherty",2)> <cfset querysetcell(emps,"department","Finance",2)> <cfset querysetcell(emps,"salary","120000",2)> <cfset querysetcell(emps,"active","Yes",2)> <cfset querysetcell(emps,"firstname","Ben",3)> <cfset querysetcell(emps,"department","Law",3)> <cfset querysetcell(emps,"salary","200000",3)> <cfset querysetcell(emps,"active","true",3)> <cfset querysetcell(emps,"firstname","Aaron",4)> <cfset querysetcell(emps,"department","Accounting",4)> <cfset querysetcell(emps,"salary","200000",4)> <cfset querysetcell(emps,"active","1",4)> <cfset querysetcell(emps,"firstname","Josh",5)> <cfset querysetcell(emps,"department","CF",5)> <cfset querysetcell(emps,"salary","400000",5)> <cfset querysetcell(emps,"active",true,5)> <cfset querysetcell(emps,"firstname","Peterson",6)> <cfset querysetcell(emps,"department","Accounting",6)> <cfset querysetcell(emps,"salary","150000",6)> <cfset querysetcell(emps,"active","0",6)> <cfset querysetcell(emps,"firstname","Damon",7)> <cfset querysetcell(emps,"department","Finance",7)> <cfset querysetcell(emps,"salary","100000",7)> <cfset querysetcell(emps,"active","N",7)> <cfset querysetcell(emps,"firstname","Tom",8)> <cfset querysetcell(emps,"department","CF",8)> <cfset querysetcell(emps,"salary","100000",8)> <cfset querysetcell(emps,"active","false",8)> <cfset querysetcell(emps,"firstname","Adam",9)> <cfset querysetcell(emps,"department","CF",9)> <cfset querysetcell(emps,"salary","300000",9)> <cfset querysetcell(emps,"active",false,9)> <cfset querysetcell(emps,"firstname","Sean",10)> <cfset querysetcell(emps,"department","CF",10)> <cfset querysetcell(emps,"salary","250000",10)> <cfset querysetcell(emps,"active","No",10)> <cfform name="form01"> <cfgrid format="html" insert="yes" insertButton="Add Row" name="grid01" selectmode="edit" width=600 collapsible="true" title="Employees" autowidth="yes" query="emps" sort="yes" groupField="active"> <cfgridcolumn name="FirstName" header="FirstName"/> <cfgridcolumn name="Department" header="Department" /> <cfgridcolumn name="Salary" display=true header="Salary" type="numeric" values="1000000,1200000" valuesdisplay="1000000,1200000"/> <cfgridcolumn name="Active" display=true header="Contract" type="boolean" /> </cfgrid> </cfform> Using the date columnThe following example shows how to use the date column. In the code, startdatecolumn is of type date. A mask,Y/m/d is used. Y is year in four digits, m months with leading zero, and d the days with leading zero. <!--- using cfgridcolum type="date" ---> <cfset emps = querynew("firstname,department, salary,startdate")> <cfset queryaddrow(emps,3)> <cfset querysetcell(emps,"firstname","Debra",1)> <cfset querysetcell(emps,"department","Accounting",1)> <cfset querysetcell(emps,"salary","100000",1)> <cfset querysetcell(emps,"startdate","2009/1/1",1)> <cfset querysetcell(emps,"firstname","Doherty",2)> <cfset querysetcell(emps,"department","Finance",2)> <cfset querysetcell(emps,"salary","120000",2)> <cfset querysetcell(emps,"startdate","2005/2/21",2)> <cfset querysetcell(emps,"firstname","Ben",3)> <cfset querysetcell(emps,"department","Law",3)> <cfset querysetcell(emps,"salary","200000",3)> <cfset querysetcell(emps,"startdate","2008/03/03",3)> <cfform name="form01"> <cfgrid format="html" insert="yes" insertButton="Add Row" name="grid01" selectmode="edit" width=600 collapsible="true" title="Employees" autowidth="yes" query="emps" sort="yes" groupField="department"> <cfgridcolumn name="FirstName" header="FirstName"/> <cfgridcolumn name="Department" header="Department" /> <cfgridcolumn name="Salary" display=true header="Salary" type="numeric" values="1000000,1200000" valuesdisplay="1000000,1200000"/> <cfgridcolumn name="StartDate" display=true header="StartDate" type="date" mask="Y/m/d"/> </cfgrid> </cfform> For details of various types of masks that can be used, see the CFML Reference Guide. Using HTML treesAn HTML cftree tag creates an Ajax-based tree data representation that you can populate from a query or a bind expression. The behavior with a query is equivalent to the behavior of applet or Flash trees. Bind expressions let you populate the tree based on the values of other controls or Spry data sets. Also, when you use a bind expression, the tree loads dynamically, getting only the data required for the current display. Populating the tree using a bind expressionYou use the bind attribute and bind expressions to dynamically and incrementally load and display tree data as the user navigates the tree. The child tree items do not exist until the parent node expands. This behavior avoids prefilling a tree with large amounts of data. It lets the tree children change dynamically (you can optionally get the children each time the item expands) and can enhance application responsiveness. For more information about binding and bind parameters, see Binding data to form fields. Bind expressions in trees work in the following ways:
When you use a bind expression to populate a cftree control, specify a CFC function, JavaScript function, or URL, and pass the following bind parameters. If you omit either of the parameters from your function call or URL, you get an error. These parameters provide information about the tree and its state, and are automatically provided by the control.
The called function or URL cannot return nested arrays and structures, that is, it can only return a single level of items. When a function or URL is first called to populate the root-level tree items, the value passed in the cftreeitemvalue variable is the empty string. Your bind function can test for an empty string to determine that it is populating the root level of the tree. The @none event specifier is also useful if you use the ColdFusion.Tree.refresh JavaScript function to manually refresh the tree. When you call the Refresh function, the bind expression fetches data from all bind parameters, including @none parameters. If you specify @none in all bind parameters that specify other controls, the tree does not respond automatically to changes in the other controls, but it does pick up data from the bind parameters when you use the ColdFusion.Tree.Referesh function to explicitly refresh the tree. The format of the data that the function or URL in a bind expression must return depends on the type of bind expression
Each structure in the array of structures or objects defines the contents and appearance of the node for a child item. Each structure must have a VALUE field, and can have the following fields. Except for LEAFNODE, these structure keys correspond to cftreeitem attributes.
Note: If a CFC does not return a value field, you
do not get an error, but the tree does not work properly.
The LEAFNODE structure element is only used in the bind response structures. It must be a Boolean value that identifies whether the node is a leaf. If the value is true, the tree does not show a +/- expansion indicator in front of the node, and users cannot expand the node. If your bind expression specifies a JavaScript function, the function must use all-uppercase letters for the field names; for example, use VALUE and DISPLAY, not value and display. ColdFusion uses all capital letters in the structure key names. ColdFusion is not case-sensitive, so CFCs can use lowercase letters for the field names; JavaScript is case-sensitive, so the JavaScript function must match the uppercase field names. If you use a URL to get the tree items from a CFML page, you can use the serializeJSON function to convert the array to JSON format. If the array with the tree items is named itemsArray, for example, the following line specifies the page output: <cfoutput>#serializeJSON(itemsArray)#</cfoutput> Example 1: a simple treeThe following simple example creates a simple hierarchical tree of unlimited depth, with one node per level. Each node label (specified by the display attribute) identifies the node depth: The following example shows the CFML page: <cfform name="testform"> <cftree name="t1" format="html"> <cftreeitem bind="cfc:makeTree.getNodes({cftreeitemvalue},{cftreeitempath})"> </cftree> </cfform> The following example shows the maketree.cfc file with the getNodes method that is called when the user expands a node: <cfcomponent> <cffunction name="getNodes" returnType="array" output="no" access="remote"> <cfargument name="nodeitemid" required="true"> <cfargument name="nodeitempath" required="true"> <!--- The initial value of the top level is the empty string. ---> <cfif nodeitemid IS ""> <cfset nodeitemid =0> </cfif> <!--- Create an array with one element defining the child node. ---> <cfset nodeArray = ArrayNew(1)> <cfset element1 = StructNew()> <cfset element1.value = nodeitemid + 1> <cfset element1.display = "Node #nodeitemid#"> <cfset nodeArray[1] = element1> <cfreturn nodeArray> </cffunction> </cfcomponent> Handling leaf nodesCode that returns the information for leaf nodes of the trees must always set the LEAFNODE structure field to true. This prevents the tree from displaying a + expansion indicator in the tree leaf node tree entries and from attempting to expand the node. The following example shows how you use the LEAFNODE field. Example 2: a more complex tree with leaf node handlingThe following tree uses the cfartgallery database to populate a tree where the top level is the art medium, the second level is the artist, and the leaf nodes are individual works of art. When the user clicks an artwork, the application shows the art image. This example shows how to generate return values that are specific to the level in the tree and the parent value. It also shows the use of the LEAFNODE return structure element. In this application, the CFC return structure keys are specified in lowercase letters, and ColdFusion automatically converts them to uppercase. Notice that the database contains entries only for the painting, sculpture, and photography categories, so just those top-level tree nodes have child nodes. The following example shows the main application page: <html xmlns="http://www.w3.org/1999/xhtml"> <head> <!--- The loadimage function displays the image of the selected art. It is called when the user clicks the image item. ---> <script> function loadImage(img) { var imgURL = '<img src="/cfdocs/images/artgallery/'+img+'">'; var imgDiv = document.getElementById('image'); imgDiv.innerHTML = imgURL; } </script> </head> <body> <!--- The form uses a table to place the tree and the image. ---> <cfform name="ex1" action="ex1.cfm" method="post"> <table> <tr valign="top"> <td> <cftree name="mytree" format="html"> <!--- When you use a bind expression, you must have only one cftreeitem, which populates the tree level. ---> <cftreeitem bind="cfc:tree.getItems({cftreeitempath}, {cftreeitemvalue})"> </cftree> </td> <td> <div id="image"></div> </td> </tr> </table> </cfform> </body> </html> The following example shows the tree.cfc file: <cfcomponent output="false"> <cfset variables.dsn = "cfartgallery"> <!--- Function to populate the current level of the tree. ---> <cffunction name="getItems" returnType="array" output="false" access="remote"> <cfargument name="path" type="string" required="false" default=""> <cfargument name="value" type="string" required="false" default=""> <cfset var result = arrayNew(1)> <cfset var q = ""> <cfset var s = ""> <!--- The cfif statements determine the tree level. ---> <!--- If there is no value argument, the tree is empty. Get the media types. ---> <cfif arguments.value is ""> <cfquery name="q" datasource="#variables.dsn#"> SELECT mediaid, mediatype FROM media </cfquery> <cfloop query="q"> <cfset s = structNew()> <cfset s.value = mediaid> <cfset s.display = mediatype> <cfset arrayAppend(result, s)> </cfloop> <!--- If the value argument has one list entry, it is a media type. Get the artists for the media type.---> <cfelseif listLen(arguments.value) is 1> <cfquery name="q" datasource="#variables.dsn#"> SELECT artists.lastname, artists.firstname, artists.artistid FROM art, artists WHERE art.mediaid = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.value#"> AND art.artistid = artists.artistid GROUP BY artists.artistid, artists.lastname, artists.firstname </cfquery> <cfloop query="q"> <cfset s = structNew()> <cfset s.value = arguments.value & "," & artistid> <cfset s.display = firstName & " " & lastname> <cfset arrayAppend(result, s)> </cfloop> <!--- We only get here when populating an artist's works. ---> <cfelse> <cfquery name="q" datasource="#variables.dsn#"> SELECT art.artid, art.artname, art.price, art.description, art.largeimage, artists.lastname, artists.firstname FROM art, artists WHERE art.mediaid = <cfqueryparam cfsqltype="cf_sql_integer" value="#listFirst(arguments.value)#"> AND art.artistid = artists.artistid AND artists.artistid = <cfqueryparam cfsqltype="cf_sql_integer" value="#listLast(arguments.value)#"> </cfquery> <cfloop query="q"> <cfset s = structNew()> <cfset s.value = arguments.value & "," & artid> <cfset s.display = artname & " (" & dollarFormat(price) & ")"> <cfset s.href = "javaScript:loadImage('#largeimage#');"> <cfset s.children=arrayNew(1)> <!--- leafnode=true prevents node expansion and further calls to the bind expression. ---> <cfset s.leafnode=true> <cfset arrayAppend(result, s)> </cfloop> </cfif> <cfreturn result> </cffunction> </cfcomponent> Binding other controls to a treeColdFusion tags that use bind expressions can bind to the selected node of a tree by using the following formats:
The bind expression is evaluated each time a select event occurs on an item in the tree. If you specify any other event in the bind parameter, it is ignored. Tree JavaScript functionsYou can use the following JavaScript functions to manage an HTML tree:
For more information, see the ColdFusion.Tree.getTreeObject and ColdFusion.Tree.refresh functions in the CFML Reference. Using the rich text editorThe ColdFusion rich text editor lets users enter and format rich HTML text by using an icon-driven interface based on the open source FCKeditor Ajax widget. The editor includes numerous formatting controls, and icons for such standard operations as searching, printing, and previewing text. Text editor controls are not covered. For detailed information on the editor icons and controls, see http://wiki.fckeditor.net/UsersGuide. Note: Do not bind to a rich text area on load of a
page, for example, from another control, such as a text box.
The following example shows a simple rich text editor. When a user enters text and clicks the Enter button, the application refreshes and displays the formatted text above the editor region. <html xmlns="http://www.w3.org/1999/xhtml"> <head> </head> <body> <!--- Display the text if the form has been submitted with text. ---> <cfif isdefined("form.text01") AND (form.text01 NEQ "")> <cfoutput>#form.text01#</cfoutput><br /> </cfif> <!--- A form with a basic rich text editor and a submit button. ---> <cfform name="form01" > <cftextarea richtext=true name="text01" /> <cfinput type="submit" value="Enter" name="submit01"/> </cfform> </body> </html> Note: If you use the rich text editor in your pages,
you cannot configure your web server to have ColdFusion process
files with the .html or .htm extensions. The default HTML processor
must handle pages with these extensions.
Configuring the rich text editorYou can customize the rich text editor in many ways. The cftextarea attributes support some basic customization techniques. For more detailed information, see the FCKEditor website at http://wiki.fckeditor.net/. Defining custom toolbarsYou can use the following techniques to control the appearance of the toolbar:
The editor has a single toolbar consisting of a set of active icons and fields, and separators. The toolbar attribute lets you select the toolbar configuration. The attribute value specifies the name of a toolbar set, which you define in a FCKConfig.ToolbarSets entry in the cf_webRoot/CFIDE/scripts/ajax/FCKEditor/fckconfig.js file. The rich text editor comes configured with two toolbar sets: the Default set, which contains all supported editing controls, and a minimal Basic set. By default, the editor uses the Default set. To create a custom toolbar named BasicText with only text-editing controls, create the following entry in the fckconfig.js file, and specify toolbar="BasicText" in the textarea tag. FCKConfig.ToolbarSets["BasicText"] = [ ['Source','DocProps','-','NewPage','Preview'], ['Cut','Copy','Paste','PasteText','PasteWord','-','Print','SpellCheck'], ['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'], ['Bold','Italic','Underline'], ['Outdent','Indent'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyFull'], '/', ['Style','FontFormat','FontName','FontSize'], ['TextColor','BGColor'], ['FitWindow','-','About'] ]; This configuration defines a toolbar with two rows that contain a subset of the full tool set designed to support basic text editing. Follow these rules when you define a toolbar:
For a complete list of the valid toolbar entries, see the Default configuration in fckconfig.js. Defining custom stylesYou can add custom styles that users choose in the Styles selector and apply to selected text. To create a custom style, add a Style element to /CFIDE/scripts/ajax/FCKEditor/fckstyles.xml. The Style XML element has the following format:
For example, the following definition creates a style that makes the selected text bold and underlined: <Style name="Custom Bold And Underline " element="span"> <Attribute name="style" value="font-weight: bold; text-decoration: underline;"/> </Style> If you use a custom XML file, instead of fckstyles.xml, to define your styles, specify the filepath in the stylesXML attribute. Defining custom templatesThe editor includes a set of basic templates that insert HTML formatting into the textarea control. For example, the ImageandTitle template places a placeholder for an image on the left of the area, and a title and text to the right of the image. Then right-click the image area to specify the image source and other properties, and replace the placeholder title and text. You create your own templates by creating entries in cf_webRoot/CFIDE/scripts/ajax/FCKEditor/fcktemplates.xml file. Each template XML entry has the following format: <Template title="template title" image="template image"> <Description>template description</Description> <Html> <![CDATA[ HTML to insert in the text area when the user selects the template. ]]> </Html> </Template> The template title, image, and description appear in the Templates dialog box that appears when the user clicks the template icon on the rich text editor toolbar. The following example template defines a title followed by text: <Template title="Title and Text" image="template1.gif"> <Description>A Title followed by text.</Description> <Html> <![CDATA[ <h3>Type the title here</h3> Type the text here ]]> </Html> </Template> The name "Title and Text" and the template1.gif image appear in the template selection dialog box. If you use a custom XML file, instead of fcktemplates.xml, to define your templates, specify the file path in the templatesXML attribute. Defining custom skinsTo create a custom skin that you specify in the skin attribute, create a subdirectory of the cf_webRoot/CFIDE/scripts/ajax/FCKeditor/editor/skins directory. The name of this subdirectory is the name that you use to specify the skin in the skin attribute. The custom skin directory must contain an images subdirectory and have the following files:
Place all other images used by the skin (that are specified in the CSS files) in the images subfolder. The most common way of customizing the skin is to change the fck_editor.css and fck_dialog.css files. For information on the skin format and contents, see the comments in those files. Using the datefield input controlThe HTML cfinput control with a type value of datefield lets users select dates from a pop-up calendar or enter the dates directly in the input box. When you use the control, keep in mind the following considerations:
The following example shows a simple tabbed layout where each tab contains a form with several datefield controls.: <html> <head> </head> <body> <cflayout type="tab" tabheight="250px" style="width:400px;"> <cflayoutarea title="test" overflow="visible"> <br> <cfform name="mycfform1"> <div style="float:left;">Date 1: </div> <cfinput type="datefield" name="mydate1"><br><br><br> <div style="float:left;">Date 2: </div> <cfinput type="datefield" name="mydate2" value="15/1/2007"><br><br><br> <div style="float:left;">Date 3: </div> <cfinput type="datefield" name="mydate3" required="yes"><br><br><br> <div style="float:left;">Date 4: </div> <cfinput type="datefield" name="mydate4" required="no"><br><br><br> </cfform> </cflayoutarea> <cflayoutarea title="Mask" overflow="visible"> <cfform name="mycfform2"> <br> <div style="float:left;">Date 1: </div> <cfinput type="datefield" name="mydate5" mask="dd/mm/yyyy"> (dd/mm/yyyy)<br><br><br> <div style="float:left;">Date 2: </div> <cfinput type="datefield" name="mydate6" mask="mm/dd/yyyy"> (mm/dd/yyyy)<br><br><br> <div style="float:left;">Date 3: </div> <cfinput type="datefield" name="mydate7" mask="d/m/yy"> (d/m/yy)<br><br><br> <div style="float:left;">Date 4: </div> <cfinput type="datefield" name="mydate8" mask="m/d/yy"> (m/d/yy)<br><br><br> </cfform> </cflayoutarea> </cflayout> </body> </html> Note: In Internet Explorer versions previous to IE
7, this example shows the calendars for the first three fields in
a page behind the following input controls.
Using autosuggest text input fieldsWhen you create a text input (type="text") in HTML, use the autosuggest attribute to specify a static or dynamic source that provides field completion suggestions as the user types. Use the autosuggestMinLength attribute to specify the number of characters the user must type before first displaying any suggestions. Note: To place label text next to a cfinput control
that uses an autosuggest attribute and have it
display correctly in both Internet Explorer and Firefox, surround the
label text in an HTML div tag with a style="float: left" attribute.
Also if you have multiple controls, and place them on separate lines,
follow the input controls with three <br> tags,
as in the following example. Otherwise, the label and control do
not lay out properly.
<div style="float: left"> Name: </div> <cfinput name="userName" type="text" autosuggest="Andrew, Jane, Robert"> <br><br><br> The control suggests entries from a static list of values. To use a static suggestion list, specify the list entries in the autosuggest attribute, and separate the entries by the character specified by the delimiter attribute (by default, a comma), as the following example shows: <cfinput type="text" autosuggest="Alabama\Alaska\Arkansas\Arizona\Maryland\Minnesota\Missouri" name="city" delimiter="\"> In this example, if you type the character a (in uppercase or lowercase) in the cfinput control, the list of states that start with A appears in a drop-down list. You navigate to a selection by using the arrow keys, and press Enter to select the item. You also have the control suggest values from a dynamically generated suggestion list. To use a dynamic list, specify a CFC function, JavaScript function, or URL in the autosuggest attribute. Use the autosuggestBindDelay attribute to specify the minimum time between function invocations as the user types. This limits the number of requests that are sent to the server. If you use a dynamic list, the input field has an icon to its right that animates while suggestions are fetched. When you use a bind expression you must include a {cfautosuggestvalue} bind parameter in the function call or URL parameters. This parameter binds to the user input in the input control and passes it to the function or page. A CFC or JavaScript autosuggest function must return the suggestion values as a one-dimensional array or as a comma-delimited list. The HTTP response body from a URL must consist only of the array or list of suggestion values in JSON format. In ColdFusion, you can use the serializeJSON function to convert an array to JSON format. If an array with the suggestions is named nodeArray, for example, the following line would specify the only output on a CFML page that is called by using a bind expression with a URL: <cfoutput>#serializeJSON(nodeArray)#</cfoutput> You do not have to limit the returned data to values that match the cfautosuggestvalue contents, because the client-side code displays only the values that match the user input. In fact, the called function or page does not even have to use the value of the cfautosuggestvalue parameter that you pass to it. However, use the parameter if the returned data would otherwise be long. The following example shows how to use a bind expression to populate autosuggest lists. The Last Name text box displays an autosuggest list with all last names in the database that match the keys typed in the box. The First Name text box uses binding to the Last Name text box to display only the first names that correspond to the last name and the text entered in the box. The database query limits the responses to only include results that match the autosuggest criteria, so the autosuggest list displays all the returned results, and the suggestions only match if the database entry has a case-correct match. To test this example with the cfdocexamples database, type S in the first box and the autosuggest list shows Smith and Stewart. If you select Smith and enter A or J in the First Name box, you get a name suggestion. The following example shows the application: <html xmlns="http://www.w3.org/1999/xhtml"> <head> </head> <body> <cfform> Last Name:<br /> <cfinput type="text" name="lastName" autosuggest="cfc:suggestcfc.getLNames({cfautosuggestvalue})"><br /> <br /> First Name:<br /> <cfinput type="text" name="firstName" autosuggest="cfc:suggestcfc.getFNames({cfautosuggestvalue},{lastName})"> </cfform> </body> </html> The following example shows the suggestcfc.cfc file: <cfcomponent> <cffunction name="getLNames" access="remote" returntype="array" output="false"> <cfargument name="suggestvalue" required="true"> <!--- The function must return suggestions as an array. ---> <cfset var myarray = ArrayNew(1)> <!--- Get all unique last names that match the typed characters. ---> <cfquery name="getDBNames" datasource="cfdocexamples"> SELECT DISTINCT LASTNAME FROM Employees WHERE LASTNAME LIKE <cfqueryparam value="#suggestvalue#%" cfsqltype="cf_sql_varchar"> </cfquery> <!--- Convert the query to an array. ---> <cfloop query="getDBNames"> <cfset arrayAppend(myarray, lastname)> </cfloop> <cfreturn myarray> </cffunction> <cffunction name="getFNames" access="remote" returntype="array" output="false"> <cfargument name="suggestvalue" required="true"> <cfargument name="lastName" required="true"> <cfset var myarray = ArrayNew(1)> <cfquery name="getFirstNames" datasource="cfdocexamples"> <!--- Get the first names that match the last name and the typed characters. ---> SELECT FIRSTNAME FROM Employees WHERE LASTNAME = <cfqueryparam value="#lastName#" cfsqltype="cf_sql_varchar"> AND FIRSTNAME LIKE <cfqueryparam value="#suggestvalue & '%'#" cfsqltype="cf_sql_varchar"> </cfquery> <cfloop query="getFirstNames"> <cfset arrayAppend(myarray, Firstname)> </cfloop> <cfreturn myarray> </cffunction> </cfcomponent> Using the cfslider tagThe cfslider tag places a slider control, for selecting a numeric value from a range, in a ColdFusion form. The slider can be used within a cfform tag for forms in HTML and applet format. The cfslider is not supported with Flash forms. In HTML forms, you can specify maximum, minimum, and increment values, to help you quickly filter complex results. The available slider controls are: Vertical, with controls that can be adjusted to the top or bottom; Horizontal, with controls that can be adjusted to the left or right; Tip, that displays the values as data tips; and Snapping, that moves in incremental values. Manipulating slider at runtimeThe following code illustrates how you can manipulate a slider at runtime: <script language="javascript"> //use Coldfusion AJAX functions var sliderChange = function(slider,value) { //get slider name slidername = slider.getId(); //get slider value currValue = ColdFusion.Slider.getValue(slidername); //set a new slider value newValue = parseInt(currValue+10); ColdFusion.Slider.setValue(slidername,newValue); //hide slider if(confirm("Do you want to hide slider?")) { ColdFusion.Slider.hide(slidername); } //show slider if(confirm("Do you want to show slider?")) { ColdFusion.Slider.show(slidername); } //disable slider if(confirm("Do you disable the slider?")) { ColdFusion.Slider.disable(slidername); } //enable slider if(confirm("Do you enable the slider?")) { ColdFusion.Slider.enable(slidername); } } var sliderDrag = function(slider) { //get slider name slidername = slider.getId(); document.getElementById('currentSliderValue').innerHTML = "Current Slider value : <font color='red'><strong>" + ColdFusion.Slider.getValue(slidername) + "<strong></font>"; } </script> <br> <cfform name="frm1"> <p> <span id="currentSliderValue">Current Slider Value: <font color="red"><strong>50</strong></font></span><br> </p> </cfform> <p> <br><b>Volume</b>: <cfslider name="s" format="html" min=1 max=100 value="50" tip="yes" onChange="sliderChange" onDrag = "sliderDrag" vertical="no" width="200pt" > </p> Using geographical mapsThe cfmap tag lets you embed a geographical map within your ColdFusion page. The following are the supported map types:
Using the marker windowThe marker window opens when you click the marker icon in the map. It is used to provide information pertaining to the locations in the map, for example address or latitude and longitude. The marker window can be populated with static or dynamic content. Populating data using static contentTo manually populate data in the marker window, specify the value in the markerwindowcontent attribute. Populating dynamic data using bind expressionTo dynamically populate data, use the markerbind attribute with a bind expression that calls a CFC, JavaScript function, or a URL. The bind expression uses bind parameters to specify dynamic information and the values of any other form field attributes. Pass the bind parameters to the bind expression. If you omit any of the parameters in the function call or URL, you get an error. These parameters send information about the map and its state to the data provider function. The data for these parameters is provided automatically. You do not set any values manually. Provide the data as provided in the following code: <br> <cfoutput> <table> <tr> <td bgcolor='red'><h4><font color='white'>URL Bind Example</font></td> </tr> </table> Map Name: #cfmapname#<br> Latitude, Longitude: (#DecimalFormat(cfmaplatitude)#,#DecimalFormat(cfmaplongitude)#)<br> Address: #cfmapaddress#<br> </cfoutput> The following table provides details of the parameters:
The format of the returned data depends on how you get the data:
Use the showmarkerwindow attribute to control the display of the window. The following example uses a bind expression and a CFC to populate dynamic data using a CFC bind expression. The CFML page contains the following: <br> <cfmap centeraddress="Hobart, Tasmania, Australia" name="map1" type="map" tip="Hobart, Tasmania, Australia" zoomControl="small3d" markerbind="cfc:maps.getMapData({cfmapname}, {cfmaplatitude}, {cfmaplongitude}, {cfmapaddress})" showmarkerwindow = true> <cfmapitem name="m1" address="Taj Mahal, Agra, India" tip="Taj Mahal, Agra, India"> <cfmapitem name="m2" latitude="40.46" longitude="117.05" showmarkerwindow=true tip="Great Wall of China, Bejing"> <cfmapitem name="m3" address="Stonehenge, England" tip="Stonehenge, England" showmarkerwindow = false> </cfmap> The map.cfc is as follows: <cfcomponent> <cffunction name="getMapData" access="remote"> <cfargument name="cfmapname"> <cfargument name="cfmaplatitude"> <cfargument name="cfmaplongitude"> <cfargument name="cfmapaddress"> <cfsavecontent variable="markup"> <br> <cfoutput> <table> <tr> <td bgcolor='red'><h4><font color='white'>CFC Bind Example</font></td> </tr> </table> Map Name: #cfmapname#<br> Latitude, Longitude: (#DecimalFormat(cfmaplatitude)#,#DecimalFormat(cfmaplongitude)#)<br> Address: #cfmapaddress#<br> </cfoutput> </cfsavecontent> <cfreturn markup> </cffunction> </cfcomponent> The following example shows how to populate dynamic data using a JavaScript bind expression: <script language="JavaScript"> var getMapData = function(cfmapname, cfmaplatitude, cfmaplongitude, cfmapaddress){ var msg = ""; msg = msg + "Map Name: " + cfmapname + "<br>"; msg = msg + "Latitude,longitude: " + "(" + cfmaplatitude + "," + cfmaplongitude + ")" + "<br>"; msg = msg + "Address: " + cfmapaddress + "<br>"; //alert(msg); return "<br><table><tr><td bgcolor='red'><h4><font color='white'>" + "Javascript Bind Example" + "</font></td></tr></table><hr>" + msg; } </script> <cfmap centeraddress="Hobart, Tasmania, Australia" name="map1" type="map" tip="Hobart, Tasmania, Australia" zoomControl="small3d" markerbind="javascript:getMapData({cfmapname}, {cfmaplatitude}, {cfmaplongitude}, {cfmapaddress})" showmarkerwindow = true> <cfmapitem name="m1" address="Taj Mahal, Agra, India" tip="Taj Mahal, Agra, India"> <cfmapitem name="m2" latitude="40.46" longitude="117.05" showmarkerwindow=true tip="Great Wall of China, Bejing"> <cfmapitem name="m3" address="Stonehenge, England" tip="Stonehenge, England" showmarkerwindow = false> </cfmap> The following example shows how to populate dynamic data using a URL bind expression: <cfmap centeraddress="Hobart, Tasmania, Australia" name="map1" type="map" tip="Hobart, Tasmania, Australia" zoomControl="small3d" markerbind="url:mapdata.cfm?cfmapname={cfmapname}&cfmaplatitude={cfmaplatitude}&cfmaplongitude={cfmaplongitude}&cfmapaddress={cfmapaddress}" showmarkerwindow = true > <cfmapitem name="m1" address="Taj Mahal, Agra, India" tip="Taj Mahal, Agra, India"> <cfmapitem name="m2" latitude="40.46" longitude="117.05" showmarkerwindow=true tip="Great Wall of China, Bejing"> <cfmapitem name="m3" address="Stonehenge, England" tip="Stonehenge, England" showmarkerwindow = false> </cfmap> Specifying Google map keyThe Google Maps API key is required to embed Google Maps in your web pages. The following URL provides details of how to sign up for the Google Maps API key: http://code.google.com/apis/maps/signup.html Currently, ColdFusion supports only embedding of Google map. To generate a map, provide a valid Google map API key, and specify the latitude and longitude of the location, or the address of the location. The Google map API key can be specified in the following ways:
Styling markersYou can specify the following:
Using the cfprogressbar tagThe cfprogressbar tag has the following
characteristics:
Progress bar modesThe progress bar supports the following two modes: Dynamic modeUser specifies the bind expression to provide data for the progress bar to display. The bind attribute specifies a function that determines the indicator length. The following CFM code shows how to use a CFC bind expression: <cfajaxproxy cfc="pbar" jsclassname="pbar"> <head> <script> var utils = new pbar(); var count = 0; var init = function() { document.getElementById('cfpbLabel').style.display = 'block'; ColdFusion.ProgressBar.show('pBar'); ColdFusion.ProgressBar.start('pBar'); } var hideProgessBar = function() { document.getElementById('cfpbLabel').style.display = 'none'; ColdFusion.ProgressBar.hide('pBar'); utils.resetStatus(); } </script> </head> <cfform> <div id="cfpbLabel" style="display:none"> Saving File: </div> <cfprogressbar name="pBar" autodisplay=false bind="cfc:pbar.getProgessData()" onComplete="hideProgessBar" width="400" > <cfset ajaxOnLoad('init')> </cfform> The following pb.cfc has the function that returns data for the progressbar: <cfcomponent> <cffunction name="resetStatus" access="remote"> <!--- Clear count from session so that next time the progress bar runs from the start time. ---> <cfif session.count gte 10> <cfset structdelete(session,"count")> </cfif> </cffunction> <cffunction name="getProgessData" access="remote"> <!--- use a count to track progress ---> <cfif not isdefined('session.count')> <cfset session.count = 1> <cfelse> <cfset session.count = session.count + 1 > </cfif> <!--- struct with status and message components of the progressbar ---> <cfset data = {status=session.count * 0.1,message=(session.count * 10) & "%"}> <cfreturn data> </cffunction> </cfcomponent> The following CFM code explains how to use the URL bind expression: <head> <script> var init = function() { document.getElementById('cfpbLabel').style.display = 'block'; ColdFusion.ProgressBar.show('pBar'); ColdFusion.ProgressBar.start('pBar'); } var hideProgessBar = function() { document.getElementById('cfpbLabel').style.display = 'none'; ColdFusion.ProgressBar.hide('pBar'); } </script> </head> <cfform> <div id="cfpbLabel" style="display:none"> Saving File: </div> <cfprogressbar name="pBar" autodisplay=false bind="url:progressdata.cfm" onComplete="hideProgessBar" width="400" > <cfset ajaxOnLoad('init')> </cfform> The following is the Progressdata.cfm: <!--- use a count to indicate progress ---> <cfif not isdefined('session.count')> <cfset session.count = 1> <cfelse> <cfset session.count = session.count + 1 > </cfif> <!--- the struct to be sent back; using the populate the status and message components of the progressbar ---> <cfset data = {status=session.count * 0.1,message=(session.count * 10) & "%"}> <!--- clear count from session to start afresh the next time the program is run ---> <cfif session.count eq 10> <cfset structdelete(session,"count")> </cfif> <!--- data sent back via URL binds must use SerializeJSON() ---> <cfoutput>#SerializeJSON(data)#</cfoutput> The following CFM code has the JavaScript bind expression: <head> <script> var count = 0; var init = function() { document.getElementById('cfpbLabel').style.display = 'block'; ColdFusion.ProgressBar.show('pBar'); ColdFusion.ProgressBar.start('pBar'); } var hideProgessBar = function() { document.getElementById('cfpbLabel').style.display = 'none'; ColdFusion.ProgressBar.hide('pBar'); } var getProgessData = function() { count++; if(count > 10) return {STATUS:1,MESSAGE:"Done"} else return {STATUS:count*0.1,MESSAGE:(count * 10) + "%"} } </script> </head> <cfform> <div id="cfpbLabel" style="display:none"> Saving File: </div> <cfprogressbar name="pBar" autodisplay=false bind="javascript:getProgessData()" onComplete="hideProgessBar" width="400" > <cfset ajaxOnLoad('init')> </cfform> Manual modeIn the manual mode, you specify the duration the progress bar takes to complete the display of progress. In the following example, autodisplay is set to false as a result of which the progress bar is not shown when the page is first loaded. When the page is loaded, init function is invoked and the function displays and runs the progress bar. The default interval used in this mode is one second. <head> <script> var init = function() { document.getElementById('cfpbLabel').style.display = 'block'; ColdFusion.ProgressBar.show('pBar'); ColdFusion.ProgressBar.start('pBar'); } var hideProgessBar = function(){ document.getElementById('cfpbLabel').style.display = 'none'; ColdFusion.ProgressBar.hide('pBar'); } </script> </head> <cfform> <div id="cfpbLabel" style="display:none"> Saving File: </div> <cfprogressbar name="pBar" duration="10000" autodisplay=false onComplete="hideProgessBar" width="400" /> <cfset ajaxOnLoad('init')> </cfform> Working with a progress bar at runtimeThis section illustrates how to use the JavaScript API to update the progress bar status. The following CFM code loads a progress bar using the JavaScript API ColdFusion.ProgressBar.updatestatus. On program load, intit function displays the progress bar and calls the getProgressData JavaScript function to manually update the progress bar. The getProgressData function assigns the status and message variables passed to the JavaScript API update status. While working with a progress bar at runtime, ensure that you specify a dummy duration (for instance, duration=5000). Even though the custom JavaScript function decides the actual duration, duration is a mandatory attribute. <cfajaxproxy cfc="pbar" jsclassname="pbar"> <head> <script> var utils = new pbar(); var init = function() { document.getElementById('cfpbLabel').style.display = 'block'; ColdFusion.ProgressBar.show('pBar'); getProgessData(); } var hideProgessBar = function() { document.getElementById('cfpbLabel').style.display = 'none'; ColdFusion.ProgressBar.hide('pBar'); } var getProgessData = function() { for(i=1;i <= 10;i++) { var status = parseFloat(i * 0.10); var message = Math.round(status * 100) + "%"; ColdFusion.ProgressBar.updateStatus('pBar',status,message); utils.sleep(1000); } hideProgessBar(); } </script> </head> <cfform> <div id="cfpbLabel" style="display:none"> Saving File: </div> <cfprogressbar name="pBar" autodisplay=false duration=15000 onComplete="hideProgessBar" width="400" > <cfset ajaxOnLoad('init')> </cfform> The sleep function in the following CFC provides sleep functionality in the JavaScript code: <cfcomponent> <cffunction name="sleep" access="remote"> <cfargument name="timetosleep" default="1000"> <cfset sleep(timetosleep)> </cffunction> </cfcomponent> Using the cfmessagebox tagThe cfmessagebox tag lets you define controls for displaying pop-up messages. In addition to the standard alert box, this tag lets you include a prompt and entry field in the box. Using confirm dialogThe following code shows how to build a confirm message box with two buttons YES and NO. <cfmessagebox type="confirm" name="msgbox1" title="Confirm Dialog" message="Do you want proceed?" buttonType="YesNo" icon="info" labelYes="Click Yes to continue" labelNo="No" x=100 y=200> <!--- This example illustrates usage of the Confirm dialog in "YesNoCancel" mode ---> <cfmessagebox type="confirm" name="msgbox2" title="Save File" message="Do you want to save the file?" buttonType="YesNoCancel" icon="question" labelYes="Click Yes to save the file" labelNo="No" labelCancel="Quit" width="400" x=500 y=200> <br><br> <input type="button" name="confirm1" onClick="javascript:ColdFusion.MessageBox.show('msgbox1');" value="YesNo Confirm" > <input type="button" name="confirm2" onClick="javascript:ColdFusion.MessageBox.show('msgbox2');" value="YesNoCancel Confirm" > Styling a message boxThe bodyStyle attribute, a CSS style specification for the body of the message box helps you to style the message. As a general rule, use this attribute to set color and font styles. The following example illustrates the usage of the bodyStyle attribute: <cfmessagebox type="alert" name="msgbox1" title="Download Status" message="File Download Complete" icon="info" width="400" bodyStyle="background-color:white;color:blue" x=300 y=200> <br><br> <input type="button" name="alert" onClick="javascript:ColdFusion.MessageBox.show('msgbox1');" value="Alert MessageBox" > |