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 trialJennelle Barajas
5,317 PointsWhat is happening when we bindTaskEvents?
What is happening in this function:
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");
????
It is called in an instance like this:
//Mark a task as incomplete
var taskIncomplete = function() {
console.log("Task incomplete...");
//Append the task list item to the #incomplete-tasks
var listItem = this.parentNode;
incompleteTasksHolder.appendChild(listItem);
bindTaskEvents(listItem, taskCompleted);
}
I get really really confused about this at about minute 7:30 in the video. Where Andrew is explaining
var listItem = this.parentNode
I thought we were appending a child, not a parentNode.
Please help explain! Thank you!
1 Answer
Meagan Waller
19,382 PointsHi Jennelle,
The bindTaskEvents
function is the function that we pass our taskListItem
to when we loop through every li
element in the ul#incomplete-tasks
or the ul#completed-tasks
.
Basically, what this is doing is for every li
it's binding some events to children elements located in that li
.
If you take a look at your index.html
file you'll see that each li
has some elements inside of it,
<li><input type="checkbox"><label>Pay Bills</label><input type="text"><button class="edit">Edit</button><button class="delete">Delete</button></li>
(this an example inside of the ul#incomplete-tasks
.)
However, we want actions to be able to happen when the user presses the edit button, or checks the checkbox, for instance. The way we make this happen is by binding our events (the functions we created in the beginning stages, like editTask
or deleteTask
) to those elements. Otherwise, when we click the delete button, nothing will happen because our delete button hasn't been told to listen for an onclick
action from the user.
You'll see inside of the bindTaskEvents
function that we're setting editButton.onclick = editTask
. When we do this, what we're doing is setting that editButton
located in that particular taskListItem
to perform the editTask
function when that particular button is clicked. That means that when that particular edit button is clicked, and the editTask
function is executed (because we are telling it to listen for when the user clicks) it will perform that editTask
function in the context of that particular edit button.
Alright, so hopefully that explains the bindTaskEvents
function a little more clearly.
The reason that bindTaskEvents
is being called in our taskIncomplete
function is because we're creating a new list item that didn't exist the first time we called bindTaskEvents
. Remember a couple of videos back when we created the for
loop that cycled (or iterated) over all our elements inside both the incompleteTasksHolder
and completedTasksHolder
? Well, now we've appended a new list item (either by the user marking a task as incomplete, or by creating a new task) to that incompleteTasksHolder
but since it wasn't part of the incompleteTasksHolder
when we initially ran our program (and bound the events to each li
that was already inside of the window.document
(document
)) we need to bind events to the elements located inside of the new tasks li
so that it behaves as expected. Without using the bindTaskEvents
function on new tasks the user creates, pressing the edit, or delete button, for instance, will do nothing. For each new li
that gets created when a user creates a new task we need to tell it's edit button, delete button, checkbox, etc, what to do what the user interacts with those particular elements.
And what we're doing with the var listItem = this.parentNode
is a little bit confusing, but I'll try my best to explain :)
When we're inside of the taskIncomplete
function it's because it's been triggered on a checkbox. If you'll remember in the bindTaskEvents
function we add this line:
checkBox.onchange = checkBoxEventHandler;
(and the checkBoxEventHandler
is just a function that we passed in in the second argument), so for the sake of this example:
checkBox.onchange = taskIncomplete;
so this means, when the user changes this check box the taskIncomplete
function is being executed. However, when the function gets executed, it's in the scope of the check box, so if we were to put console.log(this)
inside of the taskIncomplete
function you'd see that this
in the scope of that function is the checkBox.
But, what we need is to know the parent of the check box, that's why you see:
var listItem = this.parentNode;
because if we just said:
var listItem = this;
it wouldn't be correct, because this listItem
isn't the check box, it should be the li
that the check box is located inside of. By calling this.parentNode
we are getting access to the parent of the check box (it's sort of like the opposite of the .children
method we used inside of our for loop)
Once we have access to the listItem
, then we can append it (the entire listItem
) to the incompleteTasksHolder
.
I hope this was helpful, if there's anything that I skipped over or if you feel lost please let me know!
Jennelle Barajas
5,317 PointsJennelle Barajas
5,317 PointsMeagan,
That totally cleared things up for me!
That was a very thoughtful answer. I wish I could upvote this like 20 more times.
Thank you!