1 00:00:00,000 --> 00:00:05,000 So, now we've created our view which has a list in it, and our locate button will 2 00:00:05,000 --> 00:00:08,000 actually update the application's current location. 3 00:00:08,000 --> 00:00:13,000 The next thing we want to see is if our new collection can be sorted by the distance 4 00:00:13,000 --> 00:00:18,000 from the current location to each notes location. 5 00:00:18,000 --> 00:00:23,000 Now, this is going to be a tricky process, so let's do it in small steps. 6 00:00:23,000 --> 00:00:27,000 The first thing I like to find out is to make sure that the comparator is 7 00:00:27,000 --> 00:00:33,000 actually working properly based on the locate button, or just even at all. 8 00:00:33,000 --> 00:00:36,000 So, I want to make sure that the comparator is working properly, that is, 9 00:00:36,000 --> 00:00:41,000 it's refreshed when we hit the locate button. 10 00:00:41,000 --> 00:00:44,000 So, one way we could test that is to create a comparator function that returns a 11 00:00:44,000 --> 00:00:51,000 random value and see if every time we update our location, if the list randomly sorts. 12 00:00:51,000 --> 00:00:54,000 So, this is our comparator function as we wrote it. 13 00:00:54,000 --> 00:00:58,000 It's just returning zero, which will be a sort of static pseudo random sort 14 00:00:58,000 --> 00:01:01,000 based on how it's stored in the database, but what we actually want to do 15 00:01:01,000 --> 00:01:09,000 is call a method on note that we will call "distanceFromCurrent," and this method 16 00:01:09,000 --> 00:01:13,000 will handle all the logic of comparing the notes distance from the 17 00:01:13,000 --> 00:01:15,000 application's current distance. 18 00:01:15,000 --> 00:01:19,000 So, let's go up to the note model and begin defining that method. 19 00:01:19,000 --> 00:01:21,000 So, here we are in our note model. 20 00:01:21,000 --> 00:01:27,000 We're just going to add another method underneath map image URL, 21 00:01:27,000 --> 00:01:33,000 and we'll call that "distanceFromCurrent." 22 00:01:33,000 --> 00:01:36,000 And then like I said, the process of calculating the distance here is actually 23 00:01:36,000 --> 00:01:45,000 pretty complicated, but what we can do is call return Math.random. 24 00:01:45,000 --> 00:01:49,000 The way the comparator works is it'll take each of the values from distanceFromCurrent 25 00:01:49,000 --> 00:01:54,000 and try to sort those, and since the values will be random, we should get a random sort 26 00:01:54,000 --> 00:01:58,000 every time we attempt to sort that collection. 27 00:01:58,000 --> 00:02:04,000 Now, to get a little more information here, I'm going to go ahead and add a few notes. 28 00:02:04,000 --> 00:02:06,000 [? Music ?] 29 00:02:06,000 --> 00:02:10,000 [Many Notes Later] 30 00:02:10,000 --> 00:02:13,000 And so, that's the last of all those new notes. 31 00:02:13,000 --> 00:02:21,000 If we go to nearest notes here, we can see we have a lot more notes. 32 00:02:21,000 --> 00:02:24,000 Hopefully, all of them have some location information here. 33 00:02:24,000 --> 00:02:27,000 Unfortunately, it's all going to be the same location, which we'll have to 34 00:02:27,000 --> 00:02:30,000 worry about in a moment. 35 00:02:30,000 --> 00:02:34,000 So, if everything's working right, when we click the locate button, 36 00:02:34,000 --> 00:02:38,000 it should update our location and try to sort, and since our sort is random, 37 00:02:38,000 --> 00:02:41,000 we should see these sort of just shuffle around. 38 00:02:41,000 --> 00:02:48,000 Now, I'm not seeing that quite yet, so let's see why that might be. 39 00:02:48,000 --> 00:02:51,000 Let's see if our distanceFromCurrent is being called. 40 00:02:51,000 --> 00:02:57,000 So, I'm just going to add a console.log here and say "distanceFromCurrent" 41 00:02:57,000 --> 00:03:00,000 and just see if that's being called at all. 42 00:03:00,000 --> 00:03:05,000 So if we click "locate," it looks like I just need to refresh the page 43 00:03:05,000 --> 00:03:15,000 in order for that to take effect, because now it is not only giving us distanceFromCurrent here, 44 00:03:15,000 --> 00:03:19,000 we're also getting the sorting by random values here. 45 00:03:19,000 --> 00:03:22,000 Let's make sure that the console.log is not the thing that changed here, 46 00:03:22,000 --> 00:03:27,000 so let's remove that, refresh, and try again. 47 00:03:27,000 --> 00:03:31,000 Cool, so every time we click the locate button it's resorting, and since the comparator 48 00:03:31,000 --> 00:03:37,000 is giving us a random value, we're getting a random sort. 49 00:03:37,000 --> 00:03:41,000 So, we have now updated our nearest notes view page to be able to 50 00:03:41,000 --> 00:03:43,000 sort based on the location. 51 00:03:43,000 --> 00:03:48,000 The locate button will get the current location, store it into a value in the 52 00:03:48,000 --> 00:03:53,000 application object, and now what we need to do is write a comparator function 53 00:03:53,000 --> 00:03:57,000 that will compare each note to that current location. 54 00:03:57,000 --> 00:04:02,000 With latitude and longitude, finding out the distance isn't as simple 55 00:04:02,000 --> 00:04:06,000 as using the Pythagorean Theorem in a flat space. 56 00:04:06,000 --> 00:04:11,000 The earth is round, which makes calculating the distance between two points, 57 00:04:11,000 --> 00:04:16,000 measured in latitude and longitude, a fairly complicated equation. 58 00:04:16,000 --> 00:04:19,000 Now, I don't know this calculation off the top of my head, 59 00:04:19,000 --> 00:04:24,000 but I do know what the name of the calculation is, and I will let you know. 60 00:04:24,000 --> 00:04:28,000 It's called the haversine distance, and it is how you measure between 61 00:04:28,000 --> 00:04:32,000 two points on a sphere. 62 00:04:32,000 --> 00:04:34,000 With that, you can Google it, you can just Google measuring the distance 63 00:04:34,000 --> 00:04:40,000 between latitude and longitude, and you can find a page like this, 64 00:04:40,000 --> 00:04:45,000 and this gives you a little bit of information, including a JavaScript tool 65 00:04:45,000 --> 00:04:50,000 that will help you calculate the distance between two latitude and longitude points. 66 00:04:50,000 --> 00:04:55,000 Now, the main reason that we have such a complicated equation is because 67 00:04:55,000 --> 00:05:01,000 the Earth is spherical, and the way longitude works is as you move higher 68 00:05:01,000 --> 00:05:05,000 in latitude, the distance between two longitudinal degrees decreases as you 69 00:05:05,000 --> 00:05:08,000 move towards the North and South Pole. 70 00:05:08,000 --> 00:05:10,000 When you get to the North and South Pole, there's actually no distance 71 00:05:10,000 --> 00:05:14,000 between any of the longitudinal distances. 72 00:05:14,000 --> 00:05:17,000 So, the calculation that we have to do has to take into account how far from the 73 00:05:17,000 --> 00:05:23,000 Equator we are and the actual radius of the Earth. 74 00:05:23,000 --> 00:05:27,000 Now, in addition to explaining all of these formulas really well and providing an 75 00:05:27,000 --> 00:05:32,000 interactive tool, this particular page actually offers us a JavaScript 76 00:05:32,000 --> 00:05:38,000 version of the haversine formula which we're going to adapt to our needs. 77 00:05:38,000 --> 00:05:41,000 Basically, it takes into account the radius of the earth, and right now it's 78 00:05:41,000 --> 00:05:47,000 doing it in kilometers, so our final value will actually be in kilometers. 79 00:05:47,000 --> 00:05:51,000 If we replace that value with the radius of the Earth in miles, we could do it in 80 00:05:51,000 --> 00:05:57,000 miles or any other value, and then we do all of this math. 81 00:05:57,000 --> 00:06:01,000 So basically, what I'm going to do is, I'm going to copy in my version of this, 82 00:06:01,000 --> 00:06:04,000 which I've adapted from this version. 83 00:06:04,000 --> 00:06:11,000 So, let's go into our code again. 84 00:06:11,000 --> 00:06:14,000 And our distanceFromCurrent here, let's remove this random here. 85 00:06:14,000 --> 00:06:18,000 We don't need that anymore, and I'm going to paste this in, and I'm going to 86 00:06:18,000 --> 00:06:25,000 explain as much of this as I can without getting too deep into the math of it. 87 00:06:25,000 --> 00:06:28,000 Now, the first thing I've done here is I've added a convenience function 88 00:06:28,000 --> 00:06:32,000 to convert from degrees into radians. 89 00:06:32,000 --> 00:06:35,000 All of this calculation works in radians, and if you actually look at the original 90 00:06:35,000 --> 00:06:41,000 source, to convert it it uses a method which isn't really defined in our browser, 91 00:06:41,000 --> 00:06:46,000 so I've converted the two rad method calls to a function call, which is simply 92 00:06:46,000 --> 00:06:53,000 multiplying degrees times Pi divided by 180. 93 00:06:53,000 --> 00:06:59,000 Then really what we need to do is define our lat 1/lat 2, long 1/long 2 variables, 94 00:06:59,000 --> 00:07:01,000 which are used in the equation. 95 00:07:01,000 --> 00:07:07,000 So, latitude and longitude 1 are going to come from App.currentlocation.latitude, 96 00:07:07,000 --> 00:07:10,000 and lat and long 2 will be based on this note. 97 00:07:10,000 --> 00:07:15,000 It doesn't matter which one you set, so long as you make sure that lat and long 1 98 00:07:15,000 --> 00:07:20,000 match up and lat and long 2 match up. 99 00:07:20,000 --> 00:07:24,000 Then basically, the equation goes through finding the distance between the latitudes 100 00:07:24,000 --> 00:07:30,000 and longitudes, and it does a lot of trigonometry here to figure out the total distance 101 00:07:30,000 --> 00:07:34,000 between the two on a spherical object, 102 00:07:34,000 --> 00:07:39,000 finally resulting in D, which should be our distance in kilometers. 103 00:07:39,000 --> 00:07:42,000 Now, there is one thing we do need to protect against, is if we try to call 104 00:07:42,000 --> 00:07:46,000 distanceFromCurrent, there may be a couple situations where this won't work. 105 00:07:46,000 --> 00:07:50,000 For instance, if the current location inside of our application has not 106 00:07:50,000 --> 00:07:56,000 been set, we are going to fail, and if there's no note for the current note, 107 00:07:56,000 --> 00:07:58,000 we're also going to fail. 108 00:07:58,000 --> 00:08:04,000 So, we want to put a guard at the top of our distanceFromCurrent to return quickly 109 00:08:04,000 --> 00:08:09,000 if this note is not geotagged or if there's no current location. 110 00:08:09,000 --> 00:08:13,000 So, what I'm going to do on the first line here is paste this in, 111 00:08:13,000 --> 00:08:19,000 and if this is not geotagged, or if the app doesn't have a current location, 112 00:08:19,000 --> 00:08:24,000 we'll return zero, and this value really depends on where you would want the 113 00:08:24,000 --> 00:08:29,000 untagged notes to appear when you sort by distance. 114 00:08:29,000 --> 00:08:32,000 If you want them to appear at the end of the list, you would want to return a large 115 00:08:32,000 --> 00:08:37,000 number like infinity or the max value of the number class. 116 00:08:37,000 --> 00:08:40,000 Or, if you wanted them to be at the top of the list, zero or a negative number 117 00:08:40,000 --> 00:08:43,000 would also be a good case. 118 00:08:43,000 --> 00:08:45,000 For right now, I'm just going to return zero. 119 00:08:45,000 --> 00:08:49,000 So, let's save this out and see if it works. 120 00:08:49,000 --> 00:08:53,000 So, if we refresh, let's hope we don't get any syntax errors, and we're good there, 121 00:08:53,000 --> 00:08:57,000 and let's click the locate button. 122 00:08:57,000 --> 00:09:01,000 Now, it's not sorting any differently, which can be a good thing, 123 00:09:01,000 --> 00:09:04,000 but we don't quite know what these values are. 124 00:09:04,000 --> 00:09:08,000 Now, one thing I want to do is I actually do want to show the values here. 125 00:09:08,000 --> 00:09:11,000 I do want to show the values here, but, however, even if I do show the 126 00:09:11,000 --> 00:09:15,000 values, I'm pretty sure that we're not going to get a resorting, 127 00:09:15,000 --> 00:09:19,000 because they should actually all be the same. 128 00:09:19,000 --> 00:09:22,000 All of the development that I've done on my computer has actually been done 129 00:09:22,000 --> 00:09:27,000 on a desktop computer with its geolocation not moving 130 00:09:27,000 --> 00:09:30,000 because the computer hasn't moved. 131 00:09:30,000 --> 00:09:34,000 In fact, all of our notes should actually have the exact same latitude and longitude, 132 00:09:34,000 --> 00:09:38,000 which becomes an interesting problem when you're working on a desktop computer 133 00:09:38,000 --> 00:09:43,000 on an application that deals with geolocation. 134 00:09:43,000 --> 00:09:46,000 If your ocation is not physically changing, you need to either work in 135 00:09:46,000 --> 00:09:51,000 some debug code that will change the latitude and longitude values, 136 00:09:51,000 --> 00:09:54,000 or you need to actually move around so it has to actually change 137 00:09:54,000 --> 00:09:57,000 your latitude and longitude values. 138 00:09:57,000 --> 00:10:02,000 What I prefer to do here is I prefer to add in some debug code that will actually 139 00:10:02,000 --> 00:10:07,000 fuzz or move my latitude and longitude around every time I ask for it. 140 00:10:07,000 --> 00:10:11,000 But, before I do that, let's go ahead and see if we can't get the current distance 141 00:10:11,000 --> 00:10:15,000 displayed in each of our notes. 142 00:10:15,000 --> 00:10:19,000 So, that's going to be something for the view, which is going to be in our 143 00:10:19,000 --> 00:10:22,000 index.html in our list item here. 144 00:10:22,000 --> 00:10:24,000 Here we have the title. 145 00:10:24,000 --> 00:10:30,000 Since RA tag is getting a little more complex, let's just reformat it a little bit, 146 00:10:30,000 --> 00:10:42,000 and let's put it in parantheses in the list, 147 00:10:42,000 --> 00:10:49,000 and let's write note.distanceFromCurrent, I believe 148 00:10:49,000 --> 00:10:51,000 was the name of our method. 149 00:10:51,000 --> 00:10:57,000 Let's doublecheck, distanceFromCurrent, 150 00:10:57,000 --> 00:11:00,000 and let's refresh. 151 00:11:00,000 --> 00:11:02,000 All right, they're all showing up as zero, which could mean one of two things. 152 00:11:02,000 --> 00:11:06,000 Either our safety case of returning zero is always being called, 153 00:11:06,000 --> 00:11:11,000 or the current latitude and longitude are the same as each notes latitude and longitude, 154 00:11:11,000 --> 00:11:14,000 which also should be the case. 155 00:11:14,000 --> 00:11:20,000 So, let's go into application.js and change our escape value from zero to -1. 156 00:11:20,000 --> 00:11:23,000 That way, notes without any information will show up as -1, and notes with any 157 00:11:23,000 --> 00:11:27,000 information will show up as zero. 158 00:11:27,000 --> 00:11:29,000 Right now, they're all -1. 159 00:11:29,000 --> 00:11:34,000 If we locate, this is the only note without location, so we can see it's -1, 160 00:11:34,000 --> 00:11:37,000 and everything else is showing a zero distance away, which is absolutely 161 00:11:37,000 --> 00:11:42,000 true since it's all been done in the same room. 162 00:11:42,000 --> 00:11:45,000 What we're going to do is rewrite our code with some debug information in it, 163 00:11:45,000 --> 00:11:49,000 so that whenever we create new notes in a debug mode, it will change the 164 00:11:49,000 --> 00:11:53,000 latitude and longitude ever so slightly so we get a little bit of variation in our notes.