Heads up! To view this whole video, sign in with your Courses Plus account or enroll in your free 7-day trial. Sign In Enroll
Preview
Video Player
00:00
00:00
00:00
- 2x 2x
- 1.75x 1.75x
- 1.5x 1.5x
- 1.25x 1.25x
- 1.1x 1.1x
- 1x 1x
- 0.75x 0.75x
- 0.5x 0.5x
In this video we learn how to calculate the distance between two coordinates and how to use that to create a List View of all of our notes.
This video doesn't have any notes.
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
So, now we've created our view which has a list in it, and our locate button will
0:00
actually update the application's current location.
0:05
The next thing we want to see is if our new collection can be sorted by the distance
0:08
from the current location to each notes location.
0:13
Now, this is going to be a tricky process, so let's do it in small steps.
0:18
The first thing I like to find out is to make sure that the comparator is
0:23
actually working properly based on the locate button, or just even at all.
0:27
So, I want to make sure that the comparator is working properly, that is,
0:33
it's refreshed when we hit the locate button.
0:36
So, one way we could test that is to create a comparator function that returns a
0:41
random value and see if every time we update our location, if the list randomly sorts.
0:44
So, this is our comparator function as we wrote it.
0:51
It's just returning zero, which will be a sort of static pseudo random sort
0:54
based on how it's stored in the database, but what we actually want to do
0:58
is call a method on note that we will call "distanceFromCurrent," and this method
1:01
will handle all the logic of comparing the notes distance from the
1:09
application's current distance.
1:13
So, let's go up to the note model and begin defining that method.
1:15
So, here we are in our note model.
1:19
We're just going to add another method underneath map image URL,
1:21
and we'll call that "distanceFromCurrent."
1:27
And then like I said, the process of calculating the distance here is actually
1:33
pretty complicated, but what we can do is call return Math.random.
1:36
The way the comparator works is it'll take each of the values from distanceFromCurrent
1:45
and try to sort those, and since the values will be random, we should get a random sort
1:49
every time we attempt to sort that collection.
1:54
Now, to get a little more information here, I'm going to go ahead and add a few notes.
1:58
[? Music ?]
2:04
[Many Notes Later]
2:06
And so, that's the last of all those new notes.
2:10
If we go to nearest notes here, we can see we have a lot more notes.
2:13
Hopefully, all of them have some location information here.
2:21
Unfortunately, it's all going to be the same location, which we'll have to
2:24
worry about in a moment.
2:27
So, if everything's working right, when we click the locate button,
2:30
it should update our location and try to sort, and since our sort is random,
2:34
we should see these sort of just shuffle around.
2:38
Now, I'm not seeing that quite yet, so let's see why that might be.
2:41
Let's see if our distanceFromCurrent is being called.
2:48
So, I'm just going to add a console.log here and say "distanceFromCurrent"
2:51
and just see if that's being called at all.
2:57
So if we click "locate," it looks like I just need to refresh the page
3:00
in order for that to take effect, because now it is not only giving us distanceFromCurrent here,
3:05
we're also getting the sorting by random values here.
3:15
Let's make sure that the console.log is not the thing that changed here,
3:19
so let's remove that, refresh, and try again.
3:22
Cool, so every time we click the locate button it's resorting, and since the comparator
3:27
is giving us a random value, we're getting a random sort.
3:31
So, we have now updated our nearest notes view page to be able to
3:37
sort based on the location.
3:41
The locate button will get the current location, store it into a value in the
3:43
application object, and now what we need to do is write a comparator function
3:48
that will compare each note to that current location.
3:53
With latitude and longitude, finding out the distance isn't as simple
3:57
as using the Pythagorean Theorem in a flat space.
4:02
The earth is round, which makes calculating the distance between two points,
4:06
measured in latitude and longitude, a fairly complicated equation.
4:11
Now, I don't know this calculation off the top of my head,
4:16
but I do know what the name of the calculation is, and I will let you know.
4:19
It's called the haversine distance, and it is how you measure between
4:24
two points on a sphere.
4:28
With that, you can Google it, you can just Google measuring the distance
4:32
between latitude and longitude, and you can find a page like this,
4:34
and this gives you a little bit of information, including a JavaScript tool
4:40
that will help you calculate the distance between two latitude and longitude points.
4:45
Now, the main reason that we have such a complicated equation is because
4:50
the Earth is spherical, and the way longitude works is as you move higher
4:55
in latitude, the distance between two longitudinal degrees decreases as you
5:01
move towards the North and South Pole.
5:05
When you get to the North and South Pole, there's actually no distance
5:08
between any of the longitudinal distances.
5:10
So, the calculation that we have to do has to take into account how far from the
5:14
Equator we are and the actual radius of the Earth.
5:17
Now, in addition to explaining all of these formulas really well and providing an
5:23
interactive tool, this particular page actually offers us a JavaScript
5:27
version of the haversine formula which we're going to adapt to our needs.
5:32
Basically, it takes into account the radius of the earth, and right now it's
5:38
doing it in kilometers, so our final value will actually be in kilometers.
5:41
If we replace that value with the radius of the Earth in miles, we could do it in
5:47
miles or any other value, and then we do all of this math.
5:51
So basically, what I'm going to do is, I'm going to copy in my version of this,
5:57
which I've adapted from this version.
6:01
So, let's go into our code again.
6:04
And our distanceFromCurrent here, let's remove this random here.
6:11
We don't need that anymore, and I'm going to paste this in, and I'm going to
6:14
explain as much of this as I can without getting too deep into the math of it.
6:18
Now, the first thing I've done here is I've added a convenience function
6:25
to convert from degrees into radians.
6:28
All of this calculation works in radians, and if you actually look at the original
6:32
source, to convert it it uses a method which isn't really defined in our browser,
6:35
so I've converted the two rad method calls to a function call, which is simply
6:41
multiplying degrees times Pi divided by 180.
6:46
Then really what we need to do is define our lat 1/lat 2, long 1/long 2 variables,
6:53
which are used in the equation.
6:59
So, latitude and longitude 1 are going to come from App.currentlocation.latitude,
7:01
and lat and long 2 will be based on this note.
7:07
It doesn't matter which one you set, so long as you make sure that lat and long 1
7:10
match up and lat and long 2 match up.
7:15
Then basically, the equation goes through finding the distance between the latitudes
7:20
and longitudes, and it does a lot of trigonometry here to figure out the total distance
7:24
between the two on a spherical object,
7:30
finally resulting in D, which should be our distance in kilometers.
7:34
Now, there is one thing we do need to protect against, is if we try to call
7:39
distanceFromCurrent, there may be a couple situations where this won't work.
7:42
For instance, if the current location inside of our application has not
7:46
been set, we are going to fail, and if there's no note for the current note,
7:50
we're also going to fail.
7:56
So, we want to put a guard at the top of our distanceFromCurrent to return quickly
7:58
if this note is not geotagged or if there's no current location.
8:04
So, what I'm going to do on the first line here is paste this in,
8:09
and if this is not geotagged, or if the app doesn't have a current location,
8:13
we'll return zero, and this value really depends on where you would want the
8:19
untagged notes to appear when you sort by distance.
8:24
If you want them to appear at the end of the list, you would want to return a large
8:29
number like infinity or the max value of the number class.
8:32
Or, if you wanted them to be at the top of the list, zero or a negative number
8:37
would also be a good case.
8:40
For right now, I'm just going to return zero.
8:43
So, let's save this out and see if it works.
8:45
So, if we refresh, let's hope we don't get any syntax errors, and we're good there,
8:49
and let's click the locate button.
8:53
Now, it's not sorting any differently, which can be a good thing,
8:57
but we don't quite know what these values are.
9:01
Now, one thing I want to do is I actually do want to show the values here.
9:04
I do want to show the values here, but, however, even if I do show the
9:08
values, I'm pretty sure that we're not going to get a resorting,
9:11
because they should actually all be the same.
9:15
All of the development that I've done on my computer has actually been done
9:19
on a desktop computer with its geolocation not moving
9:22
because the computer hasn't moved.
9:27
In fact, all of our notes should actually have the exact same latitude and longitude,
9:30
which becomes an interesting problem when you're working on a desktop computer
9:34
on an application that deals with geolocation.
9:38
If your ocation is not physically changing, you need to either work in
9:43
some debug code that will change the latitude and longitude values,
9:46
or you need to actually move around so it has to actually change
9:51
your latitude and longitude values.
9:54
What I prefer to do here is I prefer to add in some debug code that will actually
9:57
fuzz or move my latitude and longitude around every time I ask for it.
10:02
But, before I do that, let's go ahead and see if we can't get the current distance
10:07
displayed in each of our notes.
10:11
So, that's going to be something for the view, which is going to be in our
10:15
index.html in our list item here.
10:19
Here we have the title.
10:22
Since RA tag is getting a little more complex, let's just reformat it a little bit,
10:24
and let's put it in parantheses in the list,
10:30
and let's write note.distanceFromCurrent, I believe
10:42
was the name of our method.
10:49
Let's doublecheck, distanceFromCurrent,
10:51
and let's refresh.
10:57
All right, they're all showing up as zero, which could mean one of two things.
11:00
Either our safety case of returning zero is always being called,
11:02
or the current latitude and longitude are the same as each notes latitude and longitude,
11:06
which also should be the case.
11:11
So, let's go into application.js and change our escape value from zero to -1.
11:14
That way, notes without any information will show up as -1, and notes with any
11:20
information will show up as zero.
11:23
Right now, they're all -1.
11:27
If we locate, this is the only note without location, so we can see it's -1,
11:29
and everything else is showing a zero distance away, which is absolutely
11:34
true since it's all been done in the same room.
11:37
What we're going to do is rewrite our code with some debug information in it,
11:42
so that whenever we create new notes in a debug mode, it will change the
11:45
latitude and longitude ever so slightly so we get a little bit of variation in our notes.
11:49
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up