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 Perfect

Getting 2 bind list events then another below it in the console

Hey everyone. Everything works right but I have something odd going on. When I refresh the page the console shows a 2 next to 'bind list item events', but then on the line below that I have another line that says 'bind list item events'. So instead of this all being on 1 line with a 3 next to it it's on 2 lines.

So when I add a new task it works but then it adds a new blank task to the incomplete tasks. It's like somewhere the bindTaskEvents function is being called somewhere else but I can't find it. I don't get errors in the console, only odd behavior.

***JavaScript

// Problem: User interaction doesn't provide desired results
// Solution: Add interactivity so the user can manage daily tasks

var taskInput = document.getElementById("new-task"); // new-task input text box
var addButton = document.getElementsByTagName("button")[0]; // this grabs the first button tag which would be at index 0; [0]
var incompleteTasksHolder = document.getElementById("incomplete-tasks"); // incomplete-tasks
var completedTasksHolder = document.getElementById("completed-tasks"); // completed-tasks


// New Task list item
var createNewTaskElement = function(taskString) {
  // create list item  
  var listItem = document.createElement("li");


  // createElement creates a new element and adds it to the current list
  // Input checkbox
  var checkBox = document.createElement("input"); // checkbox
    // Label
  var label = document.createElement("label");
    // Input (text)
  var editInput = document.createElement("input");
    // Button with class #edit
  var editButton = document.createElement("button");
    // Button with class #delete
  var deleteButton = document.createElement("button");

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

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

  label.innerText = taskString;




    // each element needs appended (added)
  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...");

  // Create a new list item with text from #new-task input box
  var listItem = createNewTaskElement(taskInput.value);

  // Append new listItem to incompleteTasksHolder
  incompleteTasksHolder.appendChild(listItem);
  bindTaskEvents(listItem, taskCompleted)

  taskInput.value = '';  // This clears out text box after ADD buton is pressed to add the event

}


// Edit existing tasks
var editTask = function () {
  console.log("Edit task...");

  var listItem = this.parentNode;
  var editInput = listItem.querySelector("input[type=text]");
  var label = listItem.querySelector("label");
  var containsClass = listItem.classList.contains("editMode");


  // If class of parent is .editMode
  if (containsClass) {
      // Switch from editMode
      // Make label text become input value
      label.innerText = editInput.value;  // The lable becomes the value of the input in the box by the user
    // Else
  } else {
      // Switch to .editMode
      // Input value becomes label's text
      editInput.value = label.innerText;  // The text that is put in by the user becomes the new text
  }
    // Toggle .editMode
  listItem.classList.toggle("editMode");  // Pressing the edit button allows us to edit or saves the text that is input and applies the new text to the label

}



// Delete an existing task
var deleteTask = function () {
  console.log("Delete task...");
  // When delete button is pressed
  var listItem = this.parentNode;
  var ul = listItem.parentNode;  // call it a grandparent.  We need to move up 2 parent levels by looking at HTML.  So we traverse from the button to list to unordered list

  // Remove parent list item from ul
  ul.removeChild(listItem);
}


// Mark a task as complete
var taskCompleted = function() {
  console.log("Complete task...");

  // Append (add) task list item to completed-tasks when checbox is checked
  var listItem = this.parentNode;
  completedTasksHolder.appendChild(listItem);
  bindTaskEvents(listItem, taskIncomplete);


}



// Mark a task as incomplete
var taskIncomplete = function() {
  console.log("Incomplete task...");

  // Append (add) to incomplete-tasks to completed checkbox is unchecked
  var listItem = this.parentNode;
  incompleteTasksHolder.appendChild(listItem);
  bindTaskEvents(listItem, taskCompleted);

}


var bindTaskEvents = function(taskListItem, checkBoxEventHandler) {
  console.log("Bind list item events");
    // select taskListItem 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 click handler to the addTask function
addButton.onclick = addTask; // () are not added after addTask because we don't want the function to run UNTIL the user clicks the button.  If we add () the function will run right away.



// *****  Cycle over incompletedTaskHolder ul list items
for ( var i = 0; i < incompleteTasksHolder.children.length; i +=1 ) {

    // bind events to list items's children (taskIncomplete) 
  bindTaskEvents(incompleteTasksHolder.children[i], taskCompleted);

 }

    // This is what the bindTaskEvents function is doing
      // select ul list items children
      // bind editTask to edit button
      // bind deleteTask to delete button
      // bind taskCompleted to checkbox


var ajaxRequest = function() {
   console.log("AJAX Request");
} 

// Set the click handler to the addTask function
    addButton.addEventListener("click", addTask);
    addButton.addEventListener("click", ajaxRequest);

// *****  Cycle over completedTaskHolder ul list items
for ( var i = 0; i < completedTasksHolder.children.length; i +=1 ) {

  // bind events to list items's children (taskCompleted)
  bindTaskEvents(completedTasksHolder.children[i], taskIncomplete);    
}

    // This is what the bindTaskEvents function is doing
      // select ul list items children
      // bind editTask to edit button
      // bind deleteTask to delete button
      // bind taskCompleted to checkbox
*** HTML
<!DOCTYPE html>
<html>
  <head>
    <title>Todo App</title>
    <link href='http://fonts.googleapis.com/css?family=Lato:300,400,700' rel='stylesheet' type='text/css'>
    <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8">    
  </head>
  <body>
    <div class="container">
      <p>
        <label for="new-task">Add Item</label><input id="new-task" type="text"><button>Add</button>
      </p>

      <h3>Todo</h3>
      <ul id="incomplete-tasks">
        <li><input type="checkbox"><label>Pay Bills</label><input type="text"><button class="edit">Edit</button><button class="delete">Delete</button></li>
        <li class="editMode"><input type="checkbox"><label>Go Shopping</label><input type="text" value="Go Shopping"><button class="edit">Edit</button><button class="delete">Delete</button></li>

      </ul>

      <h3>Completed</h3>
      <ul id="completed-tasks">
        <li><input type="checkbox" checked><label>See the Doctor</label><input type="text"><button class="edit">Edit</button><button class="delete">Delete</button></li>
      </ul>
    </div>

    <script type="text/javascript" src="js/app.js"></script>

  </body>
</html>

Any help would be greatly appreciated

Could you maybe post everything including your HTML to Codepen or JSFiddle? That would make helping easier :)