ColdFusion 8: AJAX UI Layouts

Today I begin a series of blog posts looking at the new AJAX UI elements in ColdFusion. Let me start off by saying that when I first discovered that ColdFusion would be shipping UI elements I was a bit.... wary. I mean - how many of you are using CFTABLE? The only real success ColdFusion has had in UI elements is Flash Forms... which frankly are dead to me now that I can use Flex 2 for free. So I think I'm being quite honest when I say I didn't have high expectations when I first started to dig into these features. After playing with them though I'm beginning to really like them. Let's start with the simplest of the UI controls - the layouts.

ColdFusion ships with two tags that I will be focusing on tonight - cflayout and cflayoutarea. These tags have multiple uses, but I'll be focusing on the border type. The border type acts a lot like frames. Everyone remember frames? If you are new to the whole web thing then you may have missed out on them. They rose to popularity quickly and then dropped out of usage almost as quickly. A few places still use them. A good example of this is the ColdFusion Administrator. Speaking personally - I haven't used frames for a while. I did use them for SpoolMail. It seemed to make sense for the application. I think the same applies to the border layout controls. While I wouldn't build a blog with them, I could see them being very useful AJAX style applications, or RIAs in general.

So enough pontificating. Let's look at some code. At a base level, you begin your border layout by wrapping your content with cflayout:

<cflayout type="border">

   
</cflayout>

You now have the option to place 5 different items. These items are all placed in one of the following positions: top, bottom, left, right, center.

So consider a simple example:

<cflayout type="border">

   <cflayoutarea position="top" title="Top Layout Area">
   This is the top layout area.
   </cflayoutarea>
   
   <cflayoutarea position="center">
   This is the center layout area.
   </cflayoutarea>
   
</cflayout>

In this example I've added two cflayoutareas. One on top, with a title, and one in the center position. The center position isn't allowed a title. When you do use a title in the cflayoutarea, it adds a graphical header to the section. Want to add another section? Just add it and specify a position:

<cflayout type="border">

   <cflayoutarea position="top" title="Top Layout Area">
   This is the top layout area.
   </cflayoutarea>
   
   <cflayoutarea position="center">
   This is the center layout area.
   </cflayoutarea>

   <cflayoutarea position="bottom" title="Bottom Layout Area">
   This is the bottom layout area.
   </cflayoutarea>
   
</cflayout>

Here is a screen shot of how this looks:

Want to get crazy? Add a left and right layoutarea as well:

<cflayout type="border">

   <cflayoutarea position="top" title="Top Layout Area">
   This is the top layout area.
   </cflayoutarea>
   
   <cflayoutarea position="center">
   This is the center layout area.
   </cflayoutarea>

   <cflayoutarea position="bottom" title="Bottom Layout Area">
   This is the bottom layout area.
   </cflayoutarea>

   <cflayoutarea position="left" title="Left Layout Area">
   This is the left layout area.
   </cflayoutarea>

   <cflayoutarea position="right" title="Right Layout Area">
   This is the right layout area.
   </cflayoutarea>

</cflayout>

Which results in this:

The layoutareas that surround the center have numerous options. You can set an initial size. You can set a max and min size. You can even allow them to be collapsed or even closed. Most of these options require the splitter attribute to be true. This creates a "grippable" handle that lets you change the size of the area. Consider this example:

<cflayout type="border">

   <cflayoutarea position="center">
   This is the center layout area.
   </cflayoutarea>

   <cflayoutarea position="left" title="Menu" splitter="true" collapsible="true" size="200" maxsize="200">
   <p>
   <a href="">Link One</a><br />
   <a href="">Link Two</a><br />
   <a href="">Link Three</a><br />
   </p>
   </cflayoutarea>


</cflayout>

I've set up a left area with both an initial size, a max size, and set it so that it can be collapsed. This is how the layout is rendered:

Now you may have noticed that my demo code created a menu in the left hand side. What happens when you put a real link in? It may not be what you expect. If you use this:

<a href="item1.cfm">Link One</a><br />

The contents of item1.cfm will actually load in the entire window. Most likely that isn't what you want. There is the new AjaxLink function:

<a href="#ajaxLink('item1.cfm')#">Link One</a><br />

But this simply keeps the link inside the layout area (the left hand menu). Luckily there is a nice API we can use with our Ajax UI controls. One of them is the ColdFusion.navigate function. It lets you take a layoutarea and load in another URL. For our left hand menu items to really work, they would need to look like so:

<a href="javaScript:ColdFusion.navigate('center2.cfm','center')">Link One</a><br />

In this example, the first value passed to navigate is the URL. The second value is the name of the layoutarea. For this to work, I changed my center area to this:

<cflayoutarea position="center" name="center">

Ok, so before we wrap up - imagine the left hand menu having a "Home" link. We would use it to return to the main welcome page, or in our nice new shiny Ajax app, the content we saw in the center when the page first loaded. How can we do that? Well obviously we can use the ColdFusion.navigate function again, but remember our original code looked like this:

<cflayoutarea position="top" title="Top Layout Area">
This is the top layout area.
</cflayoutarea>

In order to restore this text again, we can simply move it to a file, lets say center.cfm, and then we can update our layoutarea like so:

<cflayoutarea position="center" source="center.cfm" name="center"/>

I've added the source attribute which simply tells ColdFusion to load the data via an Ajax-based request.

Any questions?

Comments

Appears to not work if you are using ports in urls: such as 127.0.0.1:83/playground/index.cfm.

The content is there but no formatting and and js error about Error: ColdFusion is not defined
Source File: http://127.0.0.1:83/play/layout.cfm
Line: 28

Works if I take it out of the vhost.
# Posted By Scott P | 6/6/07 11:15 PM
Has anybody noticed that this Ajax stuff doesn't create XHTML conform output? Just start your template with the DOCTYPE below and see, what happens...

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitiona...;

Maybe this is just a RC issue and will be fixed in the final CF8? I hope so!
# Posted By Juerg Anderegg | 6/7/07 2:18 AM
ups the above line has been truncated; here's the rest:

l.dtd">

so that the end looks like ...DTD/xhtml1-transitional.dtd">

just like Transitional HTML should look like...
# Posted By Juerg Anderegg | 6/7/07 3:54 AM
I wonder how it would go through a screenreader for the blind . . .

And Jurgen, have you filed a bug report?
# Posted By Lola LB | 6/7/07 8:32 AM
There's absolutely NO reason that Adobe should be writing anything other than compliant xHTML code. Using these tags, you should be able to validate a page perfectly against the W3 validator.

I do hope they fix it in the final release.
# Posted By Andy Matthews | 6/7/07 8:43 AM
Found something in the release notes for RC1: Known Issues with this Release; Number 67448 =>

If you specify a DOCTYPE at the top of a page that includes a cflayout tag with type="border", the cflayout tag must have a style attribute with a height property; otherwise, the layout contents does not display properly.

If I validate the page through thw w3c-validator; I get two more error messages in the line

_cf_loadingtexthtml = "<div align='center'><img src='/CFIDE/scripts/ajax/images/loading.gif'/> Loading... </div>";

>> document type does not allow element "div" here.
and
>> required attribute "alt" not specified.

Juerg
# Posted By Juerg Anderegg | 6/7/07 9:48 AM
@Juerg:

Truthfully, this is were the validator code fails. The problem is validator doesn't understand that the <div> tag is actually within a JavaScript string--and not within the actual DOM element.

You can work around this by actually creating DOM elements using native DOM creation methods (document.createElement("div").)
# Posted By Dan G. Switzer, II | 6/7/07 11:21 AM
Anything special you have to add to get this to work? I just cut and pasted the code from the top box over at HostMySite and I got
ColdFusion is not defined
};ColdFusion.Event.registerOnLoad(_cf_layout_init_1181236422880);
http://h127882.cf8beta.com/test_layout.cfm
Line 78
and
ColdFusion is not defined
ColdFusion.Ajax.importTag('CFLAYOUT-BORDER');
http://h127882.cf8beta.com/test_layout.cfm
Line 18
# Posted By Gareth | 6/7/07 12:15 PM
I've seen a lot of people post with issues on HostMySite and the Ajax stuff. Check the other entries for how they solved it.
# Posted By Raymond Camden | 6/7/07 1:03 PM
Gareth,

Contact HostMySite support for adding CFIDE mapping for your site. It would fix AJAX layout issue.
# Posted By SC | 6/7/07 1:19 PM
@Dan: Actually, it's ColdFusion that is creating this line of code; I don't think that I can take my hands on that code snipplet... I saw, that this cflayout stuff creates quite a lot additional code; includes...

Juerg

@Gareth: Had the same on my server; the CFIDE mapping solved it!
# Posted By Juerg Anderegg | 6/7/07 2:16 PM
I love this CF 8 stuff!

I have an complex (frames-based) app. that I have been looking forward to re-working in a frames-free way.

I have struggling with a way to re-work the coding to retain the frames version (for older installs) while breaking free from frames - the biggest stumbling block was the 'whole' page nature of the application's templates.

I'm glad to see cflayoutarea accepts a (full file) source. So it now looks like the same templates can serve both a frameset and a Ajax setup!

cheers

David
# Posted By David Whiterod | 6/7/07 11:53 PM
Thanks for all the help everyone!
# Posted By Gareth | 6/8/07 7:19 AM
Nice but if the rays code is surrounded with normal <html> <body> tags the layout completely disappear with IE7 and is only partial visible in Firefox.
That's a big bug or only something wrong with my beta??

Thanks

Andrea
# Posted By Andrea | 6/9/07 11:13 AM
Solved with attribute style="height:500px;" but the code is still dirty against a w3c validator.

What you think ray about this problem?

Andrea
# Posted By Andrea | 6/9/07 11:18 AM
I would just tell you to report it to Adobe so they can try to fix it.
# Posted By Raymond Camden | 6/11/07 8:25 AM
Raymond -

Can you give a demo page, so I can try it out.

Pat
# Posted By Patrick Whittingham | 6/15/07 6:25 AM
Patrick, you can always download CF8 and try it. :)
# Posted By Raymond Camden | 6/15/07 7:41 AM
Patrick, you can sign up for free CF8 Beta account at HostMySite.com. http://www.hostmysite.com/cf8. You can try Ray's example code. :-)
# Posted By SC | 6/15/07 12:08 PM
Well... i was very excited about the new cflayout stuff... but i just can't get it to work in IE7... am I missing something? i used the exact sample on this page (one with collapsible=true) and can't get it to look like that. anyone else get it to work in IE7?
# Posted By Shane M | 6/29/07 1:54 AM
i guess it helps to add the cfide folder to as an virtual directory. then it works great.
# Posted By Shane M | 6/29/07 2:06 AM
This stuff is fun and a lot quicker than defining layouts in css...although I played and played and ended up doing it the "old" manual stylesheet way anyhows. My main problem was getting rid of the borders. No matter where i set border to 0px or to my background color...they wont go away?anybody else experienced this or am I just overlooking something obvious?
# Posted By Devon | 8/24/07 4:07 PM
I started messing around with the CFLayout commands. I don't see how you can hide the borders. I like the layout feature but I don't want my site to look like a bunch of gray boxes all the time. I tried the style attribute on the border but it doesn't seem to work for me. I can't seem to hide the default gray border or change it's color.
# Posted By Ken | 10/10/07 10:07 AM
Well the border _must_ be there - that is part of the feature. But I'm sure you can change the CSS. Maybe try Firebug or the Web Dev toolbar to see what classes are being used.
# Posted By Raymond Camden | 10/10/07 10:12 AM