Home > Articles > Networking > Wireless/High Speed/Optical

WMLScript

Tutorial

This section illustrates a few common uses of WMLScript, including validation, user interaction, formatting, calculations, and telephone operations. We show how simple procedural logic and library functions can enhance an existing WML application.

When adding WMLScript to your application, you can use the following steps:

  1. Decide on a name for your WMLScript compilation unit (file), and create a file with this name plus a comment header in the file that describes the file's functionality.

  2. Declare public functions that are to be accessible from WML or other WMLScript as extern.

  3. Build one function at a time, and unit test these functions using a test WML deck that invokes each function. Make use of debug statements in your code using print statements such as the Console print functions provided by the Phone.com simulator.

  4. Create private functions to support the public functions.

  5. We used the Phone.com UP Simulator (version 4.0), available from www.phone.com, to test our application. To run WMLScript functions, simply load the test deck that contains the calls to your functions as you would any WML deck. For example, to load a local WML deck on the C drive, you would enter something like this in the Go area: file://c:/wap/tutorial/mydeck.wml.

Error Handling

WMLScript does not provide an exception-handling mechanism like that found in Java and other heavier-weight languages. You should be careful when testing your WMLScript programs to exercise all the branches of your scripts during testing. Common coding mistakes that can lead to errors include these:

  • Using invalid variables in calculations

  • Dividing by zero

  • Using integers where floats are expected, and vice versa

  • Nesting functions too deeply (the stack memory is very limited on many handsets)

Predictable errors, such as user errors, should be trapped, and a consistently formatted error message should be displayed along with a means to cancel or continue as appropriate.

The Tutorial Application

The application that we will use for our tutorial is an extension of the health inspection system introduced in the Wireless Markup Language articles. We will add functionality to the kitchen inspection cards to calculate the size of the kitchen and to validate the information entered about the kitchen (for example, to ensure that there are enough fans to ventilate a kitchen of the specified size). The complete WML and WMLScript for this application is found here.

The size of the kitchen will be determined from its length and width (assuming that the kitchen is rectangular). For this, we will need a function called area that accepts length and width parameters and that sets the area in a WML Browser variable. We need to declare this function inside a compilation unit and will call this file kitcalc1.wmls, where the wmls extension stands for WMLScript:

/* Health Inspection Application 
   Kitchen calculations
*/

// Calculate the area of a rectangle and go to
// the results card
extern function area(length, width) {
  var area = length * width;  
  WMLBrowser.setVar("area", area);
  WMLBrowser.go("#Results");
};

The WMLScript begins with a block comment describing this compilation unit. This is followed by the area function with its own comments. This is a public function (using the extern keyword), and it accepts parameters for length and width. It allocates a variable area and assigns the results of multiplying length by width to this variable. It then sets the area variable in the browser context and returns control to the browser at the Results card within the calling deck (relative URL #Results). Note the use of a semicolon to terminate the function declaration (`};').

Following our own advice, we create a WML deck to test our new function. Initially this will contain two cards, Enter and Results. Note that the XML prologue has been omitted for clarity:

<wml>
  <!--Kitchen Functions Test Deck--> 
  <card id="Enter" newcontext="true">
    <do type="accept" label="Submit">
      <go href="kitcalc.wmls#area($length, $width)"/>
    </do>
    <p>
      <strong>Enter Kitchen Size</strong><br/>
      Length (m): <input name="length" format="N*N"/>
      Width (m): <input name="width" format="N*N"/>
   </p>
  </card>

  <card id="Results">
    <do type="accept" label="Another">
      <go href="#Enter"/>
    </do>
    <p>
      Area is: $area sq.metres<br/>
    </p>
  </card>
</wml>

The Enter card prompts the user to enter the size of the kitchen, storing the input in length and width variables. Note the use of the N*N format mask attribute to force entry of at least one digit. This card defines an accept event handler that invokes the area function in the kitcalc.wmls file. The newcontext attribute ensures that the length and width variables will be cleared every time this card is displayed. The second card, Results, displays the area browser variable, relying on the WMLScript to set this variable and transfer control to this card. It defines an event handler that allows the tester to enter another kitchen size. Figure 1 displays these cards.

Figure 1 area test deck

The next thing we need to do is to create a function that validates the items that a health inspector notes about a kitchen. We will call this function validate and will pass it the values entered on the inspection card. For now, we will just validate the lighting and ventilation values.

/* Validate light and fans for the specified area
   Light minimum is measured at counter level
   for preparation area (550 LUX)
   Assume fan averages 500 cubic metres/hour,
   kitchen ceiling is 2.5 metres high, and we need
   8 complete air changes per hour:
     # of fans = (room volume * 8) / 500  or
                 (room area / 25)
*/
extern function validate(area, light, fans) {
  // valid values
  var validLight = 550; // LUX measured at counter height
  var validFans = Float.ceil(area / 25); // see above
  var warning = "";

  // build warning message if required
  if (light < validLight)
    warning += "Light is < " + validLight + " lux. ";
  if (fans < validFans)
    warning += "Should have at least " + validFans + " fans. ";

  // return to the appropriate card in the calling deck
  if (warning == "") { // no problems
    WMLBrowser.setVar("validLight", validLight);
    WMLBrowser.setVar("validFans", validFans);
    WMLBrowser.go("#OKResults");
  }
  else {
    // update browser context with warning
    WMLBrowser.setVar("warning", warning);
    WMLBrowser.go("#Warnings");
  };
}; 

First we declare some variables that are set to the valid minimum values for light and number of fans. To calculate how many fans are needed, the area is divided by 25 (see the code for an explanation of this number). Note the use of the ceil function from the Float library, which ensures that we always round up (for example, 26 square metres will require two fans). The next statement initializes a warning string that is added to depending on whether the light meets the minimum standard (550 LUX) and whether the number of fans is at least that required. The final block tests to see whether we have any warnings and, if there are no problems, sets the valid values in the browser context so that they may be displayed for reference on the OKResults card. If there are problems, the warning text is set in the browser context, and control is transferred to the Warnings card.

To test this we need to add some cards to the test.wml deck. First, we will add a new card that allows us to select which WMLScript function to test:

We rename the Enter card from our previous test deck to EnterLogin and add a new card to enter inspection values (EnterValues):

<card id="EnterValues" newcontext="true">
  <do type="accept" label="Validate">
    <go href="kitcalc.wmls#validate($area, $light, $fans)"/>
  </do>
  <p>
    <strong>Enter Values</strong><br/>
    Area (sq.m.): <input name="area" format="N*N"/>
    Light (lux): <input name="light" format="N*N"/>
    Number of Fans: <input name="fans" value="0" 
                           format="N*N"/>
 </p>
</card>

This card enables the tester to enter an area, as well as illumination and ventilation values. It provides an event handler that passes these values to the validate function in kitcalc.wmls. Note that all values are required (use of format mask N*N) to ensure that there is no problem when calling the validate routine.

We now need cards to display results for when the inspection values are alright (OKResults) and for when there are problems (Warnings):

Figure 2 shows how these cards and the validate function work. The first five screens show a sequence leading to a warning card. The final card shows the results of a test where no violations were found.

Figure 2 Validation test sequences

So far, our health inspection example has shown how we can use WMLScript to process user input, performing calculations and validation. Next, we will add entry and validation of the fuels that are used for cooking. This requires modifications to our test WML deck to add a multiple select list for cooking fuels and new validation output added to the OKResults card:

Cooking Fuel
<select name="fuel" value="gas" multiple="true">
  <option value="gas">Natural Gas</option>
  <option value="electric">Electric</option>
  <option value="propane">Propane</option>
  <option value="wood">Wood</option>
</select>
.
.
.

Fuels: $fuel OK

We also need to update the kitcalc.wmls file to add a new fuel validation routine and call this from the general validate function:

// use getVar to get fuels list
var fuel = WMLBrowser.getVar("fuel");
var VALID = "VALID";  // assume fuel OK
var validFuel = validateFuel(fuel, VALID);
.
.
.
if (light < validLight)
    warning += String.format("Light is < %d lux. ", validLight);
if (validFuel != VALID)
    warning += validFuel;
.
.
.
// Validate fuel combinations returning a warning
// string if invalid or VALID if OK
function validateFuel(fuel, VALID) {
  var SEPARATOR = ";";
  var GASES="gas,propane";
  var gasesSelected = false;
  var WOOD="wood";
  var woodSelected = false;
  var WARNING = "Illegal to mix gas fuels and wood!";

  var nFuels = String.elements(fuel, SEPARATOR);
  for (var i=0; i= 0)
      gasesSelected = true;
    if (thisFuel == WOOD)
      woodSelected = true;
    if (gasesSelected && woodSelected)
      break;
  };

  if (woodSelected && gasesSelected)
    return WARNING; 

  return VALID;
};

The first few lines were added to the validate function to obtain the fuel value from the browser, set a default (VALID) result, and call the validateFuel private function. The next group of lines also were added to validate; the test for valid light was updated to illustrate the use of string formatting (light intensity is now displayed using the format function). A new test of the output from validateFuel will append this function's output to the warning message if the function returns an invalid result string. Note the use of the += operator, which performs string concatenation because its operands are both strings.

The validateFuel function accepts a string containing one or more fuels and a default return value named VALID. Recall that the result of a multiple select list is a string that may contain multiple tokens separated by a semicolon (;). We determine how many fuels have been selected using the elements function of the String standard library. We use this value (nElements) to construct a for loop that searches for gases (propane or gas) as well as wood. The String function elementAt retrieves the fuel tokens one by one, and the String.find function determines whether a fuel is a gas. The break element is used to exit this loop as soon as we have found at least one gas and wood. Note the use of capital letters for constants GASES and WOOD; these constants localize changes to the WML Script if we need to update the fuel list in the calling WML deck. If we find a combination of gas and wood, we return a warning message; otherwise, we return VALID. Figure 3 illustrates the new validation input and results. The inputs include substandard illumination and ventilation, as well as an illegal fuel combination of natural gas and wood.

Figure 3 Fuel validation sequences

So far, we have relied on WML cards to interact with the user. The WMLScript Dialogs library gives us another way to do this. We will alter our application to include a dialog that alerts the user to warnings if the validation function finds problems and offers two options—a new test or re-entry of the existing test.

if (Dialogs.confirm(warning, "New Test", "Redo" ))
  WMLBrowser.go("#SelectTest");
else
  WMLBrowser.go("#EnterValues");

Figure 4 illustrates this change.

Figure 4 Confirm dialog

The final modification that we will make to our health inspection application is to provide an option for an inspector to dial the office in case there is a problem with an inspection. We will modify the dialog created previously to provide this option and add a WMLScript that uses the WTA public library to make a voice call:

if (Dialogs.confirm(warning, "New Test", "Call Office" ))
  WMLBrowser.go("#SelectTest");
else
  WTAPublic.makeCall("4577175");  
WMLBrowser.go("#SelectTest");

Following display of the dialog, the user could choose to make a voice call to the office. A confirmation dialog will be displayed to allow the user to confirm the telephone number. The WTA Public library function makeCall will then initiate a voice call, suspending the WMLScript function until this call is completed; at that point, control will return to the browser at the SelectTest card. Because of limitations of the Phone.com simulator, it is not possible to illustrate this function.

That concludes our tutorial. The WML test deck and WMLScript code can be found here along with a modified health inspection deck that uses the WMLScript functions. Join us next time for a discussion of where WAP is heading, including current issues and trends.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020