Acrobat User Community

Conditional execution and Acrobat JavaScript

By Thom ParkerJanuary 12, 2010

One of the most important features of any programming language is the ability to make decisions, called Conditional Execution. It is the ability to execute a piece of code depending on some condition. In Acrobat JavaScript, the primary element of conditional execution is the "if" statement. While there are others, none is as generic and widely used as the "if" statement.

Writing an "if" statement

In computer programming, all decisions are made by comparing values. For example, on an order form we might want to give the customer a discount if they spend more than $100. To express this idea in English, in the context of our form we might say "If the Subtotal is greater than 100, then set a 10% discount." In this case, we are comparing the value of the order’s subtotal to the constant value 100, then placing a percentage of the subtotal into the discount field if the result of the comparison is true. The Acrobat JavaScript code for performing this conditional calculation is exactly the same as our English statement, only it is expressed in JavaScript syntax. The following code is placed in the calculation event for the discount field:

var nSubTotal = this.getField("subtotal").value;
if( nSubTotal > 100) event.value = nSubTotal * 0.10;

The first rule of writing conditional statements is to clearly and simply express the complete set of conditions in English. The conditions must make sense, not conflict with one another, and be testable from concrete values available to the code.

Problems with conditional execution are a very common issue posted to the forums. All too often, the root problem is revealed as an unclear and/or conflicting statement of the necessary conditions. It can’t be stated too often or too strongly that the first step of writing conditional code is to state the conditions clearly and make sure they do not conflict. As we’ll see, this is especially important for complex conditions.

Now let’s rewrite the "if" block code (shown above) in pseudo code so we can better understand how it’s constructed.

if(  ) 

This pseudo code shows the simplest way to write a decision block. This particular "if" block can be divided into two parts-- the condition, and the code that is run when the condition is met. The condition is a short piece of code that results in a true or false value, and it is called a Boolean Expression.

Value comparisons and the Boolean expression

Boolean Logic is a system of mathematics that deals with true and false values, called Boolean values. As we will see, Boolean Logic is actually very simple and it is a key element of computer programming. A Boolean expression is a piece of code that operates on, and/or results in, a Boolean value. Boolean expressions are created using the comparison and Boolean operators. In our previous example, the condition is the expression:

nSubTotal > 100

where the operator is the Greater Than, ">", comparison operator. If nSubTotal is greater than 100, the expression returns a value of True; otherwise it returns a value of False. The other comparison operators are: Less Than; "<", Equals to; "==" and Not Equals; "!=". There are also compound-comparison operators that combine Greater Than and Less Than with Equals to; "<=" and ">=". All these comparison operators return Boolean values. Most of the time, they will be the starting point for a Boolean expression, converting values from the form into true or false values that will be used to make decisions with an "if" statement.

It’s important to note that these comparison operators work for both number and text values. This is important because many of PDF form fields return text values. For example, both radio buttons and checkboxes export a text value. The checked or selected value is set by the form designer, but the unchecked/unselected value is always "Off." We can use this value in a Boolean expression to detect and make decisions based on the unchecked checkbox, or the unselected Radio button group.

The code below is used in a form-level validation script to let users know they have to check "I Agree" before submitting a form:

var cAgree = this.getField("AgreeCheck").value;
if( cAgree == "Off" ) app.alert("You must select ‘I Agree’ before continuing");

So now we’ve seen how to create a simple Boolean expression by using a comparison operator to compare two values to one another. But what do we do if our condition is more complex? For example, what if we need to test that a field value is within a range between two values, or something even more complex? To handle these situations, we need to write a Compound Boolean expression.

Compound Boolean expressions

Complex Boolean expressions are created by combining simple expressions with the Boolean operators. The basic Boolean operators are: And; "&&", Or; "||", and Not; "!". Along with grouping sub-expressions in parentheses, these operators can be used to create conditional expressions for almost any situation you will ever need. In fact, as previously stated, there is a whole branch of mathematics devoted to studying Boolean expressions. But for our purposes here, and for the majority of situations you’ll be dealing with, we can stick to the basics.

To write a complex expression, it first has to be expressed in English. In our first example, a discount was created based on the subtotal being greater than 100. Let’s modify that condition to this: "If the subtotal is greater than 100 and the subtotal is less than or equal to 200, then apply a 10% discount." This conditional contains a second condition tied to the first part with "AND." The "AND" means both parts have to be true in order for the total expression to be true. The implementation is exactly as stated.

event.value = 0;
// Initial discount value var nSubTotal = this.getField("subtotal").value;
if ( (nSubTotal > 100) && (nSubTotal <= 200) ) event.value = nSubTotal * 0.10;

This code is nearly the same as the first example. The only difference is the addition of the second condition. But there are a few very important details here worth noting. The first is the use of the compound comparison operator "<=". Using this operator has made our job much easier because it’s packing two comparisons into one. The sub-expression returns true for two conditions, subtotal is less than 200 and subtotal is equal to 200. Without the compound comparison operator, we’d have to write the expression with three conditions.

The second detail of note is that the two comparisons are grouped using parentheses. This is important for two reasons. First, it makes reading the code easier, and second, it ensures proper execution of the expression. Strictly speaking, the parentheses are not always necessary, but unless you are an expert at precedence of operator execution, you should always group the sub-expressions you want to execute as a single entity. Otherwise, the JavaScript engine may just decide to do the execution differently.

And finally, we get down to the "&&". This operator only returns true if both conditions are true, so this is where we need to make sure our conditions make sense. You can very easily write nonsensical expressions. For example, here’s a small change to our Boolean expression.

(nSubTotal < 100) && (nSubTotal > 200)

There is nothing wrong with this code as far as the Acrobat JavaScript engine is concerned. It will not complain, but obviously this expression will never be true. A number cannot be both less than 100 and greater than 200. This may seem silly, but it is surprisingly easy to set up unrealistic and conflicting conditions.

To stretch this concept a bit further, let’s add an additional layer of complexity by also applying the discount when the customer is a member of our company website, as indicated by a checkbox on the form. So, our statement of conditions is now: "If the subtotal is greater than 100 and the subtotal is less than or equal to 200, or if the members checkbox is checked, then apply a 10% discount." The "if" statement is shown below, but for brevity, the supporting code is not included; and to make the groupings more obvious, the parentheses are color-coded:

var bMember == this.getField("MemberCheck").isBoxChecked(0);
if ( ( (nSubTotal > 100) && (nSubTotal <= 200) ) || bMember) <. . .>

Notice that our original two conditions are grouped, making them a single entity in the expression and allowing us to use the original expression unchanged. Expressions and sub-expressions can be nested within parentheses as deep as necessary to create the condition. The total condition here is true if either the checkbox is checked or our original set of conditions is true.

The final logical operator "!" is used to invert the return value of a sub-expression. Let’s change the expression to only apply the discount when the customer is not a member. So here’s our new statement of conditions: "If members checkbox is not checked and the subtotal is greater than 100 and the subtotal is less than or equal to 200, then apply a 10% discount." In this case, we are not using an OR operation. Instead, we are adding to the AND of the original conditions. Here’s the if code:

if ( !bMember && (nSubTotal > 100) && (nSubTotal <= 200) )
<. . .>

Now we’re ready to move on to the next level of complexity, setting up multiple conditions.

Multiple conditions

All conditional expressions have two results. The condition is met, or it’s not met. So far, we’ve only looked at running code for the situation where the condition is met. But we can also run code for the negative result by constructing the "if" statement with an "else" section, like this:

if(  )  else 

Using this structure, we can rewrite the first example to apply a zero discount if the condition is not met:

var nSubTotal = this.getField("subtotal").value;
if( nSubTotal > 100) event.value = nSubTotal * 0.10;
else event.value = 0;

But, the "else" is for more than running the negative result code. It provides for default execution. The "if" block can contain multiple conditions, each with its own section of conditional code. If none of these conditions is met, then the "else" code is run, making sure we have a way to cleanly finish things off, i.e., perform a default action.

For example, say we need to apply different discounts for different purchase amounts. Our new condition statement is then: "If the subtotal is greater than $200, then apply a 20% discount, else if the subtotal is greater than $100 apply a 10% discount, else if the subtotal is greater than $50 then apply a 5% discount, otherwise no discount is applied." The multiple condition "if" is structured with "else if" sections like this:

var nSubTotal = this.getField("subtotal").value;
if( nSubTotal > 200 ) event.value = nSubTotal * 0.20;
else if( nSubTotal > 100 ) event.value = nSubTotal * 0.10;
else if( nSubTotal > 50 ) event.value = nSubTotal * 0.05;
else event.value = 0;

We can build "if" blocks with as many "else if" sections as necessary, or none at all. The "else" section is optional as well, but if there is one there can only be one, and it must be last. The "if" section is of course mandatory and it must come first.

For each condition in the code above, the discount is actually applied to a range of values. For example, the 10% discount is applied for purchase amounts between $100 and $200. But because these amounts are a progression, we can make the code more efficient and easier to write by starting with the largest amount first and working down. It’s always a good idea to try to arrange the conditions so they create the most efficient and sensible flow through the logic. If none of the conditions is met, then default code in the "else" section sets the discount to zero.

Running multiple lines of code

All the examples shown so far run a single line of code for the conditional execution. I’ve done this for simplicity, but of course we can run any amount of code in a condition. To do this, the code needs to be surrounded by curly braces "{}", called block delimiters. Any code inside the curly braces is grouped into a single entity by the JavaScript engine. This same grouping structure is used with several different types of code flow operators in the JavaScript language, such as functions and loops. Here’s a modification of the first example that not only sets the discount, but also displays a popup message to the user.

var nSubTotal = this.getField("subtotal").value;
if( nSubTotal > 100) {
	event.value = nSubTotal * 0.10;
	app.alert("Congratulations, you get a discount",2);
} else {
	event.value = 0; app.alert("Sorry, no discount for you",2);
}

More "if"

It’s important to understand that the "if" statement is purely Core JavaScript. I’ve presented it here in the context of Acrobat JavaScript and specifically for creating conditional calculations. However, the concepts presented (the "if" structure and Boolean expressions) are very general-purpose and widely used throughout all implementations of JavaScript, as well as many other languages including C, Java, and ActionScript. You can find out more from a Core JavaScript Reference.

My favorite Core JavaScript reference is "The Definitive JavaScript Guide" from O’Reilly.

The official Core JavaScript web reference is here:
http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference

You can find an example PDF that uses the "if" statement in conditional calculations here:
http://www.pdfscripting.com/public/47.cfm#CondCalcs
And if you look around at just about any sample code, you’ll find examples of "if" statements.