CFSCRIPT

1The CFSCRIPT tag
1.1 CFSCRIPT is a ColdFusion block tag that accepts no attributes. All operations take place between the beginning and end CFSCRIPT tag (i.e. in the tag body).
<CFSCRIPT>
     operations
</CFSCRIPT>
1.2A CFSCRIPT block can not be empty. It must contain at least one operation.
1.3A CFSCRIPT block can not use CF tags within its body.
1.4The body of a CFSCRIPT tag is an evaluation zone. This means that ALL 'words*' that are not reserve words, quoted strings or numbers will be treated as if they are variables and an attempt will be made to evaluate them. This also means that there is NO need for pound (#) signs within a CFSCRIPT block. See appendix B for a more in-depth coverage of Evaluation.
1.5Along with the standard list of ColdFusion reserve words, CFSCRIPT has a number of extra ones. These words should not be used as variable or function names. A list of these reserve words is in Appendix A.
1.6There are six types of operations used within a CFSCRIPT tag:
     Comments
     Variable Assignment
     Function Execution
     Decision Statements
     Loop Statements
     User Defined Function Definitions

2Comments
2.1There are two types of comments in CFSCRIPT:
     Single line
     Multi line
2.2 Single line comments allow you to set special characters and all text after the characters is considered a comment and will not be processed. These characters are a double forward slash (//). The comment is considered to end once the line is finished (a new line character).
<CFSCRIPT>
     // Comment here
</CFSCRIPT>
2.3 Multi-line comments allow special characters to be set before and after one or more lines of code to cause them to be considered comments. These special characters are the forward slash followed by a asterisk (/*) to start the comment and an asterisk followed by a forward slash (*/) to end it. If a multi-line comment is not closed an error will be thrown.
<CFSCRIPT>
     /*
          this is the first line of the comment
          this is another
     */
</CFSCRIPT>

3Variable Assignment
3.1 A variable assignment is any operation where a variable name is placed on the left hand side of an equal sign (=) and some value or operation is placed on the right hand side. This value or the result of the operation will be assigned to a variable with a reference name equal to the left hand side value.
3.2All variable assignments must end in a semicolon (;).
3.3 Possible values for a variable are:
     Numbers
     Quoted text strings
     Quoted text strings with delimited variables inside (using pound signs)
     Previously defined variables
     Results of a function
     Mathematical or string concatenation operations
<CFSCRIPT>
     variable=5;
     Variable="text value";
     variable="the date is #now()#";
     variable=now();
     variable=othervariable;
     variable=5+5;
     variable="The time is "&timeformat(now());
</CFSCRIPT>
3.4 Setting a dynamic variable name can be done using the standard method of placing the dynamic portion of the variable name within pound signs (#) and then placing it (and any text portion of the variable name) within quotes. It is preferred to use the SetVariable() function rather than this method of setting a dynamic variable name.
<CFSCRIPT>
     // Set a variable called dynamicvariable with a value of "variablename"
     dynamicvariable = "variablename";
     // Set a variable called variablename with a value of "text value".
     "#dynamicvariable#" = "text value";
     // Set a variable called Myvariablename with a value of 5
     "My#dynamicvariable#" = 5;
</CFSCRIPT>

4Function Execution
4.1 A function execution is any use of a function where the results are NOT being assigned to a variable name. A list of ColdFusion functions that can be run in this manner (Execution Functions) can be found in appendix C.
<CFSCRIPT>
     // Set a variable using an assignment statement
     datenow = now();
     // Set a variable with the SetVariable function
     SetVariable('datenow', now());
</CFSCRIPT>

5Code Statements: General
5.1CFSCRIPT uses a number of standard code statements that resemble those used in ECMAScript (JavaScript). They are used for Decisions (IF, Switch), loops (FOR, While, etc.) and function creation (UDF).
5.2A code statement do not take a semicolon (;) at the end (except in a single special case).
5.2Each code construct must have an operation after it.
5.3multiple operations can be grouped with a single code statement by placing them within curly brackets ({}).
<CFSCRIPT>
     // An IF statement with a block of code after it
     IF (statement)
     {
          operation1;
          operation2;
          operation3;
     }
</CFSCRIPT>
5.4 A code statement can have additional code statements after it, even if the additional code statements are within a block.
<CFSCRIPT>
     // An IF statement with a block of code after it
     IF (statement)
     {
          IF(statement);
               inner operation1;
          outer operation1;
          outer operation2;
     }
</CFSCRIPT>
5.5 The following code statements are currently available:
     IF/ELSE statements
     Switch/Case statements
     For loops
     While loops
     Do While loops
     For In loops
     User Defined Function definitions

6IF/ELSE Statement (Decision)
6.1 An IF statement in CFSCRIPT has the following format: An IF followed by an open and closed parenthesis. Between the open and closed parenthesis will go the entire comparison statement.
<CFSCRIPT>
     IF (Statement)
          operation;
</CFSCRIPT>
6.2As with other comparison locations (such as CFIF, While loops, etc.), a statement may be made up of many clauses.
<CFSCRIPT>
     IF (clause1 and clause2)
          operation;
     IF (clause1 or clause2)
          operation;
</CFSCRIPT>
6.3 IF code constructs follow the same rules as other comparison operations in ColdFusion. The use of short circuited boolean evaluation and functions in text comparisons should always be used.
6.3.1 Remember Short Circuited Boolean Evaluation - This feature was introduced in ColdFusion 4.01 and was a fantastic addition. It basically says that when a comparison statement (CFIF, CFELSEIF, IIF(), etc.) has more than one clause, the result of the first clause can effect if the second is run at all.
  • If the joiner is AND and the first clause is false, the entire statement is false and the second clause will never run.
  • If the joiner is OR and the first clause is true, then the entire statement is true and the second will never run.
  • If the joiner is IMP and the first clause is false, the entire statement is true and the second will never run.
In all cases, placing your clauses to take advantage of these rules can speed them up.
6.3.2 When doing comparisons between a text value and some other piece of data, use functions such as Len(), CompareNoCase(), and FindNoCase(). This is faster and more efficient.
6.4 The IF code construct has an ELSE construct that works with it. If the IF statement is false, the ELSE condition will occur.
<CFSCRIPT>
     IF (clause1)
          operation;
     ELSE
          operation2;
</CFSCRIPT>
6.5 There is currently no ELSEIF code construct in CFSCRIPT. This can be created by nesting IF and ELSE code constructs.
<CFSCRIPT>
     IF (clause1)
          operation;
     ELSE
          IF (clause1)
               operation2;
          ELSE
               operation3;
</CFSCRIPT>
6.6 Proper nesting is a must when dealing with multi-layered IF and ELSE code statements.
6.7 Multiple operations can be contained within an IF code statement by placing them within curly braces ({}).
<CFSCRIPT>
     IF (clause1)
    {
          operation1;
          operation2;
    }
</CFSCRIPT>
6.8 ALWAYS use IF code constructs over the IIF() function. The code statement (and tag for that matter) is more efficient.
6.9 When doing multiple comparisons against the same variable, the switch/case code statement may be more efficient and should be used.

7 Switch/Case Statement (Decision)
7.1 A switch statement takes a single variable or function and evaluates it. This value is then compared against the value contained in any number of case statements. If the value matches the case, that case is run.
<CFSCRIPT>
     switch(variable)
     {
          case statements
     }
</CFSCRIPT>
7.2 The case statements associated with a switch are always contained within curly braces ({}).
7.3 A switch statement must have at least one case or default statement within it.
<CFSCRIPT>
     switch(variable)
     {
          case "michael":
          {
               operation;
               break;
          }
     }
</CFSCRIPT>
7.4 Each case statement contains a single simple value (text or numeric) that will be compared against the switch value.
7.5 Each case must contain at least one operation that will occur if that case is 'run'.
7.6 Each case should also contain a break statement within the curly brackets of the case. If not, then the code will not stop and will run each additional case statement.
7.7 A default statement exists that will run if no case has a value equal to the switch expression value. This follows all the rules concerning a case statement. While the break is not needed in a default statement, it is used for proper coding practices.
<CFSCRIPT>
     switch(variable)
     {
          case "michael":
          {
               operation;
               break;
          }
          default:
          {
               operation;
               break;
          }
     }
</CFSCRIPT>

8 For Loop (Loop)
8.1 A For loop will loop over a single operation or a block of operations contained within a set of curly braces ({}). The loop takes three arguments with each one being optional.
     Initial Value
     Condition to continue the loop
     Operation to take at end of iteration.
8.2 The initial value is usually set as a normal variable set. This will create a variable and give it an initial value. This is a global variable and care must be taken so it does not affect other variables or pieces of code.
8.3 The condition to continue the loop takes a standard comparison statement and checks if it is true. If it is, then the loop will go again. This check is done at the beginning of each loop iteration.
8.4 The operation to take at the end of the loop iteration is a standard assignment that will occur when a loop iteration is done but before the check to continue is performed.
8.5 A standard For loop may look like this. The variable i is set to an initial value of 1. At the end of the loop, i is incremented and then it is checked to see if it is less then or equal to 10. If it is, then the loop will run another iteration.
<CFSCRIPT>
     For (i=1;i LTE 10; i=i+1)
          writeoutput(i&' ');
</CFSCRIPT>
8.5.1 The LTE syntax is used due to the order of operation. If the operation was LT 10, then there would only be 9 iterations of the loop. If the EQ syntax was used, it would fail to run in the first place.
8.5.2 The syntax i=i+1 is used because ColdFusion does not have an incrementation syntax of i++. The IncrementValue() function could be used, but is both slow and is wasted here.
8.6 The variable set and the end operation do not have to be numeric in nature. This example shows how to set the initial value to a character, increment the character and check it to see if the loop should end. It will output the letters M, N and O seperated by a space.
<CFSCRIPT>
     For (i="M";i NEQ "P"; i=Chr(Asc(i)+1))
          writeoutput(i&' ');
</CFSCRIPT>
8.7 A For loop can also be used to loop through a query object. This For loop will loop through a query and output each row of column record to the browser. (This example is provided to show that you can use CFSCRIPT to loop over a query. If this is the only operation you are doing, a CFLOOP or a CFOUTPUT would be perfered).
<CFSCRIPT>
     For (i=1;i LTE Queryname.Recordcount; i=i+1)
          writeoutput(Queryname.Record[i]&'<BR>');
</CFSCRIPT>
8.8 A For loop can also be used to loop through a list. This For loop will loop through a list and output each item.
<CFSCRIPT>
     For (i=1;i LTE ListLen(list); i=i+1)
          writeoutput(ListGetAt(list, i)&'<BR>');
</CFSCRIPT>

9 While Loop (Loop)
9.1 A While loop will take a comparison statement and as long as the statement returns true, the loop will run.
9.2 The comparison statement used in a While loop uses the same comparison logic and structure used in an IF statement.
9.3 This example will loop while i is less than 10. It has the same effect as the For loop example discussed earlier
<CFSCRIPT>
     i=1;
     while (i LTE 10)
     {
          WriteOutput(i&' ');
          i=i+1;
     }
</CFSCRIPT>
9.4 The examination of the condition takes place at the beginning of the loop. If the comparison statement fails, the loop will not operate.

10 Do While Loop (Loop)
10.1 A Do While loop will take a comparison statement and as long as the statement returns true, the loop will run.
10.2 The comparison statement used in a Do While loop uses the same comparison logic and structure used in an IF statement.
10.3 This example will loop while i is less than 10. It has the same effect as both the For loop and While loop discussed earlier
<CFSCRIPT>
     i=1;
     Do
     {
          WriteOutput(i&' ');
          i=i+1;
     }
     While (i LTE 10);
</CFSCRIPT>
10.4 The semicolon at the end of the While statement is the only time a semicolon is used for a code construct.
10.5 The examination of the condition takes place at the end of the loop. Even if the comparison statement fails, it will not fail until at least one iteration of the loop has performed.

11 For In Loop (Loop)
11.1 A For In loop will loop over a structure. It will NOT loop over the complex data set returned from a COM object.
11.2 The For In loop will set a variable with the 'key' used in each record in a structure. This key variable can then be used to access the value in the structure.
<CFSCRIPT>
     For (key in Session)
          WriteOutput(Session[key]&' ')
</CFSCRIPT>

AReserve Words
There are 3 basic groups of 'words'* that should be treated as reserved in ColdFusion and never used as the name of a variable. Inside an Evaluation Zone*, all words are evaluated. In the case of variables, they are turned into their values. In the case of reserve words, they are used in some operation depending on what they are. For example, the reserve word 'AND' is used inside a comparison statement (IF, While, Do While) to join two clauses 3 together. The reserve word Mod is used in an operation 4 to get the remainder of a division operation.
The first group of reserve words are used in comparison and mathematical operations.
AND CONTAINS EQ EQUAL
EQV GT GTE IMP
IS LT LTE MOD
NEQ NOT OR XOR

Using these reserve words as variable names will always cause a ColdFusion error. While the additional words DOES, CONTAIN, GREATER, LESS, THAN, and TO are not reserved by ColdFusion it is a good practice to not use them as variable names.
In addition to the comparison and mathematical reserve words, the following scopes should be considered reserved as well.
VARIABLES URL FORM CGI
CLIENT SERVER SESSION APPLICATION
ATTRIBUTES REQUEST THISTAG CALLER
COOKIE CFFTP (CFFTP) CFHTTP (CFHTTP) ERROR (CFERROR)
FILE (CFFILE) CFCATCH (CFCATCH)

The use of the scope reserve words as a variable will not throw an error but may overwrite data that is contained in the scope.
The final list of reserve words CAN be used as variable names in ColdFusion unless they will also be used inside a CFSCRIPT block. Within CFSCRIPT they are considered reserve. It is best to not use these words as variables even if you never plan to use CFSCRIPT.
FOR WHILE DO IF
ELSE SWITCH CASE BREAK
DEFAULT IN CONTINUE Function
Var Return Arguments

A forth group of reserve words does exist, but is limited to SQL statements and will be examined at another time. Proper use of variables will allow for programs that will work on all systems and will survive upgrades with minimal problems.


BEvaluation

Evaluation is the act of turning a variable, function or expression into its value. Conceptually this can be divided up into two zones. The first, called an evaluation zone, is a location where variables and functions can be evaluated1 without the need for pound signs (#)2. In addition, it is the only location where expressions3 will be evaluated. The other location will be termed an output zone. This is a place where a variable or function needs pound signs (#) to be evaluated. This difference is mostly a cosmetic one and has almost nothing to do with code tightness and speed. On the other hand, proper usage of pound signs (#) is a sign of a good ColdFusion programmer4.

Location Needs # Variables Functions Text needs quotes Processes Strings Expressions
Evaluation Zones
Right hand side of a CFSET statement No Yes Yes Yes Yes
Anywhere inside a CFIF statement No Yes Yes Yes Yes
Inside any Function No Yes Yes Yes Yes
Inside Array/Structure brackets ([]) No Yes Yes Yes Yes
Inside a CFSCRIPT tag block5 No Yes Yes No Yes
Output Zones
Inside the body6 of a ColdFusion tag (not CFSET/CFIF) Yes Yes Yes Yes No
Inside a CFOUTPUT tag block Yes Yes No No No
Inside a CFQUERY tag block Yes Yes No No No
Inside a CFMAIL tag block Yes Yes No No No
Dynamic (Left hand side) CFSET Yes Yes Yes Yes Yes

Evaluation in Strings

A string is simply text to be viewed or manipulated at will. Normally, a string does not have to have any special evaluation--unless there is a variable or function embedded within it.

The way to embed a function or variable within a string is rather easy. You simply wrap the variable or function inside pound signs (#) and it'll be seen by ColdFusion as something to be evaluated. Style wise, this is something that should never be done within an evaluation zone, only within output zones. In past versions of ColdFusion, there was a speed penalty for this but that penalty seems to be gone in the latest versions.

Inside evaluation zones, the proper way of using variables with strings is to treat them like expressions and concatenate them together. This will tell the ColdFusion engine to take the string and append the value of the variable or function to it. As above, this is seen as 'tight and proper' coding and makes people think you know what you're doing. :) On the other hand, there is a time and place where it is better to write your strings and variables/functions together. That time is when you are in a rush and have no time and that place is where you will have a LOT of text and variables mixed together.

CFSET

CFSET is a special case even among evaluation zones, as it has some added functions. The standard function of the tag is to take some value (assigned on the right hand side of an equal (=) sign) and assign it to a variable name that is on the left hand side of the equal sign (=). This is rather straightforward, until you want to dynamically create the name of a variable. This event breaks the rules of using variables. To create a dynamic variable, you place the text AND the variable inside of quotes. This is basically what we described above. It'll work and it is useful, but using the SetVariable() function is stylistically better. It should be noted that this behavior extends to creating variables in CFSCRIPT as well as in the CFSET tag.

<CFSET var1="name">
<CFSET "first#var1#"="Michael">

This results in a variable called firstname with a value of Michael.

Order of Operation

Functions have an order of operation when it comes to their evaluation. The reason for this is that you can nest functions and a function can have an expression as an attribute. Before a function can be evaluated, all of its attributes have to be evaluated. If one of those attributes is a function with attributes, then the nested function's attributes have to be evaluated. Let's look at an example:
<CFSET Form.list="1,2,3,4,5">
<CFSET list2="6,7,8,9,10">
<ListGetAt(form.list&list2,>
<randrange(listfirst(form.list),listlast(list2)))>

The order of operation here is:

  1. Evaluate the expression form.list&list2.
  2. Evaluate the variable form.list.
  3. Use the value of form.list as the attribute for listfirst().
  4. Evaluate the variable list2.
  5. Use the value of list2 as the attribute for listlast().
  6. Use the results of listfirst() and listlast() as the attributes for randrange().
  7. Use the value of form.list&list2 along with the final value of randrange as the attributes for listgetat().

Now you see why we don't want to think about this. It's tedious and obvious once you look at it. Evaluation moves from left to right and from inside out. As a side note, this is also the order of operation for any complex statement using functions and/or expressions such as the code inside the brackets([]) of an array or structure call.

Evaluation is one of the cores of ColdFusion and having a strong understanding of it is a must. With a deep understanding of it, you can create some really complex code.


CExecution Functions
Certain ColdFusion Functions may be run without setting the results to a variable. When these functions are run, it is more efficient and cleaner to use the following syntax for them.

<CFSCRIPT>
      Function();
</CFSCRIPT>

The following functions can be used in this way:

ArrayAppend ArrayClear ArrayDeleteAt
ArrayInsertAt ArrayPrepend ArrayResize
ArraySet ArraySwap CF_SetDataSourceUsername
CF_SetDataSourcePassword CFUSION_SETODBCINI CFUSION_SETTINGS_REFRESH
CFusion_DBConnections_Flush QueryAddRow QuerySetCell
SetLocale SetProfileString SetVariable
StructClear StructDelete StructInsert
StructUpdate WriteOutput

This is usually used in such statements as the following one, which will delete a user session:

<CFSCRIPT>
     StructClear(Session);
</CFSCRIPT>
This example will disconnect all data sources.

<CFSCRIPT>
     // This will disconnect the data sources
     cfusion_dbconnections_flush();
</CFSCRIPT>
This final example will write a variable to the output of the page.
<CFSCRIPT>
     WriteOutput(Url.FirstName);
</CFSCRIPT>