Building the All Tasks Screen

Building the All Tasks Screen

Once again, we will start with a mockup of the screen (displayed in Figure 4–8). The screen, as you might expect, shows a list of all the outstanding tasks, with the due date.

Figure 4–8. Design mockup of the to-do list main screen Based on what’s displayed in the preceding mockup, we are pretty much covered in

terms of our Storage methods, as we can both get tasks in priority order and complete tasks. This, then, is simply going to be a UI and wiring exercise.

It would be great if the back button were automatically displayed for any screen that isn’t the main screen of the application. It will be worth adding some additional code to the PROWEBAPPS.ViewManager module to provide us with that functionality.

It’s time to implement the UI. This will involve the following:

1. Implementing the basic HTML layout in the todolist.html file.

2. On activation of this screen, reading the current items from the database and generating a list of those items.

3. Handling a user tapping on an individual item. This will show the details (and the complete task link) for that item, hiding the previously selected item. Some nice jQuery transitions ( slideUp, slideDown) will look good here.

4. Finally, handling a user marking a task as complete. This will be an exercise for you.

86 CHAPTER 4: Constructing a Multipage App

First is the HTML layout. There isn’t much required here as most of the display for this screen will be dynamically generated using JavaScript:

<div id="alltasks" class="view"> <h1 class="fancy">All Tasks</h1> <ul id="tasklist"> </ul>

</div> From here we move on to reading the current items from the database and populating

the display. This involves some application code to handle activation of the #alltasks div. We create the handler method in the TODOLIST module (we put it right after the activateMain function added before):

activateAllTasks: function() { TODOLIST.Storage.getTasksInPriorityOrder(function(tasks) { // update the current tasks currentTasks = tasks;

populateTaskList();

// refresh the task list display jQuery("ul#tasklist li").click(function() {

toggleDetailsDisplay(this); });

jQuery("ul#tasklist a.task-complete").click(function() { // complete the task alert("complete the task");

You can see that this code updates a variable called currentTasks, and then calls a function called populateTaskList, and finally attaches event handling to the newly created list items (assuming there are tasks). If a list item is clicked, the toggleDetailsDisplay function is called to display the description and complete button for that task.

The currentTasks variable should be created in the TODOLIST module scope so that any code that would like to access this variable can do so:

TODOLIST = (function() { ...

// define an array that will hold the current tasks

var currentTasks = [];

// define the module var module = {

return module; })();

CHAPTER 4: Constructing a Multipage App

We then create our populateTaskList function as a private function in the TODOLIST module scope:

function populateTaskList() { function pad(n) { return n<10 ? '0'+n : n; }

var listHtml = "", monthNames = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"];

// iterate through the current tasks for (var ii = 0; ii < currentTasks.length; ii++) {

var dueDateHtml = "<ul class='calendar right'>" +

"<li class='day'>" + pad(currentTasks[ii].due.getDate()) + "</li>" + "<li class='month'>" + monthNames[currentTasks[ii].due.getMonth()] +

"</li>" +

"<li class='year'>" + currentTasks[ii].due.getFullYear() + "</li>" + "</ul>";

// add the list item for the task listHtml += "<li id='task_" + currentTasks[ii].id + "'>" + dueDateHtml +

"<div class='task-header'>" + currentTasks[ii].name + "</div>" + "<div class='task-details'>" +

currentTasks[ii].description + "<br />" + "<a href='#' class='task-complete right'>COMPLETE TASK</a> " +

"</div>" + "</li>";

} // for

jQuery("ul#tasklist").html(listHtml); } // populateTaskList

The preceding code populates the ul#tasklist with the HTML required to display both the task name, due date, description, and complete task link. Let’s take a peek at how that looks. With a couple of tasks in the database, it renders a display like the one shown in Figure 4–9.

88 CHAPTER 4: Constructing a Multipage App

Figure 4–9. The All Tasks display with no style applied. What did we do before CSS? It’s pretty obvious that the screen needs to have some style applied, and it’s probably

appropriate that we do that now before implementing any more JavaScript (otherwise we won’t be able to tell when something is selected). The following CSS will give us a result similar to the mockup:

ul#tasklist { margin: 0; padding: 0; list-style-type: none;

ul#tasklist > li { padding: 0; margin: 0; clear: both; background: #ececec;

ul#tasklist > li:nth-child(2n) { background: #cccccc; }

ul#tasklist .task-header { padding: 19px 0px 17px 10px; }

ul#tasklist .task-details { clear: both; background: #333333;

CHAPTER 4: Constructing a Multipage App

color: white; padding: 8px; display: none;

} ul#tasklist .task-details a {

color: white; text-decoration: none; font: bold 0.8em Arial;

} While most of this is common CSS, note the bold CSS3 selector for the list items within

#tasklist. This selector matches every second list item in the task list, and thus an alternative background color is applied. There are quite a few additional CSS selectors available in the CSS3 selectors specification ( www.w3.org/TR/css3- selectors/#selectors), so it’s well worth keeping an eye on what’s going on in that space. While we won’t go through them in detail here, we would definitely encourage you to visit the link at the W3C site and experiment with them in your own applications.

We also apply some extra styles to make our date look like a nice little calendar: ul.calendar {

-webkit-border-radius: 4px; -webkit-box-shadow: 0 0 2px #333333; background: -webkit-gradient(linear, left top, left bottom, color-stop(0.0,

#F8F8F8), color-stop(1.0, #AAAAAA)); margin: 6px 6px 6px 0; padding: 0 6px; list-style-type: none;

} ul.calendar li {

margin: 0; padding: 0;

text-align: center; font-weight: bold; font-size: 0.7em;

Download from Wow! eBook <www.wowebook.com>

} ul.calendar li.day {

font-size: 0.85em; padding: 1px 0 0 0;

} With the stylesheet applied, our screen should look something like the one in Figure 4–

90 CHAPTER 4: Constructing a Multipage App

Figure 4–10. With some CSS applied, it’s starting to look the part. So we are almost there. We just need to go back and add the required JavaScript to

toggle the display of the task description and complete the task link: function toggleDetailsDisplay(listItem) {

// slide up any active task details panes jQuery(".task-details").slideUp();

// if the current item is selected, implement a toggle if (activeItem == listItem) {

activeItem = null; return;

// in the current list item, toggle the display of the details pane jQuery(listItem).find(".task-details").slideDown();

// update the active item activeItem = listItem;

} // toggleDetailsDisplay

CHAPTER 4: Constructing a Multipage App

EXERCISE 4–2: FINISHING OFF THE ALL TASKS SCREEN

We’re going to go on ahead and implement those extensions to the PROWEBAPPS.ViewManager module to support automatically adding a Back link for screens other than the application main screen. If you wouldn’t mind finishing off the All Tasks screen, that would be fantastic.

From here, all that really needs to be done is to implement the complete-task functionality—but that should be pretty simple given we did it on the main screen. You could also add some additional CSS to show that a task is overdue (as per the mockup).