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

Jose Linares
Jose Linares
5,062 Points

When the for loop runs ???

I'm having a hard time to understand this for loop. I know that when the page loads it runs, but does it run again when I click on a checkbox ???, and If it does not, how are the functions taskCompleted() and taskIncomplete() called ??? (the for loops are in the end)

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
function createNewTaskElement(taskString){
//create list items
  var listItem = document.createElement("li");
  var checkbox = document.createElement("input");
  var label = document.createElement("label");
  var editInput = document.createElement("input");
  var editButton = document.createElement("button");
  var deleteButton = document.createElement("button");
//appending list items
  listItem.appendChild(checkbox);
  listItem.appendChild(label);
  listItem.appendChild(editInput);
  listItem.appendChild(editButton);
  listItem.appendChild(deleteButton);

  return listItem;
}

//add a new task
function addTask(){
  console.log("Add task....");

//create a new list item with the text from #new-task
  var listItem = createNewTaskElement("some new task");

//append listItem to incompleteTasksHolder
  incompleteTasksHolder.appendChild(listItem);
  bindTaskEvents(listItem, taskCompleted);
}

//edit an existing task
function editTask(){
  console.log("Edit task....");

}

//delete an existing task
function deleteTask(){
  console.log("Delete task....");

}

//mark task as completed
function taskCompleted(){
  console.log("Complete task....");

//append the list item to the #completed-tasks
  completedTasksHolder.appendChild(this.parentNode); //this.parentNode is the listItem (this = checkbox)
  bindTaskEvents(this.parentNode, taskIncomplete); //this.parentNode is the listItem (this = checkbox)
}

//mark task as incomplete
function taskIncomplete(){
  console.log("Task incomplete....");

//append the list item to the #incomplete-tasks
  incompleteTasksHolder.appendChild(this.parentNode); //this.parentNode is the listItem (this = checkbox)
  bindTaskEvents(this.parentNode, taskCompleted); //this.parentNode is the listItem (this = checkbox)
}

function bindTaskEvents(taskListItem, checkboxEventHandler){
  console.log("bind list item events");
  //select taskListItem's children
  var checkbox = taskListItem.querySelector("input[type=checkbox]");
  var editButton = taskListItem.querySelector("button.edit");
  var deleteButton = taskListItem.querySelector("button.delete");

  //bind editTask to edit button
  editButton.onclick = editTask;

  //bind deleteTask to delete button
  deleteButton.onclick = deleteTask;

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

//set the click handler to the addTask function
addButton.onclick = addTask;

//cycle over incompleteTasksHolder ul list items
for(var i = 0; i <incompleteTasksHolder.children.length; i++){
  //bind events to list item's children (taskCompleted)
  bindTaskEvents(incompleteTasksHolder.children[i], taskCompleted);
  console.log("incomplete running");
}

//cycle over incompleteTasksHolder ul list items
for(var i = 0; i <completedTasksHolder.children.length; i++){
  //bind events to list item's children (taskIncomplete)
  bindTaskEvents(completedTasksHolder.children[i], taskIncomplete);
  console.log("completed running");
}

2 Answers

Samuel Webb
Samuel Webb
25,370 Points

So this is all based on which ID a task list has (#incomplete-task or #completed-task). When the loops run, they assign either the taskCompleted function or taskIncomplete function to the onclick property of any list item contained in whichever task list was passed in. That's why you have 2 loops. Now that those functions have been assigned to the onclick properties, the proper one can fire off when you either check it off - taskCompleted() or uncheck it - taskIncomplete(). The loop doesn't actually invoke those 2 functions, it just assigns them to onclick properties. That's why the don't have parenthesis after them when you pass them into the bindTaskEvents function.

Hopefully I didn't make that even more confusing.

Jose Linares
Jose Linares
5,062 Points

Ohhh, now that makes sense. That was perfect man. Thank you so much.

Samuel Webb
Samuel Webb
25,370 Points

No problem, glad to help.

Samuel Webb
Samuel Webb
25,370 Points

No, the loops only run once.

Unless called, functions aren't run when the JS file loads. They're just stored in memory so that they can be called at another time. So when you click the button, it fires off the addTask() function. The only section of code that runs is whatever is between { }. It doesn't run through the rest of the file again.

Jose Linares
Jose Linares
5,062 Points

Yeah but that's only if I click on the addButton, but when I clicked on a checkbox somehow it fires the functions taskIncomplete() or taskCompleted() ??? Do you see in the code why this happens ??? I know if you are not watching the video is really hard.