Using List Variables

 < Day Day Up > 



Until now, all the variables you've used in your ColdFusion templates have held simple values — either a string or a number, such as id=25 or fullname="Don Van Vliet" or, in the case of query variables, they've held the results of SQL queries. But like most programming languages, ColdFusion supports variables capable of holding complex data. One of these is the list variable type, which can hold a list of values — either strings or numbers. To understand how a list variable might be used, consider a Web form that contains several check boxes. The check box section of the form might look like this:

<h3>Select Your Hobbies</h3> <input type="checkbox" name="hobbies" value="sports"> Sports<br> <input type="checkbox" name="hobbies" value="loafing"> Loafing<br> <input type="checkbox" name="hobbies" value="reading"> Reading<br> <input type="checkbox" name="hobbies" value="eating"> Eating<br>

All the check boxes use the same variable name, but each has a different value associated with it. This is a common technique in Web forms designed to record user preferences. If a user checked the first three boxes and then submitted the form, hobbies would be sent to the form's action page containing the following:

sports,loafing,reading 

So rather than containing a simple value, hobbies actually contains three values, separated by commas. This type of variable is called a list variable.

Note 

List variables are one of several types of complex variables supported by ColdFusion. The others include structure variables, which store data indexed by key names, such as firstname="Charles" lastname="Mohnike" and array variables, which store data in multiple dimension, indexed by position. ColdFusion MX also supports components, objects, and XML documents as complex variables. While these variable types are beyond the scope of this chapter, you touch on some of them in future chapters. You'll also find a more complete reference to both variable types in your ColdFusion documentation.

ColdFusion includes several tools for working with list variables, notably a set of functions that enable you to find and retrieve individual items in a list, as well as a tag called <cfloop> that enables you to perform an action for each item in a list.

Note 

Commas are the default delimiters for list variables, but they're by no means the only ones. In fact, ColdFusion enables you to use just about any character as a delimiter in a list as long as you specify that character when you use list functions or <cfloop>. You learn how to do so in the following sections.

start sidebar
Using <cfset> to Define a Variable Manually

You've already learned how variables can be defined by the output of a SQL query, from form input, or from a URL. ColdFusion also provides a tag enabling you to manually create and define variables within your templates manually: <cfset>.

Using <cfset> is straightforward:

<cfset firstname = "Charles"> <cfset visit = 0>

String values are enclosed in quotes, as in the first example; numeric variables don't require the quotes, as in the second.

You can also use numeric operators, ColdFusion functions, and existing variables in the process of defining a new variable with <cfset>:

<cfset visit = visit + 1> <cfset initial = Left(last_name, 1)>

You may also manually define list variables with <cfset>:

<cfset interests = "skating,eating,loafing">

After you define a variable with <cfset>, you can call it anywhere in that template using the same hash-mark method as other ColdFusion variables:

<cfoutput>#firstname#</cfoutput> <cfoutput>#visit#</cfoutput> 
end sidebar

Using ColdFusions list functions

To explore the use of ColdFusion's list functions and understand how to use them in common tasks, start by copying the form  personal_data_form.htm on the accompanying CD-ROM to a folder in your Web root. If you still have it, the polls folder from the examples in Chapter 49, that makes a great place to store the form.

Note 

You can design your own form and use it with the following examples as long as it uses multiple check boxes with the same name attribute.

For reference, the form's source is shown in Listing 51-3.

Listing 51-3: personal_data_form.htm

start example
<html> <head> <title>Personal Data Form</title> <meta http-equiv="Content-Type" content="text/html; charset=iso- 8859-1"> </head>     <body> <h2>Personal Data</h2> <form action="personal_data_action.cfm" method="post">      <h3>Select Your Hobbies</h3>      <p>      <input type="checkbox" name="hobbies" value="sports"> Sports<br>      <input type="checkbox" name="hobbies" value="loafing"> Loafing<br>      <input type="checkbox" name="hobbies" value="reading"> Reading<br>      <input type="checkbox" name="hobbies" value="eating"> Eating<br>      </p>            <h3>Select Your Interests</h3>      <p>      <input type="checkbox" name="interests" value="current events">  Current Events<br>      <input type="checkbox" name="interests" value="religion">  Religion<br>      <input type="checkbox" name="interests" value="politics">  Politics<br>      <input type="checkbox" name="interests" value="travel"> Travel<br>      </p>      <input type="submit"> </form> </body> </html> 
end example

To test the functions in the following sections, you also need to create an action page for the form. Create a new ColdFusion template called personal_data_action.cfm and save it in the same folder as your form.

Finding a list item with ListFind()

You might want your action page to display a custom message to users who express an interest in politics. One way to achieve this is with the function ListFind(), which accepts two items as input: the name of a list variable in which to search, and string to search for. It returns the index number of the list where the string was found, or "0" if the item isn't found.

Insert the following snippet of code into your action page:

<cfif ListFind(form.interests, "sports")>      <p>You specified an interest in sports. May we suggest you visit  Wild Wally's Sports Haven for a variety of sports memorabilia and  sporting goods?</p> <cfelse>      <p>You aren't interested in sports? That's too bad.</p> </cfif>

Take a closer look at the first line of code. The ListFind() function includes the form scope with the interests variable — not absolutely necessary in a page this basic, but good practice. The string you want to search for is enclosed in quotes.

The code also uses <cfif> with its "not equal" operator to determine whether ListFind() finds the word "sports" in the list variable interests. For example, if "sports" is the first (or only) item in the interests list, the function returns a value of "1"; if it were the second item in the list, the function would return, and so on. In this case you don't need to be concerned about where sports occurs in the list, only that it does occur, hence the neq 0.

Note 

You may be wondering why to use ListFind() to check for the occurrence of a string in a list variable. Why not just use the <cfif> operator contains as detailed in Chapter 49.

<cfif form.interests contains 'politics'>

You'd be correct that contains would also work in the current example. However, consider a situation in which there were two check boxes, "politics" and "politics: international". Using contains to search for "politics" would return a match even if the only item in the list was "politics: international". ListFind() provides a more exact match because it returns a positive result only if the specified string is exactly equal to an entire list element.

Note 

The ListFind() function is case-sensitive. When you want to match a string without case sensitivity, use ListFindNoCase().

Adding a list item with ListAppend()

As users submit the form, you might want to add a default interest to the list variable automatically. You can do so with the function ListAppend(), which takes as input the name of a list and the string you want to append. Try adding the following snippet to your action page:

<cfset form.interests = ListAppend(form.interests, "filling out Web  forms")>     <p>Thanks for completing our survey. You've shown an interest in the  following areas:</p> <p><cfoutput>#form.interests#</cfoutput></p>

This example uses <cfset> (see the sidebar in this chapter) to change the value of form.interests, the list variable sent by the user's form submission. The phrase "filling out Web forms" is added to the variable as a new list element, so if the user checked only the first Interests box on the form, the value of interests after the ListAppend() action would be as follows:

current events, filling out Web forms

You can also use ListAppend()to append the contents of a variable to an existing list. For example, if you want to combine the contents of the hobbies and interests variables into one, you could use code like this:

<cfset interests_and_hobbies = ListAppend(form.interests,  form.hobbies)>

This would create a new list variable, interests_and_hobbies, containing the contents of both hobbies and interests.

Tip 

Another ColdFusion function, ListPrepend(), enables you to add a value to the beginning of the list rather than the end.

Counting list elements with ListLen()

If you want to show your users a count of the items they checked, you can use ListLen(). This function accepts only one parameter — the name of a list variable — and returns the number of elements in the list:

<cfoutput>Thanks for completing our form. You selected  #ListLen(form.hobbies)# hobbies and #ListLen(form.interests)#  interests.</cfoutput>

Tip 

All of ColdFusion's list functions support an optional extra parameter specifying the delimiter to use when evaluating a given list variable. For example, consider a list like this one:

<cfset pasttimes = "Travel, Eating Exotic Food, Reading">

If you use a function such as ListLen() to evaluate the length of pasttimes but don't use the optional delimiter parameter, ListLen() assumes you want to use the default list delimiter, the comma. In this case, the length of pasttimes would be 3. However, if you used ListLen() with a different delimiter, such as a space as follows:

<cfoutput>#ListLen(pasttimes, " ")#</cfoutput>

ListLen() would return a value of 5, because there are five elements in pasttimes when you use a space, rather than a comma, as a delimiter. The elements are

Travel, Eating Exotic Food, Reading

By using different delimiters you can nest one list inside another. For example, the following:

<cfset nestedList = "Sam,Neff,Contributor|Joyce,Evans,Author">

Is a pike (|) delimited list of comma (,) delimited lists.

Creating a keyword search with <cfloop>

List variables enable you to perform an action for each element in a list. For example, you could build a form allowing users to enter one or more keywords, and then query a database for each of those keywords, one by one. This section starts with a sample form and action page, after which you can customize the code to work with one of your own databases.

Use the ed_wood datasource you set up earlier in this chapter. You start with a form to collect users' keywords. You can build your own using the code in Listing 51-4, or find a file titled  film_search_form.htm on the CD-ROM accompanying this book.

Listing 51-4: film_search_form.htm

start example
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>Search the Ed Wood film database</title> <meta http-equiv="Content-Type" content="text/html; charset=iso- 8859-1"> </head>     <body> <h3>Search the database of Ed Wood films</h3>     <form action="film_search_action.cfm" method="post">      <p>Enter some keywords for which to search:</p>      <p><input type="text" name="keywords"></p>      <input type="submit"> </form>     </body> </html> 
end example

A user who completes this form may supply just a word, such as "monster," or a list of words, such as "monster ghoul ghost." It doesn't matter how many items the user chooses because your action page treats the passed keywords variable as a list. This list may have only one element, or it may have 10; the code won't care either way.

The action page for this form uses a powerful ColdFusion tag, called <cfloop>, to process the list and perform a search for each element found within. Because <cfloop> is a new tag in your arsenal, take a closer look at it before you move on. Here's a stripped-down example of <cfloop> in action:

<cfloop list="#form.interests#" index="interest">      Thanks for selecting <cfoutput>#interest#</cfoutput><br> </cfloop>

<cfloop> processes lists in much the same way <cfoutput> processes the results of a query. When used in "list" mode, all the code or text contained within the <cfloop> tag set repeats for each element in a list. For example, if a user checked three interests on a form, the preceding snippet would display the following output to the user:

Thanks for selecting current events Thanks for selecting religion Thanks for selecting politics

Take a look at the opening <cfloop> tag. It specifies a list variable, including the hash marks, and creates a name for the list's index. The index is an arbitrary variable name you use within the <cfloop> to denote the list item currently being processed. The preceding snippet could have used index="blahblah" as long as it also used "Thanks for selecting #blahblah#" within the loop tags.

Note 

Processing the contents of a list is only one of <cfloop>'s capabilities. See the sidebar in this chapter for some other uses.

Now move on to the keyword search function. Listing 51-5 shows one way to use <cfloop> in your search form's action page.

Listing 51-5: film_search_action.cfm

start example
 <html> <head> <title>Search Results</title> <meta http-equiv="Content-Type" content="text/html; charset=iso- 8859-1"> </head>     <body> <h2>Search Results</h2>     <cfloop list="#keywords#" index="keyword" delimiters=" ">        <cfquery name="search" datasource="ed_wood">             select id, title              from films              where title like '%#keyword#%' or description like  '%#keyword#%'    </cfquery>      <h3>Results for Keyword <i><cfoutput>#keyword#</cfoutput></i></h3>   <ul>    <cfif search.recordcount eq 0>     <li>No items were found for this keyword</li>    <cfelse>       <cfoutput query="search">          <li><a href="film_detail.cfm?id=#id#">#title#</a></li>       </cfoutput>    </cfif>   </ul> </cfloop>     </body> </html>
end example

Like ColdFusion's list functions, <cfloop> enables you to specify a list delimiter other than the default comma. The <cfloop> tag on the form's action page specifies a space as the delimiter, so if the user enters "monster bride plan," each word is treated as a unique list element.

For each element, it finds in the keywords list, <cfloop> performs a query looking for either a film title or description containing that word. If the user entered only one word, this process completes only once, and so on. Figure 51-6 shows sample output when the user inputs "monster bride plan."

click to expand
Figure 51-6: Displaying search results using <cfloop>

Tip 

The sample action page in this section omits form validation for the sake of clarity. For example, a user who clicks Submit without entering any keywords won't see a message prompt requesting at least one keyword. In a real-world environment, you could improve on this basic action page by adding form validation, as described in the previous chapter.

Listing 51-4 also contains another new tool, the recordcount variable. After a <cfquery> completes, you can get a count of the records it selected by referencing a special variable:

#[query name].recordcount#

In the context of a search, recordcount is particularly valuable because you can use it conjunction with <cfif> to display a "no records found" if the query doesn't return any results.

The text appearing within a <cfloop> tag set behaves much the same way as text within <cfoutput> tags. In Listing 51-5, the action page takes advantage of this by displaying the current keyword to the user, then lists the films in which that keyword was matched in the film title or description (if any).

Tip 

For best performance, it's a good idea to only use lists with small groups of data, say up to a dozen elements. Larger groups should use other methods such as an array.

start sidebar
More about <cfloop>

When you use the <cfloop> tag with the "list" attribute, the tag automatically goes into list mode, in which it loops through each element in a specified list. But that's just one use of <cfloop>. It can also be used as a powerful flow-control tag to give you more control over the processes in your templates. Following are two other types of loops used with <cfloop>. For details on either, check your ColdFusion documentation.

The For loop

This type of loop is used when you need an action to occur for a specified number of times. For example, to populate a form select box with the months 1 through 12, you would write the following code:

<select name="month"> <cfloop from="1" to="12" index="month">      <option value="#month#"> </cfloop> </select> 

For loops include "from" and "to" attributes, which specify how many times the loop should run. They also accept an optional "step" attribute, which causes the "from" value to increment by a number other than the default of 1. For example, to populate a select box with multiples of 5, you would write the following code:

<select name="players"> <cfloop from="1" to="100" index="players" step="5">      <option value="#players#"> </cfloop> </select>

This code produces a select box populated with the numbers 1, 5, 10, and so on up to 100.

The While loop

While or conditional loops run continually as long as a specified expression remains true. For example, to display a count from 1 to 10, you could use a loop like the following. (lte means "less than or equal to.")

<cfset count = 0> <cfloop condition = "count lte 10">      <cfset count = count + 1>      The current count is <cfoutput>#count#</cfoutput><br> </cfloop>
end sidebar



 < Day Day Up > 



Macromedia Studio MX Bible
Macromedia Studio MX Bible
ISBN: 0764525239
EAN: 2147483647
Year: 2003
Pages: 491

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