This document will deconstruct a simple interface panel and business logic for the PDB2PQR service.


...For 1.0.2 The PDB2PQR service is releated to the APBS application; it's purpose is to convert a PDB formatted molecule into the PQR format required by APBS. This particular example was chosen because it is relativley simple to create yet makes comprehensive use of Gemstone's functionality.

Usage of PDB2PQR is straightforward:

  1. The user selects a single input file, a PDB, either by dragging it over from the Gemstone Filesystem view or by clicking the "Select PDB..." button
  2. Parameters are chosen via a menu and several checkboxes
  3. The user clicks the "Run" button
  4. When complete, focus transfers to the "Output" tab which displays any output generated
  5. Output is viewed by clicking it's "Open..." button and can be saved to the local desktop either by dragging the "Save..." button over to the Filesystem view or by clicking it.

The rest of this document will describe how these steps were represented in XUL and JavaScript. When line numbers are given they will be for an HTML version of the XUL source loacated at".


Before starting make sure that you're familiar with general usage and the developer overview. The actual backend Opal Web service will not be discussed in any detail here but there is full documentation available:

The Interface

There are over 100 XUL widgets (see the list) available to use when designing an interface, not including HTML elements which can also be used. The next few sections only cover usage of a few key widgets as they relate to the PDB2PQR interface. For a comprehensive introduction, visit XULPlanet's tutorial:

PDB2PQR Input PDB2PQR Output


XUL interfaces are contstructed primarily of different types of boxes, each of which has a different use. Even elements like textboxes and buttons are boxes at heart.

The simplest kind of boxes are the vbox and the hbox which orient their children vertically and horizontally respectively. Vboxes and hboxes are only used for organization of other elements and don't display content of their own--that is, a vbox without any children will not display anything on the screen. These boxes can hold nearly any type of child content; on lns 36 and 98, vboxes are used to group a large number of elements together into related sub-panels. Liberal use of these

Specialized boxes have a specific function or method of laying out content. Some examples used in the PDB2PQR panel include tabs, groupboxes and grids.

When the panel has just been opened the service hasn't been run and there is no output yet to display, but we want to keep an output placeholder ready for when there is some. In order to reduce interface clutter we can put the output container into a tab element which will be hidden until it's needed. The user can then click back and forth between the Input and Output tabs and see only the part they want. XUL tabpanels are contained in a tabbox (ln 28).

The Input panel is further subdivided into two groupboxes named "Run" and "Input", (lns 37 and 61). Groupboxs are often used to visually distinguish a group of related elements. An optional caption can be used to further distinguish the group. Grid elements, the XUL equivelent of HTML tables, are commonly paired with groupboxes to lay out elements in an orderly row/column fashion. Check here for additional explanation and examples of grid usage.

In most cases the layout engine does a good job of positioning, sizing and ordering XUL elements efficiently on the page. If desired though, the developer can alter the look of an element either with CSS or individually with attributes Some of the boxes in PDB2PQR use flex attribute to tell the layout engine to make the element "greedy" and take up additional space on the page if it exists. The effect is that elements with higher flex numbers expand faster than elements.

The next two sections will discuss in more detail how the Run and Input panels were designed.

Run Panel

The Run panel provides a single button on ln 47that, when clicked, calls a JavaScript function to run the service. The button's oncommand attribute is what connects the action "run()" to the button.

Once the run button is clicked, a special XUL widget called the progressmeter can be used to keep track of the job's duration. Every time the service returns status, another function is called to update a status message in the textbox on ln 54.

Input Panel

The purpose of this panel is to provide users means of selectiong various options for the Web service. Of the four options, two are "switches" (debumping, hydrogen optimization) meaning that the option is either present or not, one requires a choice between several options (forcefield), and one requires direct user input (Propka).

There are several choices to represent the "switches": checkboxes, radio buttons, or even a menu. In this case, checkboxes were chosen (lns 73-74).

For the multiple choice option, the obvious and best choice is a menulist (ln 80). This, in turn, contains a menupopup which displays several menuitems in a drop-down menu.

A textbox (ln 90) is used to get text input from the user. Notice that this textbox has the attribute hidden set to true; hidding the box helps make the interface cleaner by only showing the option when it's asked for. To enable the hiding/revealing, a JavaScript function sets or removes the hidden attribute based on whether the checkbox on ln 75 is checked.

Finally, the "Select PDB" (71) button calls a JavaScript function that opens a Filepicker for the user to browse their system.


The last part showed how the PDB2PQR interface was designed, this section will show the JavaScript used to make the interface interactive. The JavaScript for PDB2PQR (located at needs to accomplish two major tasks: respond to user interaction, and process input/output for the Job object.

The first event to happen though is that ithe init() function gets called when the XUL is finished loading. init() takes the service endpoint from the Gemstone created selfInfo variable and displays it at the top of the page to let the user know that the panel is ready for use.

User Interaction


Only two of the options in the Input panel require immediate handling: "Select PDB" needs a function to "get" a file, and "..PROPKA" needs a function to reveal the hidden textbox.

"...PROPKA" is simple to handle. When the checkbox on ln 75 is checked, togglePropka() either sets or removes the hidden attribute on the ph_val textbox and its label.

When clicked, "Select PDB" calls selectPdb() without any parameters, yet the JavaScript definition lists two: mode and path. The reason is that this same function is also to recieve data when the user drags a PDB to the panel rather than clicking the button. This is also done to highlight the fact that with JavaScript, functions can take a variable number of arguments, named or not. Instead of naming arguments as in the example, a special arguments local variable can be used to gain access. In this particular case the function just ignores the arguments if they don't exist and assumes that we want the user to browse their system for a file; showFilePicker() is the Gemstone API function that does the work to open up that file browsing dialog. Once selected, the file's name is set into the pdb-text textbox to show the user that they were sucessful.

Drag and Drop for the entire Input box is enabled on ln 61 in conjunction with the broadcaster element on ln 19. A broadcaster is used "when you want multiple elements to share one or more attribute values, or when you want elements to respond to a state change". So rather than typing the ondragover, and ondragdrop attributes in multiple places we can just type observes="drag" instead.

When a file is dragged over the panel, dropObserver.onDragOver is checked to make sure that the action is allowable. Only one action, dropping a file on a textbox is disallowed in this case. Once the file is finally dropped selectPdb() is called with its path as an argument.


Output for the PDB2PQR Web service is a series of links pointing to the converted file, the original input, and a file containing any error information. The function updateOutputDisplay() processes this output and dynamically creates XUL for the user to download or view the files.

First, the output SOAP message (specified by Opal) is converted to a DOM structure. This DOM structure can be used to do an XPath query as on ln 175 which searches for all occurences of a file type (stdErr, stdOut, outputFile). For each result of this query a row is added to the Output panel which contains two buttons: "Open..." opens a browser window to view the file, "Save..." opens a Filepicker to save the file. The lines:

btn2.setAttribute( "v" , url );
btn2.setAttribute( "ondraggesture", "nsDragAndDrop.startDrag(event,outputFileObserver);" );

1) set the file's URL as an attribute of the button capable of being dragged 2) make the button drag-aware. When dragged the outputFileObserver takes the special attribute and and starts the drag & drop transfer.

Running The Web Service

The run() function accomplishes several things:

  1. resets the Input and Output panels: this prevents confusion in case users run multiple jobs in the same panel
  2. creates an input SOAP message: the createInput() function "scrapes" the interface for parameters and constructs the input message according to the Opal WSDL and PDB2PQR's metadata.
  3. sets up a Job object: adds callbacks to listen to the job's lifecycle events
  4. launches the Job: (optionally) adds the Job object to the Job Manager and launches it
  5. disables further user input: since it might take a moment for the Web service to respond, this prevents the user from accidentally launching the same job multiple times

Although the implementation varys, these same five steps are repeated for nearly every service/panel combination.

Steps 2 and 3 are particulary important. PDB2PQR does not require many parameters to run and therefore does not require any complex interface design; a more complex service/interface might choose to keep an internal hash of input parameters rather than using the "screen scrape" method used here.

The responseHandler() function used for step 3 is used as the callback for every job lifecycle event. Each event leads to a status update except for "onjobcompletion" which leads to the Output sequence described earlier.

The gemstone project can be contacted through the mailing list or the member list.
Copyright © 2000-2017. All rights reserved. Terms of Use & Privacy Policy.