Instructor: All right, now that we know about
event delegation, we're finally gonna start implementing
the code to delete income or expense items from the app.
And so in this lecture, you're gonna learn how
to use event delegation in practice,
using the concepts of event bubbling and target element,
and you're also gonna learn how to use unique IDs
in HTML to connect user interface with the data model,
and how to use the parent node property for DOM traversing.
All right, so we're gonna start by adding
an event handler here, and we do that
here in our setupEventListeners function, right?
And remember that we're gonna do event delegation,
so we're going to setup the event on a parent element
of the elements that we're actually interested in.
So let's first check out our HTML file
so that we can decide where to add,
or to attach our EventListener.
So first of all we want our items to be deleted
when the user hits on this button here, okay?
So this button called "item__delete--btn"
and there's one of these buttons in each and every income,
and also expense elements here.
But again, we don't want to attach our event handler
to these, because we wanna do event delegation.
So we wanna find an element that is
the parent of all of these items,
both the incomes and all of the expenses.
And if we look closely at our HTML document structure here,
we see that the first element that satisfies this condition
is this one here, so this one called "container,"
so it has the container class, and that's because
all the incomes are inside of this income container here,
and all of the expenses are in this expense container,
so we cannot attach the event handler to these,
because then we would need two,
but we only want one of them.
So we find the element that is common to all of them,
and that's, again, this one here,
so with the class of container.
So this is where we're gonna put our event handler, okay?
So we say document.querySelector to select that element,
and now we need to add this element to our DOMstrings object
up here, right, so as we always did,
and I'm just gonna call the container here as well.
Okay, and for the class, container.
All right, so let's go back.
So what we want is DOM, 'cause remember, in here,
in this function it's not called DOMstrings, but DOM,
which is this variable here where we get
this DOMstrings object from the UI controller, right?
So DOM.container, and this is where we add
our EventListener, and it will be on the click event,
and the function that we wanna call,
I'm gonna call it ctrlDeleteItem,
so ctrlDeleteItem, okay?
So it's a name similar to ctrlAddItem,
so this one will be ctrlDeleteItem.
And so now we need to create this function
which is gonna be called each time someone clicks
somewhere on this container, okay?
So let's do it down here, actually after this ctrlAddItem,
so var ctrlDeleteItem, so a function, and here we go.
And actually, we need to pass something into this function,
which is the event, and I'm sure
that you remember what the event object is,
so let's check out the other event handler.
So in this event handler here, we also used
the event object, so remember that the callback function
of the addEventListener method has always access
to this event object, and we can call it whatever we want.
We just call it event so that we always know what it is.
And so it works, see in this anonymous function
that we wrote here in this case,
but it also works if we pass another function in it,
so in this case ctrlDeleteItem,
and then we can also say that we want access to
the event object simply by putting this parameter in here.
And the reason why we need this event here
is because we wanna know what the target element is,
so remember, that's what we talked about before.
So in event delegation, an event bubbles up,
and then we can know where it came from,
so where it was first fired, by looking at
the target property of the event.
So let's simply start by console logging this property okay,
so console.log(event.target).
All right, so let's now test this.
I'm just reloading this file, then let's hit somewhere here.
So now the target of this click was this h2 element here,
which actually even gets highlighted here.
So if I now click somewhere here let's say,
then this one is the target element,
so the element where the event was fired.
So in this case, where I clicked.
If I click here it's the container, so this element here.
Now let me add something here, say Project.
Okay, so if I now click here on this button,
let's see what we get.
All right, so we clicked here on this "i" element,
so this icon, and what this means now
is that each time that we hit this button here,
actually we don't hit the button,
but we hit the icon, okay?
So let's get back at our HTML
and take a look at this i element.
Okay, so this one here.
So when we click on the button,
we actually click on this i element.
Now when we hit the button, it is not just a button
that we want to delete, right,
so we actually want to delete all of this here, right,
because all of this is the item on the user interface,
and each of these items is identified
by their unique ID name, which is this one here,
so actually we are not interested just in this element here,
which is the target one, but we're actually interested
in this element here, so in this parent element.
So again, this element here that we click
is not actually the one that we're interested in,
but it's this parent element, so this entire div element
that we're actually interested in,
and that we wanna have access to.
So we need to move up in the DOM from here,
and that is something called DOM traversing.
So we're gonna traverse the DOM.
So let's see how we can do that.
So back in our app file, we can now say
that we want the parent node of this target.
So this target property here, what it returns
is an HTML node in the DOM.
So when we wanna move up from that,
we can simply say parentNode, okay?
So let's see what happens if we now hit the button.
So reload, and now I need to add it again,
and just something random here, okay,
and now I'm hitting it and now we see button,
so it's no longer the i element, but the button.
So let's go back, and what this means is that
we actually moved up to the parent element, right?
So let's make this more visible, okay.
So you see the button element here is
the parent element of the i, right?
Now we don't wanna just move up to the button,
but in fact we wanna move up all the way to the income,
so we don't need one parent node,
but we need two, three and four.
So if you wanna move all the way up here,
we need to use the parent node property for times,
and we can actually do that.
So like this, parentNode.parentNode.parentNode.
So this actually looks a bit strange,
but it's gonna work, I hope so at least!
So test, something, and now I'm hitting
the button again, and here we are.
So this is now the div element that we're actually
interested in, and in fact, what we're interested in
is the id here, because again,
this is the unique identifier let's say, of this item.
So we can simply use the id property here,
so that's it, with this we have the id.
So just to prove it to you, here it is, so income-0.
If we put another one, then it's gonna be income-1, okay?
So each one has this unique id,
and this is gonna be very important,
and we're gonna talk about that in a second.
So now instead of logging it, let's save it
to a variable called itemID, okay?
Let's remove this one here, and then also
declare it as a variable, so itemID.
Now this is probably not the cleanest solution here,
using all of these parentNodes, because with this
we are heavily relying on the DOM structure, right,
so basically we hard-coded the DOM structure here,
but let's just leave it like this
because we in fact also hard-coded the HTML in here, right,
so the HTML that generates all of these items,
so it's not a big deal, it's not a big problem
if we also hard-code the traversing of
that very DOM structure here as well.
Now what happens if we click somewhere else on the page?
For example, if we click here, then there is no ID, right?
Or here, or here, or whatever,
anywhere we click there's no id,
and that's because there are no other ids
in the whole HTML document, and so we can now use this fact
to say that we only want stuff to happen later
if the id is actually defined, okay?
So now we can say if(itemID),
then we want something to happen, okay?
And we already did this before, but again,
this will work basically because this isn't going
to be coerced or converted to true if this exists,
and if it doesn't, then it will be coerced to false.
All right, now what are we actually gonna do with that ID?
So again, let's take a look at how it is.
So it basically contains both the type,
so income or expense, and the unique ID of this item
in our data structure, right, so 0, 1,
and so on and so forth, and that is because
this is exactly the way that we coded it.
So let's see it back here, so in this method here
where we actually add the list items,
we retrieve the ID from the new object, right,
and then print it to our webpage.
So in case of an income, it's income and then the ID,
and if it's an expense, it's expense ID,
and actually let me change it here from income to inc,
and here to exp, so that we have always
the same type designation throughout our app,
and not sometimes inc and sometimes income, right,
so that wouldn't be so consistent,
and this way it's much better.
So right now this ID here encodes both
the item type and the item ID, right?
So this will be extremely useful
because later we can then use this data to tell
the budget controller which item it should delete
when we hit the button, and also which item
should be deleted from the user interface.
So let's use this ID here, okay?
So back here, we now use this ID.
Now the format of the ID, as we saw,
is something like inc-1, or whatever number,
so we now need a way to split this up,
and thankfully there is a very handy method
in JavaScript that all strings have access to,
and that's called "split."
Now you may be wondering why I said
that all the strings have access to this method,
because we always said that a string is a primitive,
and not an object, right?
Now the thing is that as soon as we call
one of these methods on a string,
then JavaScript automatically puts a wrapper around
the string and converts it from a primitive to an object,
and then this object has access to a lot of string methods,
and the same thing actually happens to numbers.
So numbers also have methods because JavaScript simply
transforms them from a primitive to an object,
so that we can use methods on them.
So we will now use the "split" method.
So let's say splitID, should be the itemID.split,
so it's the usual method, and then we say
that the split string should be the dash, okay,
and I will show you this in a second.
Let me just declare it here, so splitID, okay,
so let's actually test this out in the console
to see what the result will be.
So imagine that we use this string,
var s is inc-1, and then we say s.split like we did before,
and so what this returns is an array
where in the first element is inc, so this part
that comes before our split string here,
and then the second element is what comes after that, okay?
And s could even be bigger than that,
so I imagine it would be inc-1-type-3,
whatever, it doesn't really matter,
just to show it to you, and then it would return an array
of all of these elements that come after
and before these split strings.
So basically this allows us to break up a string
into different parts, and removing then the split string.
So now we can simply say that the type is splitID[0] right,
because remember, this is the array that we just saw,
and the first element is the type, right,
because it's this inc.
So income or expense are the types,
and I also need to declare this of course,
so type, and then we're also gonna have ID.
So that's the next one, so ID is the splitID
and element number 1, so the second element in fact.
All right, and now we have all the ingredients
to be able to delete the item from both
the user interface and our data model,
so the budget controller.
And so let's look what we had on our to-do list
for this part of the application.
So first we wanted to delete the item
from the data structure, then we delete
the item from the user interface,
and then we update and show the new totals,
or the new budget actually, because that's
the way we've been calling it, right?
Because of course as soon as we remove an item from
the expense or from the incomes,
then all of the budget has to be updated.
So in the next lectures, we're going to create
a function in the budget controller for this one,
so for deleting from the data structure,
and then a method for deleting
the item from the user interface.
And then finally we wanna update and show the new budget.
So just to recap, what we did in this lecture,
we first added an EventListener here to the container,
which is the first element that all of
the income and expense items have in common,
so this is where we set our EventListener,
and we did it so because we want to do event delegation,
which means that instead of adding one EventListener
to all of the elements that we're interested in,
like all the incomes and all the expense items,
we add them to the container, and then let
the event bubbling up.
So the function that we then attached to
the container is the ctrlDeleteItem,
which is this one here, okay?
And then from here we were at the target element, okay,
so using the event.target property,
which is exactly the element where the click happened,
so where the event was fired.
And we then moved up in the DOM,
so we traversed the DOM all the way up
to the element that we're actually interested in,
and then, in here we retrieved the ID from it,
and stored it here in this variable,
and this variable is gonna be very useful for us
because we know that in here is encoded the item type,
so if it's an expense or an income, and also the unique ID.
So we then isolated each of these into a different variable
using the split method for this string.
And so now the stage is set so that we can delete
the item from the data structure,
and from the user interface over the next lectures.