Ask a Jedi: Does ColdFusion have a htmlfoot tag?
Rob asks:
Is there a <cfhtmlfoot> tag? One that would write at the end of html file, before </body> tag...
In case folks don't get why he is asking, ColdFusion comes with a cfhtmlhead tag that lets you dynamically add stuff to the HEAD portion of an HTML document. There is not a corresponding tag like what Rob wants, but there is no reason we can't hack one up in a custom tag. My solution will make use of both the Request scope and the oft-maligned (by me) onRequest function. First, a sample page:
<cf_htmlfoot text="<p>© Raymond Camden #year(now())#">
<html>
<head>
<title>Test</title>
</head>
<body>
<p>
Woohoo,web design kicks butt.
</p>
</body>
</html>
This is a trivial page with simple text on it. Note the call to the custom tag, htmlfoot, on top. The custom tag just does this:
<!--- the text to add --->
<cfparam name="attributes.text" default="">
<!--- where we store it --->
<cfparam name="request.footertext" default="">
<!--- add it --->
<cfset request.footertext &= attributes.text>
As you can see, we simply take your text, and append it to the text we want to add to the foot. This actually makes my tag better as I don't think you can have multiple cfhtmlhead tags. If I weren't so lazy, I'd also make the custom tag support this syntax:
<cf_htmlfoot>
Foo Foo
</cf_htmlfoot>
Anyway, the last step is to enable onRequest to notice the Request scope variable we created:
<cffunction name="onRequest" returnType="void">
<cfargument name="thePage" type="string" required="true">
<cfset var content = "">
<cfsavecontent variable="content">
<cfinclude template="#arguments.thePage#">
</cfsavecontent>
<cfif structKeyExists(request, "footertext")>
<cfset content = replacenocase(content, "</body>", "#request.footertext#</body>")>
</cfif>
<cfoutput>#content#</cfoutput>
</cffunction>
There isn't much to talk about here. All I did was look for the Request variable, and if it existed, I insert it into the result HTML before outputting it to the browser. Again, I'm not a big fan of onRequest, but this is an interesting example of how one could use it.
Comments
Then the little lightbulb comes on.
sure you don't HAVE to have your javascript in the head tag but I like it there, its neater.
And if you use a MVC framework you don't typically have access to the htmlhead so if you do want to jam some javascript, css or metadata tags into the head of the page from your display page you need to use it.
Then again if you are using an MVC framework you could declare two variables htmlhead and htmlfoot and output them in the appropriate places in your layoutpage, then you simply need to set those variables with whatever it is you want to output when you want stuff jammed in the header or footer....no need to create a custom tag to do it, no need to use onRequestEnd.
at the end of the specific page
<cfset somevariable = "html goes here">
and in the OnRequestEnd.cfm
<cfif IsDefined("somevariable")>#somevariable#</cfif>
and then the rest of the "footer" layout follows.
if the html is complex, maybe use cfsavecontent?
My code is brief, probably needs some better coding.
Tell me what you think?
Thanks Ray.
I don't think onRequestEnd is a good way to do layout stuff. Nor would I recommend Application.cfm. Nor onRequestStart/End.
I recommend using custom tags for layout. So my page would look like so:
<cf_layout title="foo">
some page
</cf_layout>
I've got a blog entry on it here on the blog somwhere.
The reason I don't like using app.cfm/onrequestend.cfm/app.cfc is that if you have a page that DOESN'T need layout, like a popup window, then you have to embed code in those files to block it. To me, this should be done on the page instead.
The application.cfm looks for this and does not include "header.cfm", "menu.cfm", etc. The same for OnRequestEnd.
I've always had a gut feeling that this is wrong. I will look into it when I have some time. Unfortunately my current client wants results now, so I have to code as I know how to code.


Unless code reuse is DEEPLY related here, I dont see why doing this would be good. Maybe because cfhtmlhead doesnt make that much sense either for me :(