Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Clara Roldan
Clara Roldan
3,074 Points

"Perfected" version + add support for return key event

Here's my version of the To-do app with the recommended improvements. I've also added events for the return key, so you can also press return to create / save a task.

Any feedback welcome!

//Problem: user interaction doesn't provide desired results

//Solution: add interactivity so the user can manage daily tasks

//Interaction needed:

var taskInput = document.getElementById('new-task');

var addButton = document.getElementsByTagName('button')[0];
var editButton;
var deleteButton;

var incompleteTaskHolder = document.getElementById('incomplete-tasks');
var completedTaskHolder = document.getElementById('completed-tasks');

var createNewTaskElement = function(taskString) {

  var listItem = document.createElement('li');

  //add input (checkbox)
  var checkbox = document.createElement('input');
  checkbox.type = "checkbox";

  //label
  var label = document.createElement('label');
  label.innerText = taskString;

  //input (text) for editing
  var editInput = document.createElement('input');
  editInput.type = "text";

  //button .edit
  var editButton = document.createElement('button');
  editButton.className += " edit";
  editButton.innerText = "Edit";

  //button .delete
  var deleteButton = document.createElement('button');
  deleteButton.className += " delete";
  deleteButton.innerText = "Delete";

  //apppend all elements to document
  listItem.appendChild(checkbox);
  listItem.appendChild(label);
  listItem.appendChild(editInput);
  listItem.appendChild(editButton);
  listItem.appendChild(deleteButton);

  return listItem;
}

//add a task
var addTask = function() {
  console.log('Add task');
  console.log(taskInput.value);

  if(taskInput.value){
    //create news list item with the text from #new-task
    var listItem = createNewTaskElement(taskInput.value);

    //bind events to new task
     bindTaskEvents(listItem, taskCompleted);

    //append listItem to the incomplete list
    incompleteTaskHolder.appendChild(listItem);

    //clear input value
    taskInput.value = '';
  } else {
    alert("Please enter a task");
  }
}

//add a task by pressing enter on task input
var enterKeyPress = function(e, handler){
  if (e.which == 13 || e.keyCode == 13){
    console.log('You pressed the enter key!');
    handler(e);
  }
}

//edit a task
var editTask = function(e) {
  console.log('Edit task');

  var eventTarget = e.currentTarget;
  var listItem = eventTarget.parentNode;
  var label = listItem.querySelector('label');
  var editInput = listItem.querySelector('input[type=text]');
  var editButton = listItem.querySelector('button[class=edit]');

    //if the parent has class .editMode
  if(listItem.classList.contains('editMode')){
    //exit .editMode, switch to normal mode
    listItem.classList.remove('editMode');
    //update label text with input value (save task)
    label.innerText = editInput.value;
    //update edit button text
    editButton.innerText = 'Edit';
  } else {
    //enter .editMode, reveal edit input
    listItem.classList.add('editMode');
    //make input value the text from the label
    editInput.value = label.innerText;
    //update edit button text
    editButton.innerText = 'Save';
  }
}

//delete a task
var deleteTask = function() {
  console.log('Delete task');
  //remove the parent (li) from list (ul)
  var listItem = this.parentNode;
  var ul = listItem.parentNode;
  ul.removeChild(listItem);
}

//mark a task as complete
var taskCompleted = function(){
  console.log('Task completed');
  //append (move) task to the #completed-tasks
  var listItem = this.parentNode;  
  completedTaskHolder.appendChild(listItem);
  bindTaskEvents(listItem, taskIncomplete);
}

//mark a task as incomplete
var taskIncomplete = function() {
  console.log('Task incomplete');
  //append (move) task to the #incomplete-tasks
  var listItem = this.parentNode;  
  incompleteTaskHolder.appendChild(listItem);
  bindTaskEvents(listItem, taskCompleted);
}

var bindTaskEvents = function(taskListItem, checkBoxEventHandler){
  console.log('bind list items event');
  //select taskListItems children
   var checkbox = taskListItem.querySelector('input[type=checkbox]');
   var editButton = taskListItem.querySelector('button.edit');
   var editInput = taskListItem.querySelector('input[type=text]');
   var deleteButton = taskListItem.querySelector('button.delete');

  //bind editTaskt to edit button
    //when clicking on button
    editButton.addEventListener('click', editTask);
    editInput.addEventListener('keypress', function(e){
      enterKeyPress(e, editTask);
    });

  //bind deleteTask to delete button
    deleteButton.addEventListener('click', deleteTask);

  //bind checkBoxEventHandler to checkbox
    checkbox.onchange = checkBoxEventHandler;
};

//Add task event by clicking on button
addButton.addEventListener('click', addTask);

//Add task event by pressing Enter key
taskInput.addEventListener('keypress', function(e) {
  enterKeyPress(e, addTask);
});

var falsefunction = function(){
  console.log('false function');
}

addButton.addEventListener('click', falsefunction);

//Add events to items
//cycle over incompleteTaskHolder ul li items
    var incompleteChildren = incompleteTaskHolder.children;
    for (var i = 0; i < incompleteChildren.length; i++) {
      //bind events to children elements to mark tasks as completed (taskCompleted)
      bindTaskEvents(incompleteChildren[i], taskCompleted);
    }


//cycle over completedTaskHolder ul li items
    var completeChildren = completedTaskHolder.children;
    for (var i = 0; i < completeChildren.length; i++) {
      //bind events to children elements to mark tasks as completed (taskCompleted)
      bindTaskEvents(completeChildren[i], taskIncomplete);
    }
Alison Kirk
Alison Kirk
6,326 Points

Thanks for posting! Cross-comparing helped me track down a silly error in my code.