Question

I'm working on a website that was coded in ColdFusion. I have a CSS/HTML template I would like to apply to the content of every page, without duplicating any more code than necessary. I've gotten kind of spoiled by ASP.NET's master pages, which would be my preferred way to implement this site. Unfortunately, that option is unavailable to me. This site has to run on Coldfusion MX 7. Also, the developer leading the project doesn't like Fusebox, so that option's out.

The main navigation, graphical header, and footer will be the same on every page. The title tag, meta tags, and level-2 navigation will likely vary from page to page. Aside from that, only the page's "main content area" will be different.

Given these parameters, how can I code the site for maximum maintainability?

Was it helpful?

Solution

There are a huge number of ways to do this with ColdFusion.


Application.cfc is executed on every request and has two methods (onRequestStartand onRequestEnd) that can be used to prepend/append content to the main script in a page.

Also worth noting, it is possible to extend/inherit your Application.cfc, allowing for a more complex set of RequestStart/End events. More details here and here.


Custom Tags allow you to create a tag that you can wrap around each template to apply the layout/etc. It also allows attributes/etc to define common but changing text.

For example:

<cf_page PageTitle="My Page">
    [main page content]
</cf_page>

And inside the custom tag (page.cfm) you have:

<cfif ThisTag.ExecutionMode EQ 'start'>
    <cfparam name="Attributes.PageTitle" default=""/>
    <cfcontent reset/><cfoutput><!DOCTYPE html>
    <html>
    <head>
        <title>My Website - #Attributes.PageTitle</title>
        [styles and scripts and stuff]
    </head>
    <body>
        <div id="heading">
            <img src="my_website_logo.png" alt="My Website"/>
        </div>
        <ul id="mainmenu" class="nav">
            [menu]
        </ul>
        <h1>#Attribute.PageTitle#</h1>
    </cfoutput>
<cfelse>
    <cfoutput>
        <div id="footer">
            [footer]
        </div>
    </body></html></cfoutput>
</cfif>

And of course you can either create multiple custom tags, or one tag which works in multiple ways depending on the Attributes specified.


Henry has already mentioned MVC Frameworks, but you don't need to do MVC to make use of templating/layout functionality.

Fusebox can do MVC, but it doesn't require you to do so, and eitherway FB's ContentVariables are a good tool for implementing modular content with - unless your lead developer can justify his dislike for Fusebox (and suggest an alternative that fits your project better!) then there is absolutely no reason not to go for it - it is a mature and well-known framework, easy to use, plenty of developers, and so on.

However, if Fusebox really is not an option, take a look at Charlie Arehart's list of frameworks - that page in general is a huge list of tools worth looking at.


Anyway, that should give you enough things to consider for now...

OTHER TIPS

ColdFusion developers started using a custom tag called cf_bodycontent in the late 90s to avoid having to include separate header and footer files. That was six or seven years before ASP.NET's Master Pages. ;-)

Now there's a native tag that does the same thing: cfsavecontent. Here's the essence of how people use cfsavecontent in templates.

   <!--- index.cfm --->
   <cfsavecontent variable="content">
      <cfinclude template="#url.action#.cfm">
   </cfsavecontent> 

   <cfinclude template="template.cfm">

   <!--- template.cfm --->
   <cfparam name="title" default="Welcome">
   <html>
      <head><cfoutput>#title#</cfoutput></head>
      <body>
         ... header, menu, sidebar, whatever ...
         <cfoutput>#content#</cfoutput>
         ... right column, footer ...
      </body>
   </html>

   <!--- foo.cfm --->
   <cfset title="Welcome to Foo">
   Hello World! I'm the page at index.cfm?action=foo

   <!--- bar.cfm --->
   <cfset title="Welcome to Bar">
   Hello World! I'm the page at index.cfm?action=bar

If you want put a template within a template, just add another cfsavecontent.

   <!--- index.cfm --->
   <cfsavecontent variable="content">
      <cfinclude template="#url.action#.cfm">
   </cfsavecontent> 

   <cfsavecontent variable="content">
      <cfinclude template="internal_template.cfm">
   </cfsavecontent>

   <cfsavecontent variable="content">
      <cfinclude template="master_template.cfm">
   </cfsavecontent>         

   <cfoutput>#content#</cfoutput>         

You could refactor to cut out the redundancy.

   <!--- index.cfm --->
   <cfsavecontent variable="content">
       <cfinclude template="#url.action#.cfm">
   </cfsavecontent> 

   <cfparam name="templates" default="internal,master">

   <cfloop list="#templates#" index="t">
       <cfsavecontent variable="content">
           <cfinclude template="#t#_template.cfm">
       </cfsavecontent>
   </cfloop> 

   <cfoutput>#content#</cfoutput>  

If you want to have one template "extend" another, you could maybe do so by turning the list into a stack, and having each template push its parent onto the stack.

  <!--- internal_template.cfm --->
  <cfset templates = listAppend("master", templates)>  

  ...
  <cfoutput>#content#</cfoutput>
  ...


  <!--- index.cfm --->
  <cfsavecontent variable="content">
      <cfinclude template="#url.action#.cfm">
  </cfsavecontent> 

  <cfparam name="templates" default="internal">

  <cfloop condition="listlen(templates) gt 0">
      <cfset t = listFirst(templates)>
      <cfset templates = listRest(templates)>
      <cfsavecontent variable="content">
          <cfinclude template="#t#_template.cfm">
      </cfsavecontent>
  </cfloop> 

  <cfoutput>#content#</cfoutput> 

And thus you have StackBox, a ColdFusion framework invented on StackOverflow. :-)

You may try one of the MVC frameworks with template support (almost everyone has it).

ColdBox, Model-Glue, Mach-II, Fusebox...

This Galleon Forum Ports Comparisons page highlights how each framework handles Templates...

check out CFINCLUDE

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top