[ Silence ] >> Okay so we're going to get started in just a second here. I think we're all set with the cameras. Great. So the first thing we're going to do today, well first user directions, my name is RJ, this is Rob and we'll be the teaching fellows for S-76 this year. And these labs are meant to be time for more hands on exercises where we'll give some instructions. We'll break up into groups kind of like this, work through them. And we'll floating around to help out. And then we'll go over an example solution or take example solutions from the group. >> Yeah if you ever have any questions and one of us, even if like RJ's talking, I can come over and help whenever. >> Especially these early labs we'll be getting everyone's configuration on the same page is the most important thing. So definitely raise your hand if something doesn't seem quite the same as it is up here or something doesn't seem to be quite working. If you got my email a while ago there's a link in there on how to install Zamp. You can clink the link in there and install Zamp. That's the first thing we're going to do is just download that software, get it installed, try to put an example html file in your sites folder and get that to load. So anything you put in that file and pull it up. So who here has installed Zamp? Has successfully installed Zamp? Oh great, okay, who has not? >> Or other web server? Is there anyone who is in the process of installing it? >> So we'll get that set up. So for those of you who have installed it, have you been able to put a file in your sites folder to try things out? If not let's open up your favorite text editor and save a file in your sites folder. Okay so everyone has got everything set up. We're going to keep pushing ahead. For those that have not gotten things fully set up just raise your hand and David is floating around to help out as well. So the next thing we're going to do is you just have at least a basic index html or test study html or the lectures examples in that folder. We're going to take one of those files and make it a little more useable. So we're going to add the meta tag in the head as we saw in lecture and add a viewpoint element to that, a viewpoint property to that. In addition we're going to add some script types and add some JavaScript to make it a little more dynamic. So I want you guys to make a page that has at the very least a textbox and a button, a submit button, and a div of some sort with an id. And so collaborate with your group. The goal is when you click the submit button, whatever is in that text box populates that div. So Rob is going to draw a picture. Is that what Rob's doing? >> Okay. [laughter] [ Silence ] What did you say, a button? [ Silence ] >> The goal is first up, the html, has this textbox, the submit button and then some space below. >> It can be an invisible space. Like if you have a div you're not going to be able to see it but it'll be there. And then whatever you type here and submit, it should show up down here. >> So once you have the structure base all set up you'll need two things at the very least, a script tag that includes JavaScript and you'll likely have a script tag that includes jQuery, as we saw in lecture. So if you don't remember exactly how to do that, feel free to collaborate with your partners, look on the courses website or raise your hand and we'll be floating around. But the goal is to, again, once you click that submit button, have the contents reflected in the div below. >> Just to put something out, this little line right here is what I'm using to include jQuery so if you wanted you could just download jQuery locally and then include it with like scriptsource=jQuery.js or whatever, if it were inside of the same directory as this exercise1.html. Here Google happens to provide a jQuery link online so I'm just directly linking to Google and pulling down jQuery that way so either works. Okay so a couple things I've added just to get you going if you're stuck. So notice I've given some ID's to my div and my form and my input textbox. Because jQuery is going to conveniently, some of them didn't really need ID's but it's convenient to have them. Remember this syntax is going let me $(# is going to refer to the element with that ID. I wasn't very creative with my ID name so we've exercised one form, exercised one text and exercised1-id div. Okay so what this particular line of jQuery is saying is grab, select, this particular item so we're selecting the item with id exercise1 form which is this guy. There should only be one thing in your entire document with that id and so that's this guy. And we're saying when the submit event is triggered, so when we actually hit submit on that form, we're going to run this function. So I haven't defined what the function does yet but we're going to want the function to do something like copy this text down into this div and also make sure that the form doesn't actually end up submitting. So let's actually talk about the third point first. We saw this in lecture, how do we prevent the form from actually submitting? What do we need to do? [inaudible background comment] Yes. So we can do that just by return false. If we return true that means the form should actually submit. And this is going to be useful for things like validating the submission because like if you didn't fill out a textbox maybe you don't want the form to submit so return false will prevent that. But if it is filled out then you do want it to submit so you can return true. And for points one and two I'm going to use jQuery. You can use regular straight JavaScript but what is the selector? And this being the selector, this jQuery selector, what is the selector I'm going to want to use in order to get something from this? [laughter] Yeah, this is the selector. So remember that the pound, the hash, the whatever you want to call it, refers to the element with that id. If I said this, that would mean the element with that tag, which there isn't any. You might see that if I did something like div or if I did, actually div would be pretty good so we don't want that from form, we want that from text. So the text is inside of this input box, exercise1 text. I gave it that id just to get the text. We have now selected the item and this is where you kind of just learn them or you can go through the jQuery documentation. But what we're going to want to do to actually get the text that's inside the text box is .val. And so then I can store that in just a variable. Our text equals blah. Okay so [laughter] the line I just added, I wrapped that around everything we had so far, inside of this skirt tag, is another jQuery thing. So you'll notice, and there are some shortcuts you might know so .submit also exists but I'm not going to use those. So whenever you see .on that refers to like something should happen when this event happens. So submit is one event that happens whenever you like submit a form. So ready is another event that happens whenever that thing has been fully loaded on the page. So here we're saying when the entire page has been loaded, do this. So without this line then we are doing this function before we've even gotten to the html that causes these things to exist. So when the page fully loads, then do this stuff. And this is a very common pattern that you don't want to do things until the page is loaded. [inaudible background question] No, well, no, you can do that. The thing is that like eventually this will probably get put into like, or should probably get put into a separate JavaScript file, which you could include at the bottom but I usually see like all these script tags at the top. [inaudible background question] Yeah so the .ready function is an alternative to this. [inaudible background question] Sure, we'll do the last point now. Insert the text into the div. So what selector do you want to use? It's exactly this guy, #exercise1-div. And then we're going to want to put inside of it whatever was in that text box and so you can look at the various jQuery methods that are available to you. Here I happen to know that I want to use the text method which is kind of confusing because I call this variable text so let's say this is text box. So we're using the text method and calling or putting inside of it text box. So this line is saying that take this div, replace whatever is inside of it with whatever is in this variable. >> And after the lab we'll definitely post our example solution with extensive comments, similar to this but with a little more explanation. >> Yeah. >> So that if you missed a bit or don't understand what one line does you can see it after the lab is over. [ Classroom discussion ] So I'll get us started on the second part of this. So if you haven't fully got this working, flag us down, we'll help get it working. But the second part is going to tease a bit behind the mechanics of the project. So we'll look at, if you go to cs76.net, there's a projects tab on the left and there's the link for our first project which is due approximately two weeks hence. Yeah, project I've got attention. As for the project there's a section labeled, let me get the name right, geocoding, and there's a link to Google's geocoding API. So through jQuery, and the project [inaudible], you're able to make external requests, asking for information from an external API like the geocoding API. In this sense the geocoding API allows you to turn addresses or zip codes into, or get more information about them. So we're going to extend this example to change, instead of changing text, when you type in a zip code we want you to send that zip code through the geocoding API and get back the city and state for that zip code. So as the first test go to link on cs76.net, go to the projects tab to projects link and there's a link to the geocoding API. Look at the example there and try it out just by going to the URL at the geocoding API. And definitely talk with the people at your table to see if you can't seem to find the page I'm talking about. Then you're going to want to modify this to make your submit box and the request to this geocoding API with jQuery's get [inaudible] function. So I'll float around to help get exercise1 working which was up there a second ago and then we can push ahead on with this second example. >> Okay so once again I'm going to use jQuery for this, although you can use straight JavaScript but as you saw in lecture, when you start using Ajax requests where jQuery becomes like a single line of stuff, JavaScript tends to be a whole bunch of if else's and making sure it works for internet explorer and all that stuff so jQuery makes this stuff nice. And so you can look through the jQuery documentation looking for the appropriate functions. In this spec we give you the hint that you can use getjason. And so just Googling for that I get this guy. It will also reference the fact that this is shorthand for the .Ajax function so jQuery also provides an Ajax function which is like a very general Ajax can do anything you want. But it has some shorthand functions like getjason and .get and .post that fill in some default parameters for you. So here we're going to use getjason. And so if we look here we figure out the URL, the data and success we'll get to in a second but that's going to be a function that will handle whatever the response from that Ajax request was. So first we need to figure out what the URL is going to be. >> So I want to show jQuery's example .jason. >> This guy, well that's making a request to, there's a URL and there's a function so. The jQuery's documentation, if you look at it, it's going to give you a bunch of examples for these functions. Here their example is a $ sign. When you see the $ sign you immediately jQuery so $.getjason and then this is the URL they're giving it and this just happens to mean like if you had a file in your like, if you had a file inside a folder Ajax called test.jason you could do this, unfortunately you don't. You could create one if you wanted. But you can also include here links to like http://google something so any type of URL can go in there. And then here is an example of a success function where the function takes one argument, it can take more, but here we only need to take one argument data, which is the data that the server returned. And so then inside of this function we can do stuff with that data. And so in our example the URL is going to be something with the geocoding API and the data that it's going to return is hopefully something in which we can find the city and state. Okay so this is an example URL. This will only currently work for Cambridge, MA so we're going to want to programmatically replace this with zip code and I'll guess I'll just use URL because that's simple. So how do we do that? Just zip code so in JavaScript you can concatenate strings like this. So to enter zip code just enter the middle of the string, we can do this. Yeah? [inaudible background question] >> Is looking here, one sec, so do you want to try? Well now we're in, hold on, hit escape and then command. You don't have the same, common, nice. So here's an example of [inaudible] API. If we go to the URL, maps.googleapi.com/map/ api/geocode/Jason?=02138 and hit enter, this is what we get back. There's all sorts of data here. There's something called results, inside of results something called address components and long name and short name and all of this data is what you'll get back if you do jQuery's getjason function and give it this URL. And then you can access this data by using JavaScript, you'll get it back as an object so you use data.results would be the first thing and that gives you access to all of these, everything inside the results. Data.results.addresscomponent would give you access to the address components. And so you may want to try just doing, without patching the zip code or taking example code here and seeing if you consult.log or alert data.results, which come back as an array or object. But see if you can jason.working without worrying too much about what you do with the data. Just you know get it working to the point where you are sending a request to Google and you're getting something back and you know that part is working. >> It's very common in this, like once you start dealing with Ajax requests and things, like set up the call. Don't set up what you actually want to do with the data yet. Just log to make sure the data got there because if it didn't get there then everything else you're doing isn't going to work yet. And if in Chrome, you should get very familiar with, well I get to it by going here but there are other ways to open this. This little console tab down here so in this console tab you can just type regular JavaScript or whatever you console that log in your JavaScript files appear down here. I can show you that pretty readily. For those interested how we got there, you right click and click inspect element and then click the console tab or in the view bar click view. In the view bar click developer, JavaScript, console. That's the other way to get this console to come up. And from here you can type in JavaScript and so you can type in any JavaScript you want in here. So like I happen to have jQuery already loaded which means I can also type jQuery on there so body.css background color red. It's not css. It is style. I have no idea what it is. Background color boom. So you can interactively place with your page in this little JavaScript console to test out what things do. >> So let's say you were testing out a one line jQuery function just to make sure you know that you're putting the right line in your code trying to figure out which line isn't working. >> And this is also where, and so this is where like I insert console.log ready here. So this is a very proven thing that I do like when the document loads, this function should be called and so I console.log to actually verify that it is called. And so we reload this page we see down here. And so ignoring this stuff in the previous reload but every time I reload you'll see another ready. Because when the document is ready it's supposed to console.log that. >> And there are advanced debugging tools that allow you to go through line by line and make break points and pause your code but sometimes when I'm kind of frustrated and want to figure out which line isn't working, I'll put console.log12345 and I'll try to figure out which ones aren't showing up, to figure out which blocks of my code aren't being run. [ Inaudible background question ] >> I literally have no idea and I want to ask David that. So basically there's three things you're going to need to be Ajaxing for the P set. Two of them you need to do jasonp. I could not figure out why this one I did not need to so it's obviously something so I'm just going to ask. I'll get back to you. I'll post it on the forum. Yeah there'll be, sure, sure. We'll take a break or we can continue. >> We promise we will not progress without an example solution in the next seven minutes. So stretch your legs. I'm going to look up why. >> Lets first see whether this is returning what I want it to be returning so I'm hoping that this returns some stuff, like the geocode API says what the return stuff looks like but let's just see how this runs again. So H13 submit, so now since I console.log over here, the stuff that got returned, that's what I should be seeing down here. This and you'll see that I can click on this to like expand the object and inside of the object we have a results array, inside of that we have this guy so I'm going to, for simplicity I'm just going to copy and paste. I won't copy and paste just Cambridge, MA. I'll copy paste this way. We could go further and like pars it but let's just do this. Or you could go into the address components and actually we'll do that. Alright so you can also do this, just like see what the object actually looks like. So now I know that in data, data's going to have, we have data.results so there's going to be array and inside of results we only care about the first thing in the array. So this is how you traverse objects is the .notation and results is an array. We just want the first thing in that array. And so inside of here so now we want to traverse address components because we want to find first, we want to find Massachusetts, which apparently the political type, and we want to find Cambridge which is local so locality and administrative level 1 is what we're looking for. What I just said might have been confusing but data.result0.addresscomponents is an array of these address components that contains like cambridgema02138usa. And so in those address components we specifically want to find Cambridge and ma. And we can find those by looking at the types specified in these components where 0213 has a type postal code, which is not surprising. And Cambridge has the type locality, which is a little less intuitive. And Massachusetts has administrative area level1 which is impossible. So the two things we are looking for are city. I'll specify in here, I just like initializing them to nothing, state equals null. So now we want to traverse this array. [ Inaudible background comment ] And as a thing I'm going to go over in a bit, you might also sometimes see this sort of syntax so do not use this syntax on arrays. This syntax is exclusively for objects. So iterating over objects is this syntax. The fact that there's two different four loops is why a lot of libraries have a lot of things like an each function which reads over objects or arrays blindly but this is the syntax you want to use for arrays, which is probably similar to other programming languages you've ever used. Okay so as a shorthand I'm going to just say that. And so now this is where I tend to over consule.log. Let's make sure things are working where we want them to be. So I'm just going to log what code what code you can actually use. And it's coming back to here, refresh, 02138. So we see four things were logged where they're all objects and inside of those objects are all these things. So in each of those objects we want to look in the types to see if it has one of the types we were looking for. We were looking for specifically how many needs copies so locality and administrative area level 1. So there are a couple of different ways you can do this but how I'm going to do it is if inside comp.types, so we want to look inside comp.types and see if either these locality or administrative 1 is inside of that array. And so to do that I'm going to do .index of locality. And so if that returns negative 1, if it returns negative 1 that means that locality is not inside that locality array. If it returns anything else it's going to return the index of that string. And so if it returns the index of that string that means that it is of the correct type. So here, if it doesn't equal negative 1 then this component represents the locality which is Cambridge, I think. So now we want to store inside of city. [ Silence ] City equals comp.long_name. And I can look back here in case I forgot what it actually is but yeah it's, if locality is inside of this array then I want either long name or short name, it doesn't matter. Else if comp.types.indexof this guy does not equal negative 1, this means I found the state and so I'm going to store inside of state comp. and just so it's ma instead of Massachusetts I'll store shortening. Okay and now after this four loop I'm just going to do a sanity check where if city is still null or state is still null, that means that I was not able to find a city or state for the zip code that you entered and things have gone wrong. I don't know what we'll do. Alert, uh oh and return. Okay else, now we have our city and state so these guys are going to need to go inside of, it's hard to pull this x, notice we're still inside of this getjason function so after we have retrieved this data, inside of this we're going to want to find the city and state and now we still need to insert the city and state into our div, which is exactly what we did before. And the text is going to be city plus, plus state. [ Silence ] Okay so questions on what we just did? In the end we'll put these online with comments on exactly what everything is for. [inaudible background question] So index of, if I give you, well we could run it in the console and let's see so let's add this array, let's do var array=1234 so this is what array looks like. Inside of this array if I do arr.indexOf2 it's going to return 1, yes 1 is the index of the value 2 and index of 4 will return 3. But if I do index of 5 it will return negative 1 because it was not found in that array. So I'm using nxl to see if locality or if administrative area level 1 are inside of the types array that I'm currently searching through. And let's run this. I'll probably get some sort of errors. Ooh, unexpected. [laughter] And this is stuff that you will be doing for the project. It's unfortunate. I find the iterating through those address components things tedious but Google just kind of returns everything at you and you have to put it together however you want it to be. [inaudible background question] You're free, well the spec currently says that you have to email us about any libraries you want to use so do that. Underscore is fine is if you want to use underscore. >> For those unfamiliar, underscore is a library like jQuery. It gives you access to more functions and some functions that are handy. >> Yeah underscore can be useful in this project. But if you like, if you don't know jQuery then don't overwhelm yourself with libraries. Just use jQuery and get use to that. [ Silence ] [ Inaudible background question ] >> If you save it, what? [inaudible background question] Yes so in JavaScript, unlike in C or other languages, there is no notion of variable scoping. There is some notion but there's basically only like global scope and function scope. So in JavaScript if I define a variable inside of, not inside of here, inside of here, say blah equals hello. Then blah will still be accessible down here, if it happened to be defined inside that if. So like in C since it's defined in that set of curly braces, it would not be available outside of that set of curly braces. That's not true of JavaScript, which means what I did up here with settings city equal to null and state equal to null, I could also have just not said that at all and so what that means is city is going to be set in here and state will be set in here. And down here I can say, and you saw this in lecture, but if this type of city is undefined or type of state is undefined, so what this is just saying is if those variables have not been defined, that means we got through this whole four loop without hitting lines, var city= whatever and var state= whatever, which means we did not find a city or state and we should alert the same uh oh. So this pattern type of variable equals undefined is your way of checking to see if the variable exists. >> So for those still working on this one, keep working on it, we'll float around. Those who have finished this one. Something else you may want to try is that instead of the [inaudible] field, the geolocatingapi allows you to pass in a latitude and longitude. So lat lng equals and then latitude, longitude. So give that a try with some made up numbers, numbers you got from Google maps. And when that works try using your current location. The way you can access your current location is through a cool JavaScript thing call geolocation used by navigator.geolocate. It takes a few call backs like getjason did but take a look at some documentation and see if you can figure out how the navigator.geolocate function works in JavaScript. As a hint, it will give you a matching longitude and you'll probably want to send that long to Google. But try just getting your current latitude and longitude using navigator.geolocate. >> That says get current location, that button. >> And the easiest way to try it out, right from your console. Go to your console and type in navigator.geolocate and then pass in whatever you're supposed to pass in. It should work for you, .geolocation, .geolocate. So you type in the console .geolocation. The console tells us it has two consoles inside of it getcurrentposition, watchposition and clearwatch. We only care about the last two but we want to get this getcurrentposition function. And no arguments for example. So no arguments is not the right way to call this function. It does take one or more arguments. The call back function is a lot like getjason. If you try it without them it will tell you that you're wrong. But not to give what an example callback would be but if you look it up it will tell you what kind of function and what kind of argument it's expecting. And my bottom left corner does that, Rob. [inaudible background question] >> Yes so it's an html5 thing that in newer browsers they have a navigator object that has this geolocation ability. >> The same way you have a document under geowindow object. It just comes kind of built in. >> You don't have natural scrolling. >> Correct. >> So I looked up developer.mozilla.word, that would be the first link. That tends to be a pretty good site for documentation. And here you'll see that this I recall it it has three parameters, success, errors and options. So the only one you need to specify here is success. But remember in the problem set that there should be absolutely no way for us to trigger absolutely any errors in your console, meaning like you should never get any red warnings down here, in here. So you will probably want to, in your project you're going to want to specify an error function that's going to handle errors appropriately. If you don't specify that function then whenever something goes wrong we're going to get red text in your console. So quick callback to the previous exercise that we did before we got into the geolocation stuff. An error that we did not consider that I had meant to is what if I enter something that is an invalid zip code? So even if it is a set of five numbers that is an invalid zip code or Google doesn't have any information about it? So this is something that Google happens to say that it will return something like its data on status will be like zero results or something. So if that is the case this is just another error scenario you need to watch out for so another alert uh oh, or whatever, because if you don't look out for this then, I should do that right here, if you don't look out for this then here when you say our components equal data.results0, there will not be a results0 because that array will be empty. So you need to be making sure that everything is valid so that you don't get any of these errors. And for the recent exercise, now back to geolocation stuff, what I've changed so far is, like up there I've changed the top to be from like a text field to like a button. It says use current location. And now since I'm using a button all the way up here, what we used to have is on submit, since we're no longer submitting a form we're just clicking a button, now I'm using a different event handler. So the event now isn't submit, it's click. So when we click this button we're going to want to do our thing. And I've started with using get chrome position, the success function is going to take the position and then we need to do things with that position. And over in the console is an easy way, darn it, avigator.geolocation.getCurrent Position functionpositionconsole .logposition, there you go. Okay, I did this just to see what the object looks like that this is returning. And so I can look in here and see that there's a time stamp field and a chords field. And inside of chords there is a latitude and longitude. So I'm going to directly use those and I can say, this is unnecessary but the latitude is position.chords.latitude, longitude is position.chords.longitude and now inside of our URL we no longer we want to use Google. Before this was address and we used a zip code. Now we want to use latlng. And you can see this just in Googles on the API page that you can use latitude and longitude and I'll do lat+, I'm separating them, +long. So now we're using that. And let's see what the object looks like that it's returning, refresh, no that's 3, okay use current location. See object is it's an array of like 9 so we have 9 different objects in here. I am still using the first one which we see contains literally the entire address so 52 Oster Street, Harvard University, Cambridge, MA 02138. The rest of these objects as we go down will says United States. This one says Massachusetts, USA and United States sequence of characters, Middlesex, MA, USA. So as we go down this results array we get more and more general areas along with some different languages or something. So the top one is good enough for us because we're still iterating over these address components looking for locality and administrative area level 1. So we really didn't need to change anything else to get this working because all this up from when we're using zip code still applies. We're just now using lat and long. [ Silence ] [ Inaudible background question ] Yes. >> Manhattan is a sub locality, like New York, New York. So if I can have everyone's attention for a little bit I'm going to introduce what will be our next exercise. But if you want to keep working on the previous two, wherever you are, I'll keep floating, helping with anything. Or if you want to put those aside and move onto this one, that's also totally fine. In the interest of making sure we cover all the topics and lean toward the project, I'll just introduce this next one. So we're actually going to go back to html from the very exercise, just a textbox and a button and a div. If you deleted that or extended that it shouldn't be too much to make a new one with textbox, button, div. The goal here is to play with local storage and make it so that when you enter a word and hit submit it will add it will add to this list. So the first thing I would do is modify our exercise1 code from replacing to adding. Instead of just fully replacing the html, you'll going to want to get the html that's already there and add to it and put it back. That shouldn't be too much of a change from exercise1. The local storage however we want to make it when you refresh the page or restore the browser and come back, the list stays. Think of this like the to do list of words that I want to remember. So first exercise1, for those doing this exercise, the very first thing you do after running again, you now have add instead of replacing. And then local storage whereby you can set, you can save items in local storage. So yeah, again any exercises we've been talking about, we did just email out the solution set, the draft of the solution set from the previous ones so feel free to do whichever exercise you like. If you're looking for a tutorial on local storage, a quick Google search should bring out the methods you use to put things in local storage and bring them back out again. Rob just reminded me that jQuery has an append function that will add onto the content in a div so if this div was called text$#text.appendworld, we'll put world after whatever's inside of there so we'll need to get whatever's inside of there, remember it, add to it, put it right back. Dollar sign, a selector and then .append will allow you to add things to the content of addend. So the extra is 1.html that was sent out. This is literally the only change so far. He's changing text to append, for those getting closer to mine. [laughter] >> So the objective here is that like after I refresh this page, all of these highs would stay here but as of right now if I refresh they're gone. So as a teaser we have this local storage object in html5 and ignoring what's already in that object that apparently RJ put in there or something. You'll notice like if I do localstorage.foo=bar. Now if I refresh the page and look inside storage, we see that foo is still there. So this local storage object persists beyond refresh of the page and look inside of storage we see that foo is still there. And so you can store things in that for subsequent visits to a page and you'll probably want to be storing whatever is inside of this div in that local storage index somewhere. [ Inaudible background comment ] And for reference this is a pretty common thing in jQuery where like here if I say, let's see, if I say exercise4-div.texthello, this would insert into exercise4-div.hello. It would make the text inside of this div hello. But if instead I used the .text method with no argument, that retrieves the text that is inside of that div. Okay so I'm just going to pick, you can pick whatever name you want to store inside of local storage. You can pick whatever the key you want to call it. I'm going to call it divtext. So local storage .divtext=alltext. Okay so now what have I forgotten to do/why won't this entirely work yet? [ Inaudible background comment ] Yes and that's fine so the alternative to doing this is like, so it's kind of like if my div currently says helloworlddog or helloworldcat then my local storage .divtext also says helloworldcat. And then if I proceed to add dog I'm completely overwriting what is currently inside of local storage .divtext. Instead I could just append to it dog. So that is an alternative. But still if I miss at least succeeds in now they say localStorage.divtext. I see all that but what is the issue [ Inaudible background comment ] I'm actually wondering if that's going to be the case, ignoring that for now. Oh, I know why that will be the case. [laughter] Why does it not currently remember what was in global storage? It's remembering it but it should reappear in this div. Why is it not reappearing in the div? [ Inaudible background comment ] Because I'm updating local storage .divtext whenever there's something added to it but I'm never, when I refresh the page I need to insert that text into the div. So I want to do that, probably on ready. Okay so when the document loads I want to insert into our exercise4div. I want to give it the text and what is, okay the text we want is localStorage.divtext. And I could insert that directly in there but we'll see what this does. So it correctly inserts the text into the div. Notice if I insert something, let's do other letters. Oh there we go, so notice that they're going on separate lines and that's correct because I put a br tag here, line break. But if I refresh it all ends up on the same line. And that's because of jQuery you have to be careful of what function to use. So there's text and there is html. So text grabs literally only the text inside the data. Html will also grab all of the relevant tags and dates. So it was ignoring the br tags when I was using tags. But now we're using html so something it still wrong. Let's see what it is. Refresh first, refresh so now we see that all the br tags are literally in the code and that's because of this text up here because we want this to also be html. So when we say text it was taking the html characters literally. Like I wanted a less than sign right here. When we say html it interprets the less than sign as the beginning as the html tag. And there's one last thing that we want to do and that is going to be, so a frequent issue with local storage when you're working with, so this looks good now, as we add things, refresh and it's there. So frequent issue is like alright now we want to start over so this works for any array, any object and this is also true of local storage so to do that we just type in our console delete a localStorage.divtext. And so now it no longer exists again. But what is going to happen when I refresh? Not what I was expecting. Maybe that, [ Inaudible background comment ] So this is probably fighting me. Alright so I was hoping it would yell at me but it's not. It will yell at you depending on, so the issue here is local storage but the text is not defined. And so here when we say bartext=localstorage.divtext, text is undefined. Which just happens to work out because inside if you ever say html undefined it's just not going to put anything. The right way of doing this, and in the project you're almost assuredly going to want to do this because you're going to need to work local storage a little bit differently, is to first say if, and this is what we did before with if localStorage.divtext, is not undefined then we'll do this stuff of actually inserting it into the [inaudible]. And this is the exact same type of stuff we did before where we were like is this variable actually defined? If so then we'll actually use it and insert it. If it's not then avoid any possible errors that might happen if we try to use it as if it does exist. Questions on that? [ Background inaudible question ] It looks for what? Yes so I was actually going to ask David this but the answer is yes for an application you really make. Remember local storage and also our navigator.geolocation stuff. All of that is like html5. It's very new. If you go back to IE6 or even like early Chrome and all this stuff, you will not have those things. And so these will cause errors if you go into earlier browsers. So technically we should do something like if type of local storage does not equal undefined that means we are in a html5 compliant browser that has local storage support, then we can do this stuff. And that's, I don't have it in this but same thing with the navigator stuff. If navigator does not equal undefined then use navigator.geolocation. getcurrentposition. That is the right way of making any app. Although if your app is using a bunch of other features that your website will basically be broken if it doesn't support local storage, then usually what happens is if type of local storage is actually undefined or get a newer browser or something, which a lot of websites actually do. Or a lot of websites will say like turn on JavaScript and stuff like that. [ Inaudible background question ] Twenty five bars? [inaudible background question] Oh yeah so this is what would have been exercised by another 15 minutes. So local storage only stores strings. And you will notice in the, well you don't have to, but if you want to store an array or an object inside of local storage then you'll need to store them as strings. One way of doing that is this convenient, so using in console, we have jason.pars and jason.stringify. So what jason.strong5 is let's a, we have some array. Then jason.stringify of that array will return a string version of that array or let's say string equals ix. And then if we jason.pars, that string, it will return the original array that we had. So inside of local storage, let's say localstorage.array=x so when we refresh this page and look at localstorage.x it's undefined or we do not call it that. It shows this string 1, 2, 3, 4, which is not a valid array. And so the way we want to store it is localstorage.array =jason.stringify the array 1,2,3,4. Now when we refresh the page and look at localstorage.array we see it's in appropriate array form but it's still a string and so we can jason.pars. And so we're just showing these functions to you so that you know they're available. You're probably going to want to use them in the project. Remember localstorage cannot store objects or arrays. So if you want to store them you need to first stringify it and store it in local storage. And then when you want to retrieve it you need to pars the jason. Questions? [ Silence ] >> Okay so those are the exercises we had. The last 10 minutes will be more free form question and answer. We'll float around and definitely if you have any questions on the problems you've been doing, the example solutions, your own solutions, feel free to ask right now or reach out to us via email or post to discuss where we can discuss them as a group. >> And tonight we'll write up like nice commented versions of the things I just sent out to you. >> We'll just continue to float. >> Just to point out, the syntax, localstorage.foo is exactly the same as localstorage[foo] so any object you can reference things in either way. The exception being you can't say like .tilda or something but you can say this. It's over. [ Silence ]