Demystifying WML (part 2)

An introduction to the WML programming language.

Sweet Like Chocolate

In the first part of this article, we told you all about WML - what it is, where it came from, and why you'd want to use it - and also gave you a quick crash course in the basics. In this concluding part, we'll be taking a look at some of WML's more advanced constructs, including tables, forms and timers.

Boring, huh?

Well, how about if we toss in a couple tons of chocolate ice-cream, and the opportunity to meet your dream date?

There, we knew that would get your attention. Read on to find out what we're talking about...

Turning The Tables

Back in the good old days of HTML 2.0, when Microsoft and Netscape hadn't yet introduced <DIV>s and <LAYER>s, most Web designers relied almost entirely on tables to align and place images, text and other objects on their Web pages. And so, given that WML pages are usually displayed on tiny screens, it's essential that there be some mechanism in place to help WML developers maximize every centimeter of screen real estate.

Enter the <table> tag - albeit in slightly modified form. Take a look at this example, which demonstrates how tables can be used to format WML content.

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
 "http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="intro" title="Welcome">
<p align="center">
    Welcome to IceScream.com!<br/>
    --------------------<br/>
    Your search for the perfect ice-cream ends here...<br/>
    --------------------<br/>
    <a href="#scream1" title="Violent Vanilla">Violent Vanilla</a><br/>
    <a href="#scream2" title="Crazy Chocolate">Crazy Chocolate</a><br/>
    <a href="#scream3" title="Homicidal Honey">Homicidal Honey</a><br/>
</p>
</card>

<card id="scream1" title="Violent Vanilla">

<p align="center">
Violent Vanilla<br/>
--------------------<br/>
<table title="menu1" columns="2">
    <tr>
    <td>
    Scoop
    </td>
    <td>
    4 bucks
    </td>
    </tr>

    <tr>
    <td>
    Cone
    </td>
    <td>
    3 bucks
    </td>
    </tr>

    </table>
</p>

<p align="left">
<a href="#intro" title="back">back</a>
</p>

</card>

<card id="scream2" title="Crazy Chocolate">

<p align="center">
Crazy Chocolate<br/>
--------------------<br/>
<table title="menu2" columns="2">
    <tr>
    <td>
    Scoop
    </td>
    <td>
    2 bucks
    </td>
    </tr>

    <tr>
    <td>
    Cone
    </td>
    <td>
    3 bucks
    </td>
    </tr>

    </table>
</p>

<p align="left">
<a href="#intro" title="back">back</a>
</p>

</card>

<card id="scream3" title="Homicidal Honey">

<p align="center">
Homicidal Honey<br/>
--------------------<br/>
<table title="menu3" columns="2">
    <tr>
    <td>
    Scoop
    </td>
    <td>
    6 bucks
    </td>
    </tr>

    <tr>
    <td>
    Cone
    </td>
    <td>
    8 bucks
    </td>
    </tr>
    </table>
</p>

<p align="left">
<a href="#intro" title="back">back</a>
</p>

</card>

</wml>

Like in HTML, a WML table begins and ends with the <table>... tags; each row is represented by a <tr>...<tr> pair, with each cell further represented by pairs of <td> tags. Unlike in HTML, though, <tr> and <td> tags don't take any attributes in WML - the only attribute you can control is the alignment of a cell, and that information has to be specified in the <table> tag itself with the "align" attribute.

Note, however, that the "align" attribute failed to work in any of the simulators we tried - so you might want to watch out for errors if you decide to use it.

Additionally, unlike HTML [where pretty much anything goes], tables in WML are quite rigid - you need to specify the number of columns in the <table> tag with the "columns" attribute. If the actual number of columns ends up being greater or less than the number specified, cells will end up getting concatenated or inflated by the display device - something that's sure to displease both the author and the user.

Finally, <table> tags cannot be nested within each other in WML.

Do You? You Do!

Before we move on, we're going to spend a couple of paragraphs expounding on the design of mobile phones - specifically, the user interface and navigational aspects of a mobile phone.

Every mobile phone has an extra set of buttons, apart from the numeric keypad, which are used for tasks like initiating calls, terminating conversations, or simply navigating through on-screen menus. Each of these keys has a pre-defined function, and when a user hits these keys, he invokes the mechanisms that run behind the scenes. For example, when a user accepts a call, he invokes the ACCEPT mechanism; when he deletes an entry from his phone book, he uses the DELETE mechanism; and so on.

In order to trap these events, WML provides the <do> element. The <do> element comes with a "type" attribute, used to specify the back-end mechanism to be fired.

The important values of the "type" attribute are:

ACCEPT - invokes the "accept/OK" mechanism

DELETE - invokes the "delete" mechanism

PREV - invokes the "go back" mechanism

HELP - invokes the help mechanism

Of course, mobile phones do come with many other functions too - however, these are the most common ones.

In addition to the "type" attribute, <do> also comes with both "name" and "label" attributes - the label specifies a text string to be displayed on the display device, while the name is a unique identifier for that particular instance of the <do> element.

Of course, trapping an event is only half the story - and so WML also provides a number of "task elements" that allow you to define what happens once the event has been identified and recognized. These task elements include:

<go> - load another card or deck

<prev> - go to the previous deck or card

<noop> - do nothing

<refresh> - refresh the current deck or card

Note that all of these are "empty" tags, and need to be explicitly closed with a forward slash.

A simple example here will demonstrate the use of the <do> element:

<?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="intro" title="teaser">
    <p>
        Would you like to sign in?<br/>
    </p>

    <do type="accept" label="Yes">
        <go href="#entry" />
    </do>

    <do type="accept" label="No">
        <refresh />
    </do>

</card>

<card id="entry" title="welcome">
    <p align="center">
    Like the song goes...you can check in, but you can't check out!
    </p>

    <do type="accept" label="No, let me leave!">
        <prev />
    </do>
</card>
</wml>

In this deck, we've got two cards - the first one sets up a couple of choice, while the second one delivers the punch line. What's interesting here is the three <do> elements - each of them performs a specific task depending on which is selected. The first element activates the "go" task mechanism, and loads the card named "entry", while its counterpart simply refreshes the same card again.

Once the uses hits "Yes", he's taken to the second "entry" card, which also has a <do> element - this one simply takes him back to the previous screen via the <prev> element.

A quick note on the "go" element here - you can also use it to pass values to the server, in much the same way as a form passes name/value pairs to a server-side script. WML gives you the <postfield> element, which can be used to pass data either via GET or POST methods. For example,

<go href="http://www.somewapserver.com/abc.wml" method="post">
<postfield name="id" value="18485">
</go>

would carry out a POST transaction with the URL http://www.somewapserver.com/abc.wml?id=18485

The Perfect Date

OK, enough of all this button-clicking - how about actually getting the user to enter some information? Well, WML comes with a couple of constructs that allow you to ask for, and obtain, text and numeric information from the user - and not surprisingly, they're very similar to HTML's form elements. Here's a simple example:

<?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="question" title="The Lucky One">
<do type="accept">
<go href="#answer"/>
</do>
<p>
Who is your dream date? <br/>
<input name="date"/>
</p>
</card>

<card id="answer" title="Unavailable">
<p>
Sorry, $date is not taking your calls at the moment. Loser!
</p>
</card>
</wml>

As you can see, we've used the <input> element to obtain input from the user - this <input> element is very similar to the one used in HTML forms, although it does have some slightly different attributes.

The "name" attribute specifies the name of the input element - this name can then be used to reference the data entered. at a later stage.

The "type" attribute" specifies the type of text input - your choices are limited to either "type=text" [for clear-text input] or "type=password" [for masked input].

The "format" attribute can be used to control the format of the information entered - you can use this to add decimal signs for currency figures, for example, or enter names in a specific combination of upper- and lower-case letters. There's an example a little further down.

The "size" and "maxlength" attributes control the width and maximum number of characters to be entered into the data entry area, respectively.

In the example above, once the user enters a name and hits the ACCEPT button, the information entered into the form is assigned to a variable named $date; this variable is then used in the next card as part of a larger string. Thus, WML also allows you to pass variables between cards within a deck.

A couple of points to be noted here:

  1. We've mentioned the "format" attribute a little way up - here's an example of how you could use it to define the format in which data is entered:
<?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="question" title="Question">
<do type="accept">
<go href="#answer"/>
</do>
<p>
Enter your birthdate<br/>
<input name="date" format="NN\-NN\-NN" />
</p>
</card>

<card id="answer" title="Answer">
<p>
Don't you think you're the wrong age for a phone as cool as this?
</p>
</card>
</wml>

In this case, we've defined the format of the data to be entered as a series of numbers only - any attempt to enter alphabetic characters here will be rejected by the device.

A complete list of formatting codes is available in the WML specification - take a look if you're interested in this kind of thing.

  1. You've already seen that the dollar [$] symbol is used to represent a variable name in WML. This causes a problem when displaying currency figures printed in dollars. In such cases, you need to enter a double dollar symbol, as in the example below:
<?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="scream1" title="Violent Vanilla">

<p align="center">
Violent Vanilla<br/>
--------------------<br/>
Scoop - $$4.00 <br/>
Cone -  $$3.00 <br/>
</p>

</card>
</wml>

So Many Choices, So Little Time

How about providing the user with a list of options - maybe in a drop-down list - and letting him choose from the list? Sure!

WML provides developers with an <option> element that allows them to give the user a choice of different pre-defined options - take a look:

<?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="step1" title="Step 1">
<do type="accept">
<go href="#step2"/>
</do>
<p>
Are you:
<select name="sex">
<option value="male">Male</option>
<option value="female">Female</option>
<option value="all">All of the above</option>
<option value="none">None of the above</option>
</select>
</p>
</card>

<card id="step2" title="Step 2">
<p>
Nice to meet you! Are you free for dinner tonight?
</p>
</card>
</wml>

Again, the rules that govern the <option> tag are similar to the ones laid down in the HTML language specification. Every <select> item needs a name, which is passed to the next card, and is associated with a value; this name-value pair can also be passed to server-side scripts.

It's also possible to select multiple options from the list - simply add the "multiple" attribute.

<?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="step1" title="Step 1">
<do type="accept">
<go href="#step2"/>
</do>
<p>
Are you:
<select name="sex" multiple="true">
<option value="male">Male</option>
<option value="female">Female</option>
</select>
</p>
</card>

<card id="step2" title="Step 2">
<p>
Nice to meet you! Are you free for dinner tonight?
</p>
</card>
</wml>

You can also store the index values of the selection by setting the "iname" attribute. The example below demonstrates how this works.

<?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="question" title="Index">
<do type="accept">
<go href="#chapter"/>
</do>
<p>
My novel, "Bubble Gum On Mars", is almost complete. Which chapter would
like to read?
<br />
<select name="chapter" iname="chp">
<option value="1">Chapter 1</option>
<option value="2">Chapter 2</option>
<option value="3">Chapter 3</option>
</select>
</p>
</card>

<card id="chapter" title="Chapter">
<p align="center">
Chapter $chp<br />
----------
</p>
<p align="left">
It was a hot and humid evening on Mars. The rebellion had been crushed. It
was time for a change. A new leader was needed. I thought to myself, "Why
not me?". And the galaxy roared in approval.
<br />
[For more exciting inter-planetary adventures, keep visiting our Web site]
</p>
</card>
</wml>

Yes, yes, we know we could have written a far simpler example - but that wouldn't be as much fun, would it?!

Tick, Tick

Next up, the <timer> tag, which allows you to create timed events - for example, executing a default action after a specified period of time.

<?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="timer" title="timer" ontimer="#result">
<timer name="timer" value="100" />
<p>
Ten seconds from now...
</p>
</card>

<card id="result" title="Result">
<p>
...you'll find out what a timer is!
</p>
</card>
</wml>

The <timer> tag needs two things - the amount of time to wait, in tenths of a second, and the action to take once the timer expires. In the example above, we've set the time period to ten seconds, and also specified the name of the card to be loaded. The timer is activated when the card is loaded, and stopped once the card is exited.

Today's Special

Finally, the <template> tag allows WML authors to define task events for all the cards in a deck. For example, authors can set a default action for the ACCEPT task mechanism, which is valid across the entire deck. This ensures that every card is associated with a task mechanism, even though it may not have an explicit definition. Obviously, this default value can be overridden by an explicit card-level definition.

Here's a simple example which demonstrates how this works. We've taken our initial example, and added a template with a default action - loading the second card, or the chocolate ice-cream menu, if the user hits the ACCEPT key on any card without an explicit action definition attached to it.

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
 "http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="intro" title="Welcome">
<p align="center">
    Welcome to IceScream.com!<br/>
    --------------------<br/>
    Your search for the perfect ice-cream ends here...<br/>
    --------------------<br/>
    <a href="#scream1" title="Violent Vanilla">Violent Vanilla</a><br/>
    <a href="#scream2" title="Crazy Chocolate">Crazy Chocolate</a><br/>
    <a href="#scream3" title="Homicidal Honey">Homicidal Honey</a><br/>
</p>
</card>

<card id="scream1" title="Violent Vanilla">

<p align="center">
Violent Vanilla<br/>
--------------------<br/>
<table title="menu1" columns="2">
    <tr>
    <td>
    Scoop
    </td>
    <td>
    4 bucks
    </td>
    </tr>

    <tr>
    <td>
    Cone
    </td>
    <td>
    3 bucks
    </td>
    </tr>

    </table>
</p>

<p align="left">
<a href="#intro" title="back">back</a>
</p>

</card>

<card id="scream2" title="Crazy Chocolate">

<p align="center">
Crazy Chocolate<br/>
--------------------<br/>
<table title="menu2" columns="2">
    <tr>
    <td>
    Scoop
    </td>
    <td>
    2 bucks
    </td>
    </tr>

    <tr>
    <td>
    Cone
    </td>
    <td>
    3 bucks
    </td>
    </tr>

    </table>
</p>

<p align="left">
<a href="#intro" title="back">back</a>
</p>

</card>

<card id="scream3" title="Homicidal Honey">

<p align="center">
Homicidal Honey<br/>
--------------------<br/>
<table title="menu3" columns="2">
    <tr>
    <td>
    Scoop
    </td>
    <td>
    6 bucks
    </td>
    </tr>

    <tr>
    <td>
    Cone
    </td>
    <td>
    8 bucks
    </td>
    </tr>
    </table>
</p>

<p align="left">
<a href="#intro" title="back">back</a>
</p>

</card>

</wml>

In this case, the <template> defines what happens when a user hits the ACCEPT key on any card in the deck without an explicit action attached to it. In the example above, the template specifies that the default card to be loaded is the second menu card, which happens to be chocolate ice-cream.

And on that cheery note, we'll say goodbye. See you soon!

Note: All examples in this article have been tested on Phone.com's UP.SDK 4.0. YMMV!

This article was first published on12 Jul 2000.