How to get around HTML's restrictions with fixed decimal representations

HTML input tags do not support fixed decimal representations, so Steve Croy created a mechanism that parses a string and creates a numeric field from the contents of the string.

Many languages, such as Java, have multiple integer representations -- short, long, float, etc. -- to define variables.

But defining a variable as a fixed decimal representation is a feature not to be found in Java. JavaScript variables are very loosely typed, and though it is not a good programming practice, the same variable may be used as a character variable, numeric variable, or even a Boolean variable. But in JavaScript you cannot describe a variable with a fixed length and fixed decimal position.

DDS is a wonderful thing -- it allows us to present a panel with fields specifically defined as 7 digits, 2 decimal positions. Things those of us in the green-screen world take for granted are tightly cast variables and the ability to define and use fixed decimal fields. An input field may be defined so that the representation of the field is explicit in nature.

RPG allows us the luxury of predetermining the size of a numeric variable and the number of decimal positions. COBOL via the Picture Clause paints a very distinct definition of numeric representations.

HMTL, on the other hand, makes only a cursory definition of a field. The <INPUT> tag may describe a text box, password, text area or button. It may define the presentation length and a maximum length, though the maximum length is optional. There really isn't any such creature in HTML as fixed decimal representation. The content of a form text box, by nature, is treated as a string object and may contain characters and/or numbers.

Validating a text entry from an HTML form post can be a challenge because of the nature of the text box. The following input tag is designed to allow the user to enter a weight for an item. The weight of the item is a 7 digit, 2 decimal positions field in the database.

<INPUT TYPE="text" name=wgt$(ROW_NUM) size="8" maxlength="8" value="$(V_WCWKLO)"> 

If the form contained only a single numeric field, I would probably write a JavaScript routine to validate the form data. (** See note below.) In this case, the text box on the input tag is part of a table.

The table was generated with a Net.Data SQL macro block, hence the variable name on the input tag. Viewing the Web page, the user could enter anywhere from one to 30 entries, each entry potentially containing weight, so the table is passed to an RPG program for validation and to update the database file.

Without script editing in front of the form post, the incoming table data could contain anything. The only thing that was assured by the input tag is the length will not exceed eight characters (maxlength="8"). It may contain a decimal point; it may not. The following code is an attempt to decide whether the string contains valid numeric data and if it contains merely numbers or numbers and a decimal point -- at least that's the theory!

D WorkDS          DS  
D $weight                        7  2
D  wgt_in                 1      7
D #VALID          C                   CONST(' .0123456789')
D #ZPAD           S              8    INZ('00000000')
D w$wght          S              7  2

I start by getting the value of the table data for the weight entry using the DTW APIs, which allow my RPG program to manipulate HTML tables. The value is a text string eight characters long from the address of the table value in the specified row and column:

               ndRow = ndRow + 1;
               ndCol = 1;                          // Get weight
               ndRC = dtw_GetV(ndTable: %addr(ndValue): ndRow: ndCol);
               z$wght =  %trim(%str(ndValue:8));
               IF z$wght = *blanks;
                  p$err = 'MNF0003';
                  EXSR @exit;
               ENDIF;

Notice that I use %TRIM in retrieving the value to make sure any leading blanks are stripped. There is no guarantee the information in the text box has been right- or left-justified. Typically, I use a JavaScript function to position the cursor to a form field, but the user, of course, may hit the space bar or click the mouse and change the positioning at any time. Having retrieved the value, I'm counting on RPG string handling Built-in Functions (BIFs) to interrogate the data.

Using the constant of digits, plus the decimal point (#VALID) I check to see if I have a valid number:

               pos = %check(#valid:z$wght);   
               IF pos > 0;
                  p$err = 'MNF0003';
                  EXSR @exit;
               ENDIF;

I used the length BIF to return the length of the string. Then I used the scan BIF to find the position of the decimal point in the string. If there are more than two digits to the right of the decimal point, I use %SUBST to truncate the string two positions after the decimal point.

               IF %scan('.':z$wght) > 0;
                  A = %len(%trim(z$wght));
                  B = %len(%scan('.':z$wght));
                  D = A - B;
                  IF D > 2;
                     z$wght = %subst(z$wght:1: B + 2);
                  ENDIF;

The next set of instructions uses EVALR to load a work field with the rightmost digits after the decimal point. Of course, it's not quite that simple. If there are fewer than two digits to the right of the decimal point, it has to be padded with zeros. The trim and substring BIFs have values that are the result of an expression. The first half of the expression uses substring to get the value from the work field Z$WGHT beginning at the position of the decimal point + 1. It is concatenated with the necessary zero padding to insure the resulting string does not contain blanks.

                  EVALR w$wrk8 = %trim(%subst(z$wght: %scan('.':z$wght)+1)) +
                          %subst(#ZPAD:1:2 - %len(%trim(%subst(z$wght:
                             %scan('.':z$wght)+1))));

Having retrieved the digits to the right of the decimal point, the next step is to retrieve the digits to the left of the decimal point. Using the substring BIF the digits are retrieved starting at the first position for the length returned by using the scan BIF as an expression (position of decimal minus one). Then concatenate the results with the value to the right of the decimal position.

                  IF %scan('.':z$wght) > 1;
                     EVALR w$wrk8 = %trim(%subst(z$wght:1:
                                          %scan('.':z$wght)-1)) +
                                          %trim(w$wrk8);
                  ENDIF;
                  EVALR  wgt_in = w$wrk8;
                  w$wght = $weight; 

If no decimal point is present, the process is much simpler. The length of the string is determined. Then the value is right-adjusted and padded with zeros. I move the result into a work field, then multiply 100 to create the additional two decimal positions.

               ELSE;
                  len = 8 - %len(%trim(z$wght));
                   z$wght = %subst(#ZPAD:1:len) + %trim(z$wght);
                   EVALR  wgt_in = z$wght;
                   w$wght = $weight * 100;
               ENDIF;
               IF w$wght = 0;
                  p$err = 'MNF0003';
                  EXSR @exit;
               ENDIF;

BIF operations may be used to create complex instructions when the values are derived from expressions. The code as written extracts the digits from a text string, trimming blanks and stripping out the decimal point with just text string manipulation. The result is numeric value, with the correct number of leading zeros, and trailing zeros if necessary.

The same operation could have been performed using arrays. And I'm sure if I spent more time, I could make this routine somewhat simpler and cleaner, perhaps by using the %XLATE BIF to flip all blanks after the decimal point to zero. But string manipulation did serve the purpose.

If only HTML form fields supported fixed decimal representation, life would be so much simpler. Then, it would be great if the W3C would add EDTWRD and EDTCDE to the <INPUT> tag!

-------------------------------
About the author: Steve Croy is a programmer at USXpress Enterprises Inc. in Chattanooga, Tenn.


*** Note:

In JavaScript, it is not uncommon to pluck a value from a form field and determine if it contains only numbers. Here is an example of a script function that is invoked on the submit button. The intent is very similar to the code above. It examines the content of the form field and strips out any character that is not a number. Specifically, the field should contain a date, but before it can be used, any characters such as /, -, or any other date separators will be removed.

var chkdigits = "0123456789";
   DateValue = "";
   DateTemp = "";
   DateValue = DateForm.date1.value;

  /* Delete all chars except 0 through 9 */

  for (i = 0; i < DateValue.length; i++) {
       if (chkdigits.indexOf(DateValue.substr(i,1)) >= 0) {
        DateTemp = DateTemp + DateValue.substr(i,1);
       }
  }
  DateValue = DateTemp;


This was first published in May 2005

Dig deeper on iSeries Java programming

0 comments

Oldest 

Forgot Password?

No problem! Submit your e-mail address below. We'll send you an email containing your password.

Your password has been sent to:

SearchEnterpriseLinux

SearchDataCenter

Close