Flow Cotrol
Flow-control diagrams
graph TD
subgraph SEQ["Sequential Process"]
S1["Start"]
S2["Step 1"]
S3["Step 2"]
S4["End"]
S1 --> S2 --> S3 --> S4
end
subgraph IFTHEN["If-Then"]
IF1{If}
THEN1["Then"]
ENDIF1["EndIf"]
IF1 -->|Y| THEN1
THEN1 --> ENDIF1
IF1 -->|N| ENDIF1
end
subgraph IFELSE["If-Else"]
IF2{If}
THEN2["Then Do X"]
ELSE2["Else"]
THEN21["Then Do Y"]
ENDIF2["EndIf"]
IF2 -->|Y| THEN2
IF2 -->|N| ELSE2
ELSE2 --> THEN21
THEN2 --> ENDIF2
THEN21 --> ENDIF2
end
subgraph IFELIF["If-ElIf-Else"]
IF3{If}
ELIF1{ElIf}
ELIF2{ElIf...}
ELSE3["Else"]
THENA["Then Do A"]
THENB["Then Do B"]
THENC["Then Do..."]
THEND["Then Do Z"]
ENDIF3["EndIf"]
IF3 -->|Y| THENA
IF3 -->|N| ELIF1
ELIF1 -->|Y| THENB
ELIF1 -->|N| ELIF2
ELIF2 -->|Y| THENC
ELIF2 -->|N| ELSE3
ELSE3 --> THEND
THENA --> ENDIF3
THENB --> ENDIF3
THENC --> ENDIF3
THEND --> ENDIF3
end
subgraph WHILE["While Loop"]
W1{While}
D1["Do"]
EW["EndWhile"]
W1 -->|Y| D1
D1 --> EW
D1 -->|Loop Back| W1
W1 -->|N| EW
end
JAWS does not always perform scripts in a sequential or top to bottom manner, with each line being performed in order and only once. You may find it necessary to perform a series of statements several times within a script. You may also find it necessary to skip statements in a script based on the outcome of a condition being evaluated. These types of statements control the flow, or sequence of events, in a script or function. A script or function can contain any or all of these techniques.
Sequential
Sequential flow is the most basic type of flow control. In a sequential statement structure, JAWS performs each statement sequentially beginning with the first statement in the script and continuing to the EndScript statement.
The following script is an example of sequential flow. You can find this script in the Default.jss script file. The script selects text from the beginning of the line to the cursor. The code of the script follows:
Script SelectFromStartOfLine()
Let nSaySelectAfter = False
SelectingText(True)
SelectFromStartOfLine ()
SelectingText(False)
EndScript
JAWS performs the script above each time you press SHIFT + HOME to select the text from the cursor to the beginning of the line. JAWS performs each statement in the script only once.
Selection, Conditional, or Decision Making
In this type of statement structure, JAWS evaluates one or more conditions before processing continues. The flow of the script is then based on the outcome of the condition being evaluated. This process is often referred to as branching. Think of walking down a path and coming to a fork in that path. Before you continue, you must decide which path is the best way to continue. Your script can do the same thing. As JAWS processes your script sequentially, there may be a poInt in the script where a decision must be made. The statements JAWS processes next are based on the outcome of that decision.
::: {#the-if-then-statement}
The If Then Statement
:::
You can use the If Then statement structure to select which path in your script is taken if the preceding statement is true. You must include the If, Then, and EndIf key words in all If statement structures. You place the condition to be evaluated between the If and Then key words. When JAWS evaluates the condition and finds it to be true, JAWS performs any statements following the If statement.
An example of a basic If statement follows:
If DialogActive () == True Then
SayFormattedMessage (OT_MESSAGE, "A dialog box is active") ; The condition evaluates To True
EndIf
In the above example, JAWS can only take one path based on the outcome of the condition being evaluated in the If statement. When a dialog box is active, then JAWS performs the SayFormattedMessage () function and speaks "A dialog box is active." When the condition being evaluated is false, then JAWS does not perform the SayFormattedMessage () function and processing continues with any statements that follow the EndIf key word.
::: {#the-else-and-elif-statements}
The Else and ElIf Statements
:::
You can use two optional statements in an If Then structure. You can use the Else key word to provide an alternate path. When the condition specified in the preceding If statement is found to be false, then JAWS performs the statements following the Else key word. Thus, you can account for both true and false conditions in your If statement. An example of an If Then-Else statement follows:
If DialogActive () == True Then
SayFormattedMessage (OT_MESSAGE, "A dialog box is active") ; the condition evaluates To True
Else
SayFormattedMessage (OT_MESSAGE, "No dialog box is active") ; the condition evaluates To False
EndIf
In the above example, the If statement determines if a dialog box is active. When the If statement is true, JAWS performs the SayFormattedMessage () function following the If statement and speaks "A dialog box is active." If a dialog box is not active, then JAWS performs the SayFormattedMessage () function following the Else key word and speaks "No dialog box is active."
You can use the ElIf statement as a secondary way of formulating a branch. The ElIf statement can take the place of an Else statement. You can also use the ElIf statement in addition to the Else key word. You can use as many ElIf statements as needed in your scripts. However, when you use the ElIf statement in addition to the Else key word, those ElIf statements must precede the Else statement.
Two examples of the uses of the ElIf statement within an
If Then-Else-EndIf statement follow:
If DialogActive () == True Then
SayFormattedMessage (OT_MESSAGE, "A dialog box is active")
ElIf DialogActive () == False Then
SayFormattedMessage (OT_MESSAGE, "No dialog box is active")
EndIf
The above example uses an ElIf statement in the place of the Else key word. The If statement determines if a dialog box is active. When the If statement is true, JAWS performs the SayFormattedMessage ()function following the If statement and speaks "A dialog box is active." When the If statement is false, JAWS performs the ElIf statement that determines if there is no active dialog box. If the ElIf statement is true, then JAWS performs the SayFormattedMessage ()function following the ElIf statement and speaks "No dialog box is active." Since there are only two possibilities, JAWS must perform either the SayFormattedMessage () statement that follows the If statement or the SayFormattedMessage () statement that follows the ElIf statement.
The following example illustrates the use of an ElIf statement in conjunction with an Else statement:
If DialogActive () == True Then
SayFormattedMessage (OT_MESSAGE, "A dialog box is active")
ElIf MenusActive () == ACTIVE Then
SayFormattedMessage (OT_MESSAGE, "A menu is active")
Else
SayFormattedMessage (OT_MESSAGE, "No dialog box or menu is active")
EndIf
The above example uses an ELIF statement in addition to the Else key word in the If Then statement structure. The initial If statement determines if a dialog box is active. If a dialog box is active, then JAWS performs the SayFormattedMessage () function following the If statement and speaks "A dialog box is active." If a dialog box is not active, then JAWS performs the ELIF statement that determines if a menu is active. If the ELIF statement is true, JAWS performs the SayFormattedMessage () function following the ELIF statement and speaks "A menu is active." However, if no menu is found to be active, then JAWS performs the SayFormattedMessage () function following the Else key word and speaks "No dialog or menu is active."
::: {#nested-if-statements}
Nested If statements
:::
You can place or nest an If statement inside of another If statement. Nesting If statements allows you to check for a condition only when another condition exists. JAWS evaluates the nested If statement only when the first condition is true. JAWS performs the sequence of statements within the nested If Then statement only if both conditions are found to be true. An example of the use of nested If statements follows:
If DialogActive () Then ; determine If a dialog box is active
Let sWindowName = GetWindowName (GetRealWindow (GetFocus ())); retrieve the window name For the active dialog
If sWindowName == "Open" Then ; the Open file dialog is active
SayFormattedMessage (OT_MESSAGE, "The Open File dialog is active")
Else
SayFormattedMessage (OT_MESSAGE, "A dialog box other than the Open File dialog is active.")
EndIf
Else
SayFormattedMessage (OT_MESSAGE, "No dialog box is active")
EndIf
In the above example, the first If statement determines if a dialog box is active or being displayed. When the If statement is true, JAWS performs the let statement and retrieves theinuing to the EndScript statement. window name for the active dialog. Next, the nested If statement uses the window name to determine if the Open File dialog is active. If the nested If statement is true, then JAWS performs the SayFormattedMessage () function following the nested If statement and speaks "The Open File dialog is active." If a dialog box other than the Open File dialog is active, then the nested If statement is false and JAWS performs the SayFormattedMessage () function following the else key word and speaks "A dialog other than the Open File dialog is active."
If JAWS determines no dialog box is active, then JAWS performs the SayFormattedMessage () function following the Else key word in the outer If statement following the Else key word and speaks "No dialog box is active."
Iterative or Looping
The third type of flow control you can use in your scripts is called iterative or looping. You use the iterative statement structure to perform the same statement or group of statements repeatedly while a condition is true. You use a loop to perform a sequence of statements several times, thus shortening the number of statements required. Looping provides a way to determine the number of repetitions automatically, depending on conclusions derived from script operation.
::: {#the-while-endwhile-statement-structure}
The While-EndWhile Statement Structure
:::
You perform looping in your scripts by using the While-Endwhile statements structure. A While Loop is a statement structure that repeats or loops WHILE a condition is true.
A While loop consists of two parts:
-
The While statement which sets the condition to be tested for
-
EndWhile statement that terminates the loop.
JAWS performs all statements within the boundaries of the While and EndWhile statements repeatedly until the condition in the While statement becomes false. An example of a While-EndWhile loop structure follows:
While Variable1 < 5 ; this condition will cause the loop To be performed 4 times
; Statements To be performed go here
Let Variable1 = Variable1 + 1 ; increment the value of Variable1 by 1 with each step
EndWhile
In the above example, JAWS performs the While loop while Variable1 is less than 5. Once the value of Variable1 becomes equal to 5, the loop ends and no further processing occurs.
A loop continues until a condition becomes false. You must be careful not to set up a loop with a condition that will never become false. To do so would create an infinite loop, which will cycle forever, and lock up the computer until the program is terminated manually. Think carefully about the condition meant to terminate the loop to be sure it will become false at some time. If you find that the computer seems to lock up after you execute a new script with a While loop in it, this is probably what is happening. :::
When you create an iterative flow sequence in a script using a While loop, care should be taken not to create an infinite loop that results in a locked computer. Since a loop continues until a condition becomes false, you must be certain that the condition being tested can actually become false. One way you can avoid this problem is to include statements designed to break the loop after a certain number of repetitions. An example of this follows:
Var
Int iSafety
Let iSafety = 1
While iSafety < 10
NextLine ()
If GetLine () == "%1" Then
Let iSafety = 10 ; cause the loop To terminate
EndIf
Let iSafety = iSafety + 1 ; increment the value of the iSafety variable
EndWhile
In the above example, JAWS performs the loop while the value of iSafety is less than 10. Each time JAWS performs the loop, JAWS performs the NextLin () function to move to the next line. The If statement determines if the text at the location of the active cursor is that of "Save As ..." When the If statement is found to be true, the iSafety is given the value of 10. This makes the While statement false and the loop terminates. When the If statement is false, then the value of iSafety is incremented by 1.
When the value of iSafety becomes equal to 10, JAWS terminates the loop as iSafety is no longer less than 10.
A second example of a while loop follows:
While (hPos); perform the While loop While the value of hPos is Not zero once the value of hPos becomes zero, Then the loop terminates
; While statement could also be written as While hPos! = 0
If IsWindowVisible (hPos) Then ; determine If the window referenced by hPos is visible
SpeakWindowInformation (hPos)
EndIf
Let hPos = GetNextWindow (hPos) ; retrieve the Handle For the next window
EndWhile
In the above example, JAWS performs the loop while the value of the handle variable, hPos, is not equal to zero. Within the loop, JAWS determines if the window referenced by hPos is visible. If the window is visible, then JAWS speaks information about the window. Next, the GetNextWindo () function retrieves the handle for the next window. If the GetNextWindo () function does not actually find a next window, then th () function places zero in the hPos variable. When the hPos variable contains zero, the condition being evaluated in the While statement is no longer true as the value of the variable is now zero. This terminates the While loop.
Compound Statements
You can create compound statements using both If Then-EndIf and While-EndWhile statement structures. A compound statement can determine if 2 conditions are both true. A compound statement may also determine if one of two conditions are true.
::: {#compound-statements-using-and}
Compound Statements Using AND
:::
When you join 2 statements together using the && operators, the statement is said to be a "and" compound statement. In this type of compound statement, both conditions must be true before the entire If Then or While statement are true. If either one of the conditions being evaluated is false, the entire If Then or While statement is then considered to be false. You use two & symbols to indicate a compound statement where both sides must be true. An example of the use of the && symbols in an If Then statement follow:
Let sWindowName = GetWindowName (GetRealWindow (GetFocus ())) ; retrieve the name of the active window
If DialogActive () && sWindowName == "%1" Then
Say ("%1", OT_MESSAGE)
EndIf
In the above example, the compound If statement determines if the active dialog box is the Open File dialog. The first part of the If statement determines if a dialog box is active. The second part of the If statement determines if the name of the active dialog is that of the Open File dialog. If both conditions of the If statement are true, then JAWS performs the Say statement following the If statement and speaks "The Open File dialog is active."
When there is no active dialog, the first condition is false making the entire If statement false. Likewise, if the name of the active dialog is something other than that of "Open", then the second condition is false making the entire If statement false. In either case, JAWS does not perform the Say statement following the If statement.
::: {#compound-statements-using-or}
Compound Statements Using OR
:::
When two statements are joined together using the operators, the statement is said to be a "or" compound statement. In this type of compound statement, either condition can be true for the entire If Then or While statement to be true. However, both statements do not have to be true to make the entire If Then or While statement true.
You use the symbol to indicate a compound statement where either side must be true. An example of the use of the symbols in an If Then statement follow:
If iValue < 5 || iValue 10 Then
Say ("%1", OT_MESSAGE)
EndIf
In the above statement, either sides of the can be true for the entire If statement to be considered true. Therefore, the value of the iValue variable can be less than 5 or it can be greater than 10. A value of 4 in the iValue variable would make the entire statement true as the iValue < 5 statement is true.
Logical Operators
You use logical operators to compare variables to other variables or constants. You frequently need to know if one variable has the same value, a lesser value, or a greater value than another variable. Sometimes you must compare several items or groups of items with other items. The logical operators are usually used within If Then and While loops to check whether conditions required for logical decisions are true or false. A list of the JAWS logical operators is shown below.
| Option | Description |
|---|---|
| == | Two equals signs together in this manner ask whether the first condition is "equal to" the second condition. That is, is the expression to the left of the two equals signs equivalent to the expression on the right side. For example, the expression (A == B) asks whether A equals B. |
| != | An exclamation point and an equals sign together in this manner ask whether the first condition is "not equal to" the second condition. That is, is the expression to the left of the exclamation point and equals sign different from the expression on the right side? For example, the expression (A != B) is true if A does not equal B. |
| < | A < sign asks whether the first condition is "less than" the second condition. That is, is the expression to the left of the < sign less than the expression to the right side? Thus, the expression (A < B) is true if A is less than B. |
| <= | A < sign followed by an equals sign asks whether the first condition is "less than or equal to" the second condition. That is, is the expression to the left of the <= signs less than or equal to the expression to the right side. Thus, the expression (A <= B) is true if A is less than or equal to B. |
| > | A > sign asks whether the first condition is "greater than" the second condition. That is, is the expression to the left of the > sign greater than the expression to the right side. Thus, the expression (A > B) is true if A is greater than B. |
| >= | A > sign followed by an equals sign asks whether the first condition is "greater than or equal to" the second condition. That is, is the expression to the left of the >= signs greater than or equal to the expression to the right side. Thus, the expression (A >= B) is true if A is greater than or equal to B. |
| && | This operator is placed between two logical comparisons made using logical operators such as the ones described above. It asks whether the first condition is true "and additionally" is the second condition true. The total expression is evaluated as true only if the comparisons on both sides of the && operator are true. Thus, in the expression (A == B) && (C != D), a value of true is only returned if A does equal B and C does not equal D. |
| || | This operator is placed between two logical comparisons made using logical operators such as the ones described above. It asks whether either the first condition is true or whether the second condition is true. The total expression is evaluated as true if either of the comparisons on either side of the operator is true. Thus, in the example (A == B) || (C == D), a value of true is returned if either A equals B or C equals D. Of course, a value of true would also be returned if both expressions were true. |
Controlling the Flow of Scripts Exercises
The following exercises will give you practice in creating If-Then statements.
Using the If statement to Check for User Verbosity
The following script for Notepad uses an If statement to determine which user verbosity level is active and speaks an appropriate message. You will need to use the GetVerbosity function to determine the current verbosity level. The GetVerbosity function returns the constant BEGINNER, INTERMEDIATE, or ADVANCED depending on which level JAWS is currently set on. The constants are defined in the header file hjconst.jsh. Use the If statement and the GetVerbosity function to determine which verbosity level is currently active and speak a message accordingly.
-
Make sure that the Notepad script file is open and your cursor is at the bottom of the file ready to insert a new script.
-
Add the following information in the New Script dialog:
-
Script Name: CheckVerbosity
-
Can be Attached to Key: checked
-
Synopsis: Speaks a message based on which verbosity level is active.
-
Description: This script uses the GetVerbosity function to determine which verbosity level is active and then speaks a message accordingly.
-
Category: None
-
Assign to Key: CONTROL + SHIFT + C
-
-
The script should first check to see if the verbosity level is set to beginner. If so, a message should be spoken. After typing the keyword If, press CONTROL + I to activate the InsertFunction dialog box and insert the GetVerbosity function. Notice the function requires no parameters. The statement should look like the following and should be placed beneath the line containing the script name:
If GetVerbosity () == BEGINNER Then ; Check To see If verbosity is beginner.You do not need quotes around the word BEGINNER because it is a constant value rather than a string value.
-
On the next line use the SayFormattedMessage function to have JAWS speak the message, "Your verbosity is beginner." Be sure to indent the line first. The line should look like the following:
SayFormattedMessage (OT_Message, "Your verbosity is beginner") -
Since we are checking for three conditions (beginner, intermediate, or advanced) we must use the ElIf statement to check for intermediate verbosity. The statement should look like the following:
ElIf GetVerbosity () == INTERMEDIATE Then ; Check To see If verbosity is INTERMEDIATE -
On the next line use the SayFormattedMessage function to have JAWS speak the message, "Your verbosity is intermediate."
-
Since the verbosity level must be one of three levels, we know that if it is not beginner or intermediate then it must be advanced. Therefore we can simply use the Else statement and have JAWS speak the message, "Your verbosity is advanced."
-
After inserting the Else statement and final SayFormattedMessage function don't forget the EndIf keyword before the EndScript statement. When finished, your script should look like the following:
Script CheckVerbosity () If GetVerbosity () == BEGINNER Then ; Check To see If verbosity is beginner. SayFormattedMessage (OT_Message, "Your verbosity is beginner") ElIf GetVerbosity () == INTERMEDIATE Then ; Check To see If verbosity is INTERMEDIATE SayFormattedMessage (OT_Message, "Your verbosity is intermediate") Else ; If the verbosity is Not beginner or intermediate, it must be advanced SayFormattedMessage (OT_Message, "Your verbosity is advanced") EndIf EndScript -
Press CONTROL + S to save and compile the script. If any errors exist be sure your script looks like the one above.
-
Switch over to Notepad and press CONTROL + SHIFT + C to run your script. JAWS should speak the message telling you what your verbosity currently is.
-
Be sure to change your verbosity to all three levels and test your script. Do the following to change your verbosity:
-
Press JAWSKEY + V to open the Adjust JAWS Options dialog box.
-
Press the letter 'U' until you find the User Verbosity option and press SPACEBAR to cycle between the three values.
-
Press ENTER to accept your change and close the Adjust JAWS Options dialog box and return to Notepad.
-
Additional Practice: Extend the logic to branch on additional environment settings (for example, Braille on/off, ScreenEcho level, or KeyboardLayout) and announce a concise combined status. How can you keep the branching readable as conditions grow?
Looping Example
The following script in Notepad should make JAWS count out loud from one to ten. You will accomplish this using a While EndWhile loop. During each iteration through the loop, JAWS will speak the value of an integer variable and then increase the value of the variable by one. The SayInteger function will be used to speak the value of the integer variable.
-
Make sure that the Notepad script file is open and your cursor is at the bottom of the file ready to insert a new script.
-
Add the following information in the New Script dialog:
-
Script Name: LoopingExample
-
Can be Attached to Key: checked
-
Synopsis: Counts out loud to ten.
-
Description: This script uses a loop and the SayInteger function to count from one to ten.
-
Category: None
-
Assign to Key: CONTROL + SHIFT + L
-
-
You must first create an integer variable that will be used to count to ten. Make sure the cursor is in the body of the script and create an integer variable named iCount.
-
Using a Let statement, assign a value of 1 to the iCount variable.
-
Since we want JAWS to stop counting after it reaches ten, we use a While loop that only executes while the value of iCount is less than eleven. ENTER the following on a blank line below the Let statement:
While iCount < 11; This loop will execute 10 times -
You can now insert the SayInteger function that will speak the value of the iCount variable. On a blank line below the While statement, press TAB to indent the code inside the loop. Then press CONTROL + I to activate the InsertFunction dialog box and locate the SayInteger function.
-
After choosing the SayInteger function, The Script Manager prompts you for two parameters. The first parameter is the numeric value or integer variable containing the numeric value to be spoken. When prompted by the Script Manager for this parameter, type "iCount" without the quotation marks to indicate that the function will speak the value of the iCount variable. The Script Manager then prompts you for the second parameter, the base of the number to be used. Since this parameter is optional, press TAB until you reach the Finish button followed by the SPACEBAR to activate the button and close the InsertFunction dialog. After the function is inserted into your script, you will need to remove the comma and space between the iCount variable and the right parenthesis. The line should look like the following:
SayInteger (iCount) -
On the next line you can now increase the value of the iCount variable by one. First press TAB to indent the new line to the same level as the previous line. Now type the following Let statement:
Let iCount = iCount + 1; Adds 1 To the value of iCount. When it reaches 11, the loop will stop. -
On the next line add the EndWhile keyword to conclude the loop.
-
After performing the above steps, your script should look like the following:
Script LoopingExample () Var Int iCount Let iCount = 1 While iCount < 11; This loop will execute 10 times. SayInteger (iCount); Speaks the value of the iCount variable Let iCount = iCount + 1; Adds 1 To the value of iCount. When it reaches 11, the loop will stop. EndWhile EndScript -
Press CONTROL + S to save and compile the script. If you get a compile error, check to make sure your script matches the example above.
-
You can now move to Notepad and press CONTROL + SHIFT + L to activate your script. You should hear JAWS count from one to ten.
Additional Practice: Generalize the loop to count to a user-specified number, add an adjustable delay between counts, and speak a start/end message. How would you guard against excessively large inputs or negative numbers?