diff --git a/README.md b/README.md index e1650685..9aa999df 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,16 @@ Olin.js - Spring 2015 === ##Course Contents -* [Class 0 - Getting Ready for the Course](./classes/class0) -* [Class 1 - Course Introduction and The Internet](./classes/class1) -* [Class 2 - Intro to Javascript](./classes/class2) -* [Class 3 - Express, Templating, and MongoDB](./classes/class3) -* [Class 4 - The Clientside](./classes/class4) -* [Class 5 - Sessions, Users, Errors, CSS, and Debugging](./classes/class5) -* [Class 6 - Application Integration](./classes/class6) -* [Class 7 - Unit Testing and Task Running](./classes/class7) -* [Class 8 - Git Skils and Team Coding Techniques (Lab 1)](./classes/class8) -* [Class 9 - Architecture and Diagramming](./classes/class9) +* [Class 0 - Getting Ready for the Course](./classes/class00) +* [Class 1 - Course Introduction and The Internet](./classes/class01) +* [Class 2 - Intro to Javascript](./classes/class02) +* [Class 3 - Express, Templating, and MongoDB](./classes/class03) +* [Class 4 - The Client](./classes/class04) +* [Class 5 - Flex Day](./classes/class05) +* [Class 6 - Sessions, Users, Errors, CSS, and Debugging](./classes/class06) +* [Class 7 - Application Integration](./classes/class07) +* [Class 8 - Unit Testing and Task Running](./classes/class08) +* [Class 9 - Architecture and Diagramming](./classes/class09) * [Class 10 - Application Frameworks (Lab 2)](./classes/class10) * [Class 11 - Security](./classes/class11) * [Class 12 - Deployment and Scaling](./classes/class12) diff --git a/classes/class0/README.md b/classes/class00/README.md similarity index 100% rename from classes/class0/README.md rename to classes/class00/README.md diff --git a/classes/class1/HW1/javascripting/array-filtering.js b/classes/class01/HW1/javascripting/array-filtering.js similarity index 100% rename from classes/class1/HW1/javascripting/array-filtering.js rename to classes/class01/HW1/javascripting/array-filtering.js diff --git a/classes/class1/HW1/javascripting/arrays.js b/classes/class01/HW1/javascripting/arrays.js similarity index 100% rename from classes/class1/HW1/javascripting/arrays.js rename to classes/class01/HW1/javascripting/arrays.js diff --git a/classes/class1/HW1/javascripting/for-loop.js b/classes/class01/HW1/javascripting/for-loop.js similarity index 100% rename from classes/class1/HW1/javascripting/for-loop.js rename to classes/class01/HW1/javascripting/for-loop.js diff --git a/classes/class1/HW1/javascripting/function-arguments.js b/classes/class01/HW1/javascripting/function-arguments.js similarity index 100% rename from classes/class1/HW1/javascripting/function-arguments.js rename to classes/class01/HW1/javascripting/function-arguments.js diff --git a/classes/class1/HW1/javascripting/functions.js b/classes/class01/HW1/javascripting/functions.js similarity index 100% rename from classes/class1/HW1/javascripting/functions.js rename to classes/class01/HW1/javascripting/functions.js diff --git a/classes/class1/HW1/javascripting/if-statement.js b/classes/class01/HW1/javascripting/if-statement.js similarity index 100% rename from classes/class1/HW1/javascripting/if-statement.js rename to classes/class01/HW1/javascripting/if-statement.js diff --git a/classes/class1/HW1/javascripting/introduction.js b/classes/class01/HW1/javascripting/introduction.js similarity index 100% rename from classes/class1/HW1/javascripting/introduction.js rename to classes/class01/HW1/javascripting/introduction.js diff --git a/classes/class1/HW1/javascripting/looping-through-arrays.js b/classes/class01/HW1/javascripting/looping-through-arrays.js similarity index 100% rename from classes/class1/HW1/javascripting/looping-through-arrays.js rename to classes/class01/HW1/javascripting/looping-through-arrays.js diff --git a/classes/class1/HW1/javascripting/number-to-string.js b/classes/class01/HW1/javascripting/number-to-string.js similarity index 100% rename from classes/class1/HW1/javascripting/number-to-string.js rename to classes/class01/HW1/javascripting/number-to-string.js diff --git a/classes/class1/HW1/javascripting/numbers.js b/classes/class01/HW1/javascripting/numbers.js similarity index 100% rename from classes/class1/HW1/javascripting/numbers.js rename to classes/class01/HW1/javascripting/numbers.js diff --git a/classes/class1/HW1/javascripting/object-properties.js b/classes/class01/HW1/javascripting/object-properties.js similarity index 100% rename from classes/class1/HW1/javascripting/object-properties.js rename to classes/class01/HW1/javascripting/object-properties.js diff --git a/classes/class1/HW1/javascripting/objects.js b/classes/class01/HW1/javascripting/objects.js similarity index 100% rename from classes/class1/HW1/javascripting/objects.js rename to classes/class01/HW1/javascripting/objects.js diff --git a/classes/class1/HW1/javascripting/revising-strings.js b/classes/class01/HW1/javascripting/revising-strings.js similarity index 100% rename from classes/class1/HW1/javascripting/revising-strings.js rename to classes/class01/HW1/javascripting/revising-strings.js diff --git a/classes/class1/HW1/javascripting/rounding-numbers.js b/classes/class01/HW1/javascripting/rounding-numbers.js similarity index 100% rename from classes/class1/HW1/javascripting/rounding-numbers.js rename to classes/class01/HW1/javascripting/rounding-numbers.js diff --git a/classes/class1/HW1/javascripting/string-length.js b/classes/class01/HW1/javascripting/string-length.js similarity index 100% rename from classes/class1/HW1/javascripting/string-length.js rename to classes/class01/HW1/javascripting/string-length.js diff --git a/classes/class1/HW1/javascripting/strings.js b/classes/class01/HW1/javascripting/strings.js similarity index 100% rename from classes/class1/HW1/javascripting/strings.js rename to classes/class01/HW1/javascripting/strings.js diff --git a/classes/class1/HW1/javascripting/variables.js b/classes/class01/HW1/javascripting/variables.js similarity index 100% rename from classes/class1/HW1/javascripting/variables.js rename to classes/class01/HW1/javascripting/variables.js diff --git a/classes/class1/HW1/learnyounode/babysteps.js b/classes/class01/HW1/learnyounode/babysteps.js similarity index 100% rename from classes/class1/HW1/learnyounode/babysteps.js rename to classes/class01/HW1/learnyounode/babysteps.js diff --git a/classes/class1/HW1/learnyounode/filteredls.js b/classes/class01/HW1/learnyounode/filteredls.js similarity index 100% rename from classes/class1/HW1/learnyounode/filteredls.js rename to classes/class01/HW1/learnyounode/filteredls.js diff --git a/classes/class1/HW1/learnyounode/helloworld.js b/classes/class01/HW1/learnyounode/helloworld.js similarity index 100% rename from classes/class1/HW1/learnyounode/helloworld.js rename to classes/class01/HW1/learnyounode/helloworld.js diff --git a/classes/class1/HW1/learnyounode/myfirstIO.js b/classes/class01/HW1/learnyounode/myfirstIO.js similarity index 100% rename from classes/class1/HW1/learnyounode/myfirstIO.js rename to classes/class01/HW1/learnyounode/myfirstIO.js diff --git a/classes/class1/HW1/learnyounode/myfirstasyncio.js b/classes/class01/HW1/learnyounode/myfirstasyncio.js similarity index 100% rename from classes/class1/HW1/learnyounode/myfirstasyncio.js rename to classes/class01/HW1/learnyounode/myfirstasyncio.js diff --git a/classes/class1/README.md b/classes/class01/README.md similarity index 100% rename from classes/class1/README.md rename to classes/class01/README.md diff --git a/classes/class2/HW2/index.js b/classes/class02/HW2/index.js similarity index 100% rename from classes/class2/HW2/index.js rename to classes/class02/HW2/index.js diff --git a/classes/class2/HW2/router.js b/classes/class02/HW2/router.js similarity index 100% rename from classes/class2/HW2/router.js rename to classes/class02/HW2/router.js diff --git a/classes/class2/HW2/server.js b/classes/class02/HW2/server.js similarity index 100% rename from classes/class2/HW2/server.js rename to classes/class02/HW2/server.js diff --git a/classes/class02/README.md b/classes/class02/README.md new file mode 100644 index 00000000..29584737 --- /dev/null +++ b/classes/class02/README.md @@ -0,0 +1,626 @@ +#Class2 - JavaScript + +## JavaScript is Everywhere + +### Atwood's Law + +>Any application that can be written in JavaScript, will eventually be written in JavaScript. + +[Jeff Atwood](http://blog.codinghorror.com/the-principle-of-least-power/) + +## The Language + +Luckily, you're probably already familiar with a language similar to JavaScript. Things like variable assignment,function definition, and control flow aren't much different from Python. We'll get into the differences later. + +Type `node` in your command line to bring up the Node JavaScript REPL (read-evaluate-print-loop). + +### Variable Assignment + +```node +> var x = 5 +undefined +> x +5 +``` + +For the rest of this lesson (unless otherwise specified), `x` will be equal to the number `5` at the start of every example. + +Variable assignments in JavaScript start with `var`. If you omit `var`, the variable will be *implicitly global*. This is ***very bad*** — almost worse than the program just crashing with an error message. We'll go into why later. + +### Operators + +JavaScript operators are all the same as Python, except `**` doesn't exponentiate. + +```node +> 6 + 6 +12 +> x += 6 +11 +> x > 5 +true +> 6 ** 6 +... +``` + +The `...` means the REPL is waiting for a certain input. In this case, it just means it's confused. Press `Ctrl+C` to get back to the prompt. The way to exponentiate in JavaScript is `Math.pow`: + +```node +> Math.pow(4, 2) // raise 4 to the power of 2 +16 +``` + +The [`Math` object](http://www.w3schools.com/jsref/jsref_obj_math.asp) (we'll cover objects later) has lots of other useful constants and functions. + +#### Checking for equality + +Here's an important corollary to what I just claimed: JavaScript has two ways to check for equality: `==` and `===`. + +Double-equals does things you might expect, like this: + +```node +> 5 == 5 +true +> x == 5 +true +``` + +But it will also do things you probably won't be expecting, like this: + +```node +> '5' == 5 +true +> ' ' == 0 +true +``` + +This happens because the `==` operator performs what's known as "type coercion", or implicit type conversion. If the variables being compared have different types, JavaScript will convert one to the type of the other before comparing them. + +The `===` operator is also known as "identically equal" or "strict equals". It doesn't perform type coercion, so variables of different types will not be reported equal. + +```node +> '5' === 5 +false +> ' ' === 0 +false +``` + +Usually, you're expecting this behavior. If in doubt, use `===` (triple-equals). + +##### Checking for inequality + +JavaScript also has `!=` and `!==`. All the same rules apply — `!==` is generally safer. + +## Control Flow + +JavaScript's control flow will be familiar to Python users, with largely syntactical differences. The keywords `break` and `continue` are unchanged. + +### Conditionals + +```node +if (x === 5) { + +} +else if () { + +} +else { + // +} +``` + +### Iteration + +#### For loop + +For loops will run a block of code a certain number of times, based on the conditions in the declaration. There are two ways to declare a for loop, each with its ideal use case. + +##### For + +This is the basic for loop syntax: + +```node +for (initialization; condition; final-expression) { + statement +} +``` + +The `initialization` declares the variable that will be used to determine whether or not the `statement` should execute again each time the loop runs. The `condition` is evaluated before the loop runs each time — if it evalutes to `true`, the loop runs; otherwise, it stops. The `final-expression` is just code that runs after each iteration of the loop. In practice, for loop declarations look something like this: + +```node +for (var i = start; i < end; i++) { + ... +} +``` + +This loop reads + +>The loop will start with the iterator `i` equal to `start` and run while `i` is less than `end`, and `i` will increase by `1` after each iteration. + +##### For...in + +If the loop iterates through an array or object, you can also use this shorthand: + +```node +for (var index in array) { + var element = array[index] + ... +} + +for (var key in object) { + var value = object[key] + ... +} +``` + +#### While loop + +A while loop is useful if the amount of times the loop should run is not known before it runs (for example, it should run until a conditional evaluates to `false`). + +```node +while (condition) { + statement +} +``` + +#### Do...while loop + +The do...while loop is simply a while loop where the `statement` is guaranteed to run at least once. + +```node +do { + statement +} while (condition); +``` + +## Types + +JavaScript variables can have one of the following types: + +- `Undefined` +- `Null` +- `Boolean` +- `String` +- `Number` +- `Object` + +The types `Boolean`, `String`, `Number`, and `Object` all provide functions to convert, or cast, expressions to their type. + +```node +> String(5) +'5' +> Boolean(0) +false +> Boolean(5) // any non-zero number +true +> Number('5.6789123456789123456789') +5.678912345678913 +``` + +The `Number()` typecast supports strings and floating point numbers (and even rounds!). No need to write your own number parsing code! + +The next behavior is arguably worse than throwing an error, but also cool: You *can* do string multiplication in JavaScript! + +```node +> '3' * '4' +12 +``` + +Not really, though. It's a number now. + +```node +> typeof('3' * '4') +'number' +``` + +String addition works as expected. + +```node +> 'a' + 'b' +'ab' +> '5' + '5' +'55' +> '5' - '5' +0 +``` + +Well, anyway... + +JavaScript, like Python, is dynamically typed. This means that a variable's type isn't determined until runtime. But since JavaScript is also very weakly typed (while Python is not), functions will usually be able to operate on arguments of the wrong type (by coercing them, for example), which means a program can fail unexpectedly long after a type-related mistake is made. In this case, error messages are usually not helpful, so the best thing to do is be careful and think ahead as you write your code. + +## Functions + +Functions make complexity manageable! JavaScript is all about functions. Let's make some. + +At this point we should start putting our code in files. If you have a JavaScript file: + +###### functions.js +```node +function func1() { + return 1; +} +``` + +You can run it like this: + +```bash +$ node functions.js +``` + +In `functions.js`, we declare a function named `func1` that takes no arguments and returns the number `1`. + +We can add to `functions.js` to learn more about `func1`. + +###### functions.js +```node +... +console.log(func1) +console.log(func1()) +``` + +The function `console.log` does what you might expect — it logs arguments to the console. + +``` bash +$ node functions.js +[Function: func1] +1 +``` + +The two print statements we added to `functions.js` look almost the same, but the console output shows that they're very different. The first statement prints the function object `func1` — that is, the actual *entity* that represents the function itself (the code, the arguments, the scope in which it was declared — more on scope later). Node says that `func1` is a `Function` named `func1` — nothing unexpected here. + +Putting `()` next to the name of a function calls the function, so when we print `func1()` we get the return value of `func1`, which is `1`. + +`()` will actually always attempt to "call" the expression to its left, treating it like a function. So you can get errors like this: + +```node +> 5() +TypeError: number is not a function +``` + +A variable can also store a function declaration, so we could have done this instead: + +```node +var func1 = function() { + return 1; +}; +``` + +The above example wouldn't have acted *quite* the same, though, which brings us to what makes JavaScript functions so special. + +### Functions are Objects + +The print statements above hinted at this: in JavaScript, functions can be stored in variables and passed around to be executed elsewhere. This ability demonstrates that functions are objects. So something like this is possible: + +###### functions.js +```node +function func1() { + var func2 = function() { + return 2 + }; + return func2; +} +``` + +What will happen when we call `func1`? + +###### functions.js +```node +... +console.log(func1()); +``` + +```bash +$ node functions.js +[Function] +``` + +The function `func1` is a named function that returns the variable `func2`. We set `func2` equal to a function definition without a name — the function on the right hand side of this assignment is known as an **anonymous function**. + +So, `func1` returns a variable containing an anonymous function which returns `2`. How do we call the returned anonymous function? + +###### functions.js +```node +... +console.log(func1()()); +``` + +```bash +$ node functions.js +2 +``` + +This is totally legal. It might help to break down the expression we just printed: + +```node +func1()(); // first, func1 is called +func2(); // it returns func2 +(function() { return 2; })(); // func2 holds an anonymous function +2 // the anonymous function is called and returns 2 +``` + +## Closures + +When a function object is declared, it has access to the variables in the scope in which it was declared. + +###### closures.js +```node +var multSum = function(x, y) { + var mult = function() { + return x*y + } + return mult() + x + y +} + +console.log(multSum(5, 6)) // 5*6 + 5 + 6 +``` + +```bash +$ node closures.js +41 +``` + +The function `mult` declared inside `multSum` has access to the variables `x` and `y`, because they are in the scope in which `mult` was declared. Here, `mult` is a closure — it encompasses not just the function itself, but also the scope in which it was declared (the outer scope), and the global scope, of course (all functions have access to the global scope). + +Closures are often seen in practice as callbacks, explained next. The Mozilla Developer Network offers [a more in-depth explanation of closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures. + +## Callbacks + +Function objects let us pass around pieces of code that can be run at arbitrary times. + +Here's a really common situation: A client application requests data from a URL, and wants to process the data when it arrives. There's no way to know how long it will take the data to arrive, and even if there was, we wouldn't want to just block execution and wait until we got the data. This would be **synchronous execution**, where code is executed one line at a time, in order. It would be great if we could request the data and go about our business until we received it — then we could run the code that depends on the data. **Asynchronous execution**, where code is executed out of order (often in response to events), allows this. Luckily, this behavior is the norm in JavaScript. + +**Callbacks** are functions that we provide to be run when an event occurs. Here's an example with real code: + +```node +$.get(url, success); +``` + +You might be familiar with dot syntax from Python — if you're not, we'll cover it soon. The `$` is a stand-in for jQuery, a ubiquitous client-side JavaScript library that adds a lot of useful functionality (like better DOM/CSS manipulation and asynchronous request functions) to JavaScript. `jQuery.get` (or `$.get`) is a method that requests data from the provided `url`. + +The second argument is a success callback — it is a function that will be called, and passed the response data as an argument, if the request is successful. We could call `$.get` like this: + +```node +$.get('www.some.url', function(data) { + console.log(data); + console.log('Request was successful!'); +}); +``` + +`success` could also be a variable containing an anonymous function: + +```node +var handleSuccess = function(data) { + console.log(data); + console.log('Request was successful!'); +}; + +$.get('www.some.url', handleSuccess); +``` + +It could even be a function declared somewhere else entirely, like this. + +```node +function globalSuccessHandler(data) { + ... +} +... +$.get('www.some.url', globalSuccessHandler); +``` + +### Closures +## Objects + +Objects in JavaScript are simple key-value stores, which you may know from Python as **dictionaries**. + +We can create an empty object like this: + +```node +> var obj = {} +undefined +``` + +Properties can be added and accessed with dot syntax. + +```node +> obj.color = 'blue' +'blue' +> obj.color +'blue' +``` + +Bracket syntax lets us use variables as keys. + +```node +> var colorKey = 'color' +undefined +> obj[colorKey] +'blue' +``` + +Dot syntax is more concise than bracket syntax, so it's preferable unless bracket syntax is necessary (like if your key has a space, for some reason): + +```node +> obj['another color'] = 'red' +'red' +> obj['another color'] +'red' +> obj +{ color: 'blue', +'another color': 'red' } +``` + +Printing `obj` shows exactly how to declare objects that aren't empty. Objects can contain any variable type, including functions and other objects: + +```node +> var obj = { +... aBool: true, +... aString: 'string', +... aNum: 5.6, +... aFunc: function() { return 6; }, +... anObj: { key: 'nesting is pretty great' } +... } +undefined +``` + +Properties can be treated like you might expect: + +```node +> obj.aFunc +[Function] +> obj.aFunc() +6 +> obj.anObj.key +'nesting is pretty great' +``` + +JavaScript objects are versatile and ubiquitous — you'll see them everywhere. This brings us to the next section. + +### Arrays + +Arrays in JavaScript are also objects, which is why we covered objects first. Declare an array like this: + +```node +> var arr = [] +undefined +``` + +Or a filled one like this: + +```node +> var array = [1, 2, 3, 4] +undefined +``` + +Arrays can contain any type, and need not contain variables of the same type. + +```node +> var jsArray = [true, 'string', function() { return 'why would anyone do this'; }] +undefined +> jsArray[2]() +'why would anyone do this' +``` + +### Array Methods + +#### Array length + +Retrieve the length of an array with `Array.length`: + +```node +> array +[ 1, 2, 3, 4 ] +> array.length +4 +``` + +#### Appending and Prepending + +Use `push` to append an element to an array: + +```node +> array.push(5) +5 +> array +[ 1, 2, 3, 4, 5 ] +``` + +And `pop` to remove the last element (`pop` returns the last element): + +```node +> array.pop() +5 +> array +[ 1, 2, 3, 4 ] +``` + +Conversely, use `unshift` to prepend an element: + +```node +> array.unshift(0) +5 +> array +[ 0, 1, 2, 3, 4 ] +``` + +And `shift` to remove the first element (`shift` returns the first element): + +```node +> array.shift() +0 +> array +[ 1, 2, 3, 4 ] +``` + +#### Further Reading + +There are more built-in array methods, but we'll cover them later. JavaScript arrays generally act like Python arrays. + +Two good sources for documentation are [w3schools](http://www.w3schools.com/jsref/jsref_obj_array.asp) (easier to follow) and [Mozilla](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) (official and more complete). + +### Weird JavaScript Array Behavior + +Since JavaScript arrays are objects, they kind of act like them: + +```node +> jsArray +[ true, 'string', [Function] ] +> jsArray.question = 'Am I an object?' +'Am I an object?' +> jsArray +[ true, +'string', +[Function], +question: 'Am I an object?' ] +``` + +That string was actually stored as a property, not an element of the array: + +```node +> jsArray[3] +undefined +> jsArray.question +'Am I an object?' +``` + +Arrays are, in fact, objects, but they're special. When you index an array with a non-negative integer, it acts like an array. Indexing an object similarly just casts the integer to a string and adds it as a key. + +```node +> typeof(jsArray) +'object' +> jsArray instanceof Array // Array is a type of object +true +> typeof(obj) +'object' +> obj[4] = 6 +6 +> obj +{ '4': 6, +aBool: true, +aString: 'string', +aNum: 5.6, +aFunc: [Function], +anObj: { key: 'nesting' } } +``` + +So if you index an array with an invalid number, it won't throw an error. + +```node +> jsArray[-1] = -2 +-2 +> jsArray[3.141] = 'pi' +'pi' +> jsArray[6] = 5 +5 +> jsArray +[ true, +'string', +[Function], +, +, +, +5, +question: 'Am I an object?', +'-1': -2, +'3.141': 'pi' ] +``` + +The moral of the story is that JavaScript is remarkably robust, whether you like it or not. It will run happily where other languages would choke, so it often falls to you to write good code that will prevent weird things from happening. Leverage the flexibility of JavaScript to write elegant code — don't let it bite you. \ No newline at end of file diff --git a/classes/class02/homework.md b/classes/class02/homework.md new file mode 100644 index 00000000..a1372c3c --- /dev/null +++ b/classes/class02/homework.md @@ -0,0 +1,17 @@ +# Homework 2 + +## Reading + +Read the Node Beginner Book (in `Public/+Courses/Olinjs15/`) up to page 58 (the section marked **Handling file uploads** — the methods used there are old and no longer relevant). This resource ties together a lot of what we covered in class 1 by implementing a basic web server in Node. You'll learn how Node handles browser requests — and how Node is unique — while flexing your newly acquired JavaScript muscle. You should follow along by writing and running the code examples given. + +Read the [Airbnb Javascript Style Guide](https://github.com/airbnb/javascript). Try to incorporate these styles into your work in this class. + +## Optional Reading + +This is a fun, well-written article on how naming conventions affect the way we think and code: [Execution in the Kingdom of Nouns](http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html). + +## Turning in Homework + +### [Homework completion survey](https://docs.google.com/forms/d/1JiqQHBtdqHVmJcvL4wzNgztf7pxNHPX-Xp0nDK0FD6g/viewform?usp=send_form) + +When you've completed your homework, fill out the homework completion survey above. diff --git a/classes/class03/HW3 b/classes/class03/HW3 new file mode 160000 index 00000000..b4ba4530 --- /dev/null +++ b/classes/class03/HW3 @@ -0,0 +1 @@ +Subproject commit b4ba4530c1ded1f97775f94a906023f2d08150e4 diff --git a/classes/class3/README.md b/classes/class03/README.md similarity index 96% rename from classes/class3/README.md rename to classes/class03/README.md index cc209043..304c3ca9 100644 --- a/classes/class3/README.md +++ b/classes/class03/README.md @@ -76,7 +76,7 @@ The two routes we created are for the index page (`/`) and the olin page (`/olin So what does `app.get` do? It tells Express that every time that particular route (the first string argument) receives a `HTTP GET` request, we want to execute the anonymous function (the second argument). HTTP allows you to make different types of requests on a particular route, and these types are called **methods**. `GET` is just one of the methods you can perform, and is the most common (every time you request an image or a script for example). You can [view the other types of HTTP methods on wikipedia](http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods). But for now, let's only consider these two: * `GET` returns a resource (such as an image or an html page). This is used for when your browser wants to read information from a server. Parameters and options are communicated in the request header as part of the path (`/olin`) and query string parameters (`?pageid=12&button=2&coolsetting=super`) which you may recognize from various websites. -* `POST` is used when your browser wants to send information over to the server. For example, when you fill out an online form, that data is sent over to the server as `POST` data. This information is sent in the body of the request (not the header), and is therefor encrypted when communicating over an HTTPS connection. +* `POST` is used when your browser wants to send information over to the server. For example, when you fill out an online form, that data is sent over to the server as `POST` data. This information is sent in the body of the request (not the header), and is therefore encrypted when communicating over an HTTPS connection. ### Organizing an Express Application Express offers a tool called the `express-generator` to get a new directory up a running. This is also an example of a node module that provides a command line tool. To run node modules in your console you must install them globally using the `-g` flag and sudo permissions. Whenever you install a node module using sudo, ensure to add `-H` to prevent your cache from saving write protected files. @@ -121,7 +121,7 @@ module.exports.home = home; Then replace the contents of `app.js` with: ```javascript var express = require('express'); -var index = require('routes/index'); +var index = require('./routes/index'); var app = express(); app.get('/', index.home); @@ -134,7 +134,7 @@ Note that this time we `require` the new route file as the variable `index` then There are some initial configurations we want our app to have, such as running on a specific port, using routes, and setting up the public directory as well as some useful tricks to add to our `app.js` file. -First, were going to install 3 more modules that are used in pretty much every Express app: `npm install --save body-parser cookie-parser morgan`. +First, we're going to install 3 more modules that are used in pretty much every Express app: `npm install --save body-parser cookie-parser morgan`. Next we'll use them in `app.js` by doing the following: Add these lines to the top of the file, next to the rest of the requires: ```javascript @@ -321,10 +321,10 @@ admin (empty) local 0.078GB test 0.203125GB ``` -Mongo creates a database for us as soon as we start inserting items into it. It stores data in what's known as a `collection`. So in our case, users would be a collection. Items within a collection don't have to be consistant with each other (alice only has a name while bob has a name and a grade). +Mongo creates a database for us as soon as we start inserting items into it. It stores data in what's known as a `collection`. So in our case, users would be a collection. Items within a collection don't have to be consistent with each other (alice only has a name while bob has a name and a grade). We can also delete items: -```sh +``` > db.users.remove({'name': 'alice'}) > db.users.find() { "_id" : ObjectId("510078bee481634f390b1630"), "name" : "bob", "grade" : "A", @@ -367,6 +367,18 @@ bob.save(function (err) { } }); ``` + +The schema can also be used for querying: +```javascript +User.find({name: 'bob'}) + .sort({grade: -1}) + .exec(function(err, users) { + console.log(users); + }); +``` +Find all users with the name 'bob', sort them in descending order based on their grade, and then print them to the console. +Using the exec function allows you to chain multiple query elements (like `find` and `sort`) together before providing a callback. +This allows Mongoose to form one large Mongo query and be more performant than running additional queries in the callbacks of other queries. Check out the [getting started](http://mongoosejs.com/docs/index.html) guide on Mongoose to learn how to connect to your MongoDB database and the basics of saving and loading records. In the homework you will explore more about how to leverage MongoDB and Mongoose to store data persistently. diff --git a/classes/class3/app.js b/classes/class03/app.js similarity index 100% rename from classes/class3/app.js rename to classes/class03/app.js diff --git a/classes/class3/expressintro/app.js b/classes/class03/expressintro/app.js similarity index 100% rename from classes/class3/expressintro/app.js rename to classes/class03/expressintro/app.js diff --git a/classes/class3/expressintro/package.json b/classes/class03/expressintro/package.json similarity index 100% rename from classes/class3/expressintro/package.json rename to classes/class03/expressintro/package.json diff --git a/classes/class3/HW3/public/images/cat.jpg b/classes/class03/expressintro/public/images/cat.jpg similarity index 100% rename from classes/class3/HW3/public/images/cat.jpg rename to classes/class03/expressintro/public/images/cat.jpg diff --git a/classes/class3/expressintro/routes/index.js b/classes/class03/expressintro/routes/index.js similarity index 100% rename from classes/class3/expressintro/routes/index.js rename to classes/class03/expressintro/routes/index.js diff --git a/classes/class3/HW3/views/home.handlebars b/classes/class03/expressintro/views/home.handlebars similarity index 100% rename from classes/class3/HW3/views/home.handlebars rename to classes/class03/expressintro/views/home.handlebars diff --git a/classes/class3/expressintro/views/layouts/main.handlebars b/classes/class03/expressintro/views/layouts/main.handlebars similarity index 100% rename from classes/class3/expressintro/views/layouts/main.handlebars rename to classes/class03/expressintro/views/layouts/main.handlebars diff --git a/classes/class03/homework-solution/Procfile b/classes/class03/homework-solution/Procfile new file mode 100644 index 00000000..e1d4131b --- /dev/null +++ b/classes/class03/homework-solution/Procfile @@ -0,0 +1 @@ +web: node app.js diff --git a/classes/class03/homework-solution/app.js b/classes/class03/homework-solution/app.js new file mode 100644 index 00000000..29aca648 --- /dev/null +++ b/classes/class03/homework-solution/app.js @@ -0,0 +1,36 @@ +var express = require("express"); +var path = require("path"); +var logger = require("morgan"); +var cookieParser = require("cookie-parser"); +var bodyParser = require("body-parser"); +var exphbs = require("express-handlebars"); +var mongoose = require("mongoose"); + +var index = require("./routes/index"); +var cats = require("./routes/cats"); + +var app = express(); + +var PORT = process.env.PORT || 3000; +var mongoURI = process.env.MONGOURI || "mongodb://localhost/test"; + +app.engine("handlebars", exphbs({defaultLayout: "main"})); +app.set("view engine", "handlebars"); + +app.use(logger("dev")); +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({extended: false})); +app.use(cookieParser()); +app.use(express.static(path.join(__dirname, "public"))); + +app.get("/", index.home); +app.get("/cats", cats.list); +app.get("/cats/new", cats.new); +app.get("/cats/bycolor/:color", cats.list); +app.get("/cats/delete/old", cats.delete); + +mongoose.connect(mongoURI); + +app.listen(PORT, function() { + console.log("Application running on port:", PORT); +}); diff --git a/classes/class03/homework-solution/models/catModel.js b/classes/class03/homework-solution/models/catModel.js new file mode 100644 index 00000000..9cbbd735 --- /dev/null +++ b/classes/class03/homework-solution/models/catModel.js @@ -0,0 +1,9 @@ +var mongoose = require("mongoose"); + +var catSchema = mongoose.Schema({ + name: String, + colors: [String], + age: Number +}); + +module.exports = mongoose.model("Cat", catSchema); diff --git a/classes/class03/homework-solution/package.json b/classes/class03/homework-solution/package.json new file mode 100644 index 00000000..e4a1f2aa --- /dev/null +++ b/classes/class03/homework-solution/package.json @@ -0,0 +1,23 @@ +{ + "name": "CatDB", + "version": "1.0.0", + "description": "Olin.js class3 homwork solution.", + "main": "app.js", + "dependencies": { + "body-parser": "^1.10.1", + "cookie-parser": "^1.3.3", + "express": "^4.10.6", + "express-handlebars": "^1.1.0", + "mongoose": "^3.8.22", + "morgan": "^1.5.1" + }, + "engines": { + "node": "0.10.x" + }, + "devDependencies": {}, + "scripts": { + "start": "node app.js" + }, + "author": "", + "license": "ISC" +} diff --git a/classes/class3/expressintro/public/images/cat.jpg b/classes/class03/homework-solution/public/images/cat.jpg similarity index 100% rename from classes/class3/expressintro/public/images/cat.jpg rename to classes/class03/homework-solution/public/images/cat.jpg diff --git a/classes/class03/homework-solution/routes/catData.js b/classes/class03/homework-solution/routes/catData.js new file mode 100644 index 00000000..9ada761a --- /dev/null +++ b/classes/class03/homework-solution/routes/catData.js @@ -0,0 +1,112 @@ +var data = { + "colors": + [ + "Ivory", + "Wheat", + "Beige", + "Tan", + "Khaki", + "Silver", + "Grey", + "Charcoal", + "Blue", + "Cyan", + "Aquamarine", + "Teal", + "Forest Green", + "Olive", + "Chartreuse", + "Lime", + "Goldenrod", + "Coral", + "Salmon", + "Lavender", + "Indigo", + "Maroon", + "Crimson" + ], + "names": + [ + "Sassy", + "Misty", + "Missy", + "Princess", + "Samatha", + "Kitty", + "Puss", + "Fluffy", + "Molly", + "Daisy", + "Ginger", + "Midnight", + "Precious", + "Maggie", + "Lucy", + "Cleo", + "Whiskers", + "Chloe", + "Sophie", + "Lily", + "Coco", + "Boo", + "Callie", + "Sadie", + "Jessie", + "Jasmine", + "Nala", + "Snowball", + "Angel", + "Muffin", + "Pumpkin", + "Pepper", + "Baby", + "Zoe", + "Peaches", + "Holly", + "Dusty", + "Katie", + "Sasha", + "Scooter", + "Max", + "Sam", + "Tigger", + "Tiger", + "Sooty", + "Smokey", + "Lucky", + "Patch", + "Simba", + "Smudge", + "Oreo", + "Milo", + "Oscar", + "Oliver", + "Buddy", + "Boots", + "Harley", + "Gizmo", + "Charlie", + "Toby", + "Jake", + "Sebastian", + "Puffy", + "Bailey", + "Buster", + "Tom", + "Rocky", + "Jack", + "Felix", + "Spike", + "Simon", + "Taz", + "Rusty", + "Merlin", + "Monty", + "Dusty", + "Casper", + "Mittens", + "Pepper", + "Blackie" + ] +} +module.exports = data; diff --git a/classes/class03/homework-solution/routes/cats.js b/classes/class03/homework-solution/routes/cats.js new file mode 100644 index 00000000..ae8b5431 --- /dev/null +++ b/classes/class03/homework-solution/routes/cats.js @@ -0,0 +1,83 @@ +var path = require("path"); +var catData = require("./catData"); +var Cat = require(path.join(__dirname,"../models/catModel")); + + +var colors = catData.colors; +var numColors = colors.length; +var names = catData.names; +var numNames = names.length; + +var cats = {}; + +cats.new = function(req, res) { + var catColors = []; + for (var i = Math.floor(Math.random()*3)+1; i > 0; i--) { + catColors.push(colors[Math.floor(Math.random()*numColors)].toLowerCase()); + } + catColors = catColors.filter(function(val, ind, arr) { return arr.indexOf(val) === ind;}) + var name = names[Math.floor(Math.random()*numNames)]; + var age = Math.floor(Math.random()*numNames); + var catObj = { + name: name, + age: age, + colors: catColors + }; + var newCat = new Cat(catObj); + newCat.save(function(err) { + if (err) { + res.status(500).send('Something broke!'); + } else { + res.render("cats", { + message: "New cat created:", + cats: [catObj] + }); + } + }); +}; + +cats.list = function(req, res) { + var colorFilter; + var message; + if (req.params.color) { + colorFilter = req.params.color.toLowerCase(); + message = "Cats by age with color " + req.params.color+ ":"; + } else { + colorFilter = /^.*/; + message = "Cats by age:"; + } + Cat.find({colors: colorFilter}) + .sort({age: -1}) + .exec(function(err, cats) { + if (err) { + res.status(500).send("Something broke!"); + } else { + res.render("cats", { + message: message, + cats: cats + }) + } + }) +}; + +cats.delete = function(req, res) { + Cat.findOneAndRemove({}, {sort: {age: -1}}, function(err, cat) { + if (err) { + res.status(500).send("Something broke!"); + } else { + var cats = [cat]; + var message = "A cat disappeared into the night:"; + if (!cat) { + cats = null; + message = "No cats left!"; + } + var cats = cat ? [cat] : null; + res.render("cats", { + message: message, + cats: cats + }) + } + }) +}; + +module.exports = cats; diff --git a/classes/class03/homework-solution/routes/index.js b/classes/class03/homework-solution/routes/index.js new file mode 100644 index 00000000..4d1819b2 --- /dev/null +++ b/classes/class03/homework-solution/routes/index.js @@ -0,0 +1,11 @@ +module.exports.home = function(req, res){ + res.render("home", {"links": [ + "/cats/new", + "/cats", + "/cats/delete/old", + "/cats/bycolor/blue", + "/cats/bycolor/green", + "/cats/bycolor/orange" + ] + }); +}; diff --git a/classes/class03/homework-solution/views/cats.handlebars b/classes/class03/homework-solution/views/cats.handlebars new file mode 100644 index 00000000..216fc446 --- /dev/null +++ b/classes/class03/homework-solution/views/cats.handlebars @@ -0,0 +1,11 @@ +
+
+Some key trends to note include the rise of Chrome as well as the fall of IE and Firefox.
+Also worth noting is the rapid growth of mobile browsing (pink).
+We won't address [mobile web design](http://www.smashingmagazine.com/guidelines-for-mobile-web-development/) in this class,
+but it is definitely something to consider before launching a new site.
+
+Ok, back to the console.
+On any webpage, right-click, and select `Inspect Element`. You'll see something like this pop up in the bottom of the window:
+
+The dev console contains a ton of features (seriously, there are more features than I've even heard of).
+We'll start with the basic tabs that you use most often:
+* Elements: This is a collapsable and editable view of the HTML on the current page.
+You can double-click to edit fields or [DOM](http://en.wikipedia.org/wiki/Document_Object_Model) nodes.
+On the right side is a panel showing the CSS styling applied to the element you are highlighting. Again, double-click to edit.
+A useful shortcut here is the magnifying glass in the top-left corner of the console.
+Click that and then click in the browser somewhere to jump to the HTML of that element.
+* Network: While you're in this tab, refresh the browser.
+The tab will list all the requests that the web page makes, including the size, timing, and specific response.
+This can be useful for debugging your server's responses or other API's.
+* Sources: The holy grail of JavaScript debugging tools. Set breakpoints, step through code,
+all the fun stuff that an IDE would give you. We'll get back to this when we go over debugging in more depth.
+* Console: A full JavaScript console that operates in the current scope of the Javascript on the page (including inside breakpoints).
+Run commands, and read through your client-side `console.logs` in this window.
+As a bonus, if you click the "console icon"  in the upper-right corner,
+the console will pop up below whatever other tab you want to reference.
+
+## HTML Reprise
+We've seen some HTML before but let's go through a more formal overview of it.
+[HTML](http://en.wikipedia.org/wiki/HTML) is a markup language that uses tagged elements
+to describe the structure of a webpage.
+Elements are specified with start and end tags which enclose their content,
+including children elements (`Hi again