Team LiB
Previous Section Next Section

Dynamic Forms

Before concluding the chapter, let’s present one final example of how intelligence can be added to a Web form to make it dynamic. As we have seen throughout the chapter, it is possible to both read and write form field values; thus, besides checking data and improving form usage, we should be able to use JavaScript to subtotal orders, calculate shipping values, and fill in parts of the form dynamically. The following example shows a simple form that adds up the number of items entered and calculates a subtotal, tax rate, shipping cost, and grand total. A rendering of the example is shown in Figure 14-4.

Click To expand
Figure 14-4: Rendering of dynamic form example
<<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">>
<<html>>
<<head>>
<<title>>Dynamic Form Demo<</title>>
<<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />>
<<script type="text/javascript">>
<<!--
// Set up form variables and constants
var widgetCost = 1.50;
var gadgetCost = 2.70;
var thingieCost = 1.25;
var taxRate = 0.075;
var shippingCost = 0;

function isNumberInput(field, event) 
{
  var key, keyChar;

  if (window.event)
    key = window.event.keyCode;
  else if (event)
    key = event.which;
  else
    return true;

  // Check for special characters like backspace
  if (key == null || key == 0 || key == 8 || key == 13 || key == 27)
    return true;

  // Check to see if it.s a number
  keyChar =  String.fromCharCode(key);

  if (/\d/.test(keyChar))
   {
    window.status = "";
    return true;
   } 
  else 
  {
    window.status = "Field accepts numbers only.";
    return false;
  }
}

function format(value)
{
  // Format to have only two decimal digits
  var temp =  Math.round(value * 100);
  temp = temp / 100;
  return temp;
}

function calc()
{
  with (document.myform)
  {
    widgettotal.value = format(widgets.value * widgetCost);
    gadgettotal.value = format(gadgets.value * gadgetCost);
    thingietotal.value = format(thingies.value * thingieCost);
    subtotal.value = format(parseFloat(widgettotal.value) +
                            parseFloat(gadgettotal.value) +
                            parseFloat(thingietotal.value));
    tax.value = format(subtotal.value * taxRate);

    for (i=0; i << shipping.length; i++)
      if (shipping[i].checked)
        shippingcost = parseFloat(shipping[i].value);

    grandtotal.value = format(parseFloat(subtotal.value) +
                              parseFloat(tax.value) +
                              shippingcost);
  }
}
//-->>
<</script>>
<</head>>
<<body>>
<<form id="myform" name="myform" action="#" method="get">>
Widgets: <<input type="text" name="widgets" id="widgets"
          size="2" value="0" onchange="calc();"
          onkeypress="return isNumberInput(this, event);" />>
         @ 1.50 each
<<input type="text" id="widgettotal" name="widgettotal"
       size="5" readonly="readonly" />>
<<br />>
Gadgets: <<input type="text" name="gadgets" id="gadgets"
          size="2" value="0" onchange="calc();"
          onkeypress="return isNumberInput(this, event);" />>
         @ 2.70 each
<<input type="text" id="gadgettotal" name="gadgettotal"
       size="5" readonly="readonly" />>
 <<br />>
Thingies: <<input type="text" name="thingies" id="thingies"
           size="2" value="0" onchange="calc();"
           onkeypress="return isNumberInput(this, event);" />>
          @ 1.25 each
<<input type="text" id="thingietotal" name="thingietotal"
       size="5" readonly="readonly" />>
 <<br />><<br />><<br />>
<<em>>Subtotal:<</em>> 
<<input type="text" id="subtotal"
       name="subtotal" size="8" value="0" readonly="readonly" />>
<<br />><<br />><<br />>
<<em>>Tax:<</em>> <<input type="text" id="tax" name="tax" size="5"
               value="0" readonly="readonly" />>
<<br />><<br />><<br />>
<<em>>Shipping:<</em>>
Next day: <<input type="radio" value="12.00" name="shipping"
           id="shipping" checked="true" onclick="calc();" />>
2-day: <<input type="radio" value="7.00" name="shipping"
        id="shipping" onclick="calc();" />>
Standard: <<input type="radio" value="3.00" name="shipping"
           id="shipping" onclick="calc();" />>
<<br />><<br />><<br />>
<<strong>>Grand Total:<</strong>>
<<input type="text" id="grandtotal" name="grandtotal"
 size="8" readonly="readonly" />>
<</form>>
<</body>>
<</html>>

Note that the previous example uses field masking to avoid excessive checking of form contents and liberal use of the readonly attribute to keep users from thinking they can modify calculated fields. Also note that, because of JavaScript’s relatively poor numeric formatting, we added in a rudimentary formatting function. Given this basic example, you should see how it is possible to add calculators or other more dynamic form applications to your site.

Note 

As we mentioned in the “Validation Best Practices” section, relying on client-side JavaScript to calculate things like sales tax and purchase cost is not a good idea. Anyone can turn off JavaScript, modify the form to indicate 100 widgets at a cost of one penny each, and then submit. Scripts like the one in our previous example should be used only as a convenience to users, that is, to let them see about how much they’ll be spending before they submit the transaction to the server.


Team LiB
Previous Section Next Section