Using Ajax User Interface Components and Features

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 features

Ajax (Asynchronous JavaScript and XML) is a set of web technologies for creating interactive web applications. Ajax applications typically combine:

  • HTML and CSS for formatting and displaying information.

  • JavaScript for client-side dynamic scripting

  • Asynchronous communication with a server using the XMLHttpRequest function.

  • XML or JSON (JavaScript Object Notation) as a technique for serializing and transferring data between the sever and the client.

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 features

ColdFusion provides two types of Ajax features:

  • Data and development features

  • User interface features

Data and development features

ColdFusion 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:

  • ColdFusion supports data binding in many tags. Binding allows form and display tags to dynamically display information based on form input. In the simplest application, you display form data directly in other form fields. But usually, you pass form field data as parameters to CFC or JavaScript functions or CFM pages, and use the results to control the display.

  • The cfajaximport tag specifies the location of the JavaScript and CSS files that a ColdFusion page imports or to selectively import files required by specific tags. The ability to change the file location lets you support a wide range of configurations and use advanced techniques, such as application-specific styles.

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 features

Several ColdFusion user interface elements incorporate Ajax features. The tags and tag-attribute combinations can be divided into the following categories:

  • Container tags that lay out or display contents

  • File management tags that handle files

  • Form tags that dynamically display data

  • A menu tag that lets you create menu bars and pull-down menus

  • User assistance features that provide tool tips and form completion

  • Four other tags for using geographical maps, progress bar, media player, and message box.

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.

Tag/attribute

Description

Container tags

cfdiv

An HTML div region that can be dynamically populated by a bind expression. Forms in this region submit asynchronously.

cflayout

A horizontal or vertical box, a tabbed region, or a set of bordered regions that can include a top, bottom, left, right, and center regions.

cflayoutarea

An individual region within a cflayout area, such as the display that appears in a tabbed layout when the user select a tab. Forms in this region submit asynchronously.

cfpod

An area of the browser window with an optional title bar and a body that contains display elements. Forms in this region submit asynchronously.

cfwindow

A pop-up window within the browser. You can also use the ColdFusion.Window.createWindow function to create a pop-up window. Forms in this region submit asynchronously.

File management tags

cffileupload

A dialog for uploading multiple files from the user's system.

Forms tags

cfgrid format="html"

A dynamic, editable, sortable, data grid.

cfinput type="datefield"

An input control that users can fill by selecting a date from a pop-up calendar.

cftextarea richtext="yes"

A text area with a set of controls that let users format the displayed text.

cftree format="html"

A dynamic tree-format representation of data.

cfslider

A slider control, for selecting a numeric value from a range, in a ColdFusion form.

Menu tags

cfmenu

A menu bar or the root of a drop-down menu.

cfmenuitem

An individual item in a menu, or the root of a submenu.

User assistance tags and attributes

cfinput type="text" autosuggest="bindexpression"

A drop-down autofill suggestion box. As the user types, a list appears with completion suggestions based on the text the user has typed.

cftooltip tag, and the tooltip attribute on cfinput, cfselect, cftextarea controls

A textual description of a control or region that appears when the user hovers the mouse over the control or region.

Other tags

cfprogressbar

A progress bar to indicate the progress of an activity such as a file download.

cfmap

A geographical map within a ColdFusion web page.

cfmediaplayer

An inbuild media player.

cfmessagebox

A control for displaying pop-up messages.

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 features

ColdFusion 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

  • Data interaction

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 layout

The following layout tags let you dynamically control the display:

  • cfdiv

  • cflayout

  • cfpod

  • cfwindow

For information about how you can use these tags to submit form contents asynchronously, see Using Ajax containers for form submission.

Using the cfdiv tag

The 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 layouts

The 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:

  • Horizontally or vertically.

  • In a free-form bordered grid (panel layout) with up to five regions: top, bottom, left. right, and center. You can optionally configure the layout so that users can resize or collapse any or all of the regions, except the center region. The center region grows or shrinks to take up any space that other regions do not use. You can also dynamically show or hide individual regions, or let users collapse, expand, or close regions.

  • As a tabbed display, where selecting a tab changes the display region to show the contents of the tab’s layout area. You can dynamically show and hide, and enable and disable tabs, and optionally let users close tabs.

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 layouts

The 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 pods

The 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 windows

ColdFusion HTML pop-up windows have the following characteristics:

  • They have title bars

  • They float over the browser window and can be placed at an arbitrary location over the window.

  • They can be modal (users cannot interact with the main window when the pop-up window is displayed) or non-modal (users can interact with both windows).

  • You can specify that the user can drag, close, or resize the window.

  • You can create and show a window independently. After you create the window, you can use JavaScript functions to show and hide it multiple times without having to create it again.

Display and hide windows

You 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 events

You 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 contents

ColdFusion provides a variety of ways to set and change container tag contents:

  • You can use bind expressions in the container tag source (or for cfdiv, bind) attribute. The container then dynamically updates any time a bound control changes.

  • You can call the ColdFuson.navigate function to change the container body to be the contents returned by a specified URL. This function lets you specify a callback handler to do additional processing after the new content loads, and also lets you specify an error handler.

    The callback handler can be useful to provide information about a successful navigation operation. For example, you could make a pod's title bar italic to indicate loading (just before the navigate call), and use the callback handler to switch it back to normal once the navigate completes. Similarly, if a pod is showing pages from a book, the callback handler could update a page number in a separate field once a page loads

  • You can use the special controlName_body variable to access and change the body contents for cfpod and cfwindow controls. For example, you can use the controlName_body.innerHTML property to set the body HTML. For cfpod and cfwindow tags, you can also use the controlName_title to get or set the title bar contents of the control.

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 “Simple navigate” button calls a ColdFusion.navigate function to change the contents of the second window.

  • The “Change w2 body & title” button replaces the second window’s body and title innerHTML values directly to specific strings.

  • The “Change pod body” button changes the pod body innerHTML to the value of the second window’s title innerHTML.

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 toolbars

The cfmenu and cfmenuitem tags let you create vertical menus and horizontal toolbars.

Define menus and toolbars

  • Use a single cfmenu tag to define the general menu characteristics.

  • Create a horizontal (toolbar) menu or vertical menu by specifying a cfmenutype attribute value of horizontal or vertical.

  • Menus can have submenus, but only the top menu can be horizontal. All children of a horizontal menu are vertical.

  • The top-level menu shows initially, a submenu shows when the user moves the mouse over the menu root in the parent menu.

  • Use cfmenuitem tags to specify individual menu items.

  • To create submenus, nest cfmenuitem tags. The parent tag becomes the root of the submenu.

  • All cfmenuitem tags, except tags for dividers, must have a display attribute, which defines the text to show on the menu item, and can optionally have an image attribute.

  • A horizontal menu has dividers between all items. You place dividers in vertical menus by specifying a cfmenuitem tag with a divider attribute.

  • To make a menu item active, specify a href attribute with a URL or a JavaScript function to call when the user clicks the menu item.

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 &gt;  
                Open... &gt; Template');" /> 
            <cfmenuitem divider="true" /> 
            <cfmenuitem display="CSS" href="javascript:selected('File &gt; Open... &gt; 
                CSS');" /> 
        </cfmenuitem> 
        <cfmenuitem display="Close" href="javascript:selected('File &gt; Close');" /> 
    </cfmenuitem> 
    <cfmenuitem display="Help"> 
        <cfmenuitem display="About" href="javascript:selected('Help &gt; 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 menus

The 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:

Attribute

Description

cfmenu attributes

menuStyle

Applies to the menu, including any parts of the menu that surround the menu items. If you do not override this style in a cfmenu tag childStyle attribute or by specifying style information in the cfmenuitem tags, this attribute controls the style of the top-level items.

childStyle

Applies to the items in the top level menu and all child menu items, including the children of submenus. This attribute lets you use a single style specification for all menu items.

cfmenuitem attributes

style

Applies to the current menu item only. It is not overridden by the childStyleattribute.

menuStyle

Controls the overall style of any submenu of this menu item. This attribute controls the submenu of the current menu item, but not to any child submenus of the submenu.

childStyle

Applies to all child menu items of the current menu item, including the children of submenus.

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:

  • Keep font sizes at 20 pixels or smaller. Larger sizes can result in menu text in vertical menus exceeding the menu boundaries.

  • Consider how the style attributes interact. Because each menu and submenu consists of a surrounding menu area and individual child items, be careful when you choose background colors. For example, if you specify different background-color styles in the cfmenu tag’s menuStyle and childStyle attributes, the menu items are one color and the surrounding menu area are a different color.

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 files

The cffileupload tag lets you select multiple files and upload them to a server.

Working with the cffileupload

The cffileupload tag displays a dialog that lets you upload multiple files. The following are the file upload features:
  • Uses callback and error handlers that lets provides control over file upload process after upload completion or if errors occur.

  • Lets you style the file upload control

  • Provides option to stop or continue with upload in case of errors

  • Provides option to send custom response to callback and error handlers

Sending custom response to the callback and error handlers

The 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 styles

The 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 features

ColdFusion HTML forms and controls provide the following Ajax-based features:

  • The cfgrid, cfinput, cfselect, cftextarea, and cftree controls support binding to get control contents.

  • ColdFusion functions support asynchronous submission of forms without refreshing the entire page. When a form is in an Ajax container control, it is done automatically. Also, the ColdFusion.Ajax.SubmitForm JavaScript function and Ajax proxy setForm function support manual asynchronous submissions.

  • The cfgrid and cftree tags provide HTML grids and trees that do not require a Java applet or Flash.

  • The cftextarea control has a rich text editor option. The text editor is configurable.

  • The cfinput tag supports a datefield type with an Ajax-based pop-up calendar from which user can select the date.

  • The cfinput tag with text type supports an autosuggest attribute that lets you dynamically supply a drop-down list of field completions based on the current user input.

  • The cfinput, cfselect, and cftextarea tags support a tooltip attribute that specifies a pop-up tool tip to display when the user moves the mouse over the control. The cftooltip tag displays a tool over any region of a page, not just a form control.

Using Ajax form controls

ColdFusion 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 submission

The 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 function

The 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 function does not need to specify the form fields in cfargument tags, and the function gets the field values passed by name.

  • Form fields that have the same names as CFC arguments override the CFC argument values.

  • If you do not specify form fields in the cfargument tags, they do not necessarily follow any declared arguments, when you use positional (array) notation to access them in the arguments structure.

  • The arguments scope in the CFC function includes two fields that ColdFusion uses to control its behavior. These fields are intended for internal use, and their names might change in future releases. Both field values are set to true:

    • _CF_NODEBUG tells ColdFusion not to return debugging output in the call response.

    • _CF_NOCACHE tells ColdFusion to send a no cache header on the response, which prevents the browser from caching the response and ensures that every Ajax request results in a network call.

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 function

You 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:

  • A callback function that handles the returned results

  • An error handler that takes two parameters, an HTTP error code and a message

  • The HTTP method (by default, POST)

  • Whether to submit the form asynchronously (by default, true)

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 form

The 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 grids

The 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:

  • Sort the grid in ascending or descending order based on the column’s content.

  • Select the columns to display.

  • If the grid has a groupfield attribute: turn grouping off and on and group by the column value.

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 data

HTML 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.

Parameter name

Description

cfgridpage

The number of the page for which to retrieve data.

cfgridpagesize

The number of rows of data in the page. The value of this parameter is the value of the pageSize attribute.

cfgridsortcolumn

The name of the column that determines the sorting order of the grid. This value is set only after the user clicks a column heading.

cfgridsortdirection

The direction of the sort, may be 'ASC' (ascending) or 'DESC' (descending). This value is set only after the user clicks a column heading.

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:

Bind type

Return value

CFC

A ColdFusion structure. ColdFusion automatically converts the structure for return to the caller. Alternatively, you can return a JSON representation of the structure.

URL

A JSON representation of a structure. No other body contents is allowed.

JavaScript

A JavaScript object.

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:

  • TOTALROWCOUNT: The total number of rows in the query data set being returned. This value is the total number of rows of data in all pages in the grid, and not the number of rows in the current page.

  • QUERY: The contents of the query being returned. The QUERY value must also be an object with two keys:

    • COLUMNS: An array of the column names.

    • DATA: A two-dimensional array, where the first dimension corresponds to the rows and the second dimension corresponds to the field values, in the same order as the COLUMNS array.

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 attribute

The 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 contents

When 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:

  • Specify selectmode="edit" in the cfgrid tag. This lets the user edit the grid.

  • Specify an onChange attribute in the cfgrid tag. The attribute must use a bind expression to specify a CFC method, JavaScript function, or URL of a page that updates the data source. The bind expression has the same format as the bind expression described in Dynamically filling form data; however, it must take the following bind parameters that the grid automatically passes. These parameters send information about the grid and its state to the onChange function.

    Parameter name

    Description

    cfgridaction

    The action performed on the grid. 'U' for update, or 'D' for delete.

    cfgridrow

    A structure or JavaScript Object whose keys are the column names and values are the original values of the updated or deleted row.

    cfgridchanged

    A structure or JavaScript Object with a single entry, whose key is the name of the column with the changed value, and whose value is the new value of the field. If the grid action is delete, this structure exists but is empty.

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 contents

You 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 functions

You can use the following JavaScript functions to manage an HTML format grid:

Function

Description

ColdFusion.Grid.getGridObject

Gets the underlying Ext JS JavaScript library object.

ColdFusion.Grid.refresh

Manually refreshes a displayed grid.

ColdFusion.Grid.sort

Sorts the 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 grouping

The 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 column

The 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.

Datehandling when the attribute mask is used in ColdFusion 9.0.1

If the attribute mask is applied to a datefield column in an HTML grid, ColdFusion converts the date to an intermediate format as shown here:

MMMMM, dd yyyy HH:mms

for example,

January, 19 2005 07:35:42

This is required for proper date conversion and is applicable both when data is sent to the server (for example, when using an onChange grid event) and when data is received from the server (for example, populating a date field in a grid). Therefore, in some cases, users might have to format the date if they are updating a date column in the database.

Note: Date values which are NULL are sent as empty strings when the form is submitted. In such cases, set the value to NULL explicitly while updating the date column in the database.

Using HTML trees

An 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 expression

You 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:

  • If you use a bind expression, the cftree tag can have only a single cftreeitem tag. Therefore, the function or URL called by the bind expression must be able to populate all levels of the tree.

  • When a tree item expands, the CFC or JavaScript function or active page specified by the bind attribute returns an array with the values for the child nodes of the item. The dynamic tree code on the client constructs the child items by using these values.

  • When a control to which the tree is bound generates an event that the tree is listening for, the tree is refreshed. For example, if the tree uses a bind expression that includes a select box as a bind parameter, the tree collapses to the root nodes when the selected value in the select box changes.

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.

Bind parameter

Description

{cftreeitempath}

Passes the path of the current (parent) node to the method, which uses it to generate the next node.

{cftreeitemvalue}

Passes the current tree item value (normally the value attribute)

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

Bind type

Return value

CFC

A ColdFusion array of structures. ColdFusion automatically converts the structure to JSON format when it returns the result to the caller. Alternatively, you can return a JSON representation of the structure.

JavaScript

A JavaScript Array of Objects.

URL

A JSON representation of an array of structures. No other body content is allowed.

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.

  • DISPLAY

  • EXPAND

  • HREF

  • IMG

  • IMGOPEN

  • LEAFNODE

  • TARGET

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 tree

The 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 nodes

Code 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 handling

The 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 tree

ColdFusion tags that use bind expressions can bind to the selected node of a tree by using the following formats:

  • {[form:]tree.node} retrieves the value of the selected tree node.

  • {[form:]tree.path} retrieves the path of the selected tree node. If the completePath attribute value is true, the bound path includes the root node.

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 functions

You can use the following JavaScript functions to manage an HTML tree:

Function

Description

ColdFusion.Tree.getTreeObject

Gets the underlying Yahoo User Interface Library TreeView JavaScript object.

ColdFusion.Tree.refresh

Manually refreshes a tree.

For more information, see the ColdFusion.Tree.getTreeObject and ColdFusion.Tree.refresh functions in the CFML Reference.

Using the rich text editor

The 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 editor

You 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 toolbars

You can use the following techniques to control the appearance of the toolbar:

  • Specify the toolbar name in the toolbar attribute

  • Create custom toolbars in the fckconfig.js file.

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:

  • Start the definition with FCKConfig.ToolbarSets.

  • Specify the toolbar name in double quotation marks and brackets ([""]). Use this name, case correct, in the cftextarea tag toolbar attribute.

  • Follow the toolbar name with an equal sign (=).

  • Place all the toolbar controls inside a set of brackets, and follow the definition with a semicolon (;).

  • Group controls in brackets.

  • Place each entry in single quotation marks (') and separate the entries with commas (,).

  • Use the hyphen (-) character to specify a separator.

  • Use a forward slash (/) character to start a new row.

For a complete list of the valid toolbar entries, see the Default configuration in fckconfig.js.

Defining custom styles

You 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:

  • The name attribute specifies the name that appears in the Style selector.

  • The element attribute specifies the HTML element that surrounds the text.

  • Each Attribute child element defines the name and value of an attribute of the HTML tag.

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 templates

The 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 skins

To 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:

  • fck_editor.css: Defines the main interface, including the toolbar, its items (like, buttons, panels) and the context menu.

  • fck_dialog.css: Defines the basic structure of dialog boxes (standard for all dialogs).

  • fck_strip.gif: Defines the Default toolbar buttons and context menu icons. It is a vertical image that contains all icons placed one above the other. Each icon must correspond to a 16x16 pixels image. You can add custom images to this strip.

  • images/toolbar.buttonarrow.gif: Defines the small arrow image used in the toolbar combos and panel buttons.

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 control

The 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:

  • To correctly display label text next to the control in both Internet Explorer and Firefox, surround the label text in a <div style="float:left;"> tag and place three <br> tags between each line.

  • Consider specifying an overflow attribute with a value of visible in the cflayoutarea tag so that if the pop-up calendar exceeds the layout area boundaries, it appears completely.

  • If you use a mask attribute to control the date format, it does not prevent the user from entering dates that do not conform to the mask. The mask attribute determines the format for dates that users select in the pop-up calendar. Also, if the user types a date in the field and opens the pop-up calendar, the calendar displays the selected date only if the entered text follows the mask pattern. If you do not specify a mask attribute, the pop-up only matches the default matching pattern.

  • If the user types a date with a month name or abbreviation in the control, instead of picking a date from the calendar, the selected date appears in the pop-up calendar only if both of the following conditions are true:

    • The month position and name format match the mask pattern.

    • The month name matches, case correct, the month names specified by the monthNames attribute, or, for an mmm mask, their three-letter abbreviations.

  • If the date mask specifies yy for the years, the pop-up calendar uses dates in the range 1951-2050, so if the user enters 3/3/49 in the text field, the calendar displays March 3, 2049.

  • If the user enters invalid numbers in a date, the pop-up calendar calculates a valid date that corresponds to the invalid input. For example, if the user enters 32/13/2007 for a calendar with a dd/mm/yyyy mask, the pop-up calendar displays 01/02/2008.

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 fields

When 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>

Issue with numeric data

For CFC methods that returns numeric data with a leading zero, for example, zip code 02674, the zero is interpreted by the bind expression as an octal number and its decimal equivalent (in this case 1468) even if you set returnformat="string". To resolve this issue, for URL binds or binds routed by way of a JavaScript function (for example, using cfajaxproxy), you can set returnformat=plain to retain the numeric value. Also, leading zeros are stripped from the suggestion list for autosuggest controls.

Using the cfslider tag

The 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 runtime

The 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 maps

The cfmap tag lets you embed a geographical map within your ColdFusion page. The following are the supported map types:

  • earth

  • terrain

  • satellite

  • hybrid

  • map (default)

Using the marker window

The 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 content

To manually populate data in the marker window, specify the value in the markerwindowcontent attribute.

Populating dynamic data using bind expression

To 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:

Parameter name

Description

cfmapname

The name of the map.

cfmaplatitude

The latitude value for the location, in degrees. This value is set as the center of the map.

cfmaplongitude

The longitude value for the location, in degrees. This value is set as the center of the map.

cfmapaddress

The address of the location, which is set as the center of the map.

The format of the returned data depends on how you get the data:

Bind type

Return value

CFC

A ColdFusion structure. ColdFusion automatically converts the structure for return to the caller. Alternatively, you can return a JSON representation of the structure.

URL

A JSON representation of a structure. No other body contents is allowed.

JavaScript

A JavaScript object.

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 key

The 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:

  • Using the cfajaximport tag. You specify the map API key in the params attribute as follows:

    <cfajaximport params="#{googlemapkey='Map API Key'}#"

  • Using Application.cfc as follows:

    <cfset this.googlemapkey="Map API Key">

  • Using the Settings page in the ColdFusion Administrator. Specify the map API key in the Google Map Key field. You can also specify the map API key in runtime.cfc.

Styling markers

You can specify the following:
  • Custom marker icon: Specify the path to the icon using the markericon attribute. Ensure that you specify an image of appropriate size.

  • Marker icon color: Use the markercolor attribute. You can specify a color of your preference only for the default icon and not for others.

  • Map title: Use the title attribute.

Using the cfprogressbar tag

The cfprogressbar tag has the following characteristics:
  • Automatically runs the progress bar for a duration that you specify.

  • Dynamically loads data using bind expressions

  • Lets styling of the progress bar

  • Uses callback and error handlers that give control to the users after the progress bar completes processing or if it encounters any exceptions.

  • Lets programmatic control over progress bar using JavaScript APIs.

Progress bar modes

The progress bar supports the following two modes:

Dynamic mode

User 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 mode

In 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 runtime

This 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>

Styling the progress bar

The cfprogressbar has style attribute that lets you decide:

  • Background color of the progress bar

  • Color of the progress message

  • Color of the progress indicator

The following code illustrates styling: style="bgcolor:ADD8E6;progresscolor:6183A6;textcolor:191970"

Using the cfmessagebox tag

The 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 dialog

The 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 box

The 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" 
    >