Description
Create a web site that uses AJAX/PHP/JSON to implement user interaction with an XML database.
The essential requirements of the assignment are that the project presents a user with a form; when the user changes some of the form data, create a JSON-encoded object that includes data from the form, send it to a PHP script via an asynchronous XMLHttpRequest() using the POST method. The PHP script must create an object from the JSON string, get some data out of an XML database based on information in that object, create another object containing information obtained from the database, and return that object to the browser as another JSON string. The browser must then display information derived from the returned object without reloading the page.
The description of the project below uses a "login or register" form as the model for the project, but you do not need to use exactly this model. In fact, you are encouraged to create your own design for the project — provided only that your project incorporates all the elements outlined above. On the other hand, there is nothing wrong with following the design presented here.
Procedure
-
Set up the assignment.
Create a directory named Final_Project under your My Website directory, and create a web page named index.xhtml there. Either use the scripts and css subdirectories for your site, or create new ones inside your project directory.
-
Set up a form.
Code index.xhtml with a form where the user can enter an email address, password, and name. Style the form nicely, and make sure the XHTML and CSS validate. The form’s method and action attributes may be arbitrary values at this point because the form will not actually be submitted until much later in the project, if at all. Include a submit button, with meaningful text. Provide instructions to visitors telling them that they can log in by supplying an email address (which serves as the user name) and password, or they can register for the site by entering an email address, password, and name.
Include a paragraph on the page that tells the user that they don’t have JavaScript enabled and therefore will have to give full registration information each time they visit the site. Here is a sample screenshot. As mentioned above, I encourage you to customize your page so it doesn’t actually look like mine!
-
Set up basic JavaScript structures.
In addition to core.js used in previous projects, you will need json2.js, which you can get through the JSON website. Set up a function that will work with Core.start() in the usual way. In your init() function, hide the paragraph that says the user does not have JavaScript (needJS.style.visibility = 'hidden') and disable the submit button (submitButton.disabled = true). Set up an event listener to process change events in either the email or password fields. For now, it can just write a message to the console to be sure it is set up correctly.
-
Set up a PHP script to process XMLHttpRequest() calls.
I’ll use the name request_processor.php to refer to this file, but you can use any meaningful name you like. The big news is that this script is not valid XHTML in any way, shape, or form. It’s just a PHP script that will receive a JSON-encoded string as a POST parameter, and will echo another JSON-encoded string as its output. It’s not a web page.
There is no need to mess around here; it’s time to establish two-way XMLHttpRequest() interaction between the client (index.xhtml) and server (request_processor.php) parts of the project. When the user changes the email field to a non-empty string (for now, don’t worry about whether the email address is valid or not — any string will suffice), create an XMLHttpRequest object and send it to the server with the string as the data. No JSON at this point, just plain text. The server picks up the data, delays ten seconds, modifies the text slightly to prove that it really did operate on the data, and returns it to the client. The client’s readystatechange handler writes the response to the console. Have the server sleep for 5 seconds before replying to the request so you can verify that the exchange is actually happening asynchronously.
Be sure you set up the exchange so that no XML DOM tree is built. You do this by making sure your server script does not send an <?xml … ?> line and that it does not send a Content-Type header specifying XML or application/xhtml+xml. This issue should be no problem if you just remember that the server script is not a web page and you omit all the boilerplate code we have been using for web pages and do not generate any XHTML tags at all.
See page 311 of the text for how to set up the POST request on the client side.
If the XMLHttpRequest exchange completes with a status code of other than 200, display the returned statusText field to the user. I inserted that text in the "need JavaScript" paragraph and un-hid the paragraph. You can do it another way, but if you do use that technique, remember to hide the error message if the user changes either of the input fields again.
needJS.firstChild.nodeValue = "The error message you want to display goes here."; needJS.style.visibility = 'visible';
-
Clean up the server.
Once you have basic two-way communication working, clean up the server so that it is bullet-proof: be sure the request method was POST, and strip slashes if magic quotes is set. You should run the text through htmlspecialchars(), but do not let that function convert single or double quotes: you will need them later when processing JSON strings.
Take out the sleep() call: that’s not needed any more.
JSON escapes quotes in string data using backslashes, however this should not be affected by the call to stripslashes() because the backslashes in the JSON string should be doubly-escaped when magic quotes is on. But you will need to test your project carefully when you get to that point.
-
Exchange objects using JSON-encoded strings.
On the client side, you are to create an object that you are going to send to the server: var exchgObj = { email: emailInput.value, passwd: passwdInput.value };. Use JSON.stringify() to encode it, and pass it to the server.
On the server side, create a class that will mimic the contents of a database entry. It could look like this:
class DBentry { public $name, $email, $passwd; public function __construct($email, $passwd, $name = '') { $this->email = $email; $this->passwd = $passwd; $this->name = $name; } }
Note that the data members of this class must be public for this project. It’s not good object-oriented design, but necessary because only public members get processed when JSON-encoding objects. (This little factoid has been known to cause certain professors considerable anguish during the development stage of this assignment. Wise students should be extremely grateful to such professors for figuring this out and sharing the discovery with them.)
When the JSON-encoded object arrives from the client, decode it into another object, and use that object to create a new instance of the DBentry class:
$replyObj = new DBentry($clientObj->email, $clientObj->passwd, "Grateful Student");
JSON-encode the resulting object, and echo it back to the client. The client decodes the received string into another object, and uses the members of that object to update the web page.
-
Set up an XML database for the project.
The database is just a text file. The filename can be anything; database.xml would work, but you might want to use something less generic. The first line should be:
<?xml version="1.0" encoding="utf-8" ?>
You can use any names for the tags that you want, just make sure the structure is valid XML, which means that there has to be a root node that contains all other nodes, the tag and attribute names are case sensitive, must be properly nested, etc. Populate the database with a few entries. For example, you could have tags for email, password, and name. Modify your server so that it creates a DOM tree from the database.
Here some the code from my course calendar program you can use as a model for creating a DOM tree from an XML file and then processing information from the tree. If your database doesn’t use any attributes in the tag names, you do not have to worry about any of the attribute-processing code here:
$collegeCalendarFile = @file_get_contents("college_calendar.xml", "r") or die("Unable to read College calendar: $php_errormsg\n"); $college_dom = new DOMDocument(); $college_dom -> loadXML($collegeCalendarFile); $collegeEventElements = $college_dom->getElementsByTagName("event"); foreach ($collegeEventElements as $collegeEventElement) { if ($collegeEventElement->hasAttribute("id")) $collegeEventElement->setIdAttribute("id", true); $start = trim($collegeEventElement->getElementsByTagName('start')->item(0)->nodeValue); $endList = $collegeEventElement->getElementsByTagName('end'); $description = $collegeEventElement->getElementsByTagName('description')->item(0); $end = ($endList->length > 0) ? trim($endList->item(0)->nodeValue) : null; $noClass = $description->getAttribute('no-classes'); if ($noClass) { $firstDay = strtotime($start); $lastDay = strtotime($end); for ($day = $firstDay; $day <= $lastDay; $day += SecsPerDay) { $blockoutDates[date("Y-m-d", $day)] = true; } } etc.
When an email address and password come in, see if there is a node in the database that matches both, in which case, supply the user name from the database instead of the dummy name used above. If the email matches, but not the password, set the user name to some special value, like "wrong password", which the client will use to generate appropriate feedback for the user. If the email does not match anything in the database, set the used name to a different special value, like "not in database", which the client will use to change the label of the submit button to "Register Me".
-
Finish the project.
A working project at this point meets all the requirements of the assignment. Make sure the user interface is cleanly-coded, robust (test various kinds of inputs, including typing slashes and quotes in the various input fields), and attractive.
There are some additional features that you should add if you possibly can: the first is to vaidate email addresses on both the client and server sides, taking appropriate recovery action if either is not valid; the seond is to update the XML database to add a new user if the email address is not already in the database and all three fields are filled in; the third is to make the client operate properly when JavaScript is disabled, which will require setting up a form-processing script akin to the one in Assignment 4.
Check Your Work And Submit The Assignment
Due Date: December 22, 2007
Perform a link check on your site. If necessary, go to the Manage Sites panel and be sure you have selected the “case-sensitive link checking” option. Then right-click on your Assignment_03 directory and select the menu item from the context menu. Fix any errors you find there.
If necessary, copy your site from your development system to the lab as described above, and do a final check of your project using the ~<accountname> form of URL. Then send email to me telling me the project is ready for me to grade. I will copy the project from your account in the lab to babbage for testing.
The Subject line of your email must say, CS-90.3 Final Project, just like that, in order to get through my spam filters. Within a day, you should receive an “OK, I’ll check it out!” message from me acknowledging that I received your email.