Previous ION Script User's Guide: Creating ION Script Applications Next

Example: Creating a Complete Application

In this section, we will walk through the process of creating an interactive data-picking application. This application will do the following:

This application consists of five .ion files, located in the examples subdirectory of the ION Script installation. The following figure illustrates the relationship between the files we will be creating:


Example Code
The files for this example are included in the examples directory of your ION Script installation. You can load this example from the page index_examples.ion by clicking the "User's Guide Example Application" link

.

Figure 4-5: File Relationships

Figure 4-5: File Relationships

Step 1: Displaying an IDL-Generated Image

The first step is to create our main page, ex1_main.ion, on which we display an image. The original image is a 1200 x 1200 PNG image called landsat.png, which is located in the ion_script/examples/data subdirectory of your ION Script installation. Due to the bandwidth limitations of Web-based applications, we will display only a 320 x 256 region of the image. Another approach would be to scale the image to a smaller size.

The ION_IMAGE tag is used to insert an IDL-generated image into the page. The attributes of ION_IMAGE define basic image properties such as its width, height, and file format. The ION_IMAGE tag always contains an <IDL>...</IDL> block. The IDL tag can only be used inside the ION_IMAGE and ION_DATA_OUT tags. It is used inside an ION_IMAGE tag to define the IDL code used to generate an image, or inside an ION_DATA_OUT tag to insert textual output from IDL. In this example, we will enter the IDL code directly into the IDL block. We could also use the IDL tag to call an IDL .pro file instead. The following ION Script code displays a 320 x 256 region of the landsat.png image:

<ION_SCRIPT>  
<ION_HEADER>  
   <TITLE>ION Script Image Example</TITLE>  
</ION_HEADER>  
  
<ION_BODY>  
   <FONT SIZE=+2>ION Script Image Example</FONT>  
   <BR><BR>  
  
   <ION_IMAGE WIDTH="320" HEIGHT="256" TYPE="DIRECT">  
     <IDL>  
       ; Read in the original image:  
       image=read_png(filepath($  
          subdir=['..', 'ion_script','examples', 'data'], $  
          'landsat.png'), r, g, b)  
  
       ; Create a 320x256 region of the image:  
       region = image[440:759, 472:727]  
  
       ; Load the display color table:  
       tvlct, r, g, b  
  
       ; Display the region:  
       tv, region  
     </IDL>  
   </ION_IMAGE>  
</ION_BODY>  
</ION_SCRIPT>  

This code creates the following Web page:

 

Figure 4-6: Image Output

Figure 4-6: Image Output

Step 2: Declaring and Displaying Variables

In Step 1, we specified a subarray of our original image in order to display a smaller image on the Web page. To do this, we hard-coded the subscript values in the IDL command:

region = image[440:759, 472:727]  

Suppose we want to use these subscript values in other parts of the application, or we want to allow the user to specify these subscript values. To do this, we can define variables to hold this information, and then reuse or change these variables as needed. Our code would be more flexible if we defined the region as follows:

region = image[xstart:xend, ystart:yend]  

We can then define these IDL variables as follows:

xstart = Horizontal Center - 1/2 Region Width

xend = Horizontal Center + 1/2 Region Width - 1

ystart = Vertical Center - 1/2 Region Height

yend = Vertical Center + 1/2 Region Height - 1

Now we can define ION Script variables to hold the horizontal and vertical centers, and the region width and height. We want our region to be 320 x 256, and we'll place the center at the center of our 1200 x 1200 image, which makes the horizontal and vertical centers 600.

Declaring Variables

To define variables in an ION Script page, we use the VARIABLES tag, which contains one VARIABLE_DECL tag for each variable we declare. The VARIABLES tag resides inside the ION_HEADER. We'll add the following VARIABLES block to ex1_main.ion, in which we define the width and height of the original image, the region width and height, and the horizontal and vertical centers of the display region:

<VARIABLES>  
   <VARIABLE_DECL NAME="IMAGE_W" VALUE="1200" TYPE="INT"/>  
   <VARIABLE_DECL NAME="IMAGE_H" VALUE="1200" TYPE="INT"/>  
  
   <VARIABLE_DECL NAME="REGION_W" VALUE="320" TYPE="INT"/>  
   <VARIABLE_DECL NAME="REGION_H" VALUE="256" TYPE="INT"/>  
  
   <VARIABLE_DECL NAME="CENTER_X" VALUE="600" TYPE="INT" />  
   <VARIABLE_DECL NAME="CENTER_Y" VALUE="600" TYPE="INT" />  
</VARIABLES>  

Using Variables in ION Script Tags and IDL Code

We now need to insert the variables we have created into the code used to generate the image. To use a variable instead of an explicit value as an attribute of an ION Script tag or in IDL code, we precede the variable name with the $ symbol. This tells the ION Script parser to replace $variable with the value of variable. The following code uses our variables in the ION_IMAGE tag and in the IDL code:

<ION_IMAGE WIDTH="$REGION_W" HEIGHT="$REGION_H" TYPE="DIRECT">  
   <IDL>  
      ; Read in the original image:  
      image = read_png(filepath($  
         subdir=['..', 'ion_script', 'examples', 'data'], $  
         'landsat.png'), r, g, b)  
  
      ; Calculate the x subscripts:  
      xstart = $CENTER_X - $REGION_W/2  
      xend = $CENTER_X + $REGION_W/2 - 1  
  
      ; Calculate the y subscripts:  
      ystart = $CENTER_Y - $REGION_H/2  
      yend = $CENTER_Y + $REGION_H/2 - 1  
  
      ; Create the specified region:  
      region = image[xstart:xend, ystart:yend]  
  
      ; Load the display color table:  
      tvlct, r, g, b  
  
      ; Display the region:  
      tv, region  
   </IDL>  
</ION_IMAGE>  

Displaying Variable Values on the Page

At times, you will want to display the value of a variable on the Web page. For example, we could help the user of our application determine what portion of the image is being displayed by writing to the page the sizes of the original and displayed images, and the center of the display region. The ION_VARIABLE tag is used to insert the value of a variable into a page. We'll display three variables on our page by adding the following code to ex1_main.ion:

<BR>  
<B>Image Size:</B> (<ION_VARIABLE NAME="$IMAGE_W"/>,   
   <ION_VARIABLE NAME="$IMAGE_H"/>)<BR>  
<B>Region Size:</B> (<ION_VARIABLE NAME="$REGION_W"/>,   
   <ION_VARIABLE NAME="$REGION_H"/>)<BR>  
<B>Region Center:</B> (<ION_VARIABLE NAME="$CENTER_X"/>,   
   <ION_VARIABLE NAME="$CENTER_Y"/>)  

Loading ex1_main.ion in our browser now results in the following page:

 

Figure 4-7: Image and Variable Output

Figure 4-7: Image and Variable Output


Note
The ION_VARIABLE tag can also be used to insert an ION Script variable into an HTML tag attribute. See Variable Substitution in Attribute Values.

Step 3: Adding Interactivity

For our application to be useful, we need to allow the user to control the way in which the data is presented. We'll add a form to our page to allow the user to specify the maximum and minimum pixel values to consider, and the maximum value of the scaled result. The form will include a button used to submit the user input and request a new page with the scaled image.

Creating an ION Script Form

Our interactive application will allow color value scaling of the image, for which we use the IDL BYTSCL function. This function takes the MIN, MAX, and TOP keywords, which we will allow the user to specify. Therefore, we need to get three values from the user.

User input in an ION Script application is achieved via an ION Script form, which is created with the ION_FORM tag. Our form will use three text input fields, created with the HTML INPUT tag. We also need a way to submit user input, which we'll accomplish with an ION_BUTTON. Add the following code to ex1_main.ion to create the form:

<ION_FORM>  
   <B>Color Scale Range:</B>  
   Min  
   <INPUT TYPE="TEXT" NAME="SCALE_MIN" SIZE=4 VALUE="0">  
  
   Max  
   <INPUT TYPE="TEXT" NAME="SCALE_MAX" SIZE=4 VALUE="255">  
  
   Top  
   <INPUT TYPE="TEXT" NAME="SCALE_TOP" SIZE=4 VALUE="255">  
  
   <BR>  
   <ION_BUTTON TYPE="BUTTON" EVENT="SCALE_COLORS" LABEL="Scale 
      Colors"/>  
</ION_FORM>  

Note that each text input field is given a name. A variable called $Form.name is automatically created for each text field, where name is the NAME attribute of the INPUT tag. Therefore, we can now access the values entered by the user by referring to the $Form.SCALE_MIN, $Form.SCALE_MAX, and $Form.SCALE_TOP variables. We assign each text field an initial value using the INPUT tag's VALUE attribute. This is the value that appears in the text field when the page is initially loaded. After adding a form, the page now looks like this:

Figure 4-8: Interactive Image and Variable Output

Figure 4-8: Interactive Image and Variable Output

Defining the Event

The ION_BUTTON tag in our form uses the EVENT attribute to specify the name of the event that occurs when the user clicks the button. In this case, we called our event "SCALE_COLORS". We must now define the SCALE_COLORS event, which we do by adding to the ex1_main.ion header block an EVENTS block that contains an EVENT_DECL tag:

   <EVENTS>  
      <EVENT_DECL NAME="SCALE_COLORS" 
         ACTION="ion://ex1_scale.ion"/>  
   </EVENTS>  

This EVENT_DECL specifies that the page ex1_scale.ion is processed when the SCALE_COLORS event occurs. In this case, the SCALE_COLORS event occurs when the user clicks the button. Note that the URL in the ACTION attribute of the EVENT_DECL tag begins with ion://. This causes the specified page to be processed by the ION Script parser. If you simply wanted to load an HTML page when the user clicks the button, you could use an http:// or file:// URL.

Creating Persistent Variables

We want the scaled image to use the same region and center as the original display region. Therefore, we need to pass the values of the REGION_W, REGION_H, CENTER_X, and CENTER_Y variables declared in ex1_main.ion to the ex1_scale.ion page. To do this, we must make the variables persistent by specifying the PERSIST attribute in our VARIABLE_DECL tags as follows:

<VARIABLE_DECL NAME="REGION_W" VALUE="320" TYPE="INT"  
   PERSIST="TRUE"/>  
<VARIABLE_DECL NAME="REGION_H" VALUE="256" TYPE="INT"  
   PERSIST="TRUE"/>  
  
<VARIABLE_DECL NAME="CENTER_X" VALUE="600" TYPE="INT"  
   PERSIST="TRUE"/>  
<VARIABLE_DECL NAME="CENTER_Y" VALUE="600" TYPE="INT"  
   PERSIST="TRUE"/>  

 


Note
We do not need to declare persistent variables for the values entered by the user. Values entered in a form become $Form variables, which are automatically passed to the action page when an event occurs.

Creating the Action Page

We've provided a means of user input, established the variables as persistent so that their values can be passed to the action page, and specified that the page ex1_scale.ion be processed when the user clicks the button. All that's left is to create the ex1_scale.ion page that generates the scaled image.

We can make use of the $Form variables in the IDL code that generates the scaled image. The ex1_scale.ion page is coded as follows:

<ION_SCRIPT>  
  
<ION_HEADER>  
   <TITLE>Scaled Image</TITLE>  
</ION_HEADER>  
  
<ION_BODY>  
   <FONT SIZE="+2">Scaled Image</FONT><BR><BR>  
   <ION_IMAGE  WIDTH="$REGION_W" HEIGHT="$REGION_H" TYPE="DIRECT">  
      <IDL>  
         ; Read in the original image:  
         image = read_png(filepath($  
            subdir=['..', 'ion_script', 'examples', 'data'],$  
            'landsat.png'), r, g, b)  
  
         ; Calculate the x subscripts:  
         xstart = $CENTER_X - $REGION_W/2  
         xend = $CENTER_X + $REGION_W/2 - 1  
  
         ; Calculate the y subscripts:  
         ystart = $CENTER_Y - $REGION_H/2  
         yend = $CENTER_Y + $REGION_H/2 - 1  
  
         ; Create the region to be displayed:  
         region = image[xstart:xend, ystart:yend]  
  
         ; Scale the region:  
         scale_region = bytscl(region, MIN=$Form.SCALE_MIN,$  
            MAX=$Form.SCALE_MAX, TOP=$Form.SCALE_TOP)  
  
         ; Load the display color table:  
         tvlct, r, g, b  
  
         ; Display the region:  
         tv, scale_region  
      </IDL>  
   </ION_IMAGE>  
</ION_BODY>  
  
</ION_SCRIPT>  

After we enter some values in the form and click the button, we get the following page:

 

Figure 4-9: Output

Figure 4-9: Output

Step 4: Validating Form Data

To properly scale the image in our example, the values you enter in any of the form fields must be between 0 and 255, and the value you enter for SCALE_MIN must be smaller than the value for SCALE_MAX. We can make our application more user-friendly by checking the data entered by the user, and reporting any invalid entries. To do this, we need to be able to conditionally execute portions of our code. For example, to check for invalid SCALE_MIN values, we'd use an algorithm such as:

If SCALE_MIN is less than 0

Write "Scale min must be greater than 0" to the page

If SCALE_MIN is greater than 255

Write "Scale min must be less than 255" to the page

We can access the values submitted in the form with the variables $Form.SCALE_MIN, $Form.SCALE_MAX, and $Form.SCALE_TOP. But $Form variables are always treated as strings, therefore we cannot use $Form variables in numeric expressions. In order to check the numeric values submitted in the form, we must first declare numeric variables, and set them equal to the $Form variables. This converts the string to a numeric value. We'll therefore add the following VARIABLES block to the ex1_scale.ion page:

<VARIABLES>  
   <VARIABLE_DECL NAME="SCALE_MIN" VALUE="$Form.SCALE_MIN"  
      TYPE="INT" />  
   <VARIABLE_DECL NAME="SCALE_MAX" VALUE="$Form.SCALE_MAX"  
      TYPE="INT" />  
   <VARIABLE_DECL NAME="SCALE_TOP" VALUE="$Form.SCALE_TOP"  
      TYPE="INT" />  
</VARIABLES>  

Now we're ready to check the values submitted in the form. We do this by creating an ION_IF block. For example, we can check the value of SCALE_MIN by adding the following code to ex1_scale.ion:

<ION_IF EXPR="$SCALE_MIN LT 0">  
   <FONT COLOR="#CC0000"><BR>  
   <B>Error:</B> Scale min must be greater than or equal to 0  
   <BR><BR>  
   </FONT>  
<ION_ELSEIF EXPR="$SCALE_MIN GT 255"/>  
   <FONT COLOR="#CC0000"><BR><BR>  
   <B>Error:</B> Scale min must be less than 256 <BR>  
   </FONT>  
</ION_IF>  

For more on ION_IF, see ION_IF, ION_ELSEIF, ION_ELSE.

Now if the user submits a negative value for SCALE_MIN, an error will be written to the page, as shown in the following figure:

Figure 4-10: Output

Figure 4-10: Output

The scaled image, however, will still be generated with invalid data. Therefore, if any values are invalid, we need to change them to valid values. To change the value of a variable on the fly, we use the ION_EVALUATE statement as follows:

<ION_IF EXPR="$SCALE_MIN LT 0">  
   <ION_EVALUATE EXPR="$SCALE_MIN = 0"/>  
   <FONT COLOR="#CC0000"><BR>  
   <B>Error:</B> Scale min must be greater than or equal to 0  
   <BR>  
   </FONT>  
<ION_ELSEIF EXPR="$SCALE_MIN GT 255"/>  
   <ION_EVALUATE EXPR="$SCALE_MIN = 255"/>  
   <FONT COLOR="#CC0000"><BR>  
   <B>Error:</B> Scale min must be less than 256 <BR>  
   </FONT>  
</ION_IF>  

Step 5: Creating Reusable Pages

So far, this application uses only one image. In a real-world application, we would most likely want to be able to perform the same manipulations on multiple images. We could save ourselves from rewriting much of the code by breaking off reusable portions of code into separate files, and then including these files. To include a file, we use the ION_INCLUDE tag.

First, we'll cut the ION_FORM block from ex1_main.ion, and include a separate ION Script page, which we'll call ex1_form.ion. To do this, we replace the ION_FORM tag in ex1_main.ion with ION_INCLUDE as follows:

<ION_INCLUDE SRC="ion://ex1_form.ion" />  

The include file looks like this:

<ION_FORM>  
   <B>Color Scale Range:</B>  
   Min  
   <INPUT TYPE="TEXT" NAME="SCALE_MIN" SIZE=4   
      VALUE="0">  
   Max  
   <INPUT TYPE="TEXT" NAME="SCALE_MAX" SIZE=4   
      VALUE="255">  
   Top  
   <INPUT TYPE="TEXT" NAME="SCALE_TOP" SIZE=4   
      VALUE="255">  
   <BR>  
   <ION_BUTTON TYPE="BUTTON" EVENT="SCALE_COLORS"  
      LABEL="Scale Colors"/>  
</ION_FORM>  

Note that we do not need to use the ION_SCRIPT or ION_BODY tags in this include file. The file is simply inserted into the body of the file containing the ION_INCLUDE tag.

Our application also places all of the error-checking code into its own ION Script page called ex1_validate.ion, and uses the following tag in ex1_scale.ion:

<ION_INCLUDE SRC="ion://ex1_validate.ion" />  

Step 6: Creating Interactive Images for Data Picking

Two useful features of ION Script are its ability to assign events to images, and to capture the location on an image where the mouse was clicked. These features allow us to create powerful data-picking applications.

Since our example application displays only a portion of the original image, we could allow the user to select the portion of the image to view. We'll add an event to the image on the ex1_main.ion page that causes the image to be re-centered at the location of the mouse click.

First, we need to define an event for the image. In the EVENTS block of ex1_main.ion, we define the event as follows:

   <EVENT_DECL NAME="CENTER_IMAGE"   
      ACTION="ion://ex1_main.ion"/>  

Notice that the action of this event is to reload the same page. Now we need to add an EVENT attribute to the image itself. The ION_IMAGE tag in ex1_main.ion becomes:

<ION_IMAGE EVENT="CENTER_IMAGE" WIDTH="$REGION_W"  
   HEIGHT="$REGION_H" TYPE="DIRECT">  

Using the $Mouse System Variable

Next, we need to add code to find the new center, and make sure that we haven't reached one of the four edges of the image. Our tool for finding the location of the mouse click is the $Mouse system variable. $Mouse.x stores the x location of the mouse click, and $Mouse.y stores the y location. Because our image is always 320 x 256, the display center cannot be less than 320/2 pixels away from the left or right edges of the original image, or 256/2 pixels away from the top or bottom edges. Therefore, we must also add error-checking code to adjust the display center if the user clicks outside these boundaries. We'll add the following code to ex1_main.ion to recalculate the CENTER_X and CENTER_Y variables:

<!-- If the mouse was pressed, recompute the center -->  
<ION_IF EXPR="$Mouse.x NE 0.0">  
   <ION_EVALUATE   
      EXPR="$CENTER_X = $CENTER_X + ($Mouse.x - $REGION_W/2)"/>  
   <ION_EVALUATE   
      EXPR="$CENTER_Y = $CENTER_Y - ($Mouse.y - $REGION_H/2)"/>  
</ION_IF>  
  
<!-- Make sure we haven't reached the edge of the image -->  
<ION_IF EXPR="($CENTER_X + $REGION_W/2) GT ($IMAGE_W - 1)">  
   <ION_EVALUATE EXPR="$CENTER_X = ($IMAGE_W - 1) - $REGION_W/2"/>  
   <FONT COLOR="#0000CC">  
   <BR>Right edge of image reached, view center has been adjusted  
   </FONT>  
<ION_ELSEIF EXPR="($CENTER_X - $REGION_W/2) LT 0"/>  
   <ION_EVALUATE EXPR="$CENTER_X = $REGION_W/2"/>  
   <FONT COLOR="#0000CC">  
   <BR>Left edge of image reached, view center has been adjusted  
   </FONT>  
</ION_IF>  
  
<ION_IF EXPR="($CENTER_Y + $REGION_H/2) GT ($IMAGE_H - 1)">  
   <ION_EVALUATE EXPR="$CENTER_Y = ($IMAGE_H - 1) - $REGION_H/2"/>  
   <FONT COLOR="#0000CC">  
   <BR>Top edge of image reached, view center has been adjusted  
   </FONT>  
   <ION_ELSEIF EXPR="($CENTER_Y - $REGION_H/2) LT 0"/>  
   <ION_EVALUATE EXPR="$CENTER_Y = $REGION_H/2"/>  
   <FONT COLOR="#0000CC">  
   <BR>Bottom edge of image reached, view center has been adjusted  
   </FONT>  
</ION_IF>  

Step 7: Displaying IDL-Generated Data

Our final task for this application is to provide the user with some data about the image. We'll add a link to the ex1_main.ion page that executes a page called ex1_data.ion, which displays the minimum, maximum, and mean values in the image.

To create the link, we use the ION_LINK tag as follows:

<ION_LINK EVENT="SHOW_DATA">View Image Data</ION_LINK>  

Like an ION_BUTTON, an ION_LINK has an EVENT attribute. When the user clicks on the link, we want to load ex1_data.ion. We'll therefore define the event as follows:

<EVENT_DECL NAME="SHOW_DATA" ACTION="ion://ex1_data.ion"/>  

Next, we need to create the ex1_data.ion page. Whereas the ION_IMAGE tag displays an IDL-generated image, the ION_DATA_OUT tag is used to insert textual IDL output into the page. The following code is used to create the ex1_data.ion page:

<ION_SCRIPT>  
<ION_HEADER>  
   <TITLE>Image Data</TITLE>  
</ION_HEADER>  
<ION_BODY>  
   <FONT SIZE="+2">Image Data</FONT>  
   <BR>  
   <ION_DATA_OUT>  
      <IDL>  
         ; Read in the original image:  
         image = read_png(filepath($  
            subdir=['..', 'ion_script', 'examples', 'data'],$  
            'landsat.png'), r, g, b)  
  
         ; Calculate the x subscripts:  
         xstart = $CENTER_X - $REGION_W/2  
         xend = $CENTER_X + $REGION_W/2 - 1  
  
         ; Calculate the y subscripts:  
         ystart = $CENTER_Y - $REGION_H/2  
         yend = $CENTER_Y + $REGION_H/2 - 1  
  
         ; Create the region to be displayed:  
         region = image[xstart:xend, ystart:yend]  
  
         ; Print min, max, and mean:  
         print, '<B>Minimum Value:</B>', min(region)  
         print, '<B>Maximum Value:</B>', max(region)  
         print, '<B>Mean Value:</B>', mean(region)  
      </IDL>  
   </ION_DATA_OUT>  
</ION_BODY>  
</ION_SCRIPT>  

Note that the IDL print statements include HTML. The IDL output inserted by ION_DATA_OUT is inserted directly into the HTML stream, therefore, we can include HTML in our IDL print statements to control the way the IDL output is rendered by the browser. The following figure shows the page generated by ex1_data.ion:

 

Figure 4-11: IDL Generated Data Output

Figure 4-11: IDL Generated Data Output


Note
For another example of how ION_DATA_OUT can be used to generate HTML, see ION_DATA_OUT. Also see the examples dropframe.ion and pickfile.ion, which can be accessed by the "Dynamic Droplist Example" and "Dynamic Table Example" links on the Advanced examples page, index_examples.ion.

A Note On Using the Back Button

When you design an application, always test the behavior of the application when navigating with the browser's Back button. Using the Back button to navigate through an application may cause undesired results. Try to design your application interface to discourage use of the Back button. For example, on the ex1_scale.ion and ex1_data.ion pages, you must use the Back button to return to the previous page. We could add an ION_BUTTON to each page and assign an event that returns to the previous page. This ensures that any changed variable values are passed back to the previous page. Note, however, that you cannot depend on the user clicking your ION_BUTTON instead of the Back button. Therefore, make sure that using the Back button does not cause problems with your application, regardless of whether you provide alternative means of navigation.

Application Variations

To keep this example as simple as possible, our button event caused the action page to replace the main page. In this section, we'll explore a couple alternative ways of writing this application.

Using Frames

In some applications, you might find it useful to display an original and a manipulated image next to each other on the same Web page. One way to do this would be to use frames.


Example Code
We've included a framed version of this example in the examples directory. The file is called ex1_frame_main.html.

Load this page using a URL such as

http://myserver/cgi-bin/ion-p?page=ex1_frame_main.html  

For more information on creating frames, see Using Frames with ION Script.

Reloading the Same Page

Another option for this application would be to use the same page for the main page and the action page. In this case, when the user clicks the button, the action is to reload the same page.


Example Code
We've included this version in the examples directory. The file is called ex2_main.ion.

There are a few changes we need to make to the application when the event is to reload a page with a form:

1. First, we need to change the event declaration to load the same page:

<EVENT_DECL NAME="SCALE_COLORS" ACTION="ion://ex2_main.ion"/>  

2. The first time the page is loaded, the image is scaled using the values defined for SCALE_MIN, SCALE_MAX, and SCALE_TOP in the VARIABLE_DECL tags. When the user enters new values in the form and clicks the button, we want to use the values entered by the user rather than the values defined in the VARIABLE_DECL tags. Therefore, we need one set of variables that set the scale values when the page is initially loaded (or loaded from a form other than the one containing the entries), and another set of variables to set the scale values from the form:

<VARIABLE_DECL NAME="SCALE_MIN" VALUE="0" TYPE="INT"  
   PERSIST="TRUE"/>  
<VARIABLE_DECL NAME="SCALE_MAX" VALUE="255" TYPE="INT"  
   PERSIST="TRUE"/>  
<VARIABLE_DECL NAME="SCALE_TOP" VALUE="255" TYPE="INT"  
   PERSIST="TRUE"/>  
  
<VARIABLE_DECL NAME="USER_SCALE_MIN"  
   VALUE="$Form.USER_SCALE_MIN" TYPE="INT" />  
<VARIABLE_DECL NAME="USER_SCALE_MAX"  
   VALUE="$Form.USER_SCALE_MAX" TYPE="INT" />  
<VARIABLE_DECL NAME="USER_SCALE_TOP"  
   VALUE="$Form.USER_SCALE_TOP" TYPE="INT" />  

3. When we reload the page ex2_main.ion, we'd like the values that appear in the form fields to remain the same as the values entered by the user the last time the "Scale Colors" button was clicked. Therefore, we don't want to use the hard-coded values that ex1_form.ion uses. Instead, we'll use ION_VARIABLE to insert the user value into the form fields. Also, the original form uses SCALE_MIN, SCALE_MAX, and SCALE_TOP as the names of the form fields. We want to use the user values instead, so we'll change these names to USER_SCALE_MIN, USER_SCALE_MAX. and USER_SCALE_TOP. We'll save these changes to the form in a new file called ex2_form.ion, which now looks like this:

<ION_FORM>  
      <B>Color Scale Range:</B>  
Min  
   <INPUT TYPE="TEXT" NAME="USER_SCALE_MIN" SIZE=4  
      VALUE="<ION_VARIABLE NAME="$SCALE_MIN"/>">  
Max  
   <INPUT TYPE="TEXT" NAME="USER_SCALE_MAX" SIZE=4  
      VALUE="<ION_VARIABLE NAME="$SCALE_MAX"/>">  
Top  
   <INPUT TYPE="TEXT" NAME="USER_SCALE_TOP" SIZE=4  
      VALUE="<ION_VARIABLE NAME="$SCALE_TOP"/>">  
   <BR>  
   <ION_BUTTON TYPE="BUTTON" EVENT="SCALE_COLORS" LABEL="Scale  
      Colors"/>  
</ION_FORM>  

4. In order to use the new form page, ex2_form.ion, we need to change the ION_INCLUDE tag that includes the form:

<ION_INCLUDE SRC="ion://ex2_form.ion"/>  

5. Next, we need to retrieve the user values from the form. We do this by adding the following code to ex2_main.ion:

<ION_IF EXPR="$Form.USER_SCALE_MIN NE 'undef'">  
    <ION_EVALUATE EXPR="$SCALE_MIN = $USER_SCALE_MIN"/>  
    <ION_EVALUATE EXPR="$SCALE_MAX = $USER_SCALE_MAX"/>  
    <ION_EVALUATE EXPR="$SCALE_TOP = $USER_SCALE_TOP"/>  
</ION_IF>  

6. Lastly, we need to add an ION_INCLUDE tag in ex2_main.ion to include the validation page:

<!-- Validate the user input -->  
<ION_INCLUDE SRC="ion://ex1_validate.ion"/>   

  IDL Online Help (March 06, 2007)