Introduction to WMLAfter installing these emulators, you are ready to make the first steps in WML programming. First, you have to remember what was already true for HTML: WML is a markup language, not a programming language. It provides the structure of a document. The rendering, however, is the job of the WAP browser. That means you cannot achieve a layout that is 100% consistent over all browsers and platforms. Given the small size of most displays, it is not exactly how a page looks that is important, but whether all information is clearly readable. Whereas with HTML, you can apply some tricks to force browsers into a representation of the content exactly as planned (using CSS, for instance), WML does not offer this capability, nor is it worth any effort. Always consider that your users pay a lot of money to their providers to access your content, so minimize redundancies and let users progress to the content quickly and easily. WML StructureThe most important, and unusual, aspect of WML is the structure of a WML document. Basically, it is pure XML, so using your favorite XML editor is just fine. However underneath the hood, one WML document is called a deck. Within this deck, there exists one or more cards. The analogy to gambling is appealing and intentional. Each card is a document that can be displayed within a WAP browser. Imagine a spreadsheet document: It is one document (deck) consisting of various single sheets (cards) that can be connected with each other. One of the reasons why this structure has been chosen lies in the low connection speed. Surfing a WAP page is expensive; however, the connection is established only on demand. So on many WAP pages, the deck returned from the server does not only contain the card with the home page, but also some other cards with additional pages. When a user requests one of those already available pages, they are not loaded from the server, they are already there and are displayed immediately, without recurring online cost. The basic structure of the WML page is as follows: <?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.2//EN" "http://www.wapforum.org/DTD/wml12.dtd"> <wml> <head> <!-- (optional) head section --> </head> <template> <!-- (optional) template section --> </template> <card id="card1" title="my card"> <!-- Card 1 --> </card> <card id="card2"> <!-- Card 2 --> </card> </wml> The first line of code identifies the document as an XML document. The DOCTYPE declaration that follows in line 2 uses the DTD for WML version 1.2 (other, minimally changed versions 1.1 and 1.3 also exist). These two XML elements are mandatory and appear on each WML document:
When a WML document is loaded in the browser, the uppermost card is activated and displayed automatically. Thus, the home page of your WAP site usually lies in the first card of the first deck the server returns to the client. TextDo you know HTML? Then you know a little bit about WML. Do you know XHTML strict? Then you know a lot about WML. One of the set of strict HTML rules is that all text has to be put within paragraphs, <p> elements. This is true for WML as well. A line break can be achieved using <br/>. The slash at the end is important. In XHTML (and in WML, too), each element must be closed. Thus <br> is not valid, <br></br> or the shorter <br/> is valid. Thus, here is probably your very first WML documentone in a series of many (see Listing 19.1 and its output in Figure 19.4): Listing 19.1. A Simple WML Page<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.2//EN" "http://www.wapforum.org/DTD/wml12.dtd"> <wml> <card id="card1"> <p> WML is easier than I thought. <br/> Really! </p> </card> </wml> Figure 19.4. A simple WML page.Some characters have to be expressed using special entities. Examples for such characters are angle brackets. They fulfill a special meaning in XML; thus, they have to be provided in an alternative way. Table 19.1 is a complete list of entities predefined in the WML DTD:
The provided text can be formatted in various ways. For formatting purposes, WML offers the elements shown in Table 19.2:
Listing 19.2 is a sample that uses these options: Listing 19.2. Text Formatting<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.2//EN" "http://www.wapforum.org/DTD/wml12.dtd"> <wml> <card id="card1"> <p> Text can be made <b>b(old)</b>, <big>big</big>, <em>em(phasized)</em>, <i>i(talic)</i>, <small>small</small>, <strong>strong</strong>, or <u>u(nderlined)</u>. <br/> Really! </p> </card> </wml> However, not all browsers support all these formatting options. Figure 19.5 shows the output in the 3330 Nokia simulatoryou see no formatting at all. Figure 19.5. Text formattingbut the Nokia simulator does not implement this.LinksOne of the most important aspects on a Web page is linkingotherwise, you would have to put all information on one page. As with HTML, linking is done with the <a> element, and the href attribute contains the target of the link. Between <a> and </a>, the link text is provided: <a href="newpage.wml">click me!</a> However, when directly linking to a WML page, the uppermost card is openedsomething that is not always desirable. However, WML offers something for that, too. Using the hash symbol, you can directly link to a card on a decklike you do with anchors in an HTML page. After the hash, you provide the value of the ID attribute of the card, its identifier: <a href="newpage.wml">first card on the deck newpage.wml</a> <a href="newpage.wml#card2">card with id "card2" on the deck newpage.wml</a> <a href="#card3">card with id "card3" on the current deck</a> The following example (see Listing 19.3) is our first deck with more than one card. All three cards are connected with each other using links: Listing 19.3. Three Cards, Linked with Each Other<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.2//EN" "http://www.wapforum.org/DTD/wml12.dtd"> <wml> <card id="php3" title="PHP3"> <p> PHP 3 was really good. </p> <p> <a href="#php4">PHP4</a><br /> <a href="#php5">PHP5</a> </p> </card> <card id="php4" title="PHP4"> <p> PHP 4 was even better. </p> <p> <a href="#php3">PHP3</a><br /> <a href="#php5">PHP5</a> </p> </card> <card id="php5" title="PHP5"> <p> PHP5 is a revolution (some fanatics say). </p> <p> <a href="#php3">PHP3</a><br /> <a href="#php4">PHP4</a> </p> </card> </wml> On your WAP browser, you can now jump from card to card (see Figure 19.6). Depending on the mobile phone, a link can be activated using one or more of the buttons on the device. Figure 19.6. Card two of three.
GraphicsOne critical aspect of WML is the use of graphics. Even nowadays, most displays do not support colors, and transferring huge graphics using a slow WAP connection will not put your users in a good mood. To avoid this as much as possible, a special format for wireless Web access has been created, WBMP. The acronym stands for Wireless Bitmap, and it is basically a BMP file using only one color (no grayscale). Most of the time, to create such bitmaps, you (or the person responsible for graphics on your website) do not need any special downloads. Starting with version 7.0, Adobe Photoshop enables you to export graphics in WBMP format. If you have previously installed the Nokia Mobile Internet Toolkit, you can also create WBMP graphics from within the application. Just choose the menu command File, New, WBMP Image. For other software products, filters exist. A Windows-only converter from standard graphics format to WBMP is available at http://www.gingco.de/wap/.
Before creating or converting a graphic, do consider that the graphics will not look as crisp as you might be used to from your website. Only one available color (black) is not much. Also, remember that displays are small, so try to shrink your company logo so that it fits. Figure 19.7 shows the PHP logo as WBMP. Figure 19.7. The PHP logo as WBMP.After you have created the graphic, you can embed it into your WML page using the <img> element. The attributes shown in Table 19.3 are possible:
There are other attributes; however, these are the most important ones. Listing 19.4 inserts a graphic in a WML page; Figure 19.8 shows the result. Listing 19.4. A WML Page with a Graphic<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.2//EN" "http://www.wapforum.org/DTD/wml12.dtd"> <wml> <card id="card1"> <p> This book was published by <img src="sams.wbmp" alt="SAMS" />. </p> </card> </wml> Figure 19.8. The Sams logo as WBMP graphic.WML FormsOne of the most important features of all browser-based markup languages are forms. Most of the time, forms are the only possibility for an interaction between a website/WAP site and the user. They let users enter text information or let them choose between a number of alternatives. WML supports the following set of form elements:
Text and Password FieldsAs previously mentioned, entering text or even passwords is not as easy with mobile devices as it is on a desktop computer with an actual keyboard. However, situations exist where text must be enteredthe account number and PIN for entering your bank's WAP brokerage system, for instance, or the TAN required for each transaction. No matter whether it's a text field or a password field, the markup tag used is <input type="text">. The following attributes can be used (see Table 19.4):
If you would like to allow users to enter their ZIP code, for instance, into a WAP form, the following code represents the text field for this task: <input type="text" name="zip" size="5" maxlength="5" title="ZIP code" value="00000" format="NNNNN"/> Following is the code for a four-digit PIN, implemented using a password field: <input type="password" name="PIN" size="4" maxlength="4" title="your PIN" format="NNNN"/> Listing 19.5 is a complete listing, a login page for a (fictitious) online banking application: Listing 19.5. A Fictitious Login Page<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.2//EN" "http://www.wapforum.org/DTD/wml12.dtd"> <wml> <card id="login"> <p> Account #: <input type="text" name="Account" size="10" title="your account number"/> <br/> PIN: <input type="password" name="PIN" size="4" maxlength="4" title="your PIN" format="NNNN"/> </p> </card> </wml> Depending on the WML browser used, the display of these form elements may vary, especially when you're entering text into the password field. For instance, some browsers always display the character you currently enter, whereas all other characters in the text are masked using the asterisk (or a similar) symbol. Figure 19.9 shows the Nokia simulator. Figure 19.9. One text field, one password field.Selection Lists, Option Buttons, and Check BoxesWML is rather simple; one proof for that is that all remaining form elements are represented by the same element: <select>. The various elements in this selection list (or group of option buttons or check boxes) are assigned using the <option> element. Again, the similarities to HTML are striking. Basically, all kinds of selection lists are the same. The only difference, apart from the display and design, is how many elements may be selected at the same time. Whereas from a group of option buttons only one element may be selected, this restriction does not apply for check boxes, where an arbitrary number of elements can be checked. Selection lists offer both wayseither one element is selectable at one time, or as many times as the user desires. The two attributes of <select> shown in Table 19.5 are the most widely used ones:
The <option> element also has two useful attributes; however, they are completely optional: Listing 19.6 is a complete WML page with two lists that are shown in Figure 19.10. In the first one, up to four elements may be selected; in the second list, only one. Listing 19.6. Two WML Selection Lists<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.2//EN" "http://www.wapforum.org/DTD/wml12.dtd"> <wml> <card id="form"> <p> You have used ... <select name="earlier" multiple="true"> <option title="PHP/FI" value="php2">PHP/FI 2</option> <option title="PHP 3" value="php3">PHP 3</option> <option title="PHP 4" value="php4">PHP 4</option> <option title="PHP 5" value="php5">PHP 5</option> </select> <br/> You are currently using ... <select name="currently" multiple="false"> <option title="PHP/FI" value="php2">PHP/FI 2</option> <option title="PHP 3" value="php3">PHP 3</option> <option title="PHP 4" value="php4">PHP 4</option> <option title="PHP 5" value="php5">PHP 5</option> </select> </p> </card> </wml> Figure 19.10. The multiple selection list.
Grouping Form ElementsWhen you're designing a selection list with a lot of entries, the list can get quite long. Then it might be a good idea to bring these elements into a hierarchy and group them. Instead of one <option> element, you use an <optgroup> element (a descriptive title in an attribute title). Within this "options group," you place your <option> elements. The following listing (Listing 19.7) shows a list consisting of 10 elements, but they are grouped into three categories (see the browser output in Figure 19.11): Listing 19.7. Grouped Form Elements<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.2//EN" "http://www.wapforum.org/DTD/wml12.dtd"> <wml> <card id="form"> <p> Scripting technologies you are using <select name="scripting" multiple="true"> <optgroup title="PHP"> <option title="PHP/FI" value="php2">PHP/FI 2</option> <option title="PHP 3" value="php3">PHP 3</option> <option title="PHP 4" value="php4">PHP 4</option> <option title="PHP 5" value="php5">PHP 5</option> </optgroup> <optgroup title="Open Source"> <option title="Perl 5" value="perl5">Perl 5</option> <option title="Perl 6" value="perl6">Perl 6</option> <option>Ruby</option> </optgroup> <optgroup title="Closed Source"> <option>ASP</option> <option title="ASP.NET/C#" value="aspnet_cs">ASP.NET with C#</option> <option title="ASP.NET/VB.NET" value="aspnet_vb">ASP.NET with VB.NET</option> </optgroup> </select> </p> </card> </wml> Figure 19.11. The list of groupslist elements are displayed upon clicking the soft key.Processing Form DataWithin WML, you have a limited support for variables. Variable names start with the dollar sign; for compatibility reasons, the actual variable name should be enclosed in parentheses: $(var_name). When a form field is filled with a value, a variable is created. Its name is the name attribute of the form field; its value is the text entered (or the element selected) in the form element. Thus, the following approach for simple form data processing is effective:
The third step, printing out the values of the form variables, is astonishingly simple: just use $(var_name). If you want to make sure that all special characters are escaped, append :e (short for :escape) to the variable name: $(var_name:e). Unfortunately, semicolons are also escaped. In the next example, we do not escape semicolons (in $(earlier)).
Listing 19.8 is a complete example; Figure 19.12 shows the output of this code. The user enters data that is displayed on the second card: Listing 19.8. Form Input Is Displayed<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.2//EN" "http://www.wapforum.org/DTD/wml12.dtd"> <wml> <card id="form"> <p> Your name is ... <input type="text" name="name"/> <br/> You have used ... <select name="earlier" multiple="true"> <option title="PHP/FI" value="php2">PHP/FI 2</option> <option title="PHP 3" value="php3">PHP 3</option> <option title="PHP 4" value="php4">PHP 4</option> <option title="PHP 5" value="php5">PHP 5</option> </select> <br/> You are currently using ... <select name="currently" multiple="false"> <option title="PHP/FI" value="php2">PHP/FI 2</option> <option title="PHP 3" value="php3">PHP 3</option> <option title="PHP 4" value="php4">PHP 4</option> <option title="PHP 5" value="php5">PHP 5</option> </select> <br/> <a href="#output">Send form data</a> </p> </card> <card id="output"> <p> Hello, $(name:e)! <br/> You have used $(earlier). <br/> But you are currently using $(currently:e). </p> </card> </wml> Figure 19.12. The form input data appears on the second card.However, there is no way you can add some additional page logic to this script. Especially, you cannot break down the cryptic string for the selected list elements (the values, separated by semicolons) into something more readable. This can be done server side, and we do that with PHP. Sending Form Data Server SideThere are two ways to transfer data to a server-side script:
In general, the POST method is preferred because GET is limited to 5002000 characters (depending on the user's Web server). However, GET can be achieved appealingly simply: <a href="scriptname.php?name=$(name:e)&currently=$(currently:e)">send data</a>
For POST, you need two new elements. First, use <postfield> elements. They are like hidden form elements in HTML with name and value attributes. Set the values using WML variables: <postfield name="name" value="$(name:e)"/> <postfield name="currently" value="$(currently:e)"/> Then use the <anchor> element to make these <postfield> elements part of the link. They are then submitted as part of the HTTP request for the linked URL. To do so, enclose the <postfield> elements in a <go> element within the <anchor> element: <anchor> <go href="scriptname.php" method="post"> <postfield name="name" value="$(name:e)"/> <postfield name="currently" value="$(currently:e)"/> </go> Send form data </anchor> Listing 19.9 is a complete example, using both methods: Listing 19.9. Form Data Is Sent to a PHP Script<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.2//EN" "http://www.wapforum.org/DTD/wml12.dtd"> <wml> <card id="input" title="input"> <p> Your name is ... <input type="text" name="name"/> <br/> You have used ... <select name="earlier" multiple="true"> <option title="PHP/FI" value="php2">PHP/FI 2</option> <option title="PHP 3" value="php3">PHP 3</option> <option title="PHP 4" value="php4">PHP 4</option> <option title="PHP 5" value="php5">PHP 5</option> </select> <br/> You are currently using ... <select name="currently" multiple="false"> <option title="PHP/FI" value="php2">PHP/FI 2</option> <option title="PHP 3" value="php3">PHP 3</option> <option title="PHP 4" value="php4">PHP 4</option> <option title="PHP 5" value="php5">PHP 5</option> </select> <br/> Send form data <a href="scriptname.php?name=$(name:e)&earlier=$(earlier:e)&currently=$ |