To-do list in jQuery
I've followed this excellent tutorial on how to create a to-do list in jQuery:
http://www.youtube.com/watch?v=SkmF8eUOUrE
I've adapted it (and therefore simplified it) slightly by removing the ability to add and remove tasks. Instead the list will be populated by a database and updated every so often. Users will be able to view this task list and tick off which tasks they've done. So every user has the same task list but they can all check off their own personal progress on that task list.
Problem
The part that's missing is getting the browser to remember what tasks the user has done. When a user ticks an item on the list and refresh the page, the list refreshes and the completed tasks are forgotten.
Question
What's the best way to resolve this? I'm thinking of using cookies, but would I need to have a different cookie for every task? The to-do list will be updated regularly so in theory we might need to create thousands of cookies. Is this ok or is there a better way?
Here is my jQuery:
function completeItem(){
if( jQuery(this).parent().css('textDecoration') == 'line-through' ){
jQuery(this).parent().css('textDecoration', 'none').removeClass('due-linethrough');
}else{
jQuery(this).parent().css('textDecoration', 'line-through').addClass('due-linethrough');
}
}
jQuery(function() {
jQuery(document).on('click', '.complete', completeItem);
});
And here's the html
<ul id="noticeboard-list">
<li><label class="checkbox"><input type="checkbox" class="complete">Do task 1</label></li>
<li><label class="checkbox"><input type="checkbox" class="complete">Do task 2</label></li>
<li><label class="checkbox"><input type="checkbox" class="complete">Do task 3</label></li>
</ul>
Many thanks for your help!
Katie
Edits following suggestion to use jstorage from kri5t
Instead of cookies I'm trying to use jstorage. The following shows my new code:
jquery
function completeItem(){
taskID=jQuery(this).attr('id');
if( jQuery(this).parent().css('textDecoration') == 'line-through' ){
jQuery(this).parent().css('textDecoration', 'none').removeClass('due-linethrough');
jQuery.jStorage.set(taskID, 'done');
}else{
jQuery(this).parent().css('textDecoration', 'line-through').addClass('due-linethrough');
jQuery.jStorage.deleteKey(taskID);
}
}
HTML
<ul id="noticeboard-list">
<li><label class="checkbox"><input type="checkbox" class="complete" id="HPtask1">Do task 1</label></li>
<li><label class="checkbox"><input type="checkbox" class="complete" id="HPtask2">Do task 2</label></li>
<li><label class="checkbox"><input type="checkbox" class="complete" id="HPtask3">Do task 3</label></li>
</ul>
When a user ticks the checkbox, the taskID is set to 'done'. When they untick it, it is deleted. But how do I use this information to set the text-decoration to line-through for all checkboxes which have Keys in jstorage (e.g. HPtask1) that correspond with the matching ID (e.g. HPtask1) where the value of the key is 'done'? (Hope that makes sense!).
Thanks again :D
Many thanks Kristian - I've managed to achieve what I wanted using jStorage. I've posted my code below for interest. It seems to work - thanks for your suggestion to use jStorage - I've learnt something new! The only thing that would be nice is to expire the individual tasks after 90 days, like a cookie, but I can only see how to expire stuff in units of minutes.
There's only likely to be 4 or 5 tasks on display at any one time as the tasks will expire. But there could be thousands of expired tasks stored in the jStorage data. Would this slow things down or have any negative effect for users? If so, does anyone have any suggestions on how to improve efficiency/expire the old data?
Many thanks again,
Katie
jQuery
function completeItem(){
var taskID=jQuery(this).attr('id');
/*Check whether the task clicked already has a line-through*/
if( jQuery(this).parent().css('textDecoration') == 'line-through' ){
/*Remove the line through*/
jQuery(this).parent().css('textDecoration', 'none').removeClass('done');
jQuery(this).parent().parent().siblings().removeClass('done');
/*Remove the current task from storage (i.e. forget that it was marked as done)*/
jQuery.jStorage.deleteKey(taskID)
}else{
/*Add a line through*/
jQuery(this).parent().css('textDecoration', 'line-through').addClass('done');
jQuery(this).parent().parent().siblings().addClass('done');
/*Add the task to storage (i.e. remember that it has been marked as done)*/
jQuery.jStorage.set(taskID, 'done');
}
}
jQuery(function() {
/*Create array from task list IDs*/
var taskListIDs = jQuery("ul#noticeboard-list li input").map(function() {return this.id; }).get();
//var taskArray = jQuery.jStorage.index();
var n;
/*loop through each item in the array of tasks visible on the page*/
for (n = 0; n < taskListIDs.length; ++n) {
/*Get the ID of the nth item in the array*/
var uniqueTask = taskListIDs[n];
/*Find out whether the current task has been marked as done*/
var taskStatus = jQuery.jStorage.get(uniqueTask);
/*Check if the current task in the array has been marked as done*/
if (taskStatus == 'done'){
/*Add a line-through and add class to override blue highlighting for an item that's due*/
jQuery('#'+uniqueTask).parent().css('textDecoration', 'line-through').addClass('done');
/*Add a tick in the checkbox*/
jQuery('#'+uniqueTask).prop('checked', true);
/*Add class to override highlighting*/
jQuery('#'+uniqueTask).parent().parent().siblings().addClass('done');
}
}
/*every time user clicks on item, check if it has the class .complete. If yes, perform competeItem.*/
jQuery(document).on('click', '.complete', completeItem);
});
HTML
<ul id="noticeboard-list">
<li><div class="task"><label class="checkbox due"><input type="checkbox" class="complete" id="HPtask24">Task 1</label></div><div class="due-date due">Feb<br><span>27</span></div></li>
<li><div class="task"><label class="checkbox"><input type="checkbox" class="complete" id="HPtask31">Task 2</label></div><div class="due-date">Mar<br><span>19</span></div></li>
<li><div class="task"><label class="checkbox"><input type="checkbox" class="complete" id="HPtask54">Task 3</label></div><div class="due-date">May<br><span>06</span></div></li>
</ul>