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: Traversing Elements with querySelector

Vittorio Somaschini
Vittorio Somaschini
33,371 Points

Uncaught TypeError:

Hello.

The problem I am getting is slightly different form the error listed in the questions of this section of Javascript, so I am creating a new question.

This is what the console returns (we are creating the handlings of the event in this whole section):

Uncaught TypeError: Cannot read property 'querySelector' of undefined app.js:71bindTaskEvents app.js:71(anonymous function) app.js:102

These lines listed on the right hand side should point me to the right direction, so I take a look at those lines:

71 -> var checkBox = taskListItem.querySelector("input[type=checkbox]");

102 -> bindTaskEvents(completedTasksHolder.children[i], taskIncomplete);

Code is pretty long and I do not think it is worth to copy it all here, but what may be wrong here?

My ideas:

for line 71 is has to be the selector, I mean, it is basically the only thing that we are writing down on this line. But my code is same as video's (otherwise I am probably getting blind)

On line 102 I have no real clue. I have tried to google this error and I have read something here and there, but nothing that helped me out solving this.

Any ideas guys?

UPDATE everything else seems to be working fine, I have managed to get al the events from the site and console.log them..

Thanks

Vittorio

Hi Vittorio,

It might be easiest for you to post your whole code. I think it's only about 100 lines right? The error for line 102 should be near the end.

If you still don't want to then post the var section at the top, the for loop that's around the line 102 code, and the taskCompleted function.

2 Answers

Your problem should be in the last for loop.

// cycle over completeTasksHolder ul list items
for (var i = 0; i < incompleteTasksHolder.children.length; i++) {

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

You're supposed to loop over the children of completedTasksHolder but you're looping over incompleteTasksHolder, the same as the first loop.

It should be completedTasksHolder.children.length;

Your problem then is that the loop is running twice when it should only be running once since there is only 1 completed task on page load.

The second time through the loop you're passing completedTasksHolder.children[1] into the bindTaskEvents function. This is an undefined value because there is only 1 list item child at index 0.

Then inside that function you have var checkBox = taskListItem.querySelector("input[type=checkbox]");

This produces the error because you are calling querySelector on an undefined value.

I hope this helps clear it up for you.

Vittorio Somaschini
Vittorio Somaschini
33,371 Points

This was a brilliant solution, and also well explained.

It also made me feel so stupid which is also a plus!!

;)

Thanks Jason Anello

Vittorio

You're welcome. Don't feel stupid, it wasn't my intention.

Vittorio Somaschini
Vittorio Somaschini
33,371 Points
//Problem: user interaction does not 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

// add a new task.
var addTask = function() {
  console.log("Add task...");
  //When the button is pressed
  //Create a new list item with the text from #new-task:
    //input (checkbox)
    //label
    //input (text)
    //button.edit
    //button.delete
    //Each elements, needs modified and appended
}



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

  //Toggle .editMode on the parent

}

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

}


// Mark a task as complete.
var taskCompleted = function() {
  console.log("Task complete...");
  //When the Chockbox is checked
    //Append the task list item to the #complete-tasks

}



// Mark a task as Incomplete.
var taskIncomplete = function() {
  console.log("Task incomplete...");
  //When the checkbox is unchecked
    //Append the task list item to the #incomplete-tasks

}



var bindTaskEvents = function(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 the deleteButton
  deleteButton.onclick = deleteTask;

    // bind checkBoxEventHandler to the 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);
}


// cycle over completeTasksHolder ul list items
for (var i = 0; i < incompleteTasksHolder.children.length; i++) {

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

Ok. This is the whole code I have produced so far.

ty