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

Getting error: Uncaught TypeError: Cannot read property 'querySelector' of undefined

I keep getting this error:

Uncaught TypeError: Cannot read property 'querySelector' of undefined, bindTaskEvents @ app.js:88, (anonymous function) @ app.js:116

I've poured over the code but can't find the source of this issue. I'm going to include the entire code because I don't know where the issue might be.

//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
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
var createNewTaskElement = function(taskString) {

  //create list item
  var listItem = document.createElement("li");

  //input (checkbox)
  var checkBox = document.createElement("input");
    //label
  var label = document.createElement("label");
    //input (text)
  var editInput = document.createElement("input");
    //create button.edit
  var editButton = document.createElement("button");
    //creat button.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");
  //create a tnew list item with text from #new-task
  var listItem = createNewTaskElement("some new task");

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

//edit existing task
var editTask = function() {
  console.log("Edit task");
  //when edit button is pressed
    //if the class of the parent is .editMode
      //switch from editMode
      //label text become the inputs value
    //else
      //switch to editMode
      //input value becomes labels text

    //toggle .editMode
}

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

//mark a task as complete
var taskCompleted = function() {
  console.log("task complete");
  //append the task list item to the #completed-tasks
  var listItem = this.parentNode;
  completedTasksHolder.appendChild(listItem);
}

//mark a task as incomplete
var taskIncomplete = function() {
  console.log("task incomplete");
  //append to #incomplete-tasks
  var listItem = this.parentNode;
  incompleteTasksHolder.appendChild(listItem);
}

var bindTaskEvents = function(taskListItem, checkBoxEventHandler) {
  console.log("Bind list item events..");
    //select list item'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++ ) {
  //for each list item
    //bind tevents to list item's children (taskCompleted)
bindTaskEvents(incompleteTasksHolder.children[i], taskCompleted);
}

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

1 Answer

Brian Steele
Brian Steele
23,060 Points

It looks like you're looping through the wrong items... (comment refers to completed list items, loop is actually iterating over the incomplete list items)

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

should be

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

Thanks a lot, that was exactly it.