University of Washington, CSE 190 M, Spring 2009
Homework Assignment 8: To-Do List
due Wednesday, May 27, 2009, 11:30pm electronically

This assignment is about writing a complete Ajax-enabled "Web 2.0" application, using the Scriptaculous JavaScript library and PHP web services.

In this assignment you will create a web page for an online to-do list. The user can add an item to the end of the to-do list, delete the first item from the list, or drag the items into a different order. Any of these changes made to the list will be saved to the web server using Ajax, so that if the user leaves the page and returns later, the current state of the list will be remembered.

The following image shows a rough idea of how your page should look, but many aspects of the appearance are not rigidly specified. See the following pages for more details.

expected output

Unlike in many of the past assignments, we will not be providing you with any starter code whatsoever for this assignment. While this will make a bit more work for you, the goal is that you will gain experience creating an entire web application from scratch. Turn in the following files:

This program uses Ajax to communicate with a PHP web service. In order for Ajax and PHP to work correctly, you must upload your files to the Webster server and test them there.

Page Behavior:

Unlike in past assignments, many aspects of the exact appearance of the page is not specified. Beyond the aspects on these pages, the rest is up to you, so long as it does not conflict with what is required here. If you want to use other resources such as image files, place them on your Webster space and link to them using absolute URLs. If you are unsure whether an aspect of your page is acceptable, ask your TA or the instructor. The goal is to be creative and personalize your page. You are should not match the screenshot in this document exactly; in fact, if you do copy its appearance, you will lose points for lack of creativity.

The page should contain a heading that identifies the course and the fact that this is a to-do list program. The page should contain images somewhere that link to the W3C XHTML/CSS validators and JSLint. Your page should have a "favorites icon" ("favicon"). One acceptable favicon would be the following image:

http://www.cs.washington.edu/education/courses/cse190m/09sp/homework/8/todolist_icon.gif   todo list icon

When the page first loads, it should show the current contents of the to-do list as an ordered list. Since the items are retrieved from the server, the page will not show any items until the server has been contacted. (The W3C XHTML validator complains if you have a list with no elements, so you may need to add an empty hidden element for it to validate.) Once the items arrive, they are added to your page using the DOM.

Apply a Scriptaculous appearing effect to the items, such as making the items "fade in" or "shake" when they arrive. You can make items initially invisible by calling hide on them or by setting their display style to none. An invisible element can be shown using Scriptaculous effects such as appear or grow. To put an effect on an element being deleted, consult Ch. 12 or the Scriptaculous slides on the afterFinish event.

Once the list appears, the user should be able to change its contents in at least the three following ways:

  1. add an item to the end of the list
  2. delete the item from the front of the list
  3. drag the list items to reorder them

buttons The UI for adding and deleting is up to you. For example, you could have a text field and "Add" and "Delete" buttons. Your page should not use alert or prompt boxes for this. You should reject empty strings as to-do items but otherwise can accept any text. If the user tries to delete when there are no items in the list, no JavaScript errors should occur.

Any change to the to-do list should be accompanied by a Scriptaculous effect of your choice, along with any other visual cues you want. For example, an added item could highlight or fade into view.

The reorderability of the list items should be done using Scriptaculous. Give the list an id and make it into a Sortable list. See the textbook or slides about subtleties of sortable lists, such as the ids on elements or their event properties. Also note that the sortability of a list breaks if you add or remove elements after you've made it sortable. To fix such a case, re-specify the list to be sortable after each modification.

When any of the three preceding actions (add, delete, reorder) has been made on the page, the page should immediately send an Ajax request to a server-side PHP web service todolist.php to inform the server of the change. The exact behavior of this service is described in the next section. If you've done this properly, at any point the user should be able to refresh the browser and still see the to-do list in its current state.

Any updates to the to-do list should appear instantly on the page. The instant that the user adds, deletes, or reorders items, the page should update to reflect this action. In the background, the page may be contacting the server to inform it of the change, but the page UI should not be out of date or locked up during this. You do not need to worry about multiple rapid updates overloading the server or arriving to the server out of order. Minimize the amount of heavy changes you make to the page's DOM; you should not destroy and recreate every list item in the DOM if only one item changes (i.e. on an add or remove).

Page Styling:

No CSS code is being provided to you, so the exact styling of your page is up to you. You should, however, set a non-trivial number of CSS styles including, but not limited to, the following:

PHP web service:

Your page's Ajax code should communicate with a PHP web service must support four types of web queries. To help you develop your program incrementally, we have placed a working version of the PHP web service at the following URL. You can initially write your page's code to talk to this working version if you like, but eventually you should re-implement the service yourself and connect your page to your own service.

https://webster.cs.washington.edu/todolist_server.php

The following are the four query types. Some queries use a request type of GET and others use POST. Your code should respect this distinction and should always send its queries using the proper request type.

  1. Getting the current contents of the to-do list: Every time the browser requests your PHP service, either as a GET or POST request, regardless of what parameters (if any) are passed to it, the service's output should always be a text/plain representation of the current to-do list, with one item per line. If the browser requests your service using a GET request, you should disregard any query parameters that may have been passed, and you should simply output the to-do list's current contents.

    The Get Items query (GET)
    Parameter nameValue
    (none) (none)

    The items in the list are separated by \n. For example, if the to-do list contains the following items:

    1. buy meatballs from Ikea
    2. shave head
    3. watch Flight of the Conchords

    then the web service's output would be the following plain text:

    buy meatballs from Ikea
    shave head
    watch Flight of the Conchords
    

    Your PHP code should store the current to-do list as a text file named todolist.txt. Your service should read that file's contents as a string and print them as output. If the service is being used for the first time and no todolist.txt file exists, no output is produced.

  2. Adding an element to the end of the to-do list: If the browser sends a POST request to your PHP service and passes the following two parameters, the web service should add an item to the end of the list:

    The Add Item query (POST)
    Parameter nameValue
    action "add"
    item the new to-do item's text as a string, such as "go to the store"

    Do this in your PHP code by reading the to-do list's current contents into your program, concatenating the new item to the end of the contents, and then writing these new longer contents to the file. As stated previously, the service's output should always be the current state of the to-do list, so your response to this query should be to print the list's contents after the item is added.

  3. Deleting the first element from the to-do list: If the browser sends a POST request to your PHP service and passes the following parameter, the web service should delete the first item from the front of the list:

    The Delete Item query (POST)
    Parameter nameValue
    action "delete"

    Do this in your PHP code by reading the to-do list's current contents into your program, removing the first line's text from the contents, and then writing the new shorter contents to the file. If the to-do list is currently empty or the todolist.txt file does not exist, this query has no effect; the list remains empty, no output is produced, and the program should not crash or display an error.

    As stated previously, the service's output should always be the current state of the to-do list, so your response to this query should be to print the list's contents after the item is deleted.

  4. Setting (replacing) the entire contents of the to-do list: If the browser requests your PHP service as a POST request and passes the following two parameters, then the web service should completely replace the items in the to-do list with a new set of items:

    The Set Items query (POST)
    Parameter nameValue
    action "set"
    items a string representing to-do items separated by \n line breaks, such as:
    "buy meatballs from Ikea\nshave head\nwatch Flight of the Conchords"

    This third query replaces the entire contents of the to-do list with a new list. You can use this query to implement the rearranging of the list when the user drags an element into a new position. In your JavaScript code, use the DOM to gather the text of all elements of the to-do list into a large string, then send this string as a parameter named items in your Ajax request. In your PHP code, write this string's contents into the todolist.txt file on the server, replacing any previous contents of the file.

    The set query is powerful, but it is also inefficient since all items must be sent from the client to the server. It would be possible to implement the add and delete operations by having the page's JavaScript code re-send the entire list of elements to the server using the set action. But this would be inefficient for large lists of items, so you should not implement those operations in that way.

    In this query it is most important for you to understand the difference between GET and POST requests. Since the request you're sending holds a large amount of query data including \n line breaks, it potentially would not submit successfully as a GET request (as part of a URL query string). Make sure you are submitting this data as a POST request so that it will reach the server successfully.

    As stated previously, the service's output should always be the current state of the to-do list, so your response to this query should be to print the list's contents after the items have been set.

While attempting to write to the file todolist.txt, you may see an error of, "failed to open stream: Permission denied". This can occur when the web server's PHP process doesn't have proper permission to write to the file. Try deleting the file on Webster and letting the PHP code recreate it. You might also need to give additional write or execute permissions on your overall hw8 folder.

We recommend that you debug your queries in Firebug. You can see each Ajax query request in the Console tab. Expand it with the + sign to view the query parameters passed and the web service's response.

Extra Features:

In addition to the previous requirements, you must also complete at least one of the following additional features. If you want to complete more than one, that is fine, but only one is required.

Near the top of your HTML file, put a comment saying which extra feature(s) you have completed. If you implement more than one, comment which one you want us to grade (the others will be ignored). Regardless of how many additions you implement, the main behavior should still work as specified. If you have a different idea for an addition to the program, please ask us and we may approve it. Beyond this, you can add any other functionality you like to your page. Such functionality will be ignored for grading as long as it does not interfere with your code's stylistic quality or our ability to test the specified functionality.

Development Strategy:

There is a lot of code to be written, and none of it is being provided to you. It can be challenging to know where to start or how to make the various pieces fit together. We suggest roughly the following development strategy for this assignment:

For reference, our solution has roughly 55 lines of XHTML, 70 lines of CSS, 90 lines of JavaScript, and 40 lines of PHP including blank lines and comments. You do not need to match these totals.

Style guidelines:

Your XHTML and CSS code should be well-styled as in past assignments. For full credit, your page must pass the W3C XHTML and CSS validators. As much as possible, you should show proper separation of content, presentation, and behavior. In other words, place style information in CSS, not in XHTML or JavaScript DOM code; and place all JavaScript code in JS files, not in the XHTML page. Express CSS concisely and without unnecessary or redundant styles. Format your code with proper whitespace and indentation. Do not place more than one block element on the same line or begin any block element past the 100th character on a line. Place a comment header in each XHTML and CSS file containing your name, section, and a brief description of the assignment and the file's contents.

Your JavaScript and PHP code should follow reasonable stylistic guidelines similar to those you would follow on a CSE 14x programming assignment. Use the HTML DOM appropriately. Follow proper style in your Ajax requests, including obeying the proper query request type (GET vs. POST). Minimize redundant code, decomposing the problem into functions intelligently. Minimize the number of global variables. Utilize parameters and return values properly. Format your code: correctly use indentation and spacing, avoid long lines over 100 characters in length. Place a comment header at the top of your code files, atop every function explaining that function's behavior, and on complex code sections. You should not use any other libraries besides Prototype and Scriptaculous, unless given explicit permission from the instructor.

Your JavaScript code should pass the JSLint validator, should correctly utilize Ajax requests and XHTML DOM objects for interacting with the server and manipulating the page contents.

Your PHP code should generate no error or warning messages when run using reasonable sets of parameters.

Part of your grade will come from successfully uploading your files to the Webster server at the URL:

https://webster.cs.washington.edu/your_uw_netid/hw8/todolist.html

Please do not place a solution to this assignment online on a publicly accessible web site.