And this lecture,
we're gonna implement a feature
that will basically move the map
to the position of the workout
that was clicked in the sidebar.
So the feature that I'm in is this one.
So when I click one of these, then as I said,
the map will move to the position of that workout.
And so this is a very nice touch to the user interface
and so let's now do that.
And let's say that we're starting
with a blank page like this.
So the initial stage of our application
and so of course, right now,
there are no workouts on which we could click
and so in this case,
where should we actually attach the event handler?
So this is the situation
that I actually had mentioned already earlier.
So again,
the situation in which we don't have the element
on which we actually want to attach the event listener
because it hasn't been created yet
and so what we have to do here is one more time,
basically, event delegation.
So what we're gonna do is to add the event handler
to the parent element.
And so in our HTML,
we can see that that is this workout's
and element here.
So basically the element with the class of workouts
and so let's see here in the code, which one that is.
Alright, so it's called container workouts.
So let's add an event listener to that element there.
And remember one more time we do that in the constructor
so that event listener is added right in the beginning.
So containerworkout.addEventListener on click,
and then we're gonna create a method called
moveToPopup just like this.
So that's a copy it,
and then add it here at the end.
Now this methods that we have here,
they are not really ordered in any particular way.
So I'm just adding them as I go here.
Now, anyway,
here we are going to need the event
because now we will have to match the object
or actually the element that we're actually looking for.
So what I will do here is to create the workout element
and basically all that I'm gonna do
is to look at e.target
So that's the element that is actually clicked
and then I will look for the closest workout parent,
so closest, which is again,
essentially the opposite of a query selector.
And so, the element that I'm looking for
is the one with the class workout.
So like this,
wherever the click happens
here in the element.
So no matter if it's in one of these divs or the spans,
it doesn't matter.
All of it will then basically end up
in this Li element with the workout class,
because from the element that is clicked,
we will move up to this exact element here
using the closest method.
All right, so once again closest
is a real life saver here.
It is really, really helpful.
And so now let's start by logging
this element to the console.
Now right,
so let's wait for it
as always any values here work.
So of course we first need to have something here
and now as I click it, let's see what happens,
and indeed we get the entire element here
and that works no matter if I click out here
or here or on this emoji
or really anywhere.
So the closest method takes care of really
then selecting this entire element.
Now, why is that actually so important?
Well it's because it is right there
where I have this ID
and it is this ID
that I will now use to actually find the workout
in the workouts array
and so once again, we put this here,
because with this, we can then basically build a bridge
between the user interface
and the data that we have actually in our application.
So in this case our data in the workout's array,
because if we didn't have this ID here
stored in the user interface,
then how would we know which is the objects in the workouts
array that we need to scroll to?
And so we need this ID here
so that we can now read it
and basically then select the element
out of the workouts array using this ID.
Now let's just happen when we click outside here
in the same container.
So you see that this here is still a container outside
and so when we click this,
now we of course get null
because there is no closest parent with a workout class.
All right, and so we will actually have to
basically ignore that.
And so this is the next step.
So if basically there is no a workout element
then simply return.
And so again, this is a guard clause here
so of course we could have done also
if there is a workout element
and then the if block, but this is a bit nicer.
And so now it's time to actually get the workout data
out of the workouts array.
So workout=this.workouts
and actually that's like this
and now how do you think we will find this workout?
Well, that's right , just like in the blank list application
that we built before we are going to use the find method
to, well, essentially find an element of the array.
So that's create our callback function here
and so each element in the workouts array,
I will simply call work.
And then I want the one which has work.id equal to that ID
that I just showed you before in the dum.
and so debts workoutEL.dataset.id
so this is again, nothing new at this point
we used this technique a couple of times before,
but this is yet another really great use case of it.
And so let's take a look now,
if we are able to actually get the correct one,
so any random data here works just fine,
then I'm gonna click it
and now we get this same error
that we already had before
and we actually could have predicted this already,
couldn't we?
Because remember that this method here
is called by, "addEventListener() method,"
and so therefore the, "this" keyword in here
is not what we want it to be.
So let's move up there.
So to the place where we had the event listener,
so right here.
And so just like before we need to bind the, "this" keyword
to actually make it correct.
Right, so I already explained before
why that is necessary.
So let's just try again now I'm clicking it
and yeah, here it is actually.
So you see that this one has exactly the same ID.
Let's just add another one here
and now we get this one here, but again,
as I click this one, of course,
we still find the correct workout from the array.
And so now we can basically take the coordinates
from this element
and then move to map to that position.
So in leaflet, there is actually a method
to do exactly that
and the method is available on all map objects.
So we can take our map object
that we already have, which is this one.
And then we can call the, "setView method,"
and I really encourage you to go check out the documentation
of this one, but I'm not gonna do that right now.
So anyway, the setView method needs as a first argument,
the coordinates
and so that's at the workout.coords
then the second one is the zoom level
and to zoom level,
we actually have already used before somewhere.
So I think where we first loaded the map,
so right here.
And so it would be a bad practice
to simply repeat the same number here
and so instead I will create another field here.
So basically another object property here.
So that's gonna be called mapzoomlevel, let's say,
and I will set it to 13.
So let's a copy of this one.
So here we need, "this." and now,
then here the same thing down here.
So this.mapzoomlevel,
and finally we can pass in an object of options as always,
then here we can set animate to true.
And then we can also set the duration basically
of this animation by saying,
pen should be equal to yet another object
which should have the duration of 1.
So this is all a little bit confusing,
but again, if you want,
you can read the documentation of leaflet
and then find out why exactly it works this way.
So let me give it a save here now,
and then let's go back here
so we can get almost rid of the console here.
Okay, and add another one here,
just to make this a bit more fun
and so now let me actually click here
and yeah, beautiful, it works.
And a click on this one and of course
it then moves to that one,
and of course, if I edit even more than
that would just work all the same.
Okay, and now just to finish this,
I want to just add a very small touch here.
And that will be to simply count the clicks
that happen on each of the workouts.
Now I will not display that number anywhere
or something like that.
This, just to show you something basically.
So essentially it is to make the public interface
of these classes here a little bit more complete,
because right now we are actually not calling any of the
methods outside of the classes themselves, right?
So we are not really using any public interface
here on any of these objects
and so I want to just change that
just so you can see how that would work.
So basically here on all the workouts,
let's add a property called clicks
and we will start with zero clicks.
And then we will also have a methods
which will be called click
and all it will do is to increase the number of clicks.
All right, so very simple
but now every object gets this method
and so in each of the workouts,
we can now increase that number of clicks
and so that's very simple.
All we have to do now is to well,
is to take the object that we already have,
which is the workout,
and then using that public interface.
So that's just workout.click.
And that's actually it
and let's just test this.
And also actually, this will be helpful
to show you something else in the next video.
All right,
and so, as I keep clicking here,
the number of clicks should actually increase
but for some reason that we get this error here.
So let's see what happening in line 289.
So that's right here
telling us that the workout.click does not exist.
So why is that?
Well, let's take a look at the object here, actually.
And so, in particular at the prototype,
and so here of course click does not exist,
but here it actually is.
So indeed here it's a click method
and so the workout should have access to this method.
So that is exactly what we learned in the previous section
about the prototype chain
and about how all of this actually works behind the scenes.
So hopefully you will remember that.
But now I'm actually not sure why this isn't working.
Let's go back here
and bring back
or fake workouts here basically.
So these ones,
so we can play around with them in the console.
So you see that both of them have the clicks set to zero
and so let's use run1.click like this
and then as we look at run 1 again,
then the clicks is still at zero.
So something is clearly also wrong there.
Okay, so here, this needs to be clicks,
but I'm not sure if that was the actual error.
Okay, so now the clicks increased to two here.
So that's now check
adding something here
and then clicking it.
Okay, and you see that it moved there.
Let's click again.
Oh, and now it's actually working.
So now the clicks indeed increased to one.
So great, that works just fine
and again, this was just a way of showing you
that we can of course then interact
with each of the objects using their public interface.
And in this case, we use that using the click method here.
So that's it for this lecture in the next video,
we will then fix the fact that
when we reload the page, everything is gone.
And so actually we want data to persist
and so that is the missing piece in our application
and we will fix it in the next lecture.