SMD's Ontology Widget
Beauheim
et al, 2007
Date: January 26, 2007
Revised: July 7th, 2007
The Ontology Widget is a javascript/html application that utilizes AJAX (Asyncronous Javascript And Xml) to rapidly find and select ontology terms on a web page. The widget is intended to be used in a larger context, such as an experiment annotation page. The javascript functions query the SMD Ontology Service to retrieve and navigate ontology terms quickly and easily. The first part of this document, Widget Context and Architecture, briefly describes the environment in which the widget works. The next section, Behavior of the Ontology Widget, describes what the widget does. The third part explains how to construct an html page to use the widget. Appendix 1 is an example html page. Appendix 2 describes how to deploy the widget and Appendix 3 describes SMD Ontology Services in detail. Appendix 4 shows more detail on how an OntologyWidget is initialized, and Appendix 5 describes how to change your Apache web server settings to set up a proxy pass and proxy pass reverse.
The home page for the widget project is http://smd.stanford.edu/ontologyWidget/. Here you can find the complete gzipped package that includes this document, the war file required to deploy the servlet stub (see below), and an example html file, ExampleToEdit.html. There is also an example html file (Example_8080.html) in the war file that is configured to run at localhost:8080, the default Tomcat location. Please see the instructions in Appendix 2 for deploying the war file. A working demonstration of the widget can be accessed at http://smd.stanford.edu/js/ontology/v1/ExampleProduction.html. Finally, the javascript files are available at this site in the tar file OntologyWidgetSrc.tar.
The Ontology Widget depends on three levels of service: the client user-interface in the browser, a Tomcat servlet stub and http server provided by the implementor, and the backend SMD Ontology Service and ontology database. In Figure 1, the browser interface is shown in gray, the implementor's Tomcat server is shown in green and the SMD OntologyService is shown in blue. The browser displays an html file that includes javascript code that interprets user actions, which then generate queries to the SMD Ontology Web Services through a servlet stub. The SMD Ontology Service uses Java servlets to construct sql queries and direct the queries to our ontology database. The response from the database is packaged in an xml document that is passed back through the servlet stub to the javascript code. The javascript code interprets the xml document and draws html in the client's browser.

Figure 1. System Architecture. The widget currently supports 43 of the OBO ontologies listed at http://obo.sourceforge.net/cgi-bin/table.cgi. A current list of our ontologies can be retrieved by directly querying our SMD Ontology Service at http://smd.stanford.edu/smd/OntologyService?func=getOntologyList. Queries to the SMD OntologyService are described in Appendix 3.
The widget is composed of a title, a label, a text
field, a search button and a tree display. The
tree display is an area reserved to display the ontology as a tree. Figure 2 shows an example single
widget, as displayed on a web page.
In the text field, the user can type in characters to search for
matching terms. The text field is
connected to an auto-complete list of terms queried through the SMD Ontology
Service. As the user types into
the text field, the ontology database searches for terms that match the
typed-in characters. The SMD
Ontology Service returns a matching term list up to 50 terms. When the user
selects a term from the list, it is written to the text field. Figure 3 shows the list that matches
the characters 'res'.

Figure 2. Ontology
Widget with the Gene Ontology term Physiological Process selected as the root term in the html file.

Figure 3. Auto-complete list of terms matching 'res'
The tree display area shows the
ontology as a hierarchical tree.
Figure 4 shows the tree display for the children of Physiological
Process, a term within the Biological
Process branch of the Gene Ontology. Clicking on a term in
the tree will highlight the term and write it to the text field. Figure 4 shows the homeostasis
term highlighted in the tree and written to
the text field.
We also show paths in the tree from a selected term to the ontology root.
llTo
display a path, select a term from the auto-suggest list (as in Figure 3) or
directly from the tree (as in Figure 4) and click the Search button.

Figure 4. Selecting
a term in the tree writes it to the text area
The tree display is navigated using the common collapse and expand icons shown in Figure 5. The plus sign indicates that there are children of this term that are not displayed. Clicking the plus sign expands the tree node and shows the children. The minus sign collapses the tree at this node and hides the children.
![]()
Figure 5. Tree
Navigation Icons
The
icon with three dots is displayed when we show the path from the tree root to
the selected node, highlighted in yellow.
Only the nodes along the path of interest are shown. The icon with three dots indicates that
there are additional child nodes for a parent that are not being displayed.
When the dot icon is clicked, the hidden children of the term are displayed and
the icon disappears. Figure 6
shows the ontology tree for Physiological Process when the term 'response to pheromone' has been selected from the auto-complete list. Notice that the term, 'response to
pheronome', is highlighted in the
tree and that the term occurs in the tree two times. The dots icon here shows that all the terms along the path
from the root, physiological process, to 'response to pheromone ...' have more child
terms that are not displayed.

Figure 6. Tree
from selected term to root, showing the dots icon at multiple places
The widget is designed to
report five fields of data when a button of <input type=submit> is included on the form. The action method that is called must be supplied by the
user of the widget. Each widget
will report its ontology name, the label, title, term name and term accession
number through hidden input fields.
We provide a sample action for Submit which reports the
values in a simple table. In the
section below we describe how to construct a web page with an ontology widget
and a Submit button.
In the downloadable files (and as shown in Appendix 1), we have created an html file which can be used as a template for widget creation. The basic outline of widget creation is that the html file must initialize the SMDService by calling a javascript function, SMDService(). The SMDService handles all the queries to the SMD Ontology Service through a proxy servlet and XMLHttpRequests and responses. Then the html file defines the widget parameters in JSON format (javascript object notation). When the widgets are configured, they are dynamically placed on the page at user-specified locations. Each widget will report five fields in hidden input fields when the form is submitted. Appendix 1 gives a full listing of an example html file. The html file is described in detail below.
Ontology Widget is constructed using seven javascript files plus icon image files and a cascading style sheet (css). The tree in the annotation widget is built using YAHOO!'s public domain user interface code for widgets (http://developer.yahoo.com/yui ). It is not necessary to download the javascript files, as they can simply be included as shown in Figure 7; of course, they can be downloaded from our web site using those same urls, if you are interested in the actual code. In Figure 7, the javascript and css files are imported into the html file by referencing the files on our web server. Improvements we make are automatically available through these urls.
|
<link
rel="stylesheet" type="text/css" href="http://smd.stanford.edu/js/ontology/v1/treeview/assets/tree.css"> <script
type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/Widget.js'></script> <script
type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/SMDService.js'></script> <script
type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/Ontology.js'></script> <script
type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/OntologyTreeBrowser.js'></script> <script
type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/Term.js'></script> <script
type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/Hashtable.js'></script> <script
type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/treeview/yahoo.js'></script> <script
type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/treeview/treeview.js'></script> <script
type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/treeview/MyNode.js'></script> |
|
Figure 7.
Including the required files in the html document |
Initialization of a web page containing one or more widgets proceeds as follows. The window.onload() function is used to set up some flags and create the SMDService() (see Figure 8 for code listing; a more detailed indication of the process of flag setting and database queries is shown in Appendix 4). During the set up phase, we query the database for the currently available ontologies. This query is done in the new SMDService() function. The javascript interval checker, setInterval ('checkFlag()', 100) in the window.onload() function checks for the value of the variable 'flag' in the function checkFlag(). checkFlag() is called every 100 ms by the javascript function setInterval() until it is cleared. When the value of 'flag' changes to 2, the initial database query has returned, thus clearing the interval checker, and the function buildWidgets() is called. buildWidgets() also queries the database and these queries must return before we can continue. When the value of the variable 'flag' changes to 3, we are ready to continue and the interval checker is cleared again. The two functions shown in Figure 8 must be included verbatim in the html file. Other javascript commands may be included in the window.onload() function as required by the application, such as calling other javascript functions which lay-out other parts of the html page or making database queries for previously selected values.
|
window.onload = function()
{ document.getElementById ('init').setAttribute ('flag',
1 ); doneYet = setInterval ('checkFlag()', 100
); smdService = new SMDService(); } function checkFlag() { //query for ontology
ids has completed if ( document.getElementById ('init').getAttribute ('flag')
== 2 ) { buildWidgets(); } else if (document.getElementById ('init').getAttribute ('flag')
== 3 ) { clearInterval
(doneYet); } } |
|
Figure 8.
Javascript functions for initializing form |
The second part of the <head> section of the html file defines each widget in JSON notation. A widget needs six pieces of data:
á title to be shown on the form (string)
á ontology id (database identifier, supplied by function call)
á ontology name (string)
á term name (string)
á label (string)
á unique identifier (string or number )
Figure 9 shows the listing for a function called buildWidgets(), which is an example of how to create widgets. When defining a widget, the code must first get the database identifier for the ontology name. This is done by calling smdService.getOntologyId (ontologyName). The code below is creating an array of objects where each object will be one widget. Because javascript uses associative arrays to reference data fields and because it is not typed, care must be taken to use the identifiers exactly as defined below. The fields are title, ontId, ontName, termName, label, and uid. The values for title, label, and uid are user-specified. The label defines the context of the annotation to the page. The uid is a unique identifier, important when there are several widgets on one page. The uid can be a string or an integer; it just must be unique for each widget on the page. The termName allows the user to specify a root from which the ontology descends. If termName is the empty string, that is or or 0, the root of the ontology will be the root of the tree. If termName is a term name in this ontology, then that term will be the root. In this way, the scope of the terms can be restricted to the context of the annotation. For both the ontology name and the subroot term, we require an exact string match with the name and the term as defined in the ontology. In Appendix 3, we explain how you can check these names against our database.
The buildWidgets() function, shown in Figure 9, creates three widgets: one for The MGED Ontology, one for Gene Ontology and one for NCBI_Taxonomy. The first widget is limited to search for terms which are children of the term BiologicalProperty. The second widget is limited to those terms that are descendents of biological_process in the Gene Ontology. The third widget displays all the terms in the NCBI Taxonomy ontology. Below the widget descriptions, the function loadWidgets() is called. Optionally, we have preselected the term growth in the Gene Ontology. The preselection feature can be used to display the term selected in a previous session or a default value.
|
<script type='text/javascript'>
var smdService;
var doneYet; var termNames; function buildWidgets() { //Set up for "The MGED
ONTOLOGY", rooted at the term "BiologicalProperty"
var id1 = smdService.getOntologyId ("The MGED Ontology");
termNames = { "lookups": [
{"title" : "Biological Samples ",
"ontId" : id1,
"ontName" : "The MGED Ontology",
"termName" : "BiologicalProperty",
"label" : "Biological Samples",
"uid" : '1' }]};
//---------------------End of biological samples //Set up
for "The Gene Ontology", rooted at the term
"biological_process"
var id2 = smdService.getOntologyId ("Gene Ontology");
termNames.lookups[termNames.lookups.length] =
{"title" : "Biological Process ",
"ontId" : id2,
"ontName" : "Gene Ontology", "termName"
: "biological_process",
"label" : "Biological Process",
"uid" :'2'};
//---------------------End of biological process
//Set
up for "NCBI_Taxonomy", rooted at the root
id3 = smdService.getOntologyId ("NCBI_Taxonomy");
termNames.lookups[termNames.lookups.length] =
{ "title" : "Taxonomy",
"ontId" : id3, "ontName"
: "NCBI_Taxonomy",
"termName" : "",
"label" : "Taxonomy",
"uid" : '3'};
//---------------------end
of ncbi taxonomy
//call
the smdService to load the widgets on the page
smdService.loadWidgets (termNames );
//preselect
a term for each widget (optional)
smdService.preSelectTerm (id2, ÒgrowthÓ, 2);
} </script> |
|
Figure 9.
Example: Building three
data objects |
The last part of the html file is the body. In the body we define the <div> elements that hold a place for each widget on the page and define the five hidden inputs. The <div> elements for the widgets are named by the string id =' widget' + uid. Similarly the four hidden fields have ids in the form of: 'ontology' + uid, 'label' + uid, 'termName' + uid, 'accession' + uid. The fifth hidden input names the uid for this widget. In Figure 10, notice that the id of the form is ' MainForm ' as passed to SMDService(' MainForm').
|
<body> <form name='ExperimentalInfo'
id = 'MainForm' method=POST onsubmit = "validateForm()"> <fieldset>
<legend>Design of the
Investigation </legend>
<table border cellpadding=4
>
<!-- widget with unique id = 1. hidden fields are required for submission -->
<tr valign=top>
<td> <div id='widget1'>
<input type='hidden'
id='ontology1' name='ontology1' value="">
<input type='hidden'
id='label1' name='label1' value="">
<input type='hidden'
id='termName1' name='termName1' value="">
<input type='hidden'
id='accession1' name='accession1' value="">
<input type='hidden'
id='uid' name='uid' value="1">
</td>
</tr>
<!--
widget with unique id = 2.
hidden fields are required for submission -->
<tr valign=top>
<td> <div id='widget2'>
<input type='hidden'
id='ontology2' name='ontology2' value="">
<input type='hidden'
id='label2' name='label2' value="">
<input type='hidden'
id='termName2' name='termName2' value="">
<input type='hidden'
id='accession2' name='accession2' value="">
<input type='hidden'
id='uid' name='uid' value="2">
</td>
</tr>
<!-- widget with unique id = 3. Hidden fields are requires for submission -->
<tr>
<td> <div id='widget3'>
<input type='hidden'
id='ontology3' name='ontology3' value="">
<input type='hidden'
id='label3' name='label3' value="">
<input type='hidden'
id='termName3' name='termName3' value="">
<input type='hidden'
id='accession3' name='accession3' value="">
<input type='hidden'
id='uid' name='uid' value="3">
</td>
</tr>
</table>
<table border cellpadding=4 >
<tr> <td> <input type='submit'
></td></tr>
</table> </fieldset> <!-- init flags required for
query synchronization --> <div id='init'
flag='0'></div> <!--
url for our service <div id='url' server='http://localhost:8080/OntologyWidgetProxy/OntologySvs'></div> </form> </body> |
|
Figure 10. Body
and form for three widgets |
The last requirement is two divÕs for initialization purposes. The ÔinitÕ flag we saw above for synchronization. The URL div exposes the address of the ontology service proxy. Because of browser security issues, the proxy is necessary to avoid the Òcross-domainÓ problem. This is because browsers do not allow an html file to call a service URL in another domain. In your html file, the URL must point to the ontology service proxy in your local tomcat installation.
These instructions describe how to use SMDÕs Ontology Widget with our OntologyService. Figure 11 shows what this example html page looks like. The first time our service is accessed, there will be a security alert from Firefox. Figure 12 shows this alert. Check the box Remember this decision and click the Allow button.

Figure 11. Browser
rendering of Example_8080.html

Figure 12. Security
Alert from Firefox
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head>
<meta
http-equiv="content-type" content="text/html/charset=iso-8859-1"> <link rel="stylesheet" type="text/css" href="http://smd.stanford.edu/js/ontology/v1/treeview/assets/tree.css">
<script type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/Widget.js'></script>
<script type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/SMDService.js'></script>
<script type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/OntologyTreeBrowser.js'></script>
<script type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/Hashtable.js'></script>
<script type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/treeview/yahoo.js'></script>
<script type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/treeview/treeview.js'></script>
<script type='text/javascript' src='http://smd.stanford.edu/js/ontology/v1/treeview/MyNode.js'></script>
<script type='text/javascript'>
var smdService;
var doneYet;
var termNames;
/* *** *** *** *** ***
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *
* buildWidgets supplies
the basic data for each instance of an ontology annotator.*
* smdService looks up the
ontology name against our database as the widgets are *
* built.
*
* *** *** *** *** *** ***
*** *** *** *** *** *** *** *** *** *** *** *** *** *** */
function buildWidgets() {
//Set up for "The MGED ONTOLOGY", rooted at the term
"BiologicalProperty"
var id1 = smdService.getOntologyId ("The MGED Ontology");
termNames = { "lookups": [
{"title" : "Biological Samples ",
"ontId" : id1,
"ontName" : "The MGED Ontology",
"termName" : "BiologicalProperty",
"label" : "Biological Samples",
"uid" : '1' }]};
//---------------------End of biological samples
var id2 = smdService.getOntologyId ("Gene Ontology");
termNames.lookups[termNames.lookups.length] =
{"title" : "Biological Process ",
"ontId" : id2,
"ontName" : "biological_process",
"termName" : "biological_process",
"label" :
"Biological Process",
"uid" :'2'};
//---------------------End of biological process
//Set up for "NCBI_Taxonomy", rooted at the root
id3 = smdService.getOntologyId ("NCBI_Taxonomy");
termNames.lookups[termNames.lookups.length] =
{ "title" : "Taxonomy",
"ontId" : id3,
"ontName" : "NCBI_Taxonomy",
"termName" : "",
"label" : "Taxonomy",
"uid" : '3'};
//---------------------end of ncbi taxonomy |