Macromedia Coldfusion MX 7 Web Application Construction Kit

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.

The code in Listing 16.8 couldn't be simpler. By wrapping text in between <cfdocument> and </cfdocument> tags, content between those tags is converted into a PDF file on the fly, and embedded in the page.

In addition to PDF, ColdFusion can generate FlashPaper, a lightweight alternative to PDF, and one that only requires that the Flash Player be present on the browser. To generate FlashPaper, simply change format="pdf" to format="flashpaper" to generate a page like the one seen in Figure 16.9.

Figure 16.9. FlashPaper is a lightweight alternative to PDF that requires only the Flash Player on the client.

Of course, you're not limited to static text; you can use dynamic CFML within the document content, too. Listing 16.9 uses a mixture of HTML, CFML, and dynamic data to create a printable report (seen in 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="/books/2/448/1/html/2/../images/logo_c.gif" alt="Orange Whip Studios"> </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 contain HTML, CFML, and more.

What Is Supported by <cfdocument>?

You'll notice that the code in Listing 16.9 uses a mixture of HTML (including tags like <font>, which generally should be avoided), an image, tables, CFML expressions, and more. The <cfdocument> tag supports all of the following:

  • HTML 4

  • XML 1

  • DOM level 1 and 2

  • CSS1 and CSS2

In other words, <cfdocument> should be more than able to convert all sorts of pages into printable PDF or FlashPaper.

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. Listing 16.10 is a modified version of a page we created back in 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" Film> <!--- 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="/books/2/448/1/html/2/../images/f#movie.FilmID#.gif"> <cfset image_path=ExpandPath(image_src)> <!--- Create HTML page ---> <html> <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="/books/2/448/1/html/2/../images/f#filmid#.gif" alt="#movietitle#" 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.

The big change to this page is a line added to the links section at the bottom. A new link to a Printable page has been created; when clicked, it opens detailsprint.cfm passing the FilmID to that page. The code for that page is remarkably simple, as seen in Listing 16.11.

Listing 16.11. detailsprint.cfmPrintable Movie Details Page

<!--- 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>

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.

Figure 16.12. Include an existing page to make it printable.

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.

Table 16.9. <cfdocument> Attributes

ATTRIBUTE

DESCRIPTION

backgroundvisible

Whether or not to display page background; default is no.

encryption

Optional encryption, 128-bit or 40-bit (used by PDF only).

filename

Optional file name, if specified document is saved to disk instead of being served in the browser.

fontembed

Whether or not to embed used fonts, yes, no, or selective (default).

format

pdf or flashpaper, this attribute is required.

marginbottom

Page bottom margin, use unit to specify unit of measure.

marginleft

Page left margin, use unit to specify unit of measure.

marginright

Page right margin, use unit to specify unit of measure.

margintop

Page top margin, use unit to specify unit of measure.

name

Optional variable name to contain generated output.

orientation

Page orientation, portrait (the default) or landscape.

overwrite

Whether or not to overwrite existing documents (if using filename).

ownerpassword

Optional owner password (used by PDF only).

pageheight

Page height (used if pagetype="custom"), use unit to specify unit of measure.

pagetype

Page size, supports legal, letter, A4, A5, B5, and custom.

pagewidth

Page width (used if pagetype="custom"), use unit to specify unit of measure.

scale

Scaling factor, default is calculated by ColdFusion automatically.

unit

Unit of measure, in (inches) or cm (centimeters).

userpassword

Optional user password (used by PDF only).

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.

Table 16.10. <cfdocumentitem> 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="/books/2/448/1/html/2/../images/logo_c.gif" alt="Orange Whip Studios"></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.

Listing 16.12 warrants some explanation. The <cfdocument> content now contains the following code:

<!--- Header ---> <cfdocumentitem type="header"> OWS Budget Report </cfdocumentitem>

This code defines a page header, text that will be placed at the top of each page. A footer is also defined as follows:

<!--- Footer ---> <cfdocumentitem type="footer"> <p align="center"> <cfoutput> #CFDOCUMENT.currentpagenumber# of #CFDOCUMENT.totalpagecount# </cfoutput> </p> </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.

Table 16.11. CFDOCUMENT Scope Variables

TYPE

DESCRIPTION

currentpagenumber

Current page number.

totalpagecount

Total number of generated pages.

In addition, the code in Listing 16.12 embeds a manual page break using this code:

<!--- Page break ---> <cfdocumentitem type="pagebreak" />

<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"></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.

NOTE

When using <cfdocumentsection>, all content must be in sections. ColdFusion ignores any content outside of sections.

Категории