Step 7
Exercises
- Add a button to show the removed friends. Solution
- Insert an input to ask at the user a new email to add. Solution
Adding filters and bulk actions
Now we want to add some filters to show all, only active or only completed tasks.
The first thing we need to do is adding some markup for our filter buttons. Let’s add the following HTML under <ul id="task-list" class="list-group"></ul>
:
7.1 – the filters markup
<div class="panel-footer text-center small">
<span>Show:</span>
<button onclick="filterItems()" class="filter filter-all">All</button>
<button onclick="filterItems('active')" class="filter filter-active">Active</button>
<button onclick="filterItems('completed')" class="filter filter-completed">Completed</button>
</div>
We added a button with an onclick
handler that will execute a filterItems()
function. Let’s create that function:
7.2 – the new filterItems()
function
var filterItems = function(status) {
var itemsToShow = [];
if (status == 'completed') {
itemsToShow = listItems.filter(function(item) {
return item.completed;
});
} else if (status == 'active') {
itemsToShow = listItems.filter(function(item) {
return !item.completed;
});
} else {
itemsToShow = listItems;
}
updateList(itemsToShow);
}
This function will call updateList()
by passing a list of itemsToShow
that we create using the array filter()
function.
But there’s a catch, updateList()
will also save our tasks each time we call it!
We want this to happen when we modify our task list (for example adding, deleting, and marking items as done), but we don’t want this if we are simply applying a filter.
What can we do to avoid this? The solution is to modify our updateList()
function for accepting a second parameter, that we will call save
.
7.3 – the updated updateList()
function
var updateList = function(items, save) {
var listElement = document.querySelector('#task-list');
listElement.innerHTML = '';
items.forEach(function(item) {
listElement.innerHTML += renderItem(item);
});
if (save) localStorage.listItems = JSON.stringify(items);
}
When we will call the updateList()
function by passing true
as second parameter, the last line will be executed, otherwise our tasks will not be saved.
updateList(listItems, true) // this will save our tasks.
updateList(listItems) // this will not.
Now we can use updateList()
with the second parameter set to true
when we want to save (in our createNew()
, removeItem()
and toggleStatus()
), and without the second parameter when we want to filter. This will make our filters work as we want.
Go ahead and modify the createNew()
, removeItem()
and toggleStatus()
functions by passing true
as second parameter to the updateList()
function call!
Adding a “Clear completed” button
We also want to add a button that cleans up all completed tasks. Let’s add the markup to our panel footer:
<hr>
<button onclick="clearCompleted()" class="btn btn-default btn-xs">Clear completed</button>
The onclick
handler will call a clearCompleted()
function. Let’s create it:
7.4 – the new clearCompleted()
function
var clearCompleted = function() {
listItems = listItems.filter(function(item) {
return !item.completed;
});
updateList(listItems, true);
}
Once again we will use the filter()
function available on arrays for obtaining a copy of our listItems
containing only elements that are not completed. After, we will call updateList()
as usual, saving our tasks to localStorage
.
What we just did:
- we added filter support by implementing a
filterItems()
function - we modified our
updateList()
function by making it accept a newsave
parameter - we added a “Clear completed” button that clears completed tasks