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: Appending and Removing Elements

Why do the list items move around instead of simply adding new ones?

Okay so in this section we were creating this piece of code to make the list items move around between the two "ul"s dependent on whether we checked or unchecked the "li"s checkbox.

//Mark tasks completed
var taskCompleted = function(){
  console.log("Mark task completed...")
  var listItem = this.parentNode;
    //Append the task list item to the #completed-tasks
  completedTasksHolder.appendChild(listItem);
  bindTaskEvents(listItem, taskIncomplete);
}

//Mark tasks incomplete
var taskIncomplete = function(){
  console.log("Mark task incomplete...")
  var listItem = this.parentNode;
    //Append the task list item to the #incomplete-tasks
  incompleteTasksHolder.appendChild(listItem);
  bindTaskEvents(listItem, taskCompleted);
}

But my question is this: After appending the newly generated list items why do the original list items disappear? Isn't appending simply about creating a new element?

Here is the complete code btw.

// Problem: User interaction doesn't work
// Solution: Adding interactivity so the user can manage his tasks
var taskInput = document.getElementById("new-task"); //new-task
var addButton = document.getElementsByTagName("button")[0]; //first button
var incompleteTasksHolder = document.getElementById("incomplete-tasks"); //incomplete-tasks
var completedTasksHolder = document.getElementById("completed-tasks"); //completed-tasks

//New task list item generator
var createNewTaskElement = function(taskString){
  //Create listitem
  var listItem = document.createElement("li");
  //input checkbox
  var checkBox = document.createElement("input"); //checkbox
  //label
  var label = document.createElement("label");
  //input(text)
  var editInput = document.createElement("input");
  //button with the edit class
  var editButton = document.createElement("button");
  //button with the delete
  var deleteButton = document.createElement("button");

  //Each element needs modifying

  //Each element needs appending

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

  return listItem;
}


//Add a new task
var addTask = function(){
  console.log("Add task...")
  //When the button is pressed, we want to create a task
    //Create a new list item from the text of the input
  var listItem = createNewTaskElement(".....");

  incompleteTasksHolder.appendChild(listItem);
  bindTaskEvents(listItem, taskCompleted);
}

//Edit existing tasks
var editTask = function(){
  console.log("Edit task...")
   //When the edit button is pressed 
    //if the class of the parent is .editMode
      //Switch from .editMode
      //label text become the input's value
    //else
      //Switch to .editMode
      //input's value becomes the label's text
    //toggle editmode
}

//Delete an existing task
var deleteTask = function(){
   console.log("Delete existing task...")
   //When the delete button is pressed
    //Remove parent list item from the ul
}

//Mark tasks completed
var taskCompleted = function(){
  console.log("Mark task completed...")
  var listItem = this.parentNode;
    //Append the task list item to the #completed-tasks
  completedTasksHolder.appendChild(listItem);
  bindTaskEvents(listItem, taskIncomplete);
}

//Mark tasks incomplete
var taskIncomplete = function(){
  console.log("Mark task incomplete...")
  var listItem = this.parentNode;
    //Append the task list item to the #incomplete-tasks
  incompleteTasksHolder.appendChild(listItem);
  bindTaskEvents(listItem, taskCompleted);
}

var bindTaskEvents = function(taskListItem, checkBoxEventHandler) {
  console.log("Bind list items"); 
  //select its list item
  var checkBox = taskListItem.querySelector("input[type=checkbox]")
    //bind editTask to editButton
  var editButton = taskListItem.querySelector("button.edit");
    //bind deleteTask to deleteButton
  var deleteButton = taskListItem.querySelector("button.delete");
    //bind checkBoxEventHandler to checkbox
  editButton.onclick = editTask;
  deleteButton.onclick = deleteTask;
  checkBox.onchange = checkBoxEventHandler;
}

addButton.onclick = addTask;

//cycle over incompleteTasksHolder ul list items
for(var i=0; i < incompleteTasksHolder.children.length; i++ ){
  bindTaskEvents(incompleteTasksHolder.children[i], taskCompleted);
}
   //for each list item
    //bind events to list item children (taskCompleted)


//cycle over completedTasksHolder ul list items
for(var j=0; j < completedTasksHolder.children.length; j++){
  bindTaskEvents(completedTasksHolder.children[j], taskIncomplete);
}
   //for each list item
    //bind events to list item children (taskIncomplete)

1 Answer

rydavim
rydavim
18,813 Points

Good question! Basically, the appendChild() method is actually doing this for you. If you call it referencing an existing node, it will remove it before appending it to the new element.

If you didn't want this to happen, you would probably want to use cloneNode() instead.

Aaaaaah. Ty. Now it makes sense ^^