Approaches to Web Development for Bioinformatics
I will demonstrate AJAX with an example that gets gene information
from a Servlet. This example is lengthy but there are a number
of AJAX libraries available to simplify this.
It demonstrates a the entire round trip of collecting user
input from a HTML form, using JavaScript to post to a Servlet in the
background and updating the HTML page as the data is streamed to it
without requesting an entirely new page. Here is the HTML page
that the user starts with
(code is here: index.html).
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml">
<head>
<script
type="text/javascript"
src="ajax.js"></script>
<script
type="text/javascript"
src="example.js"></script>
</head>
<body>
<h3>Simple
AJAX Example</h3>
<form
id="getDataForm"
action="javascript:getData()" method="post">
<input
type="text"
name="geneSymbolInput" id="geneSymbolInput" value="HD"/><br/>
<input
type="submit" name="submit"
value="Get Data"/>
</form>
<!-- Place holder for search results -->
<div
id="results">
</div>
</body>
</html>
The page has an input field where the user is supposed to type in a
gene symbol. When the user clicks on the button the JavaScript function
getData() is called. This function in the file example.js:
// Collects the user's input criteria (gene symbol) and gets search
results from the server
function getData() {
var geneSymbol
=
document.getElementById("geneSymbolInput").value;
fetchData("AJAXServlet", geneSymbol,
updateSearchResults);
}
/*
* Update the search results table after the data has completed
loading from the XMLHttpRequest
*/
function updateSearchResults() {
// parse data
if (httpRequest.readyState
== 4) {
if
(httpRequest.status ==
200) {
var
id = extractTagValue(httpRequest.responseText, "id");
var
symbol = extractTagValue(httpRequest.responseText, "symbol");
var
name = extractTagValue(httpRequest.responseText, "name");
var
oldSearchResultsDiv = document.getElementById("results");
var
searchResultsParent = oldSearchResultsDiv.parentNode;
var
searchResultsDiv = document.createElement("div");
//
populate table
var
p = document.createElement("p");
var
textNode = document.createTextNode("Search Results:");
p.appendChild(textNode);
searchResultsDiv.appendChild(p);
//
table header
var
table = document.createElement("table");
var
tbody = document.createElement("tbody");
table.appendChild(tbody);
var
tr = document.createElement("tr");
tr.appendChild(createTableHeader("ID"));
tr.appendChild(createTableHeader("Symbol"));
tr.appendChild(createTableHeader("Name"));
tbody.appendChild(tr);
//
table data
var
tr2 = document.createElement("tr");
tr2.appendChild(createTableCell(id));
tr2.appendChild(createTableCell(symbol));
tr2.appendChild(createTableCell(name));
tbody.appendChild(tr2);
searchResultsDiv.appendChild(table);
searchResultsParent.replaceChild(searchResultsDiv, oldSearchResultsDiv);
} else {
alert("Error retreiving data.");
}
}
}
/*
* Extracts the tag value from the XML string
* @param xml the xml string to parse
* @param tag the tag to extract the value for
* @return the value found in the string or null if not found
*/
function extractTagValue(xml, tag)
{
var start =
xml.indexOf("<" + tag + ">") +
tag.length + 2; // starting position of the value
if (start <
0) {
return null;
}
var end =
xml.indexOf("</" + tag + ">");
// ending position of the value (+1)
return xml.substring(start,
end);
}
function createTableHeader(headerText)
{
var th = document.createElement("th");
var a = document.createElement("a");
a.setAttribute("href", "#");
textNode = document.createTextNode(headerText);
a.appendChild(textNode);
th.appendChild(a);
return th;
}
function createTableCell(cellText)
{
var td =
document.createElement("td");
textNode = document.createTextNode(cellText);
td.appendChild(textNode);
return td;
}
This page calls a generic JavaScript AJAX function called fetchData()
in file ajax.js. The URL
of the Servlet is passed in as a parameter. This function calls
the server with a POST request that includes the parameter the user
entered in the form. This is one of the keys to AJAX: either the
IE ActiveX XMLHTTP object or the Firefox XMLHttpRequest object.
It also assigns an event handler (callback) to handle the data as it is
streamed back from the server (hence the Asynchronous in AJAX).
The event handler is back in example.js (updateSearchResults()).
It dynamically manipulates the DOM to add the data to the page.
By the way, my implementation of this function is only smart enough to
parse one record of from the XML document.
I have used XML to send data from server to browser but an easier way is
JSON. XML has the advantage of better separating client and server code but
JSON is probably a better choice overall.
// HTTP Request object
var httpRequest
/*
* Fetch the given data from the server
* @param dataSource the url of the data source
* @param postData the parameters to post to the server
* @param callback the callback to invoke when the data has loaded
*/
function fetchData(dataSource,
postData, callback) {
httpRequest = false;
if (window.XMLHttpRequest)
{
httpRequest = new
XMLHttpRequest();
} else if
(window.ActiveXObject) {
try
{
httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
try{
httpRequest = new ActiveXObject("Microsoft.XMLHTTP")
}
catch (e){
alert("fetchData, e: " + e);
}
}
} else {
return
false;
}
httpRequest.onreadystatechange = callback;
httpRequest.open("POST", dataSource, true);
httpRequest.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
if (postData
== null) {
httpRequest.send(null);
} else {
var
params = "postData=" +
postData;
httpRequest.send(params);
}
}
Finally, here is the Servlet that responds to the request. This need
not be Java. The same thing can be any server side framework. Of
course, in reality you would be getting the output results from a file
or a database rather than generating from fixed strings as done
here. The source is in AJAXServlet.java.
package net.medicalComputing;
import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public class AJAXServlet
extends javax.servlet.http.HttpServlet
implements javax.servlet.Servlet {
protected void
service(HttpServletRequest request,
HttpServletResponse response)
throws
ServletException, IOException {
String symbol =
request.getParameter("postData");
PrintWriter writer =
response.getWriter();
writer.print("<geneInfo><id>3064</id><symbol>"
+ symbol + "</symbol><name>"
+
"huntingtin (Huntington
disease)</name></geneInfo>");
}
}
The files to deploy the project on Tomcat are in AJAXServlet.zip. This is what
you will see if you are successful in deploying it.
AJAX Example Input Form. Notice
the URL of the page (index.html)
And the result sent to the user after clicking the button looks like
AJAX Example Output. Notice that
the URL of the page has not changed.
As you can see developing AJAX is heavy on the JavaScript and needs
relatively less in the way of Server side generation of HTML with the
like of Java Server Pages or PHP. The code can be simplified some
by using AJAX libraries from one of a number of open source
projects, such as Direct Web Remoting
(DWR)58.
There are no user comments.
Please send ideas and opinions by email at alexamies@gmail.com.
© 2006-2007 Alex Amies