[ no speaking ] >> Unknown: All right, welcome to CS50. This is the start of week 9. So one announcement, if you haven't RSVP'd already and would like to join us, Wednesday, Mather [assumed spelling], 6 pm. [Inaudible] just RSVP. One new handout today and this is a bug of sort or a feature if you will, that's actually been circulated a bit on various blogs this past week. So it's been around for some time. I thought I'd replicate it here with this website called, Google. I was wanting to do some math the other day and it turns out Google does math. For instance, if I want to know what 3 - 2 is, hit enter, well we'll actually do that kind of math for you. But that I can do in my head, but I can't really do in my head very well something like this, this, that's a big number and then let's just minus, actually let's try to be creative here. Let's put almost the same number but 998. OK, so for anyone who's taken like Math 55, what's the answer? [ laughter ] Seven. Excellent. So it's pretty close, it should be 1 right. Pretty big numbers, but one's just 1 bigger than the other, but if you do a little Google search for this, the Google fails us. So. [ booing ] I know. [ laughter ] So this went around a while. So this isn't a bug per say because otherwise someone at Google would have addressed it. Because it's been blogged about at nauseum. So what might the explanation be? What's that? So rounding or there's some kind of imprecision here. So even though we talk mostly about this in the context of floating point values, so even with integers, we've seen in C at least, that there are upper bounds on the kinds of math that we can actually compute. So if you like this kind of thing, so there's really no big lesson here, this is in fact a feature of the way math is implemented at least by Google here, but there's actually a neat article that's been recirculated. It's called, Why Computers Suck at Math. It's an interesting article and it discusses this and other such things. So we've linked that on the course's website if you would like. Also on the course's website now, we've replaced the old big board with the new big board. The old big board in still linked there. You'll see that your classmate Charles has already figured out how to exploit financial opportunity perhaps, more likely bugs or weaknesses in our own implementation of this big board. This is sort of this funny thing, especially about teaching a Harvard class right, you know, you just want to do something nice and fun that gets the students excited about this and that. It's completely ancillary to the piece and then there's always one or more people who decide, let's see what we can break. And of course, there are weaknesses in this and that's fine, Charles is up 4000% since like 9 am this morning. If you actually look at his history by clicking his name, you'll see exactly how he did this and what he bought and things we probably shouldn't have let him buy. And again, you can essentially see into the future if you simply watch your own eTrade account or CNN.com and then make your purchases within the 15 minute window that is the delay that Yahoo Finance imposes. But that's OK. Why don't we just throw down the gauntlet and say that Charles is now the person to be. So 433,000 is currently the number one position. I think I'm doing rather the opposite. Oh actually, we're only down 1%. But one takeaway that's worth nothing here is and you may have glimpsed it really fast just now, is this is actually an Ajax implementation of this big board. Ajax is kind of a buzz word, but it refers to websites that are more dynamic and that's to update the page's content, the whole thing doesn't have to reload. You can just reload portions of the page, thereby creating a much more seamless interface and that's going to be one of the topics for this week. How can we move away, even just one week later, from this very mechanical but very reliable approach of implementing websites where one page leads to another leads to another and can we make this user experience a lot more seamless like this? And if you watch this over the course of several minutes, you'll see that these numbers do in fact fluctuate and I wouldn't be surprised if by the end of today's lecture, someone is already contesting Charles. So we shall, we shall see. Oh and also back is, Ceiling Cat. Ceiling Cat is one of the most famous of all cats. I know that the feelings on this topic in the course are mixed, but seeing as in the remaining surveys that were submitted for Peace at 5, we just finished reading through, one student actually said that he or she registered for the course because my god, the syllabus was online in advance and so few courses do that. And another student literally wrote that he or she enrolled in the course because he or she saw Ceiling Cat on version 1 of the website. So we actually removed that, worrying that it would work against us this year, but we'll put him back since this is now the web week of the course. And if you actually click him, you can read about the beginning of the earth from Ceiling Cat's perspective. So this is another famous link there. Anyhow, all right, so what have we got in store today? So last week we talked about, last week we talked about php and a little bit of My SQL and HTML and pset 7 is really going to enforce this stuff. So we're going to forge ahead this week and give you the conceptual framework for both pset 8 and probably for many of you, final projects. And as much as we've kind of promoted taking a web based approach for final projects, realize you absolutely do not have to. We just know historically in recent years, 60% plus of students in the course tackle web based final projects, even though we spend but two weeks of it officially in the semester. But you are welcome to pursue most anything per the pset, per the final project specifications. So I thought I would either try to really excite you or really crush you with the following promise which is that we can implement the entirety of problem set 6, essentially in one line of code. So that's a bit of an oversimplification but it does speak to this issue of choosing the right tool for the job. So what I went ahead and did was the following and included among your printouts for today is this file called, speller. So notice a couple of things. Speller 1 had no file extension. So even in the course we've had this habit of using file extensions like .c and .h, for the most part those are just conventions. Now with that said, some operating systems like Windows, rely on file extensions so that when you double-click it, it knows what program to load. But operating systems like Linux and Unix and MacOS, are a bit more, a bit smarter than that and they actually look inside the file to figure out what program to launch. But there's still disconvention of naming things with file extensions. But it's not necessary. I proceeded to write this program called, speller. No file extension but notice, no 0's and 1's. This is not a compiled program because I wrote this one in php. So the catch when you write a program in php, especially if you just want to run it at the command line like I did early last week when we did that very simple quote check, stock quote checking program. Four or so lines of code. I ran it at the command line as php quote.php, because I wanted to use the php interpreted, a program that may executes php code and I gave it a command line argument, the name of the file I wanted to execute. But that's a little bit annoying because now your users have to realize, oh this program happens to be written in a language called php, even though I don't care. But just to run this program I need to know to run php filename. Well you can avoid that altogether on a Mac or on a typically Linux or Unix system by including this thing atop the file. So this is what's sort of goofily called a shebang, S H E B A N G, which just means put the sharp symbol at the top, followed by bang or exclamation point, followed by the path of the program that you want to use to interpret the following lines of code. So simply by including this at the top of my file and by running this command, chamod, change mode 700 of speller and this command chamod is discussed, if you haven't read it already, in pset 7. This is going to make my file executable and what this means, if I do an LS and this is an aesthetic thing, speller is shown to me in green and with a star, at least within Putty [assumed spelling], the program I'm using on this PC. So that just means it's executable, so that means I can run at the command line, speller, or more specifically just to be really security conscience, ./speller. Run this copy of speller. So what the OS, Linux in this case, is going to do is it's going to see ah, top line of this file says use the following interpreter user/bin/php. That's just where it is on the hard drive. Let me load that program and then feed the following lines to it. So the same goal is accomplished of executing the code, but it's a little bit more user friendly that now I don't have to know or care what language this is written in. So I implemented speller and if I run it like this, I see output identical to pset 6's framework that you guys were handed. So we won't walk in great detail through this. You're welcome to do it sort of at your leisure at home, but notice I pretty much tried to look at my C code on the left hand side in a window and then I had another window open for this file and I tried to literally translate C code to php code. Partly so that you guys, if you want to curl up with this at some point with your old pset 6, or pset 6 still in progress, you can actually see how you would implement the same program but in a different language. And most of the syntax is familiar. So at the very top here, I have require. So require is similar in spirit to that sharp include. In C it means require the following file, copy and paste it's contents here. So this thing here is a little php specific. Php like a lot of languages, have different levels of error reporting. If you really want to get your hands dirty with the feedback from the program. So I'm just saying turn on, suppress things called notices and warnings and a lot of languages there's at least three types of bad things that an happen. Notices, which are like eh, you really shouldn't do that. Warnings, which are something bad could probably happen, but I'm going to proceed nonetheless. And errors, which means sorry, really bad stuff happened, I can't even run your code. So there's different levels. In C, we've pretty much turned everything into errors for you guys, to force you to actually deal with them. So for now you can just kind of take this one on faith. This is stole from the problem sets. I defined a constant in php. Syntax is different. It's not sharp define. It's define and define is actually a function that takes two arguments. The name of the constant and then a value on [inaudible] but otherwise it's the same idea. Same deal for the second constant here, words. And then down here notice that just like in C, I can have command line arguments. So if [inaudible] does not equal 2 or 3, tell the user how to run this program. So it's pretty much been a copy paste, from C to php, but I've changed my variables to have dollar signs and I've changed how I declare constants. But pretty much it's a pretty good translation. Now this thing here I did just to be a little bit anal. So these are the variables we had in speller as well, tiload, ticheck and I've initialized them just to be a little fancy to 0. now this is just me thinking I'm being clever by just saving a character. By not doing 0.0, but it's the same thing. As soon as you append a period to a number, it becomes a floating point value so and I also just didn't want to waste 4 lines of code. So again, stylistic decision. I just put them all on the same line separated by semi-colons. But it's the same approach as in C. But notice I did not have to specify for any of these variables what? A type. So again, php is loosely typed, which means there are data types underneath the hood, but php gives you so much automatic conversion or casting from one to the other, that you the programmer don't have to worry as much about it. So this is our little Tertiary operator question mark and colon, which just says if arcC is 3 assign dict to the value of ardv1 else assign if the default value in that constant. And then for the most part the rest of this you can play with or look through on your own if you want, but it's pretty much a translation of the benchmarking code that you guys used for problem set 6 and the end result and the end of this program is that it prints this output, which should be vaguely familiar at this point. So in short, I reimplemented speller in php, but of course you didn't implement speller, you implemented dictionary.c and maybe .h, so you implemented only the data structure. So I thought we would kind of do that here. Let me go ahead and move this one aside for just a moment. I'm going to create a file called dictionary.php. It's automatically going to be included when I run speller, because of that require line. Every php file has to begin and end with this or anytime you write php code specifically, you need to encase it in these things, so it's not conflated for HTML or something like that. So let's see. I need to implement a whole dictionary and let's see, what was in there? So I had a function that I had to implement called, load and it has to return a value. I had a function called, check and it took a word and now I'm going to have to write that. I had a function called, there were two more, size and that's probably pretty easy, but let's see. And then finally a function called, unload. So these were the four functions I implemented and pretty much we gave them to as blank, maybe a return value here or there. But I need to implement the data structure first. In php and some of these high level languages and scripting languages, you can implement data structures yourself. You can implement trees and tries and hash tables. But the thing is you don't' have to, because in a lot of higher level languages, you're handed this stuff for free, out of the box. It's a feature of the language. And in fact, we mentioned this briefly last time, that thing called dollar_, $_post or $_gets, that's super-global as I labeled it last week, that's what's called associative array. The syntax for that recall looked a little something like this. Post and then I could say something like name and what that variable gave me is the value that the user typed into a form called, name. Now we're mostly familiar with arrays in a numeric sense. In C we always did something like this or like this or like this, but what's nice about an associative array is that it's a generalization of the idea of an array and you can index into the array using things other than numbers. You can use arbitrary strings. So in fact, what an associative array is, it's kind of like a two column table in memory, where on the left hand column are keys and the right hand column are values, but what's really nice about the language itself is that it doesn't search these things linearly. What an associative array is implemented as, underneath the hood, is something like a hash table with chains, which is what many of you, but not all of you use, to implement your implementation of pset 6. So long story short, if I want an associative array, aka hash table, I simply have to do something like this. Give me an array. So this is going to be my hash table. It's as simple as that. So now I can put stuff into this array and I can get stuff out of this array, just by using net square bracket notation. So let's see, what else am I going to need? I'm also going to declare a global variable called, hashtablesize and I'm just going to call this, size and I'm going to initialize it to 0. So notice this is outside the scope of those functions so now all I have to do is implement the remaining functions. Well let's kind of impress just by being quick here, all right, done. So we're done with that function there. So we have three functions left. What about load? Well to get in load, oh and actually I forgot one thing in load, it did take a command line argument. The name of the dictionary to load. My goal here has to be to load the dictionary into memory and then iterate over the files and then insert each of the files into my data structure. Well how can I do that? Well it turns out that in php, there is a function called file, which returns to you an array such that every element of the array is a word from the file. So it's literally gives you that. In fact, let me do a quick, little, let's see, what do I want to do here? Let's do a quick sanity check? I'm going to go ahead and do this and I'm going to say, call this a variable called, lines equals file of dict, and this is going to get me again an array, whereby each element is a word from that file. And again, now this is sort of debugging mode. I'm going to use that recursive print function from last week, I'm going to print lines and then I'm just going to exit. So this is not a working implementation but I know speller is going to call load and I just want to see what's inside this variable temporarily and then we'll throw away these 2 lines of debugging code. So let me go ahead and save this and let me go ahead and run speller, on a very small file. Something like the Ralph Wiggim [assumed spelling] quote. And hit, enter. And in fact, that's what I see. So what you're seeing being spit out again and again, because I'm recursively printing the array, is a list of all of the words in the given dict file. In that default dictionary. You probably remember at least the last one. If you ever saw these things flow on the screen. Well there's a weird artifact here. Whereby every, there's a space between every line and that's because there are new lines in the file so, well we'll deal with that in just a moment. Well it turns out if I'm getting back an array here, I'm not even going to bother assigning it to a variable because I'm going to immediately launch into a for each construct. For each word from the file and the syntax for doing this, is this. This is a nice little piece of syntax that doesn't exist in C. Not this user friendly like and it's going to say, for each of the words in that array, so it takes an array in parenthesis, then the keyword, as, and then the name of a variable that you want to update on every iteration being the current word from that array. So this is going to induce you know, the equivalent of a wild loop or a forward loop, but it's kind of nice and compact in what it's going to do for me. So what do I want to do? Well I need to remember that each of these words is in the dictionary, but let's see how I can do that. Here's my hash table, dictionary, well I pretty much just want to do this. I don't want to index into an I location, because there's no variable I and I don't' want a hard coded number. What I want to use is the word, as a key and you know what, it suffices to say this, OK insert this word, word, into my dictionary but just say true. So I'm treating word as a key, true as a value, so that if you've now fast forwarded in your mind to the check function, how is check going to check whether there's a word in the dictionary? It's just going to check in the given word exists in dictionary, because if it gets back an answer of true, I put it there. And if nothing comes back that means I didn't put it there, which means it's not in fact a word in the dictionary. So before we clean up this function, let's fast forward and just do this. Return dictionary, bracket word and actually let's be a little more anal than this. So if I find a true value at the location in dictionary, go ahead and return true else go ahead and return, return false. So this function is actually done. If the given word is in the dictionary, return true else false. Now let me just clean this up. Because I did say that there were these new lines at the end of the file, right. Because the default dictionary word, new line, word, new line. So there's this other function and this is really just useful. Chop, the behavior of chop is to eliminate the last character from a word. Or I could use something called trim, which eliminates white space from the end or the beginning of a word. So I'm just going to clean up my word in this way and actually let's go ahead and use trim, just because it's a little more thorough and I know it's just going to get rid of white space on the beginning and end of a word. All right, so I'm pretty much done. Actually you know what, let me do this. I now need to save, return true. OK. Turns out I don't' really need these things. Let's make the code look even smaller and let me do one reasonable sanity check. So if file exists, this variable, actually if this file does not exist or this file is not, is readable, these are literally functions in php, what do I want to do if the file neither exists or is readable or is not readable? Yes, so return false. So now I'm adding a modicum of error checking here. But I'm pretty thorough here. So if the file doesn't exist or it's not readable, return false because I can't load the dictionary. Otherwise, iterate over each word in the file and then insert into my hash table, every word, and just assign it a value of true so that later I can ask a billion questions. Is the word there? Yes or no? Yes or no, iteratively in my check function. Now I need to change one thing. There's one nuisance of php, which is that even though dictionary looks like it's a global variable at the top of the file, you actually can't access global variables inside of functions unless you say, hey php, dictionary is a global variable, just so you realize. And so I need to do this in here. I need to do it in here and I need to do one other, one other place. I need to do this here. So it's stupid frankly. This is an annoying feature of php, but at least now we have access to that global variable. Unload. Is there anything to do? No, not really. Already unload. In php you don't have to manage your memory. The php interpreter does it for you. No malloc, no free, none of that. It's all done for you. So any concerns? Did I make any mistakes? Because I literally am doing this on the fly here. Good, it doesn't. It's always going to be 0 right now. So what do we want to do to fix this? Yes, might as well go in here. Guess I've got to put my brackets again and then I'm going to do size++ and then I just have to make one other change here. I have to specify that size is global. Yes? Good? OK and we can do this any number of ways. So let's save this. Let's run speller on text and now run it on the Ralph [assumed spelling] file and that's wrong isn't it. Let's do, do I want to do this right now on the fly? File exists for each file is word, dictionary, trim, word. That's OK. Size gets true. Can you see the bug? What? Capitalization. Oh, yes. Thank you, thank you very much. Capitalization. OK, so that I can fix. Stir to lower. [ laughter ] I mean, frankly you laugh, but this is one of the biggest sources of bugs in your C code right? Was given the check function, most of you probably made a copy of the word, then had to force it to lower case, then you had to chase down all these stupid memory bugs. But I mean, this is actually very reasonable, I'm passed the word, it could be in any type of capitalization. I want to force it to lowercase, so stir to lower is in fact the function for that. Let's go ahead and rerun Ralph and yes, it actually works. So what was that? Eight minutes of coding to implement problem set 6 in the better choice of languages. But surely there must be a catch. So in fact there is. So let me actually not run Ralph Because recall Ralph is a terribly short file. Right? This is and if you've never actually looked in this file, this is the, this is from the lab, so you can actually look in this file. Some of you have seen it. So that's OK. So let's take a look at speller though on something much longer like the Holmes file. So this is like 6 megabytes. So this was a very large file. It's going ahead and spell checking, spitting out all of the bogus words and let's give it a little bit here. There are a lot of misspelled, quote unquote, words, because this was an unfamiliar text. All right, so words misspelled, 17,000 out of 140, out of actually a million words in the file. So this is a big file and it took roughly 2.19 seconds to totally spell check that file. So now let me shift gears to my other window here. Same server. I'm on logged in as myself and I'm actually going to run, not the php version but the staff solution from pset 6 itself, which was called, speller here. I'm going to pass it the same text file, which is misspellings, text, Holmes So again I'm just running the C implementation of the staff's implementation of dictionary and I'm going to hit, enter and wow. So maybe it's that the staff is much better at writing code than I am right, especially since I just wrote this on the fly or maybe it also has a little something to do with the choice of language. So this is one of the trade offs and again this theme of you don't' get anything for free. So yes, I really whittled down my development time from what? Ten hours, fifteen hours, twenty plus hours for some of you, took eight minutes. Which might be a little disheartening certainly, but look at the price I'm going to pay in the long run if I use this thing to spell check very large bodies of text. So development time when down, but running time significantly went up. You notice the difference here? Notice the bug here. [ laughter ] OK, well we'll ignore that little detail that the words misspelled is slightly different. Because there is in fact a little bug somewhere. But trust me that it's the choice of language. I should get credit for pointing out the bug and letting you realize it. Maybe? So notice the order of magnitude though, 2.19 seconds versus .4 seconds and this was still a relatively small file. It's only 6 megabytes and we deal with much larger data sets these days. So what's the takeaway? Well the theme in interpreted languages like php or JavaScript or pearl or ruby or python, there's a whole bunch of popular interpreted languages. They are very convenient and they give you a lot of features out of the box for free, so that you don't have to reinvent the wheels you guys have been implementing all semester. But you really pay for it. One, you have no idea how things are implemented underneath the hood, which may or may not be a bad thing. But certainly you can't fine tune your code very effectively and if the goal, especially you know, for a job or for your research is really to maximize performance, you really need to pick up the right tool for the job. Yes? >> So when you run a reference and place it in the table in C, there [inaudible] and here you're basically referencing this table and not there [inaudible]? >> That's correct. So and I'm also taking advantage of certain features of the language So the point here is that in my own dictionary implementation and let me open my commented one which you guys have a printout of. So in my implementation notice that in my check function I'm kind of blindly checking if there is in fact a word at a give location in my dictionary, but there might not be anything there. And as you can point out in C, very bad things happen if you just index into an array, anywhere you want. So in php and in a lot of language like this, that's not a problem. You will simply by default get back a value of false or it will trigger a warning or some kind of notice and in fact I'm being a little tricky here in that the line of code that I mentioned at the very beginning of speller that suppresses notices and warnings, what you just described, indexing into an array where you should not, that in php actually triggers usually what's called a notice. You will see printed on the screen, notice, indexing into an array, not wise or something to that effect. But with this line of code, I'm actually suppressing that notice because I'm very comfortable knowing, accepting that I know there might not be anything there. So with this case I'm telling php, quiet, I don't want to know about these notices, this is OK. But there are other ways to deal with this. You could actually do something like this. So let me make one last comment on this and then we'll forge ahead. You could, I could have done this. If dictionary stir to, stir to lower word is set. So there's a function in php called, is set, that solves exactly the problem you are worried about which is a check before actually going there, is there anything there and only if there is does it return a value. Yes? So I wouldn't. I would replace one with the other at that point. I would replace one with the other. So, but I made the conscious decision to kind of gloss over some of these details just in the interest of simplicity, but frankly it's reasonable to do such if you know what you're doing, as a design decision. Other questions? OK, so then a word on why did we just put you through problem set 6 and problem set 5 and problem set 4 right? So one, there are different tools for the job. Like when you are doing various research things or you are trying to actually you know, implement the next best search engine or what not, you really do sometimes want to get very low level, closer to the operating system, into the hardware, so you can actually eek out as much performance as you might want. But there's also something to be said for actually understanding what this thing is. I would argue that there's a lot of software developers out there who completely take for granted that there is this thing called an array, you can access into it, with no appreciation of how it's actually implemented underneath the hood and therefore when to use it and when not to use it as well. And also it's around this time of the semester, especially with pset 6, where late day usage really spikes, so not to worry if you're kind of still working hard on pset 6, it's typical. Especially at the end of the semester. But realize, the common sentiment at this point in the term is you know, my god like, thank god the end is in sight and you know, you might feel like you've learned something, you might feel fairly gratified at 4 am after finishing these things, but many of you might think eh, this isn't' really for me. I don't want to go through that again. But realize, that is not necessarily what programming is and what programming computers is all about. So now that we're finally taking this step up, realize that there is this great element of fun, I think, of programming, that allows you to solve real world problems. Whether it's some new site, again or events site, the Twitter site, relatively easily including simple things like the spell checker. So you simply have to pick the right tool for the job. And that's why I think final projects around this time of the year tend to be particularly fun because you can finally, actually bite off something at your choosing and not us. So that was a lot. Why don't we take our five minute break now. All right. So it's kind of spooky that it's already time for this little announcement, but indeed, even though a month or so remains in the semester, do realize that we'll already be on the search for TF's and for CA's for next fall, 2010. Know that the role of TF involves leading section, working with your students, grading their problem sets, office hours and the like and CA'ing by contrast is a role that we've targeted particularly at alumni at CS50. So almost all of the CA's that you may have met in the lab or on email lists this year, are former CS50 students who have offered to contribute 2 hours, only 2 hours of work per week, on a volunteer basis working with their fellow classmates and their successors in this class and the lab in what is pretty much the most intense, fun part of the course and office hours. Realize that if you do choose to join us next year, it's a little more fun being on the other side of things and actually running the white board and not running to the white board. So more, just go, we'll post a link on the course's homepage before long via which you can apply by telling us a little something about yourself and what you plan for next term. So in the time that has passed, Charles has made let's see about $60,000, so he's doing quite well. So we give him our official blessing and challenge you to best him. But realize, this thing exists one just for fun, but also so that you can actually play with the staff's own implementation of CS50 finance, which you can get to by following the appropriate link here. But realize too, you need not implement your version of pset 7 exactly as the staff has. We have simply offered it for consideration. And you may have realized already, you can look at some of the code for the site. You're welcome to look at the HTML and the CSS. What you'll find is that you don't have access to the php and this is kind of a rule of thumb with web development. It's pretty reasonable and it's technologically completely possible these days to look at other people's source code with regard to HTML and CSS and even, unless they've jumped through some hoops, JavaScript as well. And I can't emphasize enough, if you like this kind of stuff, the best way to learn about how to do new things is to look at a site you like and even though it might be a little complicated at first glance, start poking around with it's source code and learn from someone else's sites. There's really not much intellectual property when it comes to XHTML and the layout of the site. The juicy stuff is in the JavaScript, which we'll see today and also in the php. The former of which we can actually obviewskate in some way to make it harder for people to take your intellectual property. But let me bring your attention to this thing here. So pset 7 recommends that you install a few free tools and we encourage you to use Firefox only because it's really useful for development purposes, but ultimately you should be testing as the spec says your code on multiple browsers. Because this is a very common thing for, you will find the hard way unfortunately, that the web browser manufacturers have always been at odds for years, 10, 15 years now, where Microsoft interprets something in the specification for XHTML one way, Mozilla interprets it another way, Apple interprets it another way, so you will see slight differences, even on your relatively simple websites across multiple browsers. And one of the things that drives us nuts for the course's website is making it look as best we can the same, no matter the OS and no matter the browser that your user is using. So we do expect that you play with at least two browsers for your project, but with Firefox you have some really useful tools. So I had this little bug at the bottom of my window, because I installed an extension. It's free software for Firefox called Firebug and it's a few different things. It is a, it allows you to view the websites, whether it's your or someone else's, XHTML or HTML, in a much more user friendly way. So notice what I've done. After clicking the bug, this little pop up opened up and what it's showing me with much nicer indentation and nesting, the structure of this webpage. By contrast, if you look at the course's website, it's an absolute mess underneath the hood, not because we were lazy and didn't really practice good style, but because a lot of the website is dynamically generated by php scripts that we wrote and even though we kept our php code and our JavaScript code pretty neat, when you start to combine all of these things, things just get messy and there's really no point trying to make this look clean, because for the most part it's only a browser that has to understand this. So we elaborated on this in the pset spec, but for learning, this is frankly a bit of a nightmare trying to find your way around this and even when we reimplemented Google last week, I relied on control F, just to find things in the document. But Firebug is useful for XHTML and HTML for this reason. You get a much nicer view of the world. Which means if I want to see what's going on in here, I can actually dive in and click on these pluses. So it looks like the body of my page has this thing called the div, which I've given an ID of raprum, there's a table in there that's laying things out, a table body, a bunch of table rows and more interesting is this. If you start to hover over tags, you'll see top left, in blue, what it is I'm hovering over. So apparently we are actually using very deliberately, an invisible table who's border is 0, thereby making it invisible. So notice, this TD, this table data element, is the white space at top right. If I scroll down a little further, this guy here is apparently that bar in the top middle and as you might guess over here, that's the guy on the right hand side. If I dive into the next table row, notice ah, there's the left hand side of the page, here's the middle, here's the right. And so if you see something on a website that you like or you wonder, wow how did they implement this it's really cool, this is a wonderful way of actually wrapping your mind around how they did it. Now CSS isn't something you need to worry so much about for the course, but if you're coming to the course with some background, realize too that Firefox lets you see the CSS that's being applied to a site. If you click on an individual element like this one in the middle, on the right hand side you will see all of the CSS rules that have been applied to that element and from top to bottom you'll see how they cascade. So again, I won't spend much time on this, only because it's not all that enlightening intellectually for the course's purposes, but this is a very common technology, but for the most part it's not necessary for our two problem sets. But realize this is there. And finally, which we'll start using on Wednesday this week, we have a script tag which actually lets you debug things that happen to be written in a language called JavaScript. So this will be invaluable too, to think of this as a GDB substitute and also useful is one other thing. So on the course's website, we have this link here, to web. Firebug is what I just mentioned, Firefox is the browser. Then there's this other debugger, which we may talk about a bit on Wednesday, then there's this thing which we will talk about today. Live HTTP headers and then web developer. This web developer toolbar is what gives me this menu here. And it also appears under your tools menu. So very important these days or very common, is for a website to be designed with a specific browser size or window size in mind. Most common these days is probably to assume that a user's screen is 1024 pixels wide by 768 pixels tall. And this wasn't always the case. Facebook, a couple of years ago, actually assumed a different monitor size which was 800 pixels by 600 pixels and a lot of websites did that, including maybe even CNN up until a couple of years ago. Well as technology proceeds and as a lot of us start to acquire widescreen laptops, your screen resolution, the number of pixels left to right, top to bottom, increases. So even Facebook a year or two ago, expanded it's site somewhat to be wider. So why is this relevant? Well at home I'm sort of you know, indulgent enough to have a 30 inch LCD, which means if I designed CS50's website on my monitor, like you'd be scrolling left and right all day long. Because I would just assume that you have my monitor. But tools like this, web developer, lets you do little tricks like this. I can click in the resize menu, 800x600 and it will just make my window be the size of an older monitor 800x600. So realize these kinds of tools can just save your, help keep you sane, but actually in this pset 5 survey, one or more of you commented that you did have to scroll rightward on the course's website and only by having that pointed out to us did we realize it. Frankly I don't notice some of these bugs on my own monitor and it was because we had made a mistake down below and it was too wide. But look, we fixed it. Now it looks better. Anyhow. [ laughter ] So let's actually do something here. So last week we looked at XHTML and php and that gives us this ability to have a client interface with the server, back and forth and the server could generate dynamic output, thereby influencing the user's experience. And that's what pset 7 is all about. But we had no form of validation really, other than a couple of quick and dirty checks on the server side and in pset 7 you'll know that it's a little annoying that if the user provides a bogus input, we encourage you just to say, to apologize to them with the apology function. Where you're saying, the message saying, invalid username, go back. Well that's kind of annoying on a modern website if you have to again, per last week's discussion, you have to go back and risk your form not even being filled out for you. You lose all of that data. So one of the very common approaches these days is for websites to use a bit of JavaScript. So JavaScript is also an interpreted language. So an interpreted language again is one that's executed line by line, top to bottom, left to right. It's not compiled into 0's and 1's. So it looks like English or it looks like actual source code. So in this case, JavaScript is a client side programming language. Php is typically server side, but there's no reason you can't run it on your own Mac or PC, but typically it's server side. JavaScript is client side. Which means when you visit a webpage that has some JavaScript code inside of it, that JavaScript code gets downloaded to your browser along with the gifs and the jpgs, along with the HTML and the CSS, all of it comes to your browser. So it's your browser's job to render, to display not only the XHTML and the graphics and all that, but also to execute the JavaScript code, top to bottom, left to right. And so it's with JavaScript that you can actually enhance the user's experience client side and many of you probably these days completely take for granted a website like Google Maps. Right? We can go up here and search for we're at 33, all right let's do the science center, 1 Oxford Street, 02138. So this was a huge leap forward a few years ago when you didn't have to click these stupid up, down, left, right buttons, which then reload the whole page and show you a new rectangle. Reload the whole page, show you a new rectangle. I mean frankly most of us and rightfully so, probably take for granted the fact that I can click and drag like this. But notice if I do it fast enough, what seems to be happening in the top left corner? It's yes, so it's gray for a moment and then it downloads. Well this is what's called Ajax. So Ajax, asynchronous JavaScript in XML, it's more of a buzz phrase than anything, but it refers to the use of JavaScript, this interpreted client side language to fetching more information from a server and inserting it inside of the webpage instead of forcing the user to reload their whole screen. So we actually do this again, on the course's homepage right now with regard to the big board. This thing updates itself every 30, Charles, doing well again. [ laughter ] This thing updates itself I think every 30 seconds or minute. I forget what timer I set for it. But I thought it would be annoying if a student visiting the webpage all of a sudden has the whole page refresh and it redownloads all of that content, which can be slow just to update a couple of values. So in fact, if we leave this page running, which I will in the background, it's going to keep updating itself in line. It's going to use Ajax and do this more seamlessly. So this was a huge leap forward because Google, when it's competitors at the time were like MapQuest and Yahoo, completely left them in the dust with this feature and you're coming to expect this. Facebook is much more laden with Ajax these days, for better or for worse and what this means is that you don't' have to click and reload as many pages. Things just kind of update. A lot of people freaked out I'm told over this new live feed or something like that. Well that's Ajax. The fact that you can see your friends like status updates in real time and they just kind of, I think they, I'm told they get inserted into the page and then kind of move the rest of the status updates downward. That's all happening in line because some people at Facebook wrote some code in JavaScript, they downloaded to your browser by embedding it in Facebook.com's webpages and it's getting executed by your browser. So let's see if we can't take a step toward that. Because problem set 8 is going to have you play an exactly that seamless world of Ajax and JavaScript with php and MySQL. So here is a terribly simple form, really didn't care so much about aesthetics this time, just functionality. I want it to collect a user's email, their password, I want it to get their password again and I wanted them to agree to some terms and conditions. Why? I wanted a few different form elements here. But you'll notice if I fill this out, it's going to lead me nowhere very interesting. Let me go ahead and pull up Firebug, just because it's a little cleaner than looking at my own source code here. I'm going to go into body, I'm going to go into form and notice, where does the form go? I'll zoom in here. What file does it submit to? What's the value of it's action line? [Inaudible].php, all right, so kind of a stupid name. It's meant to mimic a function we wrote for you for pset 7. So let me go into this. This is dump.php. This is not valid XHTML. This is not a legitimate webpage per say, but for now I just want to kind of experiment with this form submission to really understand how it works. So what I did is this quick and dirty, as we keep saying, script that apparently outputs a pre-tag which means here comes some pre-formatted text. Display it in a mono spaced font that looks like a typewriter instead of like an English essay. And then I have this and actually I don't' need this right now. I have print recursively the contents of $_gets. So recall there's two ways essentially to submit data to a website from a form. Via get, which puts all your data in the url and via post. So what was a rule of thumb here? When would you want to use post instead of get? Any thoughts? So for privacy. Right? So if you use get, by definition of it, remember that the query's end up in the url and that's how we sort of bootstrapped ourselves into reimplementing Google. We combined our user's input with their get string. With their url. But that's not so good if you're typing in private information, if you're typing in a username and password or credit card, so post hides all of that information. Post can also handle much larger submissions. So if you're uploading a photo, it's kind of hard to imagine uploading a photo to Facebook via just a url and converting it to 0's and 1's, that's also done by a post as well. And as an aside, in case you've seen it in any of my code, request is another super global variable as they're called. This has both the contents of get and post in them. So if you're being a little lazy or you want to support both get and post, you can access the same variables inside of request. But it's better designed generally to pick get or post, so that you know what to expect. So that's all dump.php is. It's going to show me the contents of what was submitted by the form and therefore automatically put into that super global called gets. So let's go ahead and do this. I'm going to type in mailin@post.harvard.edu 1234512345, I'm going to check the box and I'm going to click submit and what I get back here is this output. So again, this sort of indented output is the result of print R and this is just what it does. It dumps the contents of an array. So what you have been received server side, four variables inside of get. So if I really wanted to get to do something more interesting, rather dump to do something more interesting, I could do something like this. I could do let's say, name: and then let's duplicate this. Let's say password 1. Let's change this to password 2. And then we'll change this to check box. So just to make clear what I'm doing, let's now put not the value of the whole array but let's just print out $_get quote unquote email. Sorry I wrote something down that didn't exist. I meant to say email. And then here I want to say quote open bracket ?print$, so this is a little tedious. It turns out that if all you want to do is print a value, php has a shorthand notation which is open bracket ?= and then just put the variable that you want to put there which in this case is going to be password 1, so quote unquote and you probably get the idea. So I won't bother finishing the rest. But the point is, the top version is really just debugging. Dumping the whole array. If you actually care about individual values, you go after them using this associative array syntax. This square bracket notation. If I reload this page, thereby resubmitting the form, after saving my file, notice that what I get down here, oh I'm cheating, I'm on the wrong server. Dammit. How best to fix? Cloud.CS50.net, mailin source forms. OK, let's resubmit, mailin@post, 12345 12345, check the box and submit. OK and it's a mess. Why is it all on one line like this? Yes so no line break. So no BR's. Right? So the quick fix here and then we'll move forward is put this there, put this there, this there, this there and now finally if I reload, OK. So again, sort of a refresher of what we did last week. So now let's take things up a notch. Because right now this program, if I actually go in here and change things around like, if I just say mailin or something like this or mailin@fast or mailin@post, I don't give a valid email address, I just submit this well nothing bad happens. It just gets submitted to the server. So now the server has to do all of the validation of this data. So that might necessarily be such a bad thing, because at the end of the day that's the safest approach. Actually having your server defend against bogus user input, is by far the most robust approach. But it's kind of annoying. Because now the user have to go back, if I'm yelled at then I have to fix my form. Can't we give the user more dynamic, more immediate feedback and save them the time and the trouble of going to a whole new page, then going back and forth and back and forth? Well yes, we can. So in form2.html, we have the same form but a little bit of magic. For instance, if I decide eh, you don't' need to know this about me, I am going to proceed nonetheless, notice I immediately get yelled at. So it's a little small here, so let me zoom in. This is an alert window. It says, you must provide an email address. All right. Well where did this come from? Well let's take a look at the page's source in Firebug. But again you can go to view source and see the same thing. So open the body, open the form, oh this is interesting, what is a new attribute on the form element here that we didn't have a moment ago? So on submit. So on submit kind of self explanatory. Because it says, on submit. So when this form gets submitted, do the following. Well it turns out that what should be done when the form is submitted is the following line of code should be executed. It's just long so it wraps on two lines, but the line of code is, returnvalidopenparencloseparen;. So that's a snippet of code. It's not php code, it is in fact JavaScript code. So let's take a look. This is form2.html. So I'm just using HTML files. I'm not bothering with php. This is purely client side static content right now. So let me scroll down all the way to the bottom. Here is the same form. So that is my form tag, my email word, password, password again. This is sort of, this is pretty much all old school now from last week, but the only difference is I added this attribute here and again from last week, web browsers don't' care about white space. I decided ugh, this feels a little messy having it all on one line, so I just decided stylistically to put it on a new line and that's fine. White space inside of tags like this is OK. So what is this validate function? Well let's take a look. Well even though last week we said the only thing that belongs in your head element is the title tag, kind of a simplification because you can also put a script tag. So this tag up here is kind of new. It says, open bracket script. It then says, type=text/JavaScript That's just telling the browser hey, here comes some JavaScript So JavaScript is kind of the only language that people embed in webpages. There are other languages. There's VB script which is a Windows thing, but pretty much these days people only use this tag as follows. This is just a bit of syntax to ward off confusion. So long story short, there's certain characters on the keyboard that can confuse browsers very easily. For instance, if I wanted to say 2 less than 3, well why is this kind of expression, if I type this inside a webpage, potentially confusing to a browser? Just 2<3. What's the scary letter there? So it's this thing right? Because this is the special tag, this special symbol we seem to use everywhere to tell the browser here comes a tag. Interpret this as XHTML, not as actual text. So for now just know that this crazy syntax here, which is intentionally crazy because they figured who is ever going to need to write a sentence with these characters in it, so this thing here, who is ever going to need to write this in a sentence. So that's why it looks as crazy as it does. This just means ignore the following stuff. It is not XHTML, it's probably code or something else. So here's my first JavaScript function. Just like php, I say literally function, then I give the thing a name, then parenthesis and inside of those can be any parameters. This time there is none. So what am I doing? Well this function's purpose in life is to validate the user's input. So I could have done any number of things but let's consider for a second, what could go wrong. What could the user do that might annoy me, the person trying to trap this information? They might do what? Leave something blank. So leaving their email address blank kind of useless if the point is to register them for something. What might they also do that's wrong? Passwords might differ. They might be too short, they might be not have fancy enough characters or more simply, they might not match. Or third thing that we can pick on pretty easily? They didn't check the box right? They didn't check the box. They need to check the box if I'm going to register them. So can we detect these things client side? We can server side. And even last week recall, I used a couple of lines of php code to say, if this thing is empty, yell at the user. Make them go back. Well here we're going to give them more immediate feedback. So here's the syntax. It's a little long, but that's OK. So it's I say if document document is the webpage. It's a special global variable if you will that refers to the webpage itself, document. forms. Document.forms is an array essentially of all of the forms on the webpage. Right now there's just one so this is pretty simple. Registration is the name of the form that I care about. Well where does this come? Well if you fast forward here, actually there was one other attribute I added to the form, which we haven't used previously. I gave it a name. An arbitrary name, but one that's memorable to me. So now notice, document.forms.registration is simply the JavaScript way of saying, go examine that specific form. What do you want to examine inside of it? Well that registration form has a field called email. Where does this come from? Well fast forward to the bottom and notice the name I gave to the input for email, it's just email. So careful, the casing is important, but I did copy it literally so we're good. And then finally, that's just the form field. If I want to check the value, I do .value. So document. forms. registration. email. value, it's kind of like stepping through a tree from top to bottom, deeper and deeper and deeper until you hit this value. And I'm just saying, if it is blank, if it equals the empty string what do it do? Well this is exactly what I got yelled at for before. Javascript has built in an alert function. Looks a little different on different browsers but at the end of the day, accomplishes the same task. It triggers a little pop up with an OK button or the equivalent and then just says something to the user. But I still want to ensure that the form does not get submitted. And so I return false here and that's important because if you look back at the form tag, notice I didn't just call validate, I returned the return value of validate, so the browser realizes oh, if validate the function returns false, I should not submit this form. Like let's just short circuit the operation and not let things pass. Well what else am I checking for? Well here's one thing. If the password is blank, I catch it there. If the first password 1 does not equal the second password, I catch that. If this, notice this is another property, so if the agreement input is not true for it's checked property, then I have to say you must agree to our terms and conditions. So it's all fairly straightforward. You know, kind of along these lines so I've allowed them to wrap but pretty simple in the end. And finally, I return true. None of these problems exist. So if I go back here and I do provide an email addresses, mailin@post.harvard.edu 12345 12345, but oh I don't want to agree. Submit, it still catches that, but I'm left on the same page and notice, the url has not changed. I'm still at form2.html, I am not at dump.php because I've short circuited that process. So any gotcha's? Is there a problem with using JavaScript in this way? What do you think? Especially if you're among those more comfortable or those familiar with web programming. Can I get away with just JavaScript and skip all that php stuff from last time? You know what the answers to these questions are the same right? No. Why? Right? So it turns out that just because you tell the browser to do something, doesn't mean it has to do it and a very common way of attacking or compromising websites is to take advantage of foolish assumptions programmers have made. If you only validate the user's input client side or rather if you only validate the user's input client side using JavaScript, well what if the user you know, is mildly clever and realizes they can go to Safari and they can go to disable JavaScript They've essentially disabled all of your validation completely. So we can post on the bulletin, oh Charles, you're not doing, oh wait, oh, my internet connection is dead there. Let's see actually how Charles is doing. [ laughter ] Very nice. OK. OK. So anyhow, this is not a menu that comes by default with Safari. You have to enable it. It's very easy. Just email [inaudible].net or I'll look it up at some point. I forget how to do it. But it's there now. So this is bad. Just using JavaScript not such a good idea and in fact, some bad things happen. If you disable JavaScript and try to visit any number of popular websites, they might work, though they might be a bit shot in the foot, certain features might not work or they might just not work at all. So people have started making assumptions these days when designing websites, if you don't have JavaScript enabled, like to hell with you. Like it's not worth frankly, the time trying to implement two different versions of a website and it's actually kind of a fun experiment. At least if you're so inclined, to disable JavaScript and visit your favorite websites and see which ones break. Which ones take for granted JavaScript Now it's not all that silly to ask this, because even though Safari on the iPhone is actually pretty good, it is a real web browser. Before this I had a Blackberry who's web browser sucks frankly and they didn't support JavaScript fully, so there were so many websites I couldn't pull up because they just didn't work. So though I make fun of this you know, this trade off, it's actually a very real world concern because who do you want to cater to? People who have JavaScript enabled and don't even know that you can turn it off or do you actually want to cater to other devices that might not support JavaScript fully or do you want to deal with the really paranoid types out there who intentionally turn JavaScript off and hope and expect that the world continues to function properly? So these are the kinds of things that evolve over time. These mentalities and these features. So realize that validation client side, very useful in that it's saved me some cycles. I don't have to go reload the page and all of this, but it can be very easily circumvented and you can take advantage of these assumptions. So this other tool I mentioned and showed very briefly last week is called, live http headers. So when you request a webpage, what the browser essentially sends across the wire, across the internet, is literally something like this. Let me go ahead and use this program. Just to type something big. What a browser sent, if you go to www.let's say www.facebook.com/home.php right. This is one of their common url's. Well what the browser really does when you hit enter, is it opens an internet connection, tcpip connection to facebook.com and it sends it a request like this, getme/home.php and use version like 1.1 of http, the language that browsers and servers speak. There's 1.1, there's 1.0. That's doesn't matter so much. So this is the message that's sent. Well if you submit some variables to a website, now let's consider Google. So Google we've seen, so that was http://www.Google.com/search and then /q=foo. So this is something I'm searching for. Well what gets sent then to the website is this, /search?q=foohttp/1.1. Well notice this. It looks like I can submit anything I want to the server, just by sending that message to the server. So if I don't care to execute JavaScript or I outright disable it, nothing is stopping me from still sending bogus data to a website. So let's take a look at this registration form. So this registration form lives at form2.html and actually, let's actually go back to the first version, because it won't get in our way with JavaScript I now have this tool up. I'm going to clear it's window and now notice. Let me move one to the side here. I'm going to go ahead and type in, let's clear this, I'm going to go ahead and type in mailin@post1234512345, I'm going to check the box and click submit. Notice this page got updated because what this little program is doing for me, this Firefox plugin, it's sniffing my web traffic and it's showing me what is the browser really sending to the server. So at the very top is the url that was just submitted to and as we expected, it ends in dump.php. We knew it was going to go there. Then there's a question mark. So I'm at the very top middle of my screen, ?email=mailin@post, the funky encoding is a browser's way of making of escaping input, to make sure it's not confused for special characters, %40 is just special character than means the @ sign. So no worries there, but ampersand is important. Because ampersand separates remember, parameters from other parameters. So it looks like via gets, what's been requested is that url which means if I now look at the line below, ah that is literally what the browser is sending to the server. It's this thing here. Gets/ until the mailin and all of this and notice, all of the form elements are submitted via the url. So what's the take away? Well if you have for instance a website, a banks website that's just checking people's usernames and passwords with JavaScript and then if they're correct they let them see that person's account balance, well clearly could you circumvent that either by turning off JavaScript or just by sending data to the server, actually I'm telling the wrong story. I'm confusing my two stories. You can still send anything you want to the server and if the server just assumes that the data has already been validated, they're in for some trouble. Because clearly can you send most anything you want and in fact, even though I'm still just using a plug in to look at this content, I can very easily request a website. In fact, let me do just this. So minor aside, just to show you how simple the internet really is. We use SSH a lot, but there's also a program called TelNet. So TelNet is like an unencrypted version of a browser. I can actually do TelNet and then I can do a server's name. Let's see, I haven't done this before, so let's just try it. Facebook.com. But TelNet, by default, has it's own special port, it's 23, but I want port 80, because port 80, this is an internet thing, is a number that uniquely identifies the service we know as http. Web traffic has a port number called 80, as the cell traffic is 443, SSH which some of you have even noticed, is what number? 22. So we've seen these kinds of numbers before, but just taken them for granted. I hit, enter. Oh I am connected to www.facebook.com. Now I have an interactive session. So what do I want to do? Well let me go ahead and get/home.php and I don't know much about the language. I'm just going to use version 1 and I'm going to hit enter twice and OK, interesting. It looks like Facebook has responded with this. So this is an http thing. If the server sends back that line, location:, that's a redirect. That tells the browser, go to this url. Well I'm not a browser so I'm going to have to do this manually. So let me go ahead and copy and put that in my clipboard. Now I'm going to rerun TelNet, so let's TelNet. This time I'm, oh wait let me, I've got to fix one thing. Come on. Quit. Let's see that once more. I copied too much of it. So I just want to get /common/browser.php. All right, so now I've copied that because that's where it's telling me to go. Let's rerun TelNet, get this now, http, oops, enter. Ah, look at that, facebook.com's html. So this is the mess that your website, that your web browser would download and let's just try and scroll up, right, like so Mark's really made a mess of their website here. So look at all this stuff. Look, OK. Let's find something familiar. Oh my god, OK. [ laughter ] But notice, so this is actually JavaScript So this is intellectual property. Because Facebook is pretty sophisticated with what it does client side, all the fancy animation and all that, but they don't really want CS50 students or anyone out there, just copying their website, as has actually been done in other countries. And taking their code. So this actually is JavaScript code but it's been quote unquote obviewskated or compressed. So there are ways of not turning your JavaScript into 0's and 1's, which is a lot harder to reverse engineer, but you change all the variables to funky names so that it's really confusing what they represent. You eliminate obviously almost all the white space. There's no new lines, there's no indentation. Now frankly, this is only a slight measure of protection. So you can obviewskate your code in this way, but frankly a smart person who really knows their stuff, could certainly figure out what this code is doing. And there's plenty of tools that will convert this back to cleaner JavaScript, even though it can't recover the variable names. But this is the trade off here. If you're sort of smart enough and adroit enough with JavaScript to figure out what this is doing, odds are you could reimplement Facebook in less time, just by starting from scratch. So it's a trade off. It just raises the bar. But his is another matter of security. Ah, here we go. Finally. So it looks like Facebook is using XHTML 1.0 strict, which is a certain flavor of it. Here is the tag we've been telling you guys to use. There's a couple more things there. Here is the head. There's some meta tags here which were tags we don't care about. Oh, here's actually today's topic. So embedded in Facebook.com is all of this JavaScript So long story short, what we sort of take for granted because we're pointing and clicking all the time with browser's these days is all very low level and all of these details can be interesting and can be again exploited if you know how to send inputs to the server. So let's see if we can't be a little more clever here. That was form1.html, we saw form2, let's take a look at form3. So form3 looks like this, in source code. This is the pretty code. The only thing I did differently is actually I'm going to skip back because it's not that interesting. Let's look at 4. I veto 3. All right, so form 4. So the difference in form 4 is that something just got grayed out, even though it's a little subtle on the screen. Yes, so this is kind of annoying. Can't even submit. So right, this really annoys the user. Oh but wait a minute. Oh I checked that box and now I can submit. So how can you do things like this? Well let's introduce one more little building block and then see where we can go with this. So this is form 4. It turns out that this is the XHTML. It's pretty much copy and paste as before and notice again here I am calling return validate on submission, but there's this other one here and it's wrapping because my font is a little big, but notice you can also have an event handler as it's called, a special attribute, that actually responds not to form submission, but to clicking. So this says, when the user clicks this check box, go ahead and call a function called toggle. Well what does toggle do? Well let's scroll back up to the top. There's a validate function. We're going to ignore that for now, but here's toggle. Interesting. So again, pretty robust, but if document. forms. registration. button, that's the name I gave to the check box.disabled, so if that is true go ahead and make it false else go ahead and make it true. So it turns out that some form elements have properties not just value, which we used before for validation, they also have bullion properties like disabled. If disabled is true, it means you cannot click on that form field. You cannot fill out that box because it's disabled. So we can toggle it just by reassigning it a different truth value, false or true. So again, a tiny, little building block there, but let's us create again a more robust or more seamless interface. So why does this then get interesting that we can do things client side? Well this was just form validation. That's kind of an exercise in JavaScript syntax. Nothing more than that. Well it turns out we can use JavaScript to also go fetch more information ala Google Maps. So let's go ahead and type in here our favorite stock quote like, GOOG and click, get quote. And every previous lecture and example, this form would get submitted to a php file and present the result and I'd see the answer. Let me go ahead and click get quote. Oh, a pop up. So still not all that impressive, so let's just look at version 2. As a little teaser here. Now OK, price to be determined. Now again, I'm cutting corners on aesthetics but GOOG, let me go down here click, get quote. And now I'm updating the page dynamically and my url has not changed. And it's this very basic building block that really drives the fanciest, sexiest of websites today, whether it's maps or whether it's Facebook or most any other site you visit. So more on this on Wednesday. ==== Transcribed by Automatic Sync Technologies ====