Demystifying WMLScript (part 2)

The conclusion of our two-part WMLScript tutorial explores the language’s loops and operators, and also takes a close look at some of the pre-defined functions available to the programmer. Sample WMLScript applications – an email address validator and a currency converter – are also included.

After last week’s introduction to the world of WMLScript, you should have a clearer idea of how WMLScript variables are created and manipulated in the wireless space. In this concluding article, we’ll be exploring WMLScript’s loops, functions and in-built browser libraries, together with a look at some simple WMLScript applications that should get you started on the road to building cool toys for all the yuppies to play with on their cellphones.

Before we begin with loops, however, you need to know about the three important logical operators supported in WMLScript. They are:

the || operator – used to indicate an OR condition

the && operator – used to indicate an AND condition

the ! operator – used to indicate a NOT condition

These operators come in very handy when building compact conditional expressions.

For example, consider this:

if (a == 0 || a == 1) { do this! }
In English, this would translate to “if a equals zero OR a equals one, do this!” But in the case of

if (a == 0 && b == 0) { do this! }
the “do this!” statement would be executed only if a equals zero AND b equals zero.

The third logical operator, the NOT operator, is usually indicated by a prefixed exclamation mark[!], and is used to reverse the sense of a conditional expression. Consider the two examples below:

if (a) { do this! }
In English, “if a exists, do this!”

if (!a) { do this! }
In English, “if a does NOT exist, do this!”

Got that? All righty, let’s move on to loops!

This article copyright Melonfire 2000. All rights reserved.{mospagebreak title=Round And Round…} As you may already know, a loop is a simple programming construct which allows you to repeat a set of program statements over and over again; the number of times the statements are repeated is either dependent on the fulfillment of a pre-defined condition, or fixed in advance. WMLScript allows both types of contortions via the “while” and “for” loops (incidentally, unlike “real” programming languagss like C and Perl, these are the *only* two loops the language supports!)

The syntax of the “while” loop is as follows:

while (condition) { do this! }
Or, to make the concept clearer,

while (rich Aunt Petunia's in a good mood) { hit her for a loan }
The “condition” here is a standard conditional expression, which evaluates to either true or false.

In order to demonstrate this better, take a look at our next example, which asks for a number and calculates the factorial of that number (for those of you who flunked math class, the factorial of a number is the product of that number and all the numbers preceding it, all the way down to 1)

[fact.wml] <?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" ""> <wml> <card id="Factorial" title="Factorial"> <p> Gimme a number: <input format="N*" name="number" /> <br/> The factorial of the number $(number) is $(answer) <do type="accept" label="Calculate"> <go href="fact.wmls#factorial($(number))"/> </do> </p> </card> </wml>
The WML deck above sets up the page which asks the user to enter a number. Once the number has been entered and the user has hit the ACCEPT button, the WML page will call the factorial() function in the file “fact.wmls”

[fact.wmls] // function to calculate factorial extern function factorial(number) { var tempfact = 1; while(number != 1 && number != 0) { tempfact = tempfact * number; number--; } WMLBrowser.setVar("answer",tempfact); WMLBrowser.go("fact.wml#Factorial"); }
The factorial() function accepts a number and uses a “while” loop to count down from that number until it reaches 1. The product is then passed back to the browser via the standard WMLScript libraries.

Note the conditional expression, which ensures that a factorial is not calculated if the number entered is either 0 or 1, and the autodecrement operator –, which is used to reduce the value of the variable “number” by 1 during each iteration of the loop.

This article copyright Melonfire 2000. All rights reserved. {mospagebreak title=For Pete’s Sake} WMLScript also supports that all-time favourite of programmers everywhere, the “for” loop, which is used to execute program statements a specific number of times.

for (initial value of counter; condition; update counter) { do this! }
Doesn’t make any sense? Well, the “counter” here refers to a regular variable that is initialized to a specific numeric value [usually 0 or 1]; this counter is used to keep track of the number of times the loop has been executed.

Each time the loop is executed, the “condition” is tested for validity. If it’s found to be valid, the loop continues to execute and the value of the counter is updated appropriately; if not, the loop is terminated and the statements following it are executed.

In the following example, we’ve rewired the code above to calculate factorials using the “for” loop.

// function to calculate factorial extern function factorial(number) { var tempfact = 1; var counter; for(counter = number; counter != 1; counter--) { tempfact = tempfact * counter; } WMLBrowser.setVar("answer",tempfact); WMLBrowser.go("fact.wml#Factorial"); }
The “for” loop also comes with two additional constructs designed to provide programmers with additional flexibility: the “break” statement, which is used to terminate the loop and execute the statements immediately following the loop; and the “continue” statement, which is used to skip a particular iteration of a loop and jump to the next iteration.

This article copyright Melonfire 2000. All rights reserved.{mospagebreak title=Something Fishy} Now that loops are out of the way, it’s time to tackle user-defined functions, sometimes known as subroutines.

As you’ve seen thus far, WMLScript requires that all code be placed within functions before it can be used in your WML decks. Here’s the typical syntax for such a WMLScript function:

extern function function_name(parameters) { statement 1... statement 2... . . . statement n... }
As you can see, functions are defined with the “function” keyword; this keyword is followed by the name of the function. All the program code attached to that function is then placed within a pair of curly braces – this program code could contain loops, conditional statements, or calls to other functions.

Now, that’s fine and dandy – but you’re probably wondering what the “extern” keyword is doing hanging off the beginning of the definition. Allow us to enlighten you.

Since all WMLScript functions have to be placed in a separate file, it is essential to differentiate between functions which are available to the WML deck, and functions which are not. This is accomplished via the “extern” keyword; a function defined with “extern” can be called from any WML deck, while a function without “extern” can only be called from other functions in the same WMLScript file.

Consider this simple example.

extern function something_fishy(var1,var2) { // code here not_really(var1,var2); //more code here } function not_really(num1,num2) { // code here }
We’ve defined two functions in the above example, one with “extern” and one without. The function something_fishy() can be called from any WML deck; however, the function not_really() cannot be invoked from anywhere outside the file which contains the functions.

WMLScript also provides for the “return” statement, which is used to return a specific value from a function. The following example demonstrates this more clearly:

[fish.wml] <?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" ""> <wml> <card id="fish" title="fish"> <p> So, how big was the fish? <input format="N*" name="number" /> <br/> $(answer) <do type="accept" label="Go"> <go href="fish.wmls#fish($(number))"/> </do> </p> </card> </wml> [fish.wmls] extern function fish(number) { // declare variable var returned; // execute function returned = check_size(number); // return to browser WMLBrowser.setVar("answer",returned); WMLBrowser.go("fish.wml#fish"); } function check_size(size) { // declare variable var response; // check size and return response if (size > 10) { response = "Liar!"; } else { response = "Pretty small, huh?!"; } return response; }
In this case, function fish() receives a number and passes it to the check_size() function. The check_size() function evaluates the number and returns a response to the fish() function via an explicit “return” statement; this response value is then passed back to the WML browser.

This article copyright Melonfire 2000. All rights reserved.{mospagebreak title=What You Get For Free} As you’ve seen thus far, WMLScript comes with standard libraries which provide pre-defined functions to the programmer. A number of such standard functions are available, broken down into various categories, and they come in very handy when carrying out string and mathematical operations, displaying messages to the user and performing other basic functions.

Here’s a quick list of the important functions available in the standard libraries, together with brief descriptions – you’ve already used some of these, while others will become clear to you in the examples on the next page.

Core functions
WMLBrowser.getVar(delta) – get the value of the variable “delta”

WMLBrowser.setVar(delta, something) – assign the value “something” to variable “delta”

WMLBrowser.go(delta) – load WML deck/card “delta”

WMLBrowser.prev() – return to previous card in deck

WMLBrowser.refresh(delta) – refresh WML deck/card

Message functions
Dialogs.alert(phi) – display message “phi”

Dialogs.prompt(phi, default) – display prompt with message “phi” and default input “default”

Dialogs.confirm(phi, yes-message, no-message) – display confirmation dialog box with message “phi” and accept/cancel button text

Math functions
Lang.abs(alpha) – return absolute value of number “alpha”

Lang.min(alpha, beta) – return the smaller of two numbers “alpha” and “beta”

Lang.max(alpha, beta) – return the larger of two numbers “alpha” and “beta”

Lang.isInt(alpha) – returns whether “alpha” is an integer

Lang.isFloat(alpha) – returns whether “alpha” is a floating-point number

Lang.random(alpha) – returns a positive random number between 0 and “alpha” – returns the integer part of “alpha”

Float.round(alpha) – returns the rounded-off value of “alpha”

Float.sqrt(alpha) – returns the square root of “alpha”

String functions
String.length(gamma) – returns the length of the string “gamma”

String.isEmpty(gamma) – returns whether or not the string “gamma” is empty

String.charAt(gamma, n) – returns the nth character from the string “gamma”

String.substring(gamma, n, m) – returns a substring of length “m” starting at character “n” from the string “gamma”

String.find(gamma, pattern) – search for “pattern” in string “gamma”

String.replace(gamma, pattern, newpattern) – replace “pattern” in string “gamma” with “newpattern”

String.trim(gamma) – remove leading and trailing whitespace from string “gamma”

URL functions
URL.isValid(omega) – returns whether or not URL “omega” is valid

URL.escapeString(omega) – URL-encode URL “omega”

URL.unescapeString(omega) – URL-decode URL “omega”

This is not an exhaustive list, just the most important functions. You can get a complete list, with examples, from the WMLScript standard libraries specification, available at the WAP Forum Web site at

This article copyright Melonfire 2000. All rights reserved.{mospagebreak title=Checking Your Mail} Now that you have some idea of the functionality available to you, it’s time to start using it – and so, we’ve put together a couple of simple WMLScript applications that demonstrate the kinds of things you can do with the language.

First up, a simple email address validator. Here’s the form which sets up the input fields…

[mail.wml] <?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" ""> <wml> <card id="mail" title="mail"> <p> Enter email address: <input format="A*" name="email"/> <br/> $(message) <do type="accept" label="Go"> <go href="mail.wmls#verify('$(email)')" /> </do> </p> </card> </wml>

…and here’s the function that validates the address (note that this is very basic validation, and is intended for demonstration purposes only)

[mail.wmls] // function to verify email address extern function verify(emailIn) { // declare variables var flag1 = false; var flag2 = false; var messageSet; var counter; // fix encoded string emailIn = URL.unescapeString(emailIn); // check for null string if(String.isEmpty(emailIn)) { messageSet = "Cannot find email address!"; } else { var emailLength = String.length(emailIn); // check for . and @ characters for(counter = 0; counter < emailLength; counter++) { if(String.charAt(emailIn, counter) == "@") { flag1 = true; } if(String.charAt(emailIn, counter) == ".") { flag2 = true; } } // display message if((flag1 == false) || (flag2 == false)) { messageSet = "Invalid email address!"; } else { messageSet = "Thank you!"; } } // return result to page WMLBrowser.setVar("message",messageSet); WMLBrowser.go("mail.wml#mail"); }
In this case, once the function receives a string, it first checks to make sure that the string is not empty. Once this test is satisfied, it parses the string character by character (using a “for” loop) in search of the “@” and “.” characters, and displays an appropriate message on the screen.

Note the manner in which the various string functions have been used to perform the validation.

This article copyright Melonfire 2000. All rights reserved.{mospagebreak title=The Money Market} And finally, one more simple – and very useful – application: a currency converter that allows you to convert dollar amounts to any of three other currencies. Check it out, and feel free to add more currencies to the list!

[convert.wml] <?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" ""> <wml> <card id="converter" title="Converter"> <p> Enter amount(USD): <br /> <input format="*N" name="amount" /> <br /> Convert to: <br /> <select name="list"> <option value="GBP">British Pound</option> <option value="DEM">German Mark</option> <option value="INR">Indian Rupee</option> </select> <do type="accept" label="Go"> <go href="convert.wmls#calculate('$(amount)', '$(list)')" /> </do> </p> </card> <card id="result" title="Result"> <p> USD $(oldamt) is $(currency) $(newamt) </p> </card> </wml>

[convert.wmls] // function to perform conversion extern function calculate(amt, curr) { // set up rates var gbp_rate = 0.70; var dem_rate = 2.25; var inr_rate = 43.72; var result; // perform calculation if (curr == "GBP") { result = amt * gbp_rate; } else if (curr == "DEM") { result = amt * dem_rate; } else if (curr == "INR") { result = amt * inr_rate; } // return result to page WMLBrowser.setVar("newamt",result); WMLBrowser.setVar("oldamt",amt); WMLBrowser.setVar("currency",curr); WMLBrowser.go("convert.wml#result"); }

Here, too, a list box is used to provide the user with a list of currencies – the selected currency and the amount entered are then passed to the calculate() function, which sets up conversion rates and performs the conversion based on the currency selected. A new card is then loaded from the deck with the result of the conversion.

And that’s about it for this article. Keep checking back for more from the wireless world!

This article copyright Melonfire 2000. All rights reserved.
[gp-comments width="770" linklove="off" ]

chat sex hikayeleri Ensest hikaye