Creating Printable Pages
It's long been a hassle to easily generate printable content from within Web pages, and this is a source of serious aggravation for Web application developers (all developers, not just ColdFusion developers). Considering that a very significant chunk of Web application development tends to be data reporting and presentation type applications, this is a big problem.The truth is, Web browsers just don't print Web pages properly, so developers have had to resort to complex and painful work-arounds to put content in a printable format.ColdFusion solves this problem simply with the <cfdocument> family of tags.
Using the <cfdocument> Tag
We'll start with a really simple example. Listing 16.8 contains simple text wrapped within a pair of <cfdocument> tags. The generated output is seen in Figure 16.8.
Listing 16.8. Print1.cfmBasic PDF Generation
<!---
Name: Print1.cfm
Author: Ben Forta
Description: Simple printable output
Created: 01/10/05
--->
<cfdocument format="pdf">
Hello world!
</cfdocument>
Figure 16.8. Adobe PDF format is the most commonly used printable document format on the Web.
[View full size image]

Figure 16.9. FlashPaper is a lightweight alternative to PDF that requires only the Flash Player on the client.
Figure 16.10).
Listing 16.9. Print2.cfmData-Driven Document Generation
<!---
Name: Print2.cfm
Author: Ben Forta
Description: Data driven printable output
Created: 01/10/05
--->
<!--- Get budget data --->
<cfinvoke component="ChartData"
method="GetBudgetData"
returnvariable="BudgetData">
<!--- Generate document --->
<cfdocument format="pdf">
<!--- Header --->
<table align="center">
<tr>
<td>
<img src="../images/logo_c.gif"
>
</td>
<td align="center">
<font size="+2">Orange Whip Studios<br>Movies</font>
</td>
</tr>
</table>
<!--- Title --->
<div align="center">
<h2>Budget Data</h2>
</div>
<!--- Details --->
<table>
<tr>
<th>Movie</th>
<th>Budget</th>
</tr>
<cfoutput query="BudgetData">
<tr>
<td><strong>#MovieTitle#</strong></td>
<td>#LSCurrencyFormat(AmountBudgeted)#</td>
</tr>
</cfoutput>
</table>
</cfdocument>
Figure 16.10. Printable output may contai269, CFML, and more.
[View full size image]

What Is Supported by <cfdocument>?
You'll notice that the code in <font>, which generally should be avoided), an image, tables, CFML expressions, and more. The <cfdocument> tag supports all of the following:
- <271 4
- XML 1
- DOM level 1 and 2
- CSS1 and CSS2
Creating Printable Versions Of Pages
You will likely often need to create printable versions of existing pages. It would be tempting to try and simply conditionally include <cfdocument> tags in existing pages, but unfortunately that won't work: ColdFusion won't parse the page correctly because it thinks your tags aren't properly paired.The solution to this problem is to create a wrapper page, one that defines the printable document and includes the original page. Chapter 11, it simply displays movie details. The modified page is seen in Figure 16.11.
Listing 16.10. details.cfmMovie Details Page
<!---
Name: details.cfm
Author: Ben Forta (ben@forta.com)
Description: CFC driven data drill-down details
with complete validation
Created: 12/15/04
--->
<!--- Movie list page --->
<cfset list_page="movies.cfm">
<!--- Make sure FilmID was passed --->
<cfif not IsDefined("URL.filmid")>
<!--- it wasn't, send to movie list --->
<cflocation url="#list_page#">
</cfif>
<!--- Get movie details --->
<cfinvoke
component="ows.11.movies"
method="GetDetails"
returnvariable="movie"
FilmID="#URL.filmid#">
<!--- Make sure have a movie --->
<cfif movie.RecordCount IS 0>
<!--- It wasn't, send to movie list --->
<cflocation url="#list_page#">
</cfif>
<!--- Build image paths --->
<cfset image_src="../images/f#movie.FilmID#.gif">
<cfset image_path=ExpandPath(image_src)>
<!--- Creat260 page --->
&l275>
<head>
<title>Orange Whip Studios - Movie Details</title>
</head>
<body>
<!--- Display movie details --->
<cfoutput query="movie">
<table>
<tr>
<td colspan="2">
<!--- Check of image file exists --->
<cfif FileExists(image_path)>
<!--- If it does, display it --->
<img src="../images/f#filmid#.gif"
align="middle">
</cfif>
<b>#MovieTitle#</b>
</td>
</tr>
<tr valign="top">
<th align="right">Tag line:</th>
<td>#PitchText#</td>
</tr>
<tr valign="top">
<th align="right">Summary:</th>
<td>#Summary#</td>
</tr>
<tr valign="top">
<th align="right">Released:</th>
<td>#DateFormat(DateInTheaters)#</td>
</tr>
<tr valign="top">
<th align="right">Budget:</th>
<td>#DollarFormat(AmountBudgeted)#</td>
</tr>
</table>
<p>
<!--- Links --->
[<a href="detailsprint.cfm?FilmID=#URL.FilmID#">Printable page</a>]
[<a href="#list_page#">Movie list</a>]
</cfoutput>
</body>
</html>
Figure 16.11. It's often convenient to provide links to printable versions of pages.
[View full size image]

Listing 16.11. detailsprint.cfmPrintable Movie Details Page
Listing 16.11 creates a document using <cfdocument> tags, and includes the existing details page to generate the printable output seen in Figure 16.12.
<!---
Name: detailsprint.cfm
Author: Ben Forta (ben@forta.com)
Description: Printable version of details pahge
Created: 12/15/04
--->
<cfdocument format="pdf">
<cfinclude template="details.cfm">
</cfdocument>
Figure 16.12. Include an existing page to make it printable.
[View full size image]

NOTE
The links in details.cfm work in the generated printable output.In addition to the format attribute used here, <cfdocument> supports a whole series of attributes to give you greater control over printed output. Table 16.9 lists the supported attributes.Saving Generated Output
<cfdocument> embeds generated output in your Web page. You may opt to save the generated files to disk instead of serving them in real time. Reasons to do this include:
- Caching, so as to not have to regenerate pages unnecessarily
- Emailing generated content
- Generating pages that can be served statically
To save generated output, simply provide a filename in the filename attribute.
Controlling Output using The <cfdocumentitem> Tag
<cfdocumentitem> is used within a <cfdocument> tag set to embed additional items. <cfdocumentitem> requires that a type be specified. Table 16.10 lists the supported types.
TYPE | DESCRIPTION |
---|---|
footer | Page footer. |
header | Page header. |
pagebreak | Embed a page break, this type takes no body. |
NOTE
Page breaks are calculated automatically by ColdFusion. Use <cfdocumentitem type="pagebreak"> to embed manual breaks.Listing 16.12 is a revised printable movie listing, the output of which is seen in Figure 16.13.
Listing 16.12. Print3.cfmPrintable Output with Additional Items
<!---
Name: Print3.cfm
Author: Ben Forta
Description: Printable output with additional options
Created: 01/10/05
--->
<!--- Get budget data --->
<cfinvoke component="ChartData"
method="GetBudgetData"
returnvariable="BudgetData">
<!--- Generate document --->
<cfdocument format="pdf">
<!--- Header --->
<cfdocumentitem type="header">
OWS Budget Report
</cfdocumentitem>
<!--- Footer --->
<cfdocumentitem type="footer">
<p align="center">
<cfoutput>
#CFDOCUMENT.currentpagenumber# of #CFDOCUMENT.totalpagecount#
</cfoutput>
</p>
</cfdocumentitem>
<!--- Header --->
<table align="center">
<tr>
<td><img src="../images/logo_c.gif" ></td>
<td align="center"><font size="+2">Orange Whip Studios<br>Movies</font>
</td>
</tr>
</table>
<!--- Title --->
<div align="center">
<h2>Budget Data</h2>
</div>
<!--- Page break --->
<cfdocumentitem type="pagebreak" />
<!--- Details --->
<table>
<tr>
<th>Movie</th>
<th>Budget</th>
</tr>
<cfoutput query="BudgetData">
<tr>
<td><strong>#MovieTitle#</strong></td>
<td>#LSCurrencyFormat(AmountBudgeted)#</td>
</tr>
</cfoutput>
</table>
</cfdocument>
Figure 16.13. Generated documents may contain page headers and footers.
[View full size image]

This code defines a page header, text that will be placed at the top of each page. A footer is also defined as follows:
<!--- Header --->
<cfdocumentitem type="header">
OWS Budget Report
</cfdocumentitem>
This page footer contains two special variables. Within a <cfdocument> tag, a special scope exists named CFDOCUMENT. It contains two variables, as listed in Table 16.11. These variables may be used in headers and footers, as used in this example.
<!--- Footer --->
<cfdocumentitem type="footer">
<p align="center">
<cfoutput>
#CFDOCUMENT.currentpagenumber# of #CFDOCUMENT.totalpagecount#
</cfoutput>
</p>
</cfdocumentitem>
TYPE | DESCRIPTION |
---|---|
currentpagenumber | Current page number. |
totalpagecount | Total number of generated pages. |
<cfdocumentitem> must always have an end tag, even when no body is used. The trailing / is a shortcut that you can use. In other words, the above tag is functionally identical to:
<!--- Page break --->
<cfdocumentitem type="pagebreak" />
<!--- Page break --->
<cfdocumentitem type="pagebreak"></cfdocumentitem>
Defining Sections with <cfdocumentsection>
As you have seen, you have a lot of control over generated pages using the <cfdocument> and <cfdocumentitem> tags. But sometimes you may want different options in different parts of the same document. For example, you may want a title page to have different margins than other pages. Or you may want different headers and footers in different parts of the document.To do this, you use <cfdocumentsection> tags. A <cfdocument> tag pair may contain one or more sections, each defined using <cfdocumentsection> tags. Within each section you can specify alternate margins, and can use <cfdocumentitem> tags to specify headers and footers for each section.
