September 19, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Learning WML - Building Gadgets

  • December 10, 2002
  • By Steve Schafer
  • Send Email »
  • More Articles »

It is easy to fall into the trap of looking only for killer applications to deploy via mobile devices. Integration with other services, online databases, etc. are all worthy applications to code and offer via wireless connections. However, you shouldn't overlook the smaller, single-function applications that users might find useful or even necessary.

From Merriam-Webster's Online Collegiate. Dictionary ( http://www.webster.com/):
Gadget - an often small mechanical or electronic device with a practical use but often thought of as a novelty

My current phone has several gadgets—a calculator, a calendar, etc. Each of these makes the phone a bit more useful since I carry it with me all the time. True, it doesn't replace a PDA or other device loaded with such functionality and utility, but I find having these features a great addition to the phone.

However, not all phones have these gadgets built in. This article will create one such gadget: a tip calculator. Along the way we will explore different ways to accept user input as well as some variable-type artifacts of WMLScript.

Note: Creating online gadgets presents a tradeoff for users; although they gain the utility of the gadget, they must use airtime/online time to use it. Keep this in mind when creating such applications and strive to keep their uses simple and short.

Building a Tip Calculator

A few people I know carry a "tip card" with them to easily compute the correct amount of their tip to leave at a restaurant. This card gives whole dollar amounts and the representative percentage thereof, in 10%, 15%, and 20% values. A quick-and-dirty gadget can be implemented via WML and WMLScript to accomplish the same thing.

Description of Project

This project is very straightforward-—accept a dollar amount and display 10, 15, and 20 percent of the value entered. As an added benefit, the application should display the total of the dollar amount and tip amount.

Data Entry

To enter the amount, we can simply use a WML INPUT tag. For example, the following code snippet would do:

<card>
  <p>
  <input
name="amount"/>
  </p>
</card>

To make the data input easier for the user, we could add a format parameter to the INPUT tag to specify that the input should be numeric:

  <input name="amount" format="*N">

However, this format specification doesn't allow for symbols, namely a decimal point. The available format codes for the format parameters do not include a format with both numbers and symbols, but without letters. So we can choose from several options for getting the dollar amount from the user:

  1. We can leave out the format, leaving the user to utilize the device's options for changing to number/symbol input as required.
  2. We can have the user round to the nearest dollar and enter only whole numbers.
  3. We can preformat the data entry, specifying that one of the characters is a decimal point. For example: format="NNN.NN".
  4. We can have the user enter the whole number and decimal amounts separately.

Each of these options has a downside:

  1. If the amount isn't easy to enter, the user won't be apt to use the gadget. (Also consider the online time for using the gadget.) Most devices don't exactly make it easy to switch between numbers and symbols.
  2. Rounding to the nearest dollar won't be exact and won't allow us to display a total (amount + tip).
  3. Specifying an exact mask requires the user to follow the mask exactly, entering more data than sometimes required. For example, in our example mask ("NNN.NN"), the user must preface any amount under $100 with a zero (e.g., "090.00") to fit the mask.
  4. Entering two separate amounts, one for the whole number portion and the other for the decimal, isn't intuitive.

For this example, we will use the fourth option, entering two numbers-one for the whole portion and one for the decimal:

  <p>
    <!-- Get whole and decimal amounts separately
      to aid user input -->
    Enter amount:<br/>
    <input name="checkamt" format="*N"/><br/>
    .<br/>
    <input name="checkdec" format="*N"/>
  </p>

With the code above, the user enters the whole amount, presses ACCEPT, enters the decimal amount, and presses ACCEPT again. Although not intuitive, the data input process is very streamlined.

The input screen. Note how the decimal is displayed (on the left side, between the two text boxes) to help the user understand the screen.

Image is courtesy Openwave Systems Inc. (Openwave, the Openwave logo, Openwave SDK, Openwave SDK Universal Edition, Openwave SDK WAP Edition are trademarks of Openwave Systems Inc. All rights reserved.)

Combining the Input

Our approach for accepting input has one disadvantage; we have to combine the input to obtain the full amount. This only takes a simple WMLScript that gets the amounts from the WML code, combines them, and returns the amount to the script.

Consider the following:

WML
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
  "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
  <card id="input">
    <do type="accept">
      <go href="test.wmls#calc()"/>
    </do>
    <p>
    Enter amount of check in dollars and cents:<br/>
    <input name="num" format="*N"/><br/>
    .<br/>
    <input name="dec" format="*N"/>
    </p>
  </card>
 
  <card id="result">
    <p>
    Result is: $(result)
    </p>
  </card>
  
</wml>
WMLScript
extern function calc() {
  
var num = WMLBrowser.getVar("num");
var dec = WMLBrowser.getVar("dec");
var result;
  
dec = dec / Float.pow(10,String.length(dec));
result = num + dec;
  
WMLBrowser.setVar("result",result);
WMLBrowser.go("junk.wml#result");
}

We can reduce the amount of computation necessary to derive the total by using the dynamic nature of variable typing in WMLScript. Essentially, if we force WMLScript to treat the variables as strings, creating the total is as easy as this:

result = num + "." + dec;

Note: If no decimal amount was entered (variable "dec" is empty), the result variable will have a trailing period (.).

Displaying the Results

Now that we have the amount, a handful of additional computations will give us the results to display for the user. We need to figure 10%, 15%, and 20% of the amount and total each percentage with the amount:

// Add whole and decimal to get check amount
check = check + "." + dec;
  
// Calculate tip at 10%, 15%, 20% and totals for each amt
tip10 = check * .1;
tip15 = check * .15;
tip20 = check * .20;
amt10 = Lang.parseFloat(check) + Lang.parseFloat(tip10);
amt15 = Lang.parseFloat(check) + Lang.parseFloat(tip15);
amt20 = Lang.parseFloat(check) + Lang.parseFloat(tip20);

Note: I've replaced the generic variable name "num" with the variable name "check" above.

Notice the use of the Lang.parseFloat function. This helps ensure that WMLScript treats the amounts as floating-point numbers instead of strings. Otherwise, given these two numbers:

  check = 17.35
  tip10 = 1.735

we end up with this:

  amt10 = 17.351.735

which is the concatenation of the variables as strings, instead of their addition as floating points.

Finally, the WMLScript needs to push the variable values to WML and call a display card:

// Push values to WML
WMLBrowser.setVar("check",check);
WMLBrowser.setVar("tip10",tip10);
WMLBrowser.setVar("amt10",amt10);
WMLBrowser.setVar("tip15",tip15);
WMLBrowser.setVar("amt15",amt15);
WMLBrowser.setVar("tip20",tip20);
WMLBrowser.setVar("amt20",amt20);
  
// Call total card
WMLBrowser.go("tipchart.wml#tipamount");
}

The Completed Code

tipchart.wml

<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
  
<wml>
  
  <!-- Get amount of check and pass to calculator -->
  <card id="checkamount" title="TipCalculator">
  <onevent type="onenterforward">
    <!-- Clear previous values -->
    <refresh>
      <setvar name="checkamt" value=""/>
      <setvar name="checkdec" value=""/>
    </refresh>
  </onevent>
  
  <!-- Call calculator when amounts have been entered -->
  <do type="accept">
    <go ref="tipchart.wmls#calctip()"/>
  </do>
  <p>
    <!-- Get whole and decimal amounts separately
      to aid user input -->

    Enter amount of check in dollars and cents:<br/>
    <input name="checkamt" format="*N"/><br/>
    .<br/>
    <input name="checkdec" format="*N"/>
  </p>
  </card>
  
  <!-- Display tip amounts and totals -->
  <card id="tipamount">
  <do type="accept">
    <go href="#checkamount"/>
  </do>
  <p> 
    Check Amount: $(check)<br/>
    10% -$(tip10)<br/>
&nbsp;&nbsp;= $(amt10)<br/>
    15% -$(tip15)<br/>
&nbsp;&nbsp;= $(amt15)<br/>
    20% -$(tip20)<br/>
&nbsp;&nbsp;= $(amt20)<br/>
  </p>
  </card>
  
</wml>

tipchart.wmls

// Tip Calculator script
  
// calctip - calculate tip amount from values entered
extern function calctip() {
  
// Get check amount (and decimal portion) from WML
var check = WMLBrowser.getVar("checkamt");
var dec = WMLBrowser.getVar("checkdec");
  
// Init tip and total vars
var tip10, tip15, tip20, amt10, amt15, amt20 = 0;
  
// Add whole and decimal to get check amount
check = check + "." + dec;
  
// Calculate tip at 10%, 15%, 20% and totals for each amt
tip10 = check * .1;
tip15 = check * .15;
tip20 = check * .20;
amt10 = Lang.parseFloat(check) + Lang.parseFloat(tip10);
amt15 = Lang.parseFloat(check) + Lang.parseFloat(tip15);
amt20 = Lang.parseFloat(check) + Lang.parseFloat(tip20);
  
// Push values to WML
WMLBrowser.setVar("check",check);
WMLBrowser.setVar("tip10",tip10);
WMLBrowser.setVar("amt10",amt10);
WMLBrowser.setVar("tip15",tip15);
WMLBrowser.setVar("amt15",amt15);
WMLBrowser.setVar("tip20",tip20);
WMLBrowser.setVar("amt20",amt20);
  
// Call total card
WMLBrowser.go("tipchart.wml#tipamount");
}

The user enters the amount of the check. . .

And receives three escalating tip amounts and related totals.

Images are courtesy Openwave Systems Inc. (Openwave, the Openwave logo, Openwave SDK, Openwave SDK Universal Edition, Openwave SDK WAP Edition are trademarks of Openwave Systems Inc. All rights reserved.)

Note the addition of an initialization <REFRESH> event on the "checkamount" card. This ensures that the variables are cleared whenever this card is called, whether the first time through the code or via the "results" card.

Room for Improvement

Of course, there's always room for improvement. In this case, rounding the tip amounts to the nearest cent would be handy. This can't be accomplished directly with the Float.round WMLScript function, which only rounds to the nearest integer. The round function can be used if the decimal is moved, round is used, and then the decimal is moved back. (multiply the amount by 100, add .5, round to nearest integer, divide by 100)

What Do You Want from WML?

I'm interested in hearing what you need/want to do with WML. I'll use some of the more challenging or common ideas in upcoming articles. Send your ideas to the address below.

About the Author

Steve Schafer is chief operating officer of Progeny Linux Systems, a Linux-based consulting company in Indianapolis, Indiana. He has written several technical books and articles and can be reached at sschafer@synergy-tech.com.


This series of articles describes how to provide Web content to mobile devices through WML (Wireless Markup Language). This article covers creating small programs extending the functionality of mobile devices.

Note: These articles cover WML and WMLScript version 1.1, which are supported by the majority of mobile devices in use today. The articles assume a working knowledge of HTML and general Web technologies, and further assume that you have read the previous article(s) in this series.

# # #






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel