Adobe ColdFusion 8

Controlling Ajax UI 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, 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 and 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. Whenever the user enters text in the input box and tabs out of it, or clicks on 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 is not used by the other regions. 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, and 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 a number of 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, you should often not 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 3 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.

Displaying and hiding windows

You display a window in the following ways:

  • By using a ColdFusion cfwindow tag with an initShow attribute value of to create and show the window.
  • By using a ColdFusion cfwindow tag with an initShow attribute value of false and calling the ColdFusion.Window.show JavaScript function to display it.
  • By by using ColdFusion.Window.create and ColdFusion.Window.show JavaScript functions.

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, you must click the Create Window 2 button, followed by the Show Window 2 button. You can then hide and show it.

The following examples 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>

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

Controlling 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 shows 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 control's title bar contents.

These different techniques provide you with flexibility in writing your code. For example, the ColdFuson.navigate function and the controlName_body variable provide similar functionality. However, with the controlName_body technique, you must 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, you might 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 windowcontent.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 examples 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 examples 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>