Custom Tags

   

You can extend CFML by creating your own custom tags, which work just like standard CFML tags. Use custom tags to encapsulate application logic so that you can use and re-use it from any ColdFusion page.

Thousands of custom tags are also available through the ColdFusion Exchange at www.macromedia.com, many of them freeware or shareware. Browsing there is a good way to familiarize yourself with tags, and also to find out what you don't have to do, because someone else has already done it for you.

For more on custom tags, see customTags.htm on the CD, which includes a link to the ColdFusion Exchange at www.macromedia.com.


Custom Tags Versus ColdFusion Components

Custom tags and ColdFusion components both encapsulate application logic. However, there are important differences between them. Probably the two most significant have to do with accessibility and persistence.

Custom tags are accessible only locally and only via ColdFusion. CFCs can be accessed in a number of ways, including as Web services or via Flash Remoting, which means they are accessible remotely from a wide variety of environments. If there are capabilities in your program that you want to expose remotely to a variety of platforms, implement them as CFCs. These are likely to be the fundamental services offered by your site. If a database is at the foundation of your site, the most fundamental service usually involves returning data. For instance, if the basic purpose of your site is translation among multiple languages, returning the translated text is the basic service. This is a capability you would most likely expose as a Web service, and therefore one you would implement as a CFC. Capabilities relating to presentation (formatting and viewing), on the other hand, typically apply only to the local mechanism for consuming the service (such as a ColdFusion page that displays the translated text), and therefore might be better implemented with custom tags for encapsulation.

The other big difference is that you can persist a CFC and data in it by assigning the CFC to a persistent scope, such as the SESSION or APPLICATION scope.

There is no way to persist a custom tag. Therefore, it can't be used to store data.

There are other, more minor differences too. For instance, a custom tag has a single entry point, so it is best suited for implementing a single procedure. A CFC can contain multiple functions, which provide multiple entry points, so it's well suited for implementing multiple related procedures.

By encapsulating multiple related procedures and persistent data, a CFC takes on the characteristics of an object, whereas the custom tag remains simply a transient procedure.

In addition, Dreamweaver automates creating and deploying CFCs more than custom tags. For example, there is a drag-and-drop procedure for creating a page that calls a function in a CFC. There is nothing like that for custom tags.

One framework for thinking about the implications of the inherent difference between CFCs and custom tags is the model-view-controller (MVC) paradigm for architecting applications. The view manages graphical and/or textual output. The controller interprets input from the user , and tells the model and/or the view to change appropriately. Finally, the model does whatever the application is ultimately designed to do, such as translating for a translation application.

In this framework, CFCs are usually appropriate at the model and controller levels, whereas custom tags are appropriate at the view level, as shown in Figure 33.1.

Figure 33.1. Custom tags are often most appropriate at the view level. CFCs are usually more appropriate at the controller and model levels. (Thanks to: Benoit Hediard. See benorama.htm on the CD.)

graphics/33fig01.gif



For an example of persistence, see the link in persistence.htm on the CD accompanying this book.


To learn more about the drag-and-drop procedure for creating a page that calls a function in a CFC, see "Invoking a function in a CFC," page 312 , in Chapter 13.


Custom Tag Basics

Each custom tag is embodied in its own separate file. Although there are several ways of invoking a custom tag, a simple one is to use a tag with the name of the file, with cf_ in front of it. For example, if the custom tag is contained in a file named scrape.cfm , the custom tag is cf_scrape .

NOTE

The other ways of invoking a custom tag use cfmodule and cfimport . They are often favored for managing a large number of custom tags.


NOTE

There are two kinds of custom tags: CFML and CFX. CFX tags are written in C++ or Java. Only CFML tags are covered in this book.


ColdFusion looks for custom tags first in the same directory as the calling page, then in the CFusionMX\CustomTags directory, then in subdirectories of the CFusionMX\CustomTags directory, and finally in directories that you can specify in the ColdFusion MX Administrator.

The calling page can pass data to the custom tag page. Although custom tags do not explicitly return a value, the calling page can easily get a result from a custom tag.

Passing Data to a Custom Tag

To pass data from the calling page to the custom tag page, you have to do two things, one on the calling page and one on the custom tag page:

  • On the calling page, invoke the custom tag with one or more name/value pairs.

  • On the custom tag page, use the cfparam tag to create a corresponding parameter for each name/value pair. Create the parameter(s) in the ATTRIBUTES scope.

For now, you don't have to worry about the details of the following example, as long as you see the basic outline of the two steps just described.

The following example is implemented in screenScrapeTest.cfm (calling page) and screenScrape.cfm (custom tag) on the CD accompanying this book.


The details of invoking the screenScrape.cfm custom tag example should be clear after you read the section on "The cf_scrape Custom Tag," page 879 , in this chapter.


Suppose you have a custom tag for screen scrapingsearching a Web page for text contained between a specified start string and a specified end string. If the custom tag is embodied in a file named screenScrape.cfm and requires four parameters, named document , start , end , and matchCase , then on the calling page you will have something like this:

 <cf_screenScrape     document = "#myDoc#"     start = "#startSearch#"     end = "#endSearch#"     matchCase = "Yes" > 

In the preceding code, document = "#myDoc#" is the first name/value pair, start = "#startSearch#" is the second, and so on. The entire tag, including all name/value pairs, can be on a single line. Using multiple lines, as in the preceding example, may make the code easier to read.

On the custom tag page, screenScrape.cfm , you will have one cfparam statement for each name/value pair, like this:

 <cfparam name="attributes.document" default="#errordoc#" type="string"> <cfparam name="attributes.start" default="/////" type="string"> <cfparam name="attributes.end" default="////" type="string"> <cfparam name="attributes.matchCase" default="no" type="boolean"> 

Notice that each parameter created is assigned to the ATTRIBUTES scope: name="attributes.document" , name="attributes.start" , and so on. The calling page automatically puts the name/value pairs in the custom tag's ATTRIBUTES scope. Within the custom tag, you have to specify that scope explicitly when referencing the values.

Returning Data from a Custom Tag

Variables created within a custom tag disappear when the tag terminates. Therefore, before the tag terminates (usually just before), you must pass data back to the calling page. The key to accomplishing this is the CALLER scope. The CALLER scope in the custom tag and the VARIABLES scope in the calling page refer to the very same place.

For example, answerMaybe.cfm on the CD is a custom tag consisting of a single line:

 <cfset "caller.answer" = "maybe"> 

This line sets the answer variable in the calling file to the value "maybe" , creating the variable first if it doesn't already exist.

To use answerMaybe.cfm , all you need to do in the calling file ( answerMaybeTest.cfm on the CD) is this:

 <cf_answerMaybe> <cfoutput>#answer#</cfoutput> 

This will display the word "maybe."

The cf_scrape Custom Tag

Matthew Walker's scrape.cfm custom tag illustrates both the mechanics of custom tags and automated text retrieval.

CAUTION

As Matthew states on his site, the ethics and etiquette of screen-scraping require you to get permission, give credit, and make sure that you're not bogging someone's server down by retrieving too much information too often.


For a link to Matthews site, see scrapeLink1.htm on the CD accompanying this book.


There are basically three steps to using scrape.cfm :

  • Get some text.

  • Pass the text to scrape.cfm , along with instructions on what to search for within the text. If scrape.cfm were looking for people, the instructions would basically say, "Grab the guy between John and Bill"with the added proviso that there may be more than one John and more than one Bill, and therefore more than one guy to grab.

  • Use the result returned by scrape.cfm .

All three of these steps occur in the calling page, not in scrape.cfm .

In scrape.cfm , the action also unfolds in three phases:

  • Get the text and the instructions.

  • Loop through the text, finding all the desired items and putting them in an array.

    For more on arrays, see the "Arrays sidebar below.


  • Return the result.

Arrays

An array is an ordered, numbered list of data items. The data items are called elements . The number that identifies an element's place in the list is called the index of that element. If the array is named myArray , the second element in the array is referenced as myArray[2] . That is, you reference elements by using the name of the array, followed by the element's index in square brackets.

A difference between ColdFusion arrays and Flash arrays is that Flash arrays are zero-based . That is, the first element in a Flash array is myArray[0] . In ColdFusion, the first element is myArray[1] .

The elements of an array can be any data type, including other arrays. An array of arrays is a two-dimensional array, which you can visualize as a table or spreadsheet in which the rows can be of different lengths. In a two-dimensional array, myArray[1][2] is the second element in the first "row" (that is, in the first array).

ColdFusion can create arrays in one, two, or three dimensions. Here is an example of creating an array with the cfset tag: <cfset myArray=ArrayNew(1)> . This creates a one-dimensional array. Change the number 1 to a 2 or 3 for a two- or three-dimensional array.


In the array returned by scrape.cfm , the elements are structures .

Structures

A structure is a collection of key-value pairs, where the keys are text strings and the values can be any ColdFusion data type, including other structures. To create a structure, use the ColdFusion StructNew function. Structures are often named. For example, the following line creates a new, empty structure named myStruct :

 <cfset myStruct = StructNew()> 

Then you can add key-value pairs like this:

 <cfset myStruct.myVar1 = "true"> <cfset myStruct.myVar2 = "false"> 

The two preceding lines add two key-value pairs to the structure. The keys are myVar1 and myVar2 . The values are "true" and "false" .

You can create an array of structures as follows . The first line creates the array. The second line creates an empty structure as the first element of the array. The third line creates an empty structure as the second element of the array.

 <cfset myArray=ArrayNew(1)> <cfset myArray[1] = structNew()> <cfset myArray[2] = structNew()> 

Add key-value pairs to these structures like this:

 <cfset myArray[1].myVar1 = "true"> <cfset myArray[1].myVar2 = "false"> 

All these ways of using structures are employed in scrape.cfm .


In scrape.cfm , each structure in the array has three key-value pairs, in which the keys are start , middle , and end . The values of both start and end are arrays, and the value of middle is a text string. It's usually the middle values that you're interested in getting back from scrape.cfm , but scrape.cfm returns the whole structure. As you'll see in a minute, start and end could be of interest, as well. (I said earlier that the instructions amount to, "Grab the guy between John and Bill." Well, scrape.cfm brings John and Bill back, too, for good measure.)

Now that you know a little bit about what you're getting back from scrape.cfm , it's time to back up and look at the first step in using scrape.cfm : getting the text. Because we're interested in getting information from Web pages, we're going to use the cfhttp tag, which generates an HTTP request and stores the response from the Web server in a variable that can be referenced as #cfhttp.fileContent# . The tag looks like this:

 <cfhttp     url="http://www.someDomain.com/greendept/index.cfm"     method="get"     resolveurl="no"     timeout="3" > 

The url attribute specifies the Web page to which the request is directed. The method attribute indicates the action to be performed, in this case getting information from the Web server. (The other common method is post , which sends data to the server.) The resolveurl attribute determines whether links in the retrieved HTML text remain functional; in this case, they do not. Finally, timeout determines how long, in seconds, the ColdFusion server will wait for a response before deciding that the request has failed.

Now let's look at giving "instructions"how we specify the "John" and "Bill"to scrape.cfm . These are specified in two variables: startRegex and endRegex . Much of the power of scrape.cfm lies in the fact that the values of these variables are regular expressions rather than just text strings. A regular expression is essentially a formula for finding matching text strings. It's as if, instead of having to say "John," we could say "anyone whose name begins with J," or "anyone whose name has four letters," or " anyone whose name begins with J and has four letters ," or a thousand other descriptions. This allows for a much more flexible search.

Regular Expressions

Regular expressions combine literal text strings with special characters to create "formulas" that define a set of text strings with common characteristics. In ColdFusion, regular expressions are used to search for text that matches the formula. There are four built-in ColdFusion functions that use regular expressions: REFind , REFindNoCase , REReplace , and REReplaceNoCase . The "RE" in each of these function names stands for "Regular Expression." The first two functions find text. The second two find and replace.

The special characters used in regular expressions are

+ * ? . [ ^ $ ( ) { \

A set of characters enclosed in square brackets [] represents any one of those characters. For example,

  • "[blqr]" matches "b", "l", "q," or "r"

  • b[ia][lr]k matches "bilk," "balk," "birk," or "bark"

  • A dash indicates a range of characters. For example, "[A-Z]" matches any uppercase letter.

  • A period (.) matches any character.

An asterisk extends a single-character formula to any number of characters. For instance, "[A-Z]*" matches any number of uppercase letters (including the number zero).

A plus sign (+) extends a single-character formula to any number of characters greater than zero. For instance, "[A-Z]+" matches any non-zero number of uppercase letters.

A pair of parentheses groups a part of a regular expression into a subexpression that you can treat as a single unit. For example, the regular expression "yada" matches just one instance of the string. The regular expression "(yada)+" matches one or more instances.

A backslash " escapes " a special character so that it is interpreted as a literal character. For example, the formula for a literal asterisk is

"\*"

Use two backslashes together to indicate a literal backslash:

"\\"

There are many more rules for building regular expressions, which you can find in the ColdFusion documentation, Macromedia's livedocs, and many other sources. (However, the rules for regular expressions are not exactly the same in other environments, such as JavaScript and Perl. ColdFusion's rules are quite close to those of Perl, but there are a few exceptions, listed in the ColdFusion documentation.)

Regular expressions are powerful, but they also can be tricky to use. Use the ordinary Find , FindNoCase , Replace , and ReplaceNoCase functions when you just need to search for literal text strings. You'll avoid the complexities of having to escape special characters.


The usage of cf_scrape is illustrated in three ColdFusion files on the CD accompanying this book. You also need to install a small database file, gdQuotes.mdb , to make this example work. These are the three files:

  • scrape.cfm is the custom tag file ( cf_scrape )

  • quotePage.cfm is the page to be scraped. It displays a random quote from the three quotes in the gdQuotes.mdb database.

  • quotesScrape.cfm is the calling page. It uses scrape.cfm ( cf_scrape ) to screen scrape the quote.

Put all the cfm files in CFusionMX/ wwwroot /, copy gdQuotes.mdb to your hard disk, and create a system DSN for it named gdquotes . Then you can run quotePage.cfm or quotesScrape.cfm by typing http://localhost:8500/quotePage.cfm or http://localhost:8500/quotesScrape.cfm in your browser's address bar.

The quotesScrape.cfm file depends on the fact that quotePage.cfm uses CSS tags named quoteText and quoteAuthor to format the quote and the author's name, respectively. Here's how quotesScrape.cfm retrieves the quote text. No special characters are required; the regular expressions are just text strings.

 <cf_scrape     document = "#cfhttp.fileContent#"     startRegex = "span class = quoteText>"     endRegex = "<"     return = "quoteText"     matchCase = "Yes" > 

Here's how quotesScrape.cfm retrieves the author's name. No special characters are required in startRegex and endRegex , except the backslashes needed to escape the parentheses.

 <cf_scrape     document = "#cfhttp.fileContent#"     startRegex = "span class = quoteAuthor>\("     endRegex = "\)<"     return = "author"     matchCase = "Yes" > 



Using Macromedia Studio MX 2004
Special Edition Using Macromedia Studio MX 2004
ISBN: 0789730421
EAN: 2147483647
Year: N/A
Pages: 339

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