Developer Forums | About Us | Site Map
Search  
HOME > TUTORIALS > CLIENT SIDE CODING > XML TUTORIALS > CREATE WEB APPLETS WITH MOZILLA AND XML


Sponsors





Useful Lists

Web Host
site hosted by netplex

Online Manuals

Create Web Applets With Mozilla And XML
By Nigel McFarlane - 2003-12-24 Page:  1 2 3 4 5 6 7

Support for Scripting

The flip side of the XUL coin is scripting. Although XUL is a bit more user-responsive than HTML, it won't do business logic for you. As with HTML, that role is handled by JavaScript code. Such scripts can be light and simplistic as in HTML, or they can interact quite deeply with the Mozilla platform's many objects. To support download and back-connection of the applet to a remote server, the example in this article performs light scripting only. Mozilla's support for light scripting is quite advanced, so a great deal is still possible.

The script tags in Listing 1 add this functionality to the XUL applet. The applet works as follows:

  1. All menu items except the Login and Help menu are disabled until the user logs in. Logging in means acquiring a session ID from the Web server of origin.
  2. Once logged in, the Ticket menu is enabled.
  3. Once a specific ticket is chosen from that menu, the related form elements appear in the body of the widget and the Action menu is enabled.
  4. The server is queried for a ticket number that can be used for that ticket.
  5. If Submit is chosen from the Action menu, the ticket is sent to the server using an ordinary HTTP GET request, where it is processed as for any other HTTP submission.

I'm not examining the mundane server code required to accept that submission in this article.

To enable all this logic requires less than 200 lines of JavaScript code. Three source files are included to do this work, using XUL's version of the HTML script tag. The script file init.js performs sundry initialization, while commands.js implements all the menu options, and server.js acts as the nuts and bolts of the client-server interactions.

The init.js file, shown in Listing 4, reveals the environment in which XUL scripts run.

Listing 4. init.js performs initialization

// ---- Global variables ----

var session = null;            // log in identifier, or null

var ticket = {
  id : null,                   // set to server-supplied number.
  url : null                   // set to the page in question.
};

// ---- Perform initialisation when the page has loaded ----

window.addEventListener("load", initialise, false);

function initialise()
{
  var node;
  var cookie = window.parent.document.cookie;

  // do we have an existing session?
  if ( cookie && cookie.substr("sessionID") )
  {
    //chop up the cookie string
    session = cookie.search(/sessionID=[^;]{1,};/);
    session = session.replace(/^.*sessionID=/,"");
    session = session.replace(/;.*/,"");
    session = parseInt(session);

    document.getElementById("stext").selectedIndex = 1;
  }
  else
  {
    document.getElementById("menu_ticket").setAttribute("disabled","true");
    document.getElementById("menu_action").setAttribute("disabled","true");
  }
  
  // don't support "exit" if we're inside an <iframe>.
  if ( window.parent.location.href != window.location.href )
  {
    document.getElementById("m12").setAttribute("disabled","true");  // "Exit"
    window.focus();
  }
}

Since XUL is a flavor of XML, the many W3C standard DOM interfaces are available. These interfaces make the XUL and HTML document available as an apparent tree of Element nodes, including DOM 0 features such as cookie support and the navigator object.

Scripts can store their own state in ordinary JavaScript variables or interact with the DOM. The powerful getElementById() is the standard version of Microsoft's document.all() functionality. The objects made available by the DOM standards are entirely separate to the thousand objects that are supplied by the Mozilla platform. Only the former are used here.

In the Listing 5, the DOM is used to lodge an onload event handler which fires the initialize() function once the XUL page is fully received. The initialize() function gropes through the DOM of the applet and its parent HTML document looking for an existing session ID in the form of a cookie, and disabling menus appropriately. Unlike with a Java applet, no awkward conversion takes place between Java and JavaScript objects and types -- everything is navigable from JavaScript. Security is still enforced using automated checking.

The second listing, commands.js, is routine. It provides an event handler for each menu option. In Listing 5, the example snippet of that file shows how the panel content of the applet's deck tags can be flipped with basic DOM-style operations:

Listing 5. Flipping deck tags

function cmd_user()
{
  init_ticket();
  document.getElementById("title").selectedIndex = 1;
  document.getElementById("forms").selectedIndex = 1;
}

Here, selectedIndex for the two decks starts with zero (which is a blank pane) and is flipped to one (a set of checkboxes) if the Ticket|User Ticket menu option is picked. See the full listing for commands.js to see how these form elements are queried to extract the user's data and to construct a parameter string suitable for a HTTP GET request. Technically, a submitted ticket should use an HTTP POST request, since it's not a retrieval action, but GET is used here for simplicity.

The final script, server.js, uses the special XMLHttpRequest object that is now a standard feature of modern browsers. This allows an XUL applet (or any JavaScript code) to connect back to its server of origin through HTTP without disturbing the currently displayed page.

Mozilla supports other protocols as well, such as SOAP and WSDL, and also raw sockets. This functionality means that XML-based interfaces are now as network-enabled as Java-based interfaces. Listing 6 shows a snippet of the network-oriented code:

Listing 6. server.js lets the applet connect to server of origin

// fake ticket ID request for the purposes of this demo.
function init_ticket()
{
  ticket.id = Math.floor(Math.random()*10000);
  ticket.url = window.parent.location.href;
  document.getElementById("menu_action").removeAttribute("disabled");
  document.getElementById("f00").value = ticket.id;
}

// real implementation for a ticket request, using an HTTP server.
function init_ticket_real()
{
  var req    = new XMLHttpRequest(); // Request
  var params = window.encodeURI("action=new-ticket-id");

  // ---- HTTP GET request for the ticket id.

  req.open("GET", "id-generator.cgi" + "?" + params);
  req.send("");

  // ---- Server results for HTTP GET
  if ( req.status / 100 == 2 )  // HTTP 2xx Response?
  {
    ticket.id = req.getResponseHeader("X-Ticket-Sequence-Number")
    ticket.url = window.parent.location.href;
    document.getElementById("menu_action").removeAttribute("disabled");
  }
  else
  {
    alert("Failed to construct a new ticket. Contact support.");
  }
}

The first implementation of init_ticket() allows the applet to be played with, without any real server support. The second implementation shows how a request can be silently processed (subject to security restrictions) with the aid of a server. The req object constructs the request with open() and sends the request using send(), which blocks until a response is received.

send() can also be called in a non-blocking way. When the response is received, error checking ensures that the server succeeded. In this case, I rely on the server setting a special HTTP header named X-Ticket-Sequence-Number, which holds the unique identifier for the ticket the user is constructing. This approach is also used for acquiring a session ID and for submitting the final ticket. Feedback is provided to the user in the form of status bar messages: Green for good news, red for bad news.



View Create Web Applets With Mozilla And XML Discussion

Page:  1 2 3 4 5 6 7 Next Page: A Feel For XUL

First published by IBM developerWorks


Copyright 2004-2024 GrindingGears.com. All rights reserved.
Article copyright and all rights retained by the author.