Using Data Drill-Down


Now that you've learned almost everything you need to know about the <cfoutput> tag, let's put it all together in a complete application.

Data drill-down is a popular form of user interface within Web applications because it enables the progressive and gradual selection of desired data. Data drill-down applications usually are made up of three levels of interface:

  • A search screen

  • A results screen (displaying the results of any searches)

  • A details screen (displaying the details for any row selected in the results screen)

You won't create the search screen here (forms are introduced in the next chapter), but you will create the latter two screens. Your application will display a list of movies (similar to the screens created earlier in this chapter) and will allow visitors to click any movie to see detailed information about it.

Introducing Dynamic SQL

You've used lots of <cfquery> tags thus far, and each of them has contained hard-coded SQLSQL that you typed and that stays the same (the results may differ if the data in the database changes, but the SQL itself always stays the same). But SQL passed to ColdFusion need not be static and hard-coded, the real power of <cfquery> is seen when SQL is constructed dynamically.

To demonstrate what we mean, Listing 10.11 contains the code for a new file named dynamicsql.cfm. Save the code and execute it to see a screen like the one shown in Figure 10.13.

Listing 10.11. dynamicsql.cfmDynamic SQL Demonstration
 <!--- Name:        dynamicsql.cfm Author:      Ben Forta (ben@forta.com) Description: Dynamic SQL demonstration Created:     12/15/04 ---> <!--- Create FilmID variable ---> <cfset FilmID=1> <!--- Get a movie from database ---> <cfquery name="movie"          datasource="ows"          result="results"> SELECT FilmID, MovieTitle, PitchText FROM Films WHERE FilmID=#FilmID# </cfquery> <h1>Display Data</h1> <cfdump var="#movie#"> <h1>Display cfquery Results</h1> <cfdump var="#results#"> 

Figure 10.13. The <cfquery> result structure contains the final (post dynamic processing) SQL and additional information.


Listing 10.11 starts by creating a variable as follows:

 <cfset FilmID=1> 

Next comes a <cfquery> tag containing the following SQL:

 SELECT FilmID, MovieTitle, PitchText FROM Films WHERE FilmID=#FilmID# 

The WHERE clause specifies the row to be retrieved, and would usually an actual value. For example, to retrieve the movie with a FilmID of 1 you would use this SQL:

 SELECT FilmID, MovieTitle, PitchText FROM Films WHERE FilmID=1 

See Chapter 6, "Introducing SQL," for a detailed explanation of the SELECT statement and its WHERE clause.


And this is exactly what the code in Listing 10.11 does. #FilmID# is a ColdFusion expression, and so ColdFusion will process it, returning the value of FilmID which is 1 (as set in the <cfset> earlier).

In other words, the SQL used here is dynamic in that the actual SQL statement itself can change (in this example based on the value of FilmID). If you wanted to retrieve a different movie you could simply update FilmID so that it contained a different value.

But what if you wanted to know the actual SQL statement generated by ColdFusion (taking into account any dynamic processing)? That information is available to if you need it. Look at the <cfquery> tag again:

 <cfquery name="movie"          datasource="ows"          result="results"> 

The <cfquery> contains an additional attribute that we did not use previously, result is the name of a structure that will contain result information. result="results" tells <cfquery> to create a structure named results to contain tag execution results (in addition to the query already being created and returned).

The last block of code contains two <cfdump> tags:

 <h1>Display Data</h1> <cfdump var="#movie#"> <h1>Display cfquery Results</h1> <cfdump var="#results#"> 

The former simply dumps the returned query (the data contained in the movie variable). The latter dumps the results structure, exposing a field named SQL that contains the SQL used, and additional information (including the same query variables listed in Table 10.1 earlier in this chapter).

The use of result is always optional, but if needed it can expose useful information about tag execution.

NOTE

The result structure may contain additional members, depending on the <cfquery> attributed used.


Implementing Data Drill-Down Interfaces

Now that you've seen how dynamic SQL is used, let's return to data drill-down pages. The first screen you need to create is the details pagethe one that will be displayed when a movie is selected. Figure 10.14 shows the details for one movie.

Figure 10.14. In data drill-down applications, the details page displays all the details for a specific record.


Listing 10.12 contains the code for the file details1.cfm. Save the code, and then execute it in your browser with this URL:

 http://localhost:8500/ows/10/details1.cfm?FilmID=2 

You should see a screen like the one in Figure 10.14.

Listing 10.12. details1.cfmData Drill-Down Details
 <!--- Name:        details1.cfm Author:      Ben Forta (ben@forta.com) Description: Data drill-down details Created:     12/15/04 ---> <!--- Get a movie from database ---> <cfquery name="movie" datasource="ows"> SELECT FilmID, MovieTitle,        PitchText, Summary,        DateInTheaters, AmountBudgeted FROM Films WHERE FilmID=#URL.FilmID# </cfquery> <!--- 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">    <img src="/books/2/448/1/html/2/../images/f#filmid#.gif"         alt="#movietitle#"         align="middle">    <strong>#MovieTitle#</strong>   </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> </cfoutput> </body> </html> 

There are several important things to point out in Listing 10.12. Let's start with the SQL statement:

 SELECT FilmID, MovieTitle,        PitchText, Summary,        DateInTheaters, AmountBudgeted FROM Films WHERE FilmID=#URL.FilmID# 

The WHERE clause here is used to select a specific movie by its primary key (FilmID). But instead of comparing it to a real number, a ColdFusion variable is used#URL.FilmID#. This is dynamic SQL, similar to the example in Listing 10.11 above. When ColdFusion encounters #URL.FilmID#, it replaces that expression with whatever the value of the URL parameter FilmID is. So, if the URL parameter FilmID had a value of 2, the generated SQL would look like this:

 SELECT FilmID, MovieTitle,        PitchText, Summary,        DateInTheaters, AmountBudgeted FROM Films WHERE FilmID=2 

This is why I had you append ?FilmID=2 to the URL when you executed this page. Without a FilmID parameter, this code would have failed, but we'll get to that in a moment.

The beauty of this technique is that it allows the same details page to be used for an unlimited number of database recordseach FilmID specified generates a different page. If FilmID were 10, the SQL statement would have a WHERE clause of FilmID=10, and so on.

URL variables were briefly introduced in Chapter 9, "CFML Basics."


The rest of the code in Listing 10.12 is self-explanatory. The details are displayed in an HTML table with the title spanning two columns. Dates are formatted using the DateFormat() function, and monetary amounts are formatted using the DollarFormat() function (which, as its name suggests, formats numbers as dollar amounts).

NOTE

Support for other currencies also are available via the locale functions.


One interesting line of code, though, is the <img> tag (used to display the movie poster image):

 <img src="/books/2/448/1/html/2/../images/f#filmid#.gif"      alt="#movietitle#"      align="middle"> 

Binary data, like images, can be stored in databases just like any other data, but accessing these images requires special processing that is beyond the scope of this chapter. And so in this application images are stored in a directory and named using the primary key values. Therefore, in this example, the image for FilmID 2 is f2.gif, and that image is stored in the images directory under the application root. By using #FilmID# in the filename, images can be referred to dynamically. In this example, for FilmID 2 the <img> tag becomes

 <img src="/books/2/448/1/html/2/../images/f2.gif"      alt="Charlie'd Devils"      align="middle"> 

Try executing Listing 10.12 again, but this time don't pass the FilmID parameter. What happens when you execute the code? You probably received an error message similar to the one in Figure 10.15 telling you that you were referring to a variable that doesn't exist. You can't use URL.FilmID in your SQL statement if no URL parameter named FilmID exists.

Figure 10.15. Don't refer to a variable that doesn't exist, or an error message will be generated.


The solution (which you looked at briefly in Chapter 9) is to check that the variable exists before using it. Listing 10.13 contains an updated version of the code; save it as details2.cfm and execute it. What happens now if no FilmID is specified?

Listing 10.13. details2.cfmData Drill-Down Details
 <!--- Name:        details2.cfm Author:      Ben Forta (ben@forta.com) Description: Data drill-down details              with basic validation Created:     12/15/04 ---> <!--- Make sure FilmID was passed ---> <cfif not IsDefined("URL.filmid")>  <!--- it wasn't, send to movie list --->  <cflocation url="movies6.cfm"> </cfif> <!--- Get a movie from database ---> <cfquery name="movie" datasource="ows"> SELECT FilmID, MovieTitle,        PitchText, Summary,        DateInTheaters, AmountBudgeted FROM Films WHERE FilmID=#URL.FilmID# </cfquery> <!--- 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">    <img src="/books/2/448/1/html/2/../images/f#filmid#.gif"         alt="#movietitle#"         align="middle">    <strong>#MovieTitle#</strong>   </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> </cfoutput> </body> </html> 

The only thing that has changed in Listing 10.13 is the inclusion of the following code before the <CFQUERY> tag:

 <!--- Make sure FilmID was passed ---> <cfif not IsDefined("URL.filmid")>  <!--- it wasn't, send to movie list --->  <cflocation url="movies6.cfm"> </cfif> 

If FilmID was not passed, users should never have gotten to this page. You could simply display an error message, but instead, why not send them where they need to go? <cflocation> is a ColdFusion tag that redirects users to other pages (or even other sites). So, the <cfif> statement checks to see whether URL.FilmID exists (using the IsDefined() function). If it does not, the user is sent to the movies6.cfm page automatically. Now the SQL code won't execute without a FilmID because if no FilmID exists, the <cfquery> tag is never even reached.

The IsDefined() function was introduced in Chapter 9.


So far so good, but you're not there yet. Two other possible trouble spots still exist. Try executing the following URL:

 http://localhost:8500/ows/10/details2.cfm?FilmID=1 

1 is a valid FilmID, so the movie details are displayed. But FilmID 1 doesn't have a movie image, which means the <img> tag is pointing to a nonexistent image, causing a browser error (as seen in Figure 10.16).

Figure 10.16. When referring to images dynamically, care must be taken to ensure that the image actually exists.


In addition, try this URL:

 http://localhost:8500/ows/10/details2.cfm?FilmID=1000 

No movie with a FilmID of 1000 exists, so no movie is displayed, but no error message is displayed either.

Neither of these problems is critical, but they should be addressed anyway. Listing 10.14 contains a final version of the details page; save this file as details3.cfm.

Listing 10.14. details3.cfmData Drill-Down Details
 <!--- Name:        details3.cfm Author:      Ben Forta (ben@forta.com) Description: Data drill-down details              with complete validation Created:     12/15/04 ---> <!--- Movie list page ---> <cfset list_page="movies8.cfm"> <!--- Make sure FilmID was passed ---> <cfif not IsDefined("URL.filmid")>  <!--- it wasn't, send to movie list --->  <cflocation url="#list_page#"> </cfif> <!--- Get a movie from database ---> <cfquery name="movie" datasource="ows"> SELECT FilmID, MovieTitle,        PitchText, Summary,        DateInTheaters, AmountBudgeted FROM Films WHERE FilmID=#URL.FilmID# </cfquery> <!--- 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>    <strong>#MovieTitle#</strong>   </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> <!--- Link back to movie list --->  [<a href="#list_page#">Movie list</a>] </cfoutput> </body> </html> 

A lot has changed here, so let's walk through the code together.

The first line of code is a <cfset> statement that sets a variable named list_page to movies8.cfm. You'll see why this was done in a moment.

Next comes the check for the URL parameter FilmID. If it's not present, <cflocation> is used to redirect the user to the page referred to in variable list_page (the movie list, same as before).

Then comes the query itselfsame as before; no changes there.

After the query comes a new <cfif> statement that checks to see whether Movie.RecordCount IS 0. You will recall that RecordCount lets you know how many rows were retrieved by a query, so if RecordCount IS 0, you know that no rows were retrieved. The only way this could happen is if an invalid FilmID were specified, in which case <cflocation> would be used to send the user back to the movie list pageone problem solved. (Earlier I said that I'd show you an alternative use for RecordCount; well, I just did.)

Next comes a set of two <cfset> statements:

 <!--- Build image paths ---> <cfset image_src="/books/2/448/1/html/2/../images/f#movie.FilmID#.gif"> <cfset image_path=ExpandPath(image_src)> 

The goal here is to check that the movie image exists before the <img> tag is used to insert it. ColdFusion provides a function named FileExists() that can be used to check for the existence of files, but there is a catch.

Images always have at least two paths by which they are referredthe actual path on disk and the URL (usually a relative URL). So, in this example, the image for FilmID 2 would have a path on disk that might look similar to c:\cfusionmx\wwwroot\ows\images\f2.gif and a URL that might look similar to ../images/f2.gif. Usually, you care about only the URLthe actual physical location of a file isn't important within the browser. But to check for a file's existence, you do need the actual path (that is what you must pass to FileExists()). And the code you used to build the path (using #FilmID# in the SRC) was a relative path. Enter the two <cfset> statements. The first simply creates a variable named image_src that contains the dynamically generated relative filename (in the case of FilmID 2, it would be ../images/f2.gif), the same technique used in the <img> tag in the previous versions of this code. The second uses a ColdFusion function named ExpandPath() that converts relative paths to complete physical paths (here saving that path to image_path).

At this point, no determination has been made as to whether to display the image. All you have done is created two variables, each containing a pathone physical, suitable for using with FileExists(), and one relative, suitable for use in an <img> tag.

Next comes the details display, which is the same as it was before, except now the <img> tag is enclosed within a <cfif> statement that checks whether FileExists(image_path). If the image exists, FileExists() returns trUE and the <img> tag is inserted using image_src as the SRC. If FileExists() returns FALSE (meaning the movie had no image), the <img> tag isn't generatedproblem number two solved.

NOTE

Of course, the two variables image_path and image_src aren't actually necessary, and the code would have worked if the processing was all done inline. But, the approach used here is cleaner, more intuitive, easier to read and will help you write better code.


At the very bottom of the page is a new link that enables users to get back to the movie list page. This link also uses the list_page variable. And by now, I hope the reason that a variable for the movie link URL is used is blatantly obvious. The code now has three locations that refer to the movie list file. Had they all been hard-coded, making changes would involve more work and would be more error-prone (the likelihood of you missing one occurrence grows with the number of occurrences). By using a variable, all that needs to change is the variable assignment at the top of the pagethe rest all works as is.

The last thing to do is to update the movie-listing page so it contains links to the new details3.cfm page. Listing 10.15 contains the revised movie listing code (based on movies6.cfm). Save it as movies8.cfm, and then execute it to see a page similar to the one shown in Figure 10.17.

Listing 10.15. movies8.cfmData Drill-Down Results Page
 <!--- Name:        movies8.cfm Author:      Ben Forta (ben@forta.com) Description: Data drill-down Created:     12/15/04 ---> <!--- Get movie list from database ---> <cfquery name="movies" datasource="ows" result="x"> SELECT FilmID, MovieTitle, PitchText,        Summary, DateInTheaters FROM Films  ORDER BY MovieTitle </cfquery> <!--- Create HTML page ---> <html> <head>  <title>Orange Whip Studios - Movie List</title> </head> <body> <!--- Start table ---> <table>  <tr>   <th colspan="2">    <font size="+2">    <cfoutput>    Movie List (#Movies.RecordCount# movies)    </cfoutput>    </font>   </th>  </tr>  <!--- loop through movies --->  <cfoutput query="movies">   <tr bgcolor="##cccccc">    <td>     <strong>     #CurrentRow#:     <a href="details3.cfm?FilmID=#URLEncodedFormat(Trim(FilmID))#"> #MovieTitle#</a>     </strong>     <br>     #PitchText#    </td>    <td>     #DateFormat(DateInTheaters)#    </td>   </tr>   <tr>    <td colspan="2">     <font size="-2">#Summary#</font>    </td>   </tr>  </cfoutput>  <!--- End of movie loop ---> </table> </body> </html> 

Figure 10.17. Dynamically generated URLs make creating data drill-down interfaces easy.


Just two changes have been made in Listing 10.14. The SELECT statement in the <cfquery> now also retrieves the FilmID columnyou need that to pass to the details page. (You will recall that the details page needs the FilmID passed as a URL parameter.)

The display of MovieTitle has been changed to read

 <a href="details3.cfm?FilmID=#URLEncodedFormat(Trim(FilmID))#"> #MovieTitle#</a> 

The HTML <a href> tag is used to create links to other pages. The text between the <a> and </a> tags is clickable, and when it's clicked, the user is taken to the URL specified in the HRef attribute. So, the tag <a href="details3.cfm">Click here</a> displays the text Click here, which, if clicked, takes the user to page details3.cfm.

But you need FilmID to be passed to the details page, so for FilmID 1 the HRef needed would read

 <a href="details3.cfm?FilmID=1">Being Unbearably Light</a> 

And for FilmID 2 it would have to be

 <a href="details3.cfm?FilmID=2">Charlie's Devils</a> 

These links are created using the FilmID column so that the URL parameter FilmID is correctly populated with the appropriate value for each movie. As ColdFusion loops through the movies, it creates a link for each one of them. The links all point to the same pagedetails3.cfm. The only thing that differs is the value passed to the FilmID parameter, and this value is then used in details3.cfm to display the correct movie. So, for the movie with FilmID of 1, the URL correctly becomes

 <a href="details3.cfm?FilmID=1">Being Unbearably Light</a> 

Try it out; you should be able to click any movie to see the details and then click the link at the bottom of the details page to get back.

Pretty impressive for just two files containing less than 150 lines of ColdFusion code (including all HTML and comments).

NOTE

You probably noticed that when constructing URLs for an hrEF, two functions were used, TRim() and URLEncodedFormat(), instead of just referring to the column directly.


trim() was used to get rid of any extra spaces (if any existed). URLs have size limitations, and care should be taken to not waste URL space.

The URLEncodedFormat() function is even more important. As you already know, ? is used to separate the URL from any parameters passed to it, = is used to assign parameter values, and & is used to separate parameters. Of course, this means that these characters can't be used within URL parameter values; many others can't be used, either (spaces, periods, and so on).

So, how are these values passed? They're passed using a special format in which characters are replaced by a set of numbers that represent them. On the receiving end, the numbers can be converted back to the original characters (and ColdFusion does this for you automatically).

The URLEncodedFormat() function takes a string and returns a version of it that is URL safe.

When you populate a URL from a variable (any variable, including a database column), you run the risk that the values used might contain these illegal characterscharacters that need to be converted. Therefore, you always should use URLEncodedFormat() (as was done in the previous example) so that if any invalid characters exist, they will be converted automatically and transparently. (Even in this chapter's example, in which you know FilmID contains only numbers that are safe, it still pays to encode the values in case someone changes something someday.)

Displaying Data Using Frames

Another form of data drill-down involves the use of HTML frames. Frames enable you to split your browser window in two or more windows and control what gets displayed within each. ColdFusion templates are very well suited for use within frames.

NOTE

Frames have proven to be rather unpopular, and most large public-facing and high-profile applications avoid their use. But frames are indeed useful, and understanding how they can be used in dynamic data-driven drill-down applications remains important. As such, they are briefly covered here.


Creating frames involves creating multiple templates (or HTML pages). Each window in a frame typically displays a different template; you need two templates if you have two windows. In addition, one more page is always used to lay out and create the frames.

When the frames are created, each window is titled with a unique name. In a non-framed window, the new page is opened in the same window every time you select a hyperlink, replacing whatever contents were there previously. In a framed window, you can use the window name to control the destination for any output.

Figure 10.18 shows a frames-based version of the movie listing application. As you can see, movies are listed on the left, and when a movie is selected its details are displayed on the right.

Figure 10.18. Frames-based interfaces are effective for data drill-down applications.


Now that you know how frames work, the first thing you need to do is create the template to define and create the frames. The code for template frame.cfm is shown in Listing 10.16.

This template first defines the frames. <frameset cols="250,*"> creates two columns (or windows) one 250 pixels wide and the other as wide as the remaining space allows.

TIP

Sizes also can be specified as percentages, so <frameset cols="50%,50%"> would create two windows, each 50 percent of the width of the browser.


Listing 10.16. frame.cfmColdFusion-Powered Frames
 <!--- Name:        frame.cfm Author:      Ben Forta (ben@forta.com) Description: Frames for frames-based data drill-down Created:     12/15/04 ---> <html> <head>  <title>Orange Whip Studios - Movie List</title> </head> <!-- frames --> <frameset cols="250,*">  <frame name="left" src="/books/2/448/1/html/2/frame_movies.cfm">  <frame name="right" src="/books/2/448/1/html/2/frame_blank.cfm"> </frameset> </html> 

The two columns are then defined: <frame name="left" src="/books/2/448/1/html/2/frame_movies.cfm"> creates the left frame; the name attribute names the window; and the src attribute specifies the name of the template to initially display within the window when the frame is first displayed. Listing 10.17 contains the code for the file frame_movies.cfm.

Listing 10.17. frame_movies.cfmMovie List for Left Frame
 <!--- Name:        frame_movies.cfm Author:      Ben Forta (ben@forta.com) Description: Left frame for data drill-down Created:     12/15/04 ---> <!--- Get movie list from database ---> <cfquery name="movies" datasource="ows"> SELECT FilmID, MovieTitle FROM Films  ORDER BY MovieTitle </cfquery> <body> <!--- title and movie count ---> <cfoutput> <strong> Movie List (#Movies.RecordCount# movies) </strong> </cfoutput> <!--- Movie list ---> <ul>  <cfoutput query="movies">  <li><a href="frame_details.cfm?filmid=#URLEncodedFormat(Trim(FilmID))#"         target="right">#MovieTitle#</a>  </cfoutput> </ul> </body> 

No movie is selected when the frame is first displayed, and therefore no information exists to display in the details window (the right frame). You obviously can't display movie information in that frame before the user selects the movie to view, so instead you display an empty page. src="/books/2/448/1/html/2/frame_blank.cfm" loads a blank page in the frame named right, the source for which is shown in Listing 10.18.

Listing 10.18. frame_blank.cfmInitial Blank Right Frame
 <!--- Name:        frame_blank.cfm Author:      Ben Forta (ben@forta.com) Description: Blank initial frame content Created:     12/15/04 ---> <body> </body> 

Listing 10.17 (frame_movies.cfm) contains code similar to the code used in previous listings in this chapter. The only difference is the link itself. The <a> tag now contains a new attribute: target="right". target specifies the name of the target window in which to open the URL. Because you named the right window right (you named the left window left), when a link is clicked in the left window, the appropriate URL is opened in the right window.

TIP

Frames can be named with any names you want, but be careful not to reuse frame names unless you want to reuse the same frame. To open links in a new window (effectively creating a frame as needed), use the target of _new.


The link itself is a file named frame_details.cfm (a modified version of the details files created earlier). Listing 10.19 contains the source for this file.

Listing 10.19. frame_details.cfmMovie Details for Right Frame
 <!--- Name:        frame_details.cfm Author:      Ben Forta (ben@forta.com) Description: Detail for frames-based data drill-down Created:     12/15/04 ---> <!--- Make sure FilmID was passed ---> <cfif not IsDefined("URL.filmid")>  <!--- This should never happen --->  <cflocation url="frame_blank.cfm"> </cfif> <!--- Get a movie from database ---> <cfquery name="movie" datasource="ows"> SELECT FilmID, MovieTitle,        PitchText, Summary,        DateInTheaters, AmountBudgeted FROM Films WHERE FilmID=#URL.FilmID# </cfquery> <!--- Make sure have a movie ---> <cfif movie.RecordCount IS 0>  <!--- This should never happen --->   <cflocation url="frame_blank.cfm"> </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 ---> <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>    <strong>#MovieTitle#</strong>   </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> </cfoutput> </body> 

Just like the code for frame_blank.cfm, the code for frame_details.cfm is missing <html>...</html>, and <head><title>...</title></head>.

Listing 10.18 should be self-explanatory by this point. The only real change here is that if no FilmID is passed, or if FilmID is invalid (neither condition should ever actually occur, but it pays to be safe), file blank.cfm is loaded. You could change this to display an appropriate error message if you want.

After you have created all four files (frame.cfm, frame_blank.cfm, frame_movies.cfm, and frame_details.cfm), execute the application in your browser by going to the following URL:

 http://localhost:8500/ows/10/frame.cfm 

You should see a screen like the one previously in Figure 10.18. Try clicking any link on the left; the appropriate movie will be displayed on the right.

And there you have ittwo simple tags, <cfquery> and <cfoutput>, generating any output you can imagine.



Macromedia Coldfusion MX 7 Web Application Construction Kit
Macromedia Coldfusion MX 7 Web Application Construction Kit
ISBN: 321223675
EAN: N/A
Year: 2006
Pages: 282

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net