Before getting started with this tutorial, you should satisfy the following requirements:


http://localhost:8888/
index.js,
and is located in the application/script
directory of the project. XMLHttpRequest, the HTML that
defines the
form components
that appear on the page, and any style information. In the
AJAXlist example, this file is called list.ejs, and is
located in the application/view directory of the
project.XMLHttpRequest
and renders the view. In the AJAXlist example, this file is
called list.js, and is located in the application/controller directory
of the project. index.js file handles the initial request by
redirecting it
to the /list/show URL. The list part of the
URL is a controller, and show is one of its functions.
The show function is defined in list.js. List controller and
invokes the show function. show function creates the list, saves it into
the session, and renders the list.ejs view. XMLHttpRequest
object is created, and the client sends a POST HTTP request to the /list/compute
URL with the request paramenters representing the value that the user
entered and
the command "add", thereby calling the compute function
of List
controller with these parameters. compute function does the following:
XMLHttpRequest object is created and the compute
function is called again, this time passing
the index of the item to be deleted and the command "remove" as the
request parameters. compute function does the following:
index.js
script,
located in the script directory. This script redirects
the request to
the URL, /list/show by executing the following line:
library.httpserver.sendRedirect(library.httpserver.makeURL("/list/show"));
In this case the request is dispatched to the show
function of the List
controller. This function will render the view, as described in the
next section.
show function does is it creates a
list and stores it
into the session:
var list = invocation.session.list;Because you can only save String values in session with Phobos, you need to serialize the JavaScript list into JavaScript Object Notation (JSON) format to save it in the session. Note that serializing an object to JSON will not work if the object contains some Java objects. Finally, the controller renders the view:
if (list == undefined) {
var list = new Array();
invocation.session.list = library.json.serialize(list);
}
library.view.render("list.ejs");
list.ejs file includes the following:
XMLHttpRequest
object and sends it to the controllerXMLHttpRequest object to the controller.
list.ejs file that
creates the form, which allows the user to add items to a list and
remove items from a list.
<div id="listForm" class="listContainer">
<form name="autofillform" onSubmit="submitData(); return false;">
<input id="entryField" type="text" size="20" value="Enter New Value">
<input type="button" onclick="submitData(); return false;" value="Add to List">
</form>
<div id="list" class="listDiv"></div>
</div>
Notice that there are two div tags, one inside the other.
A JavaScript
function looks for a tag in a page using the unique IDs of div
tags.
The outer div tag wraps the form component, which
includes the field in
which the user enters an item, and the button to add the item to the
list, as well as the inner div tag. The inner div
tag identifies the
component that displays the list on the page.
When the user clicks the button, Phobos gets the ID of the entire
list and invokes the submitData method, which the next
section discusses. The response that the server returns includes
the updated list, which includes the item the user added. This
response replaces the inner div tag. The following
code is an
example of a response that shows a 2-item list:
<ol>
<li><div class=\"plain\" onmouseover=\"this.className ='over';\"
onmouseout=\"this.className ='plain';\"
onclick=\"removeItem('"0"')\">" + list[0] + "</div></li>
<li><div class=\"plain\" onmouseover=\"this.className ='over';\"
onmouseout=\"this.className ='plain';\"
onclick=\"removeItem('"1"')\">" + list[1] + "</div></li>
</ol>
Note that the removeItem function is invoked with the
index of the
item on which the user clicked. You'll see in the next section
how submitData and removeItem construct
URLs with the appropriate
request parameters so that the controller appropriately adds an item to
or removes an
item from the list.
submitData function
is invoked when
the user clicks the Add to List button and how the removeItem
function is invoked when the user clicks on an item in the list. submitData function gets the value of the text field in
which the user entered
the item to add to the list. It then creates a URL that it passes to
the initRequest function, which creates the XMLHttpRequest
object.
function submitData() {
entryField = document.getElementById("entryField");
var url = <%= library.view.quoteUrl("/list/compute") %>;
+ "?command=add&entryField=" + entryField.value;
initRequest(url);
}
Here, the quoteURL function from the view JavaScript
library available
in
Phobos returns a URL whose protocol, server, and port components are
taken from the current request. This path is the specified string,
which
identifies
the compute function of the List
controller.
The add command and the value of entryField are added
to the URL as
request parameters. The compute function of the List
controller
uses the command to determine if it needs to add an item to or remove
an item from the list.
Similarly to submitData, the removeItem
function
creates a URL, which it passes to the initRequest
function.
function removeItem(index) {
var url = <%= library.view.quoteUrl("/list/compute") %> + "?command=remove&index=" + index;
initRequest(url);
}
Note that removeItem takes the index of the item to
remove and adds it as well as the remove command to the URL as
request parameters.
The initRequest function creates the XMLHttpRequest
object and
sends it to the URL passed to it by the submitData or removeItem
functions. As shown in the
following code, the initRequest function is exactly the
same as it would
be if you were implementing this example with any other web application
framework.
function initRequest(url) {
var list = document.getElementById("list");
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
} else if (window.ActiveXObject) {
isIE = true;
req = new ActiveXObject("Microsoft.XMLHTTP");
}
req.onreadystatechange = processRequest;
req.open("POST", url, true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send(null);
function processRequest () {
if (req.readyState == 4) {
if (req.status == 200) {
list.innerHTML = req.responseText;
}
}
}
}
The preceding code does the following:
XMLHttpRequest object, first checking
if the user's browser
is Internet Explorer or not and creating the object accordingly. onreadystatechange property to
the callback function, processRequest. This means that
whenever the readyState of the object changes, this
function is invoked. processRequest function checks if the readyState
is 4,
which means that the request is completed, and then it checks if the
status of
the request is 200, which means that it was successful. In that case,
the processRequest
function replaces the list div element with the response from the
controller. initRequest function then calls the object's open
function, passing in the HTTP method, the URL to
send the request, and a boolean indicating whether or not to make the
request asynchronous. compute
function
of the List controller will be invoked.XMLHttpRequest object explained in the previous
section sends the URL to the compute
function of the List controller. In this section, you'll
see how the compute
function adds items to the list, removes items from the list, and
generates the response. The JavaScript code described in the
previous section runs in the browser, whereas the JavaScript code
detailed in this section runs on the server.The compute function uses the onMethod
function of the Phobos httpserver library to restrict
parts of its implementation to only be invoked during certain HTTP
methods.
In the case of the code that adds items to or removes items from the
list and returns
the response, the compute function ensures that this code
is only executed during a POST:
this.compute = function() {
library.httpserver.onMethod({
POST: function() {
//code to add items from the list and remove items from the list
},
Before adding items to or removing items from the list, the compute
function must deserialize the list stored in the session from JSON into
a
list variable:
var list = library.json.deserialize(invocation.session.list);Then the
compute function checks if the command request
parameter is equal to add
or remove to determine whether it should add an item or remove an item.
if (command == "add") {
var index = list.length;
list[index] = entryField;
}
if (command == "remove") {
var index = Number(request.getParameter("index"));
var length = list.length;
if (index != null) {
while (index < length - 1){
list[index] = list[index+1];
index = index + 1;
}
list.length = index;
}
After updating the list, the compute function serializes
the updated list back into JSON and stores it into the session.
After it updates the list, the compute function sends
the response back to the
client:
response.setStatus(200);Notice that for every item in the list, a
response.setContentType("text/html");
writer = response.getWriter();
writer.println("<ol>");
for (var index = 0; index < list.length; ++index){
writer.println("<li><div class=\"plain\" onmouseover=\"this.className ='over';\"
onmouseout=\"this.className ='plain';\"
onclick=\"removeItem('" + index + "')\">" + list[index] + "</div></li>");
}
writer.println("</ol>");
writer.flush();
div element is
rendered. This element
has several attributes, including an onclick attribute
that is set to the
function call removeItem('" + index +"'). When the user
clicks on an item in the list, the removeItem function is
called with the index of
the item the user
clicked.