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 Interactive Web Pages with JavaScript Traversing and Manipulating the DOM with JavaScript Perform: Modifying Elements

Eric Flood
Eric Flood
3,920 Points

Tasks no longer shift from complete to incomplete and delete only works for tasks that were pre-created.

Basically, when new tasks are created they are appended and look alright. Tasks are no longer able to move from completed to incomplete or vice versa, they have become static but only after this lesson. Here is my code.. any help would be appreciated.

var taskInput= document.getElementById('new-task'); //#newtask
var addButton = document.getElementsByTagName('button')[0];//first button
var incompleteTaskHolder = document.getElementById('incomplete-tasks'); //incomplete-tasks
var completedTasksHolder= document.getElementById('completed-tasks'); //completed-tasks

//new task lisk item
var createNewTaskElement = function(taskString){
  var listItem = document.createElement("li");
  var checkBox = document.createElement("input"); //checkbox type
  var label = document.createElement("label");
  var editInput = document.createElement("input"); //edit label
  var editButton = document.createElement("button");
  var deleteButton = document.createElement("button");


  //each element needs to be modified
  checkBox.type = "checkbox";
  editInput.type = "text";

  editButton.innerText = "Edit";
  editButton.className = "edit";
  deleteButton.innerText = "Delete";
  deleteButton.className = "delete";

  label.innerText = taskString;

  listItem.appendChild(checkBox);
  listItem.appendChild(label);
  listItem.appendChild(editInput);
  listItem.appendChild(editButton);
  listItem.appendChild(deleteButton);

  return listItem;

}

var addTask = function(){
  console.log("added task");
  var listItem = createNewTaskElement(taskInput.value); 
  //append listItem to incompleteTaskHolder
  incompleteTaskHolder.appendChild(listItem);
  bindTaskEvents(listItem, taskCompleted);
}

var editTask = function(){
  console.log("edited task");
  var listItem = this.parentNode;  
  var editInput = listItem.querySelector("input[type=text]");  
  var label = listItem.querySelector("label");

  var containsClass = listItem.classList.contains("editMode");
  if(containsClass){
    label.innerText = editInput.value;
  }else{
    editInput.value = label.innerText;
  };
  //toggle edit mode on <li>
  listItem.classList.toggle("editMode");
}

var deleteTask = function(){
    console.log("deleted task");
  //remove parent list item from <ul>
  var listItem = this.parentNode;
  //the <ul> from the <li> already selected in listeItem
  var ul = listItem.parentNode;
  //we want to remove the <li> from <ul>
  ul.removeChild(listItem);

}

var taskCompleted = function(){
  //append to #completed-tasks
  var listItem = this.parentNode;//this is the <li> element b/c we are on the checkbox itself
  completedTasksHolder.appendChild(listItem);//appending to under <li>
  bindTaskEvents(listItem, taskIncomplete);
  console.log("completed task");
}

var taskIncomplete = function(){
  var listItem = this.parentNode;
  incompleteTaskHolder.appendChild(listItem);
  bindTaskEvents(listItem, taskCompleted);
  console.log("incomplete task");
}

//STAY DRY
//cycle over list items in ul
//select list items' children 

//bind editTask to edit button
//bind deleteTask to delete button
//bind completed or incomplete to task box
var bindTaskEvents = function(taskListItem, checkBoxEventHandler){
console.log('bind item events');
  var checkBox = taskListItem.querySelector('input [type="checkbox"]');
  var editButton = taskListItem.querySelector("button.edit");
  var deleteButton = taskListItem.querySelector("button.delete");

  editButton.onclick = editTask;
  deleteButton.onclick = deleteTask;
  checkBox.onchange = checkBoxEventHandler;
}

//set click handler to addTask function - does not autocall but links them
addButton.onclick = addTask;

//cycle over the completed holder ul list items
//bind events to task items children (taskCompleted)
for(var i =0; i < incompleteTaskHolder.children.length; i++){
  bindTaskEvents(incompleteTaskHolder.children[i], taskCompleted);
}

//cycle over the completed holder ul list items
//bind events to task items children (taskIncomplete)
for(var i =0; i < incompleteTaskHolder.children.length; i++){
  bindTaskEvents(completedTasksHolder.children[i], taskIncomplete);
}

2 Answers

Inside of the addTask function, use

bindTaskEvents(listItem, taskCompleted);

this makes sure you checkbox and buttons are not binding with the event handlers.

it should look like this:

//add new task
var addTask = function() {

    //when button is pressed
    //create a new list item with text from new task
    var listItem = createNewTaskElement(taskInput.value);

    //append listItem to incompleteTasksHolder
    incompleteTasksHolder.appendChild(listItem);

    bindTaskEvents(listItem, taskCompleted);
}

Thanks for that!

Andrei Punei
Andrei Punei
14,051 Points

Thank you I had the same problem and I stood a bit just to figure it out, I much appreciate the solution you've given.