Thoroughly Document Your Use Of ColdFusion's CFHTMLHead Tag

Posted September 29, 2009 at 10:12 AM by Ben Nadel

Tags: ColdFusion

The other day on Twitter, I saw someone tweet about how they just discovered ColdFusion's CFHTMLHead tag and was planning to use it in a project. This gave me flash backs to a project I took over in which the CFHTMLHead tag was being used all over the place. Having not known about this tag at the time, I thought I was going crazy!! Stuff was showing up in the HEAD of the HTML document that wasn't there in the corresponding ColdFusion template and I couldn't for the life of me figure out where the heck it was coming from.

For anyone who has never seen the CFHTMLHead tag - please stop reading this post immediately - it takes text content and injects it into the end of the HTML HEAD element, assuming it has not yet been flushed to the client. For ease of use and demonstration, I am going to wrap the CFHTMLHead tag into a custom tag so that I can use the custom tag's generated content to set the CFHTMLHead text attribute:

htmlhead.cfm

  • <!---
  • Check to make sure this is the end of the tag. This way, we
  • will have generated content to work with.
  • --->
  • <cfif (thistag.executionMode eq "end")>
  •  
  • <!---
  • Use the generated content for the data piped into
  • the CFHTMLHead tag.
  • --->
  • <cfhtmlhead text="#thistag.generatedContent#" />
  •  
  • <!---
  • Clear the generated content. We used it for the
  • CFHTMLHead tag and have no need to output it now.
  • --->
  • <cfset thistag.generatedContent = "" />
  •  
  • </cfif>

As you can see, the CFHTMLHead tag has one attribute, Text, which is the text output that will be injected into the HTML.

Now, let's take a look at how this works:

  • <!DOCTYPE HTML>
  • <html>
  • <head>
  • <title>ColdFusoin CFHTMLHead</title>
  • </head>
  • <body>
  •  
  • <h1>
  • ColdFusion CFHTMLHead Example
  • </h1>
  •  
  • <p>
  • The CFHTMLHead tag, while seemingly powerful, can be
  • extremely hard to debug if not docummented well.
  • </p>
  •  
  • </body>
  • </html>
  •  
  •  
  • <!--- Add content to the head. --->
  • <cf_htmlhead>
  •  
  • <script type="text/javascript">
  • document.write( "Where did I come from?!?" );
  • </script>
  •  
  • </cf_htmlhead>

As you can see here, after the HTML we add a Javascript tag using the CFHTMLHead custom tag wrapper. When we run the above page, here is the page source that results:

  • <!DOCTYPE HTML>
  • <html>
  • <head>
  • <title>ColdFusoin CFHTMLHead</title>
  •  
  • <script type="text/javascript">
  • document.write( "Where did I come from?!?" );
  • </script>
  • </head>
  • <body>
  •  
  • <h1>
  • ColdFusion CFHTMLHead Example
  • </h1>
  •  
  • <p>
  • The CFHTMLHead tag, while seemingly powerful, can be
  • extremely hard to debug if not docummented well.
  • </p>
  •  
  • </body>
  • </html>

As you can see, the Javascript defined at the end of the page winds up in the HEAD tag of the rendered content. While this might have some ooh-ahh factor at first, realized that this was a very simple example; imagine yourself in the middle of a massive application with hundreds of templates! Suddenly, having things pop up in the HEAD tag out of nowhere will not only be confusing, but very hard to debug.

This is one of the few ColdFusion tags that I actually recommend people don't use. It just seems very hacky to me - like using it is a symptom of some flaw in your page architecture. However, if you are going to use it, I beg of you this one thing: document your use of it! Either put some sort of ColdFusion comment in your HEAD tag about where content might come from; or, even put a comment in your CFHTMLHead content:

  • <!--- Add content to the head. --->
  • <cf_htmlhead>
  •  
  • <!-- Content injected using CFHTMLHead. -->
  •  
  • <script type="text/javascript">
  • document.write( "Where did I come from?!?" );
  • </script>
  •  
  • </cf_htmlhead>

Regardless of how you go about it, make sure that someone can look at either the ColdFusion page template or your rendered page source and gain some insight as to where this content is coming from. Otherwise, you'll be kicking yourself down the line (or get kicked by the developer that took over your project).


You Might Also Be Interested In:



Reader Comments

Sep 29, 2009 at 10:32 AM // reply »
48 Comments

I love cfhtmlhead. I use it religiously in my Model-Glue apps. To me it makes more sense to keep my JavaScript logic in my view instead of mucking about trying to fit it all in my massive dspTemplate.cfm file and playing the viewstate.setValue('needSomeScript', true) game.

Different strokes for different folks I guess ;)


Sep 29, 2009 at 10:36 AM // reply »
11,314 Comments

@Todd,

As long as you document, it's totally fine. However, I wouldn't refer to setting things into the ViewState a "game" :) after all, it's there to carry data throughout the page request.


Sep 29, 2009 at 11:06 AM // reply »
32 Comments

It might also be a good idea to warn people that CfHtmlHead is immune to good old >cfcontent reset=true<. I had issues with some old code where I wanted to clear the output buffer and kept finding out it wasn't empty. I then finally hunted down the culprit CfHtmlHead.


Sep 29, 2009 at 11:10 AM // reply »
11,314 Comments

@David,

Very interesting. So, no matter what you do, the CFHTMLHead data gets injected.

Also, in the "Web 2.0" world, I think it's worth noting perhaps that it is recommended that a lot of linked content (ie. Javascript) be placed at the bottom of the page such that the UI can load faster.


Sep 29, 2009 at 2:19 PM // reply »
42 Comments

I've not tested it, but seems like this tag might break when the head tag has profile="" attribute. http://stackoverflow.com/questions/1477266/how-to-prevent-coldfusion-from-injecting-cfform-js-into-the-head-section


Ben
Sep 29, 2009 at 3:24 PM // reply »
3 Comments

I use CFHTMLHead to add stylesheets when a page is being built by our CMS pulling the content out of our database, we have one global one that is always used and then depending on what kind of content a user has added it will insert the correct stylesheets at the top of the datatypes cfm template.
since it doesn't really make sense to use it before closing your head tags maybe even just putting a HTML comment just before the </head> would make it easier to see what is from where


Sep 29, 2009 at 6:07 PM // reply »
13 Comments

I agree with Ben that use of cfhtmlhead should be avoided. I ended up writing up my own custom tag that copies text passed to it as a key in request scope. Since I use a central layout (MG & Fusebox), the layout file extract that key and spits it out before </head>


Sep 30, 2009 at 4:45 AM // reply »
2 Comments

That's not all.
Using <cfhtmlhead> can also bite you in the a$% if at some point you have to use <cfflush> to partially serve large files and one of the "head" calls happens after the "flush".


Sep 30, 2009 at 6:28 AM // reply »
32 Comments

I've found what looks like the best way to reset/clear anything the CfHtmlHead tag has set. Model-Glue has the best version I've seen of this approach, it works around a bug in other versions and has Railo/BlueDragon support too.

It's called "resetCfHtmlHead" and can be easily dropped into any existing code by just copying out the function itself.
http://svn.model-glue.com/tag/MG_3.0_Final%20_8_10_2009/ModelGlue/gesture/remoting/AbstractRemotingService.cfc


Oct 1, 2009 at 8:09 AM // reply »
11,314 Comments

@David,

Cool stuff. Definitely a good understanding of the internal workings of the page request / response mechanisms.


Oct 8, 2009 at 4:16 AM // reply »
32 Comments

I've managed to piece together the following code from various sources on the internet, allowing you to reset/clear or get the contents of the cfhtmlhead buffer. It works in ColdFusion only (no railo/bluedragon) and comes in quite handy if dealing with code using CFHtmlHead.

http://pastebin.com/f2560e44d


Oct 12, 2009 at 3:04 PM // reply »
17 Comments

@David: What version of ColdFusion did you test that with? I am on 8.0.1 and the getCFHtmlHead function errors on the line with local.out.getClass().getDeclaredField("headerBuffer"). It appears that my version of ColdFusion doesn't have a headerBuffer field in the NeoBodyContext class, but insead an appendHeaderBuffer and prependHeaderBuffer field. Interestingly enough, the contents of cfhtmlhead goes into appendHeaderBuffer and the JavaScript produced by cfajaxproxy shows up in prependHeaderBuffer. I guess this is the problem when dealing with uncoumented features of your app server. :)


Oct 13, 2009 at 11:22 AM // reply »
32 Comments

@Brad,

Well spotted! I've been doing this in 7 but when I tested it on 8 I forgot to remove a try/catch I had added.

I'll have a look at that and see if I can sort it out. ;)


Dec 16, 2009 at 3:37 PM // reply »
3 Comments

Howdy Folks!

Is there a Custom Tag, etc. to place content within the <body> tags of your XHTML document similarly to the way <cf_htmlhead> works?

In other words, is there a <cf_htmlbody> or equivalent? :-)

Basically, I need to place content in the <body> of my XHTML document from Application.cfm, and thought that a <cf_htmlbody> tag would be perfect.

If I'm missing something obvious, please let me know the simplest method to place content into the <body> from Application.cfm.

Thanks!

~Christian


Dec 16, 2009 at 4:37 PM // reply »
12 Comments

@Christian

I would recommend doing this with jQuery.

I actually don't know if there is a simple 'cf_htmlbody' tag, but with jQuery you can do this very quickly.


Dec 16, 2009 at 6:16 PM // reply »
3 Comments

@Roman Schlaepfer,

Thanks for the response!

I'm relatively new to jQuery, but learning more and more via jQuery UI each day. :-)

As such, could you please provide some more guidance on your solution? Do you have a specific example or code sample I can look at? Or, is there a specific function in jQuery that will do what I'm looking for?

Thanks in advance for your help!

~Christian


Jan 5, 2010 at 9:14 AM // reply »
11,314 Comments

@Christian,

What I would suggest doing instead, in your Application.cfm, is creating a variable to hold your content:

<cfsavecontent variable="additionalBodyContent">
... extra stuff goes here ...
</cfsavecontent>

And then, when you actually output your HTML, simply output this variable:

<body>
.... all your other stuff ....
....
#additionalBodyContent#
</body>

This way, it's really clear where everything is coming from.


Jan 24, 2010 at 8:45 AM // reply »
15 Comments

I use cfmhtmlhead in one of my sites, it can be handy. However since porting my site over to Railo it's now outputting that cfhtmlhead content above the xhtml document definition making the site's css break.
Guess it's just another reason not to use it!

I have come across instances where there hasn't been another solution but they are far too long-winded to explain here.


Jan 24, 2010 at 10:11 PM // reply »
11,314 Comments

@Matt,

That sounds like a bug in Railo. I can't imagine that that is the behavior team Railo intended. I am not sure it would make any sense.


Jan 25, 2010 at 9:09 AM // reply »
15 Comments

looked further into this and if you have a cfhtmlhead tag and <cfflush> tag on the same page this is what happens in Railo. It does seem to be a bug.


Jan 25, 2010 at 9:18 AM // reply »
11,314 Comments

@Matt,

The bug is probably that Railo is not throwing an error. If you use CFHTMLHead after a method that commits the request to the client (ie. starts to flush some of the content), the application server should thrown an error to let you know the request has already been committed.

This should also happen with things like CFHeader and CFContent.


Jan 25, 2010 at 9:29 AM // reply »
15 Comments

@Ben Nadel, but on my Coldfusion 8 server this code works fine, so railo should replicate this. Perhaps they both have a bug?


Jan 25, 2010 at 9:16 PM // reply »
11,314 Comments

@Matt,

Wait, you're saying that on CF8, you can call CFHTMLHead *after* you have called CFFlush?


Jan 26, 2010 at 4:53 AM // reply »
15 Comments

@Ben Nadel

no, before.


Jan 26, 2010 at 9:46 AM // reply »
11,314 Comments

@Matt,

Ah, ok, sorry I was confused. Yeah, you should be able to call CFHTMLHead before the response is committed (ie. CFFlush). If that doesn't work in Railo, it's definitely a bug on their part.


Oct 16, 2010 at 3:52 PM // reply »
1 Comments

@Matt,

That sounds like a bug in Railo. I can't imagine that that is the behavior team Railo intended. I am not sure it would make any sense.

what problem ?


Oct 16, 2010 at 8:21 PM // reply »
15 Comments

Yup def a bug in Railo, actually I cannot use Railo anymore because of the way it handles certain core functions from cf8. That and the bad spelling in the error messages has put me right off, its bloomin fast though. Good for basic code but you very rarely copy an application across and it works perfectly even if you don't use any of the advanced tags the basic ones don't behave the same. I guess it is free though, i got fed up with creating workarounds and just bought cf 9.


Dec 21, 2010 at 5:11 AM // reply »
1 Comments

but on my Coldfusion 8 server this code works fine, so railo should replicate this. Perhaps they both have a bug? 8 server ? have a bug ? waoww :)


May 23, 2011 at 6:40 PM // reply »
17 Comments

hehe, you described exactly what I've just been through with this tag. I inherited the allblacks.com website and was getting ready to insert some Facebook Open Graph meta tags. Some time later, I finally traced the meta tags to a <cfhtmlHead> tag hiding in onRequestEnd.cfm.


Feb 14, 2013 at 11:36 AM // reply »
20 Comments

I was brought onto the team for a large application (over 10K scripts) and used cfhtmlhead in the application.cfm file to define the site bookmark and app icons. Just make sure that the content is not being included in AJAX responses.



Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
Jun 19, 2013 at 2:01 PM
Experimenting With The Amazon Simple Storage Service (S3) API Using ColdFusion
I have coincidentally been beating my head against the S3 API for the last week or so. One big "gotcha" I had to work around was file names and paths containing spaces. Remember to URL Enco ... read »
Jun 19, 2013 at 1:27 PM
Using Slice(), Substring(), And Substr() In Javascript
very good article. By the way IE supports negative values in substr or slice in verson 10. ... read »
Jun 19, 2013 at 11:33 AM
Filter vs. ngHide With ngRepeat In AngularJS
In your assessment, is it correct to say that given a list of say 500 items its more performant to use the `ngHide` method over the `filter` method? ... read »
Jun 19, 2013 at 10:18 AM
ColdFusion Path Usage And Manipulation Overview
Anyone happen to know if the file created by getTempFile will be automatically removed at any point? Nothing mentioned in the docs, and restarting CF doesn't remove them, so it seems it needs manu ... read »
Jun 19, 2013 at 9:41 AM
Working With Inherited Collections In AngularJS
I actually just ran into this same situation with a demo I was putting together. Your implementation of multi-lvl $scope's > Mine :) ... read »
Jun 19, 2013 at 8:17 AM
My Experience With AngularJS - The Super-heroic JavaScript MVW Framework
@Prateek, to match a word or text you should use .toContain('word') that's a jasmine reference. website is : http://pivotal.github.io/jasmine/ ... read »
Jun 19, 2013 at 8:10 AM
My Experience With AngularJS - The Super-heroic JavaScript MVW Framework
Hi Guys, Actually i am doing e2e test of angular js of my project but i am not getting one thing that is how to press enter key through the test when my form is filled as i am not using a button but ... read »
Jun 18, 2013 at 9:20 PM
Mapping AngularJS Routes Onto URL Parameters And Client-Side Events
I couldn't find examples of passing multiple arguments using the when() routing statement so figured out through trial and error that you can pass multiple arguments using the following format: .whe ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools