1 00:00:00,000 --> 00:00:03,000 [Jim Hoskins] So we've added the ability to tag notes with our location 2 00:00:03,000 --> 00:00:07,000 and we've figured out how to add a map to the show view. 3 00:00:07,000 --> 00:00:12,000 Another cool feature of our app might be to not only sort all notes-- 4 00:00:12,000 --> 00:00:18,000 for instance, by name--but to also be able to see the Notes nearest to you, 5 00:00:18,000 --> 00:00:22,000 and that is what this second menu item is going to be reserved for. 6 00:00:22,000 --> 00:00:27,000 So what's involved with actually being able to sort the Nearest Notes to you? 7 00:00:27,000 --> 00:00:31,000 Well, one, we need to have Notes that have location, which we have. 8 00:00:31,000 --> 00:00:35,000 We need to get the current location of the user, which is something that we know how to do 9 00:00:35,000 --> 00:00:42,000 but we're going to have to come up with the idea of the current location in the application. 10 00:00:42,000 --> 00:00:46,000 And then, we need a way to compare the distance between each Note 11 00:00:46,000 --> 00:00:49,000 and the current location in the world. 12 00:00:49,000 --> 00:00:51,000 So those are the steps we need to go through. 13 00:00:51,000 --> 00:00:55,000 Let's go ahead and start with creating the list for the Nearest Notes. 14 00:00:55,000 --> 00:00:59,000 So basically, we need to create another list view here, 15 00:00:59,000 --> 00:01:01,000 just like we did for All Notes. 16 00:01:01,000 --> 00:01:04,000 In fact, it's going to be very, very similar. 17 00:01:04,000 --> 00:01:07,000 So I'm going to go into index.html 18 00:01:07,000 --> 00:01:11,000 and if we take a look at our List of Notes, we're pretty much going to do the same thing 19 00:01:11,000 --> 00:01:13,000 but with a little bit of a different twist. 20 00:01:13,000 --> 00:01:20,000 So let's go ahead and just change this to (Alphabetical) 21 00:01:20,000 --> 00:01:25,000 and basically, I'm going to take the structure of the list of Notes 22 00:01:25,000 --> 00:01:28,000 and I'm going to create a new view, which we'll call the Nearest, 23 00:01:28,000 --> 00:01:31,000 and I've pasted it in here. 24 00:01:31,000 --> 00:01:35,000 So I've given it an id="nearest" so that's the URL we're going to access it from, 25 00:01:35,000 --> 00:01:37,000 and pretty much all of it's the same. 26 00:01:37,000 --> 00:01:39,000 It has a header with a back button 27 00:01:39,000 --> 00:01:44,000 and header of Nearest Notes, and the only thing that I've really added to this view 28 00:01:44,000 --> 00:01:49,000 that wasn't in our original list view is this extra button in the header, 29 00:01:49,000 --> 00:01:52,000 which I've created using jQuery Mobile. 30 00:01:52,000 --> 00:01:57,000 It's called the Locate button, and this will be what actually triggers 31 00:01:57,000 --> 00:02:00,000 finding out the user's current location. 32 00:02:00,000 --> 00:02:05,000 We could also have a function so it locates the user when they first load the page, 33 00:02:05,000 --> 00:02:09,000 but right now, I'm going to wire it up specifically to this button. 34 00:02:09,000 --> 00:02:14,000 Then I have our content, which just has a list view with the id=nearest_notes 35 00:02:14,000 --> 00:02:17,000 which is where the actual list of Notes will go. 36 00:02:17,000 --> 00:02:20,000 So now that we've added the new view into our HTML, 37 00:02:20,000 --> 00:02:25,000 let's check it out in the browser and see where we get. 38 00:02:25,000 --> 00:02:27,000 If I refresh and we click on Nearest Notes, 39 00:02:27,000 --> 00:02:30,000 now that we have a Nearest Page, we have our Nearest Notes here 40 00:02:30,000 --> 00:02:35,000 and a Locate button that does nothing, and our Back button. 41 00:02:35,000 --> 00:02:43,000 So we now have sort of a skeleton for the place where our list of Nearest Notes will go. 42 00:02:43,000 --> 00:02:45,000 So now that we have our jQuery Mobile page set up, 43 00:02:45,000 --> 00:02:48,000 let's go ahead and create a Backbone view 44 00:02:48,000 --> 00:02:53,000 so we can handle the clicking of the Locate button appropriately. 45 00:02:53,000 --> 00:02:56,000 So let's hop into our application.js 46 00:02:56,000 --> 00:03:04,000 and let's see where we're going to put this. 47 00:03:04,000 --> 00:03:06,000 I'm just going to place it right here, 48 00:03:06,000 --> 00:03:11,000 and we're going to call this for our page--this is going to be the view for the entire page, 49 00:03:11,000 --> 00:03:15,000 not the actual list itself. 50 00:03:15,000 --> 00:03:19,000 We're going to call this class var NearestPageView = 51 00:03:19,000 --> 00:03:29,000 and this will be a Backbone.View.extend({. 52 00:03:29,000 --> 00:03:33,000 Let's go ahead and define the events that will be defined for this view. 53 00:03:33,000 --> 00:03:37,000 Basically, we just want to handle the clicking of the Locate button. 54 00:03:37,000 --> 00:03:42,000 So to define our events like we did before, we'll just do events: { here 55 00:03:42,000 --> 00:03:44,000 and create an object 56 00:03:44,000 --> 00:03:47,000 and the key is going to be a string that describes the action, 57 00:03:47,000 --> 00:03:53,000 which would be "click" and the selector for the element that we're going to be listening to, 58 00:03:53,000 --> 00:03:57,000 which is the button with the class .locate. 59 00:03:57,000 --> 00:04:04,000 And when this happens, I want to "updateLocation". 60 00:04:04,000 --> 00:04:08,000 So let's create our initliazer for this page view. 61 00:04:08,000 --> 00:04:14,000 So we'll create initialize: function(options){ 62 00:04:14,000 --> 00:04:18,000 and there's going to be a subview, which is going to be our list view 63 00:04:18,000 --> 00:04:22,000 that we want to keep track of, and that's going to be passed into the initializer, 64 00:04:22,000 --> 00:04:33,000 so let's store it as a property, so we'll say this.listView = options.listView. 65 00:04:33,000 --> 00:04:37,000 So we always want a list view to be passed in so that our page 66 00:04:37,000 --> 00:04:44,000 can manage sorting and updating that list whenever we click the Update Location button. 67 00:04:44,000 --> 00:04:49,000 So we defined that clicking the .locate should call the updateLocation method, 68 00:04:49,000 --> 00:04:52,000 so let's go ahead and write that method out, too. 69 00:04:52,000 --> 00:04:57,000 So we'll do updateLocation: function 70 00:04:57,000 --> 00:05:01,000 and it's an event handler, so it will be passed an event object(e){ 71 00:05:01,000 --> 00:05:04,000 and basically, in this view, we're going to take a couple steps. 72 00:05:04,000 --> 00:05:07,000 First, we're going to check if Geolocation is available. 73 00:05:07,000 --> 00:05:11,000 If it is, we're going to do our normal Geolocation query 74 00:05:11,000 --> 00:05:15,000 and if we get a result from that, what we're going to do is store the results of that query 75 00:05:15,000 --> 00:05:19,000 in a property of our application object. 76 00:05:19,000 --> 00:05:24,000 After we do that, we're going to want to sort our list view, 77 00:05:24,000 --> 00:05:28,000 and we do that because now our location is potentially changed 78 00:05:28,000 --> 00:05:33,000 so we need to re-sort since the sort will take into account this newly updated location. 79 00:05:33,000 --> 00:05:37,000 Let's start off with a check to make sure we have Geolocation available, 80 00:05:37,000 --> 00:05:47,000 so let's check if("geolocation" in navigator){ object, 81 00:05:47,000 --> 00:05:52,000 so if we have Geolocation capabilities, we want to do a Geolocation query. 82 00:05:52,000 --> 00:06:00,000 So we'll do navigator.geolocation.getCurrentPosition 83 00:06:00,000 --> 00:06:06,000 which take a callback (function) which will be passed a (position). 84 00:06:06,000 --> 00:06:12,000 And now, inside of this callback function is where we will handle storing our information. 85 00:06:12,000 --> 00:06:22,000 So if we have the position object and the position object has a .coordinates property on it, 86 00:06:22,000 --> 00:06:30,000 what we want to do is // Set Current Location 87 00:06:30,000 --> 00:06:37,000 and for our application, what I'm going to do is define that App.currentlocation 88 00:06:37,000 --> 00:06:45,000 will be where we store the current location of the user and we will set it to position.coords. 89 00:06:45,000 --> 00:06:49,000 Now, this is just a normal JavaScript variable; if you refresh the page, 90 00:06:49,000 --> 00:06:51,000 the current location will be lost. 91 00:06:51,000 --> 00:06:54,000 It is not stored in a database, and I think that's fine 92 00:06:54,000 --> 00:06:58,000 because it's something that's going to be updated a lot. 93 00:06:58,000 --> 00:07:01,000 Now, the last thing we want to do is to update the list view 94 00:07:01,000 --> 00:07:06,000 and tell its collection to sort itself. 95 00:07:06,000 --> 00:07:12,000 Now, one way we could do this is to call the list views collections sort method directly 96 00:07:12,000 --> 00:07:15,000 and I think that's what we'll go ahead and do. 97 00:07:15,000 --> 00:07:18,000 Now, in order to get to the list view for this view, 98 00:07:18,000 --> 00:07:24,000 we need to access this.listView, but since we're in a callback function for getCurrentPosition, 99 00:07:24,000 --> 00:07:28,000 the value of this has been changed since we're now in a new function. 100 00:07:28,000 --> 00:07:31,000 So what we have to do is somewhere outside of the function, 101 00:07:31,000 --> 00:07:38,000 we will assign the value of this to a variable and we'll give it the name pageView, 102 00:07:38,000 --> 00:07:41,000 so pageView = this;. 103 00:07:41,000 --> 00:07:47,000 So after we set the current location, we can grab pageView, 104 00:07:47,000 --> 00:07:50,000 which is this, and grab the listView, 105 00:07:50,000 --> 00:07:59,000 and on its collection, we will call .sort();. 106 00:07:59,000 --> 00:08:03,000 So now we've generated a pageView for our nearest list, 107 00:08:03,000 --> 00:08:10,000 let's go ahead and instantiate it in our page to handle our actual view in the HTML. 108 00:08:10,000 --> 00:08:15,000 So down at the bottom is where we're actually instantiating our views, 109 00:08:15,000 --> 00:08:22,000 and we'll just scroll down to where we instantiated our other views, 110 00:08:22,000 --> 00:08:27,000 and I'm just going to place it right down here. 111 00:08:27,000 --> 00:08:33,000 So we're going to assign it into app.views and we'll call this view the nearest_page 112 00:08:33,000 --> 00:08:39,000 and we'll instantiate a new NearestPageView with the element of the id "#nearest" 113 00:08:39,000 --> 00:08:45,000 and we're going to pass in a listView, which we'll call App.views.list_distance. 114 00:08:45,000 --> 00:08:50,000 Now, we haven't created that yet, so let's go ahead and instantiate 115 00:08:50,000 --> 00:08:55,000 the actual list view that will be inside of this page view. 116 00:08:55,000 --> 00:09:00,000 Now we're going to just reuse the Note list view that we used for our other Notes list 117 00:09:00,000 --> 00:09:03,000 and we're just going to pass it a different element. 118 00:09:03,000 --> 00:09:12,000 So right here, this is the view for our actual list within our nearest page, 119 00:09:12,000 --> 00:09:15,000 so the list will be based on nearest_notes 120 00:09:15,000 --> 00:09:22,000 and the collection is based on app.collections.notes_distance. 121 00:09:22,000 --> 00:09:31,000 Now, we haven't created that collection, so let's go ahead and create that collection. 122 00:09:31,000 --> 00:09:35,000 The reason we're creating a new collection for our Nearest Notes 123 00:09:35,000 --> 00:09:38,000 is because we're going to be using a different comparator 124 00:09:38,000 --> 00:09:44,000 where our all_notes is using a comparator that checks based on the title of the Note 125 00:09:44,000 --> 00:09:46,000 and its alphabetical value. 126 00:09:46,000 --> 00:09:50,000 In our collection here, we will be actually comparing 127 00:09:50,000 --> 00:09:54,000 based on the distance of the Notes coordinates from the current coordinates, 128 00:09:54,000 --> 00:09:59,000 and that's a comparator that we're going to have to write in a moment. 129 00:09:59,000 --> 00:10:03,000 So let's just call this notes_distance, 130 00:10:03,000 --> 00:10:07,000 and we'll create a new NoteList 131 00:10:07,000 --> 00:10:10,000 with null initial values (null, { 132 00:10:10,000 --> 00:10:15,000 and for our options, we're going to create a comparator: 133 00:10:15,000 --> 00:10:19,000 which is a function that takes a (note) 134 00:10:19,000 --> 00:10:25,000 and it will return some value, and right now we'll just say 0 and it will not be allowed to sort. 135 00:10:25,000 --> 00:10:28,000 So let's see if all of our code actually fits together 136 00:10:28,000 --> 00:10:32,000 because it's a good time for a sanity check to make sure we're not going to get any errors 137 00:10:32,000 --> 00:10:38,000 with all of the code that we just added in. 138 00:10:38,000 --> 00:10:42,000 So let's refresh--all right, no errors so far. 139 00:10:42,000 --> 00:10:46,000 if we click on Nearest Notes, we get a list of all of our Notes. 140 00:10:46,000 --> 00:10:49,000 Now, right now the sorting is not working, 141 00:10:49,000 --> 00:10:51,000 but at least we do have our Notes. 142 00:10:51,000 --> 00:10:56,000 Let's see if the view will handle our click here on the Locate button. 143 00:10:56,000 --> 00:10:59,000 It doesn't look like anything's happening, but it may have, 144 00:10:59,000 --> 00:11:04,000 because we may have already authorized the browser to share our current location, 145 00:11:04,000 --> 00:11:07,000 so it's not going to ask us every time. 146 00:11:07,000 --> 00:11:10,000 One way we can debug to see if the current location is set 147 00:11:10,000 --> 00:11:16,000 is in the JavaScript console, we'll check the Notes app, 148 00:11:16,000 --> 00:11:23,000 which is our application instance, and see if the current location has been set. 149 00:11:23,000 --> 00:11:27,000 If we do that, we can see that there's a coordinates object assigned to it. 150 00:11:27,000 --> 00:11:31,000 So next, we need to create the comparator function that will compare the current location 151 00:11:31,000 --> 00:11:34,000 to each of the Notes' locations.