Optimized PBL Curriculum
Welcome to the NodeJS course my the NYCDA. This document details the lessons you will be following over this 12 week program.
We are excited to offer you this course in a Problem Based Learning format. This will enhance both your learning experience and your eventual value as a developer in the professional realm.
It is of vital importance that you understand the Problem Based Learning format. It is therefore highly recommended that you read and revisit the introductory sections of this document regularly.
For questions:
About Class: contact Mentor (@mentor on Slack)
About Administration and the NYCDA: Manouk (@manoukmeilof on Slack)
About Grades & homework: (@paulvanmotman on Slack)
This course is called Web Development Intensive.
Dedication and hard work will be needed from everyone involved. This course will be fun, but do not forget that we are basically opening up en entire carreer path in a couple of weeks!
Be sure to do the pre-work you have been assigned. This course assumes you are familiar with:
- Basic HTML
- Basic CSS
- Basic terminal commands
- Basic website structure
This section details the logistical info you need to optimally use your time with us.
Together we will help you grow in three areas:
1. Coding skills in the backend, frontend and devops
Specifically: NodeJS, Postgres, HTML5/CSS3, Sass, Javascript, jQuery, GitHub
2. Self-sufficiency & rapid learning for programmers
Programming languages go in/out of fashion. You will learn to pick up new languages and frameworks quickly so you stay relevant on the job market.
3. Enthusiasm and a love for programming
Programming is basically a superpower that lets you create real world-changing things by writing down things you imagined in your head in a magical language.
Our days will follow a structure that facilitates your learning experience. Our days together will typically take the folowing structure:
Time | Activity |
---|---|
09:30 | Get settled, have coffee, play pacman |
10:00 | PBL post-discussion ( on yesterday's pre-discussion topic ) |
11:00 | Opportunity to modify homework |
12:00 | PBL pre-discussion ( on tomorrow's post-discussion topic ) |
13:00 | Lunchtime |
14:00 | Lecture/demo time! |
~~~~ | After lecture: Time to work on your post-discussion prep and exercises |
18:00 | Class ends, homework time. You are welcome to stick around! |
Please note that the pre- and post- discussions depend on your active engagement. Being prepared is a sign of respect towards your fellow students and will help you turn into a code-ninja-octocat (costume optional).
Towards the later weeks there will be less lectures and more project centered days.
Problem Based Learning is a learning structure that stimulates critical thinking and contextual learning. It requires more work on the student's and teacher's part, but results in far more consistent and in-depth skills.
The short version: it will make you very competent very fast
Click the image below for a little video about Problem/Project Based Learning
If you are used to the traditional system PBL might take some getting used to. It will however pay off in every aspect of your learning experience.
System | Learning | Study | Examination |
---|---|---|---|
Traditional | Told what you need to know | Memorize knowledge | Reproduce knowledge on exam |
PBL | Problem assigned | Identity what needs to be learned and learn it | Apply the solution of the problem |
Programming and development is a very creative skill. There are always multiple solutions to a problem, and even more styles in which to implement these solutions.
By using PBL you will not only develop programming skills, but also problem solving skills that will:
- Make you a better programmer
- Make you more valuable on the job market
- Make programming infinitely more fun
In other words:
Programming + PBL = 💰 🎉
System | Lecture approach | Study | Examination |
---|---|---|---|
Traditional | One size fits all | 'The answers are in the back' | Test knowledge |
PBL | Personalized & interactive | Show you how to approach problems | Allow you to show off your skill |
In the PBL system you collaborate closely with your teacher. Your PBL experience will be enriched with:
- Effective lectures
- Learning resources
- One on one help
While your learning experience is highly individual at no point will you be alone!
In PBL every topic is separated into three phases:
- Pre-discussion
- Research & development
- Post-discussion
Every phase in turn is separated into segments.
Session roles:
- Discussion leader - keeps the conversation professional & relevant
- Note taker - takes notes on a public whiteboard that everyone can see
- Participant - contributes to the discussion to the best of their ability
Session text components:
- Text
- Recommended reading
- Exercises
Session script:
1. Read the session text
2. Define a problem statement
3. Brainstorm about anything and everything related to the problem statement
4. Define learning goals from the discussion
Note that these are distinct phases. That means no Learning Goals are defined during the brain storm for example.
After the pre-discussion you will get a lecture that covers the topic you discussed beforehand. This lecture will give you the basic tools you need to tackle your learning goals and exercises.
All learning goals are unique, the lectures will rarely cover 100% of them!
After your lecture you have the rest of the afternoon to do additional research (for example through the recommended readings), and to use that research to complete your exercises.
The exercises are your homework for the next day after lunch
The post discussion brings you all together to discuss what you discovered in the Research & Development phase.
Session roles:
- Discussion leader - keeps the conversation professional & relevant
- Note taker - takes notes on a public whiteboard that everyone can see
- Participant - contributes to the discussion to the best of their ability
Session preparation:
- Find your answer to the learning goals
- Solve the exercises in your favorite way
Note: there is no single 'right' answer to the learning goals and the exercises. Most likely you will all come up with your own unique approaches.
Session script:
1. Share exceptional things and trouble you ran into
2. Go through the learning goals and your respective answers
3. Go through the exercises and your respective solutions
Taking notes of the pre- and post-discussions is extremely helpful. Not only will it help your learing process, but it will result your own unique summary of the entire course!
We highly recommend:
- Keeping your notes in a service like Evernote
- Making pictures of the pre- and post-discussion notes on the whiteboard
This is not final and will be subject to your teacher. It is however a general overview of what to expect.
The schedule is 5 days a week times 12 weeks is 60 days long.
Day | PBL Topic | Exercise | Non PBL Topic/Lecture |
---|---|---|---|
1 | Values, types and Operators | FizzBuzz | Breaking down problems |
2 | Functions and objects | Book library | |
3 | Scope & anonymous functions | Math Anonymous functions | Git & Github basics |
4 | Prototypes | Prototype practice | |
5 | jQuery | Project personal website | |
6 | As needed | Project personal website | HTML/CSS Refresher Livecode |
7 | As needed | "" | |
8 | Source control | Project Business website | Git branching |
9-10 | As needed | Project business website | |
11 | NodeJS | Play around | npm |
12 | Node modules | Coutry information app | |
13-14 | As needed | "" | |
15 | Retrospective | As needed | Technology stack overview |
16 | cURL | Business website on NodeJS server | Routers |
17 | Pug | User information app | Client side vs server side JS |
18-20 | As needed | "" | |
21 | AJAX | AJAX User information app | |
22-25 | As needed | "" | |
26 | SQL | Live during lecture | |
27 | Postgres | Bulletin board | |
28 | Promises & sequelize | ORM Lite + Bulletin board | |
29-30 | As needed | Bulletin board | |
31 | Cookies & sessions | Blog application | |
32-36 | As needed | "" | RESTful routing, Express generator, MVC |
37 | BCrypt | Extend application with BCrypt | |
38 | Relational databases | Database model diagram | |
39 | Frontend frameworks | Use bootstrap or other framework | |
40 | Project specification & teamwork | Group project | |
41 | Data validation | "" | |
42 | SASS | "" | |
43-45 | As needed | "" | |
46 | Testing | "" | |
47-50 | As needed | "" | Presenting |
51-60 | As needed | Final project | JS Morning exercises, optionals |
The last weeks allow for a lot of extra materials. The group will be asked for what they would like to cover.
- Recommended: Sendgrid, Domains, Hosting, PM2, Deployment
- Based on interest: Socket, Passport, React, Angular, Gulp, ES6
The exact dates for these topics will be communicated to you durng the course.
Guiding questions
- What do you recognize?
- What is a mystery to you? What could it mean?
- What do you need to know to understand this?
/*
This is a piece of code
It may seem like magic
Or maybe not
*/
var apple = 5 * 5
var success = 'Hashtag Winning'
var winner = ['Charlie', 'Sheen']
if( apple > 20 ) {
console.log( success )
} else if ( apple < 20 ) {
console.log( winner[1] )
} else {
console.log( 'Nespresso' )
}
while ( apple < 100 ) {
console.log( 'Not enough apples' )
apple ++
}
for ( var i = 0; i < 10; i++ ) {
console.log( 'the i is now ' + i )
}
if ( ( 5 < 10 ) || ( ( 10 == 10 ) && ( true ) ) ) {
console.log( 'True or false, that is the question' )
}
console.log( 9 % 3 ) // 0
console.log( 9 % 4 ) // 1
console.log( 8 % 4 ) // 0
console.log( 8 % 3 ) // 2
Recommended readings
- http://eloquentjavascript.net/ chapter "Values, Types, and Operators"
- http://eloquentjavascript.net/ chapter "Program Structure"
- http://www.w3schools.com/js/js_variables.asp
- http://www.w3schools.com/js/js_arrays.asp
- http://www.w3schools.com/js/js_operators.asp
- https://www.codecademy.com/learn/javascript
Exercises
FizzBuzz:
- "Write a program that prints the numbers from 1 to 100. But for multiples of 3 print Fizz instead of the number and for the multiples of 5 print Buzz. For numbers which are multiples of both 3 and 5 print FizzBuzz."
Grading Criteria
Build a working function with no errors 5 Points
The code implementation uses modulo in its logic 4 Points
Code is well commentented where necessary and contains a ReadMe 1 Points
Total: 10 Points
function kawaii ( ) {
console.log( 'Potato' )
}
function senpai( ) {
console.log( 'Notice me' )
}
function jarvis( speech ) {
console.log( speech )
}
function millions( money ) {
return money * 1000000
}
function skip_rope( times ) {
var counter = 0
while ( counter < times + 1 ) {
console.log( 'I jumped the rope ' + counter + ' times' )
counter ++
}
}
function over9000( amount ) {
if ( amount > 9000 ) {
console.log( 'yes' )
} else {
console.log( 'no' )
}
}
kawaii()
senpai()
kawaii()
senpai()
jarvis( 'Hello Sah' )
jarvis( 'Suit is ready' )
millions( 2 )
console.log( millions( 50 ) )
skip_rope( 100 )
skip_rope( 20 )
over9000( 50 )
over9000( 50000 )
var boolean = true
var number = 5
var string = 'Hello'
var array = [0, 1, 'yes', 6, 'potato']
var person = {
name: 'Tony',
outfit: 'Iron Suit',
affiliations: {
work: 'Stark Industries',
friends: 'Avengers'
},
money: undefined
}
console.log( person.name )
console.log( person.affiliations.work )
console.log( person.money )
person.money = 2 * 1000 * 1000 * 1000
console.log( person.money )
var object = {
property1: 'value1',
property2: 'value2',
property3: 'value3',
}
for( var objectKey in object ) {
console.log( "the property key is: " + objectKey )
console.log( "the value of that property is: " + object[objectKey] )
}
Recommended readings
- http://eloquentjavascript.net/ chapter "Functions"
- http://eloquentjavascript.net/ chapter "Objects and Arrays"
- http://www.w3schools.com/js/js_functions.asp until "Self-Invoking Functions"
- http://www.w3schools.com/js/js_objects.asp
Exercises
Book library
Create an object that represents a book:
Part 1 Give it a title property with a value that is the title of your book. Give it a body� property which has an array of strings as the value. There should be at least three strings within the array. This array represents the pages of text within your book.
Part 2 Create another object with the same format, but different title and different body.
Part 3 Now, create a function that reads the book by first printing out the title, then printing out each element (page) in the body. For a book with title "Infinite Jest" and pages "Written by David Foster Wallace", "Hal Incandenza is the youngest of the Incandenza children.", and "As a child, he was very precocious.", the output should read as follows:
Title: Infinite Jest Page 1: Written by David Foster Wallace Page 2: Hal Incandenza is the youngest of the Incandenza children. Page 3: As a child, he was very precocious.
var theword = 'Bird'
function what( word ) {
var theword = word
var butter = 'Amazing'
console.log( word )
console.log( butter )
}
console.log( theword )
console.log( butter )
what( 'Duck' )
function TwinOne( ) {
console.log( 'I am a twin' )
}
var TwinTwo = function( ) {
console.log( 'I am a twin' )
}
function butler( activity ) {
console.log( 'I will now fulfil your request' )
activity()
}
function professor ( a, b, operation ) {
console.log( operation( a, b ) )
}
var addNumbers = function ( one, two ) {
return one + two
}
butler( TwinTwo )
butler( function(){
console.log( 'Making you a cake' )
} )
professor( 2, 4, addNumbers )
professor( 5, 2, function( thing, thing2 ) {
return thing * thing2
} )
Recommended readings
- http://www.w3schools.com/js/js_function_definition.asp
- https://en.wikibooks.org/wiki/JavaScript/Anonymous_functions
- http://stackoverflow.com/questions/1634268/explain-javascripts-encapsulated-anonymous-function-syntax
- http://stackoverflow.com/questions/5752030/passing-a-function-as-an-argument-in-a-javascript-function
Exercise
Math functions
Part 1
- Create a function "findSum" that takes in two parameters and returns the sum of those parameters.
- Create a function "findProduct" that takes in two parameters and returns the product of those parameters.
Part 2
- Create a function "threeOperation" that takes in two parameters, named "x" and "operation". The first parameter is a number. The second parameter is a function.
- "threeOperation" should call the "operation" parameter as a function. It should pass the number 3 along with the "x" parameter to that function.
Part 3
- Call "threeOperation" with the values of "4" and "findSum". Check that your answer is "7".
- Call "threeOperation" with the values of "5" and "findSum". Check that your answer is "8".
- Call "threeOperation" with the values of "4" and "findProduct". Check that your answer is "12".
- Call "threeOperation" with the values of "5" and "findProduct". Check that your answer is "15".
function monster( name, type ) {
this.name = name
this.type = type
this.greet = function( ) {
console.log( "Hello, my name is " + this.name + " and I am a " + this.type )
}
}
var noodle = new monster( 'Flying Spaghetti Monster', 'Deity' )
var undead = new monster ( 'Jimmy', 'Zombie' )
console.log( 'The monsters in the house are: ' + noodle.name + " and " + undead.name )
noodle.greet()
undead.greet()
noodle.name = 'Anonymous'
noodle.greet()
monster.prototype.real = false
console.log( noodle.real )
console.log( undead.real )
Recommended readings
- http://www.w3schools.com/js/js_object_prototypes.asp
- http://stackoverflow.com/questions/572897/how-does-javascript-prototype-work
- http://javascriptissexy.com/javascript-prototype-in-plain-detailed-language/
Exercises
Prototype Practice
Create a new class called EmailList. The constructor function should take in one parameter, "name", and return an instance which contains the following:
- name, the name of the email list
- list, an array of all the emails in that list. Note that initially, the array will be empty.
Add a function to the EmailList's prototype. This function should be called "addEmail", and it should take one parameter, the email address, and add it to the "list" array of the instance.
Add another function to the prototype, called "sendEmailToAll". This function should take in one parameter: the text of the email, and then "send an email to each address". Since that lecture will be sometime in week 6, for now, simply print out the following:
"Email content:" <list the text of the email to be sent> "Sending email to:" <list all email addresses>
Additionally:
For the following questions, make sure to include at least two tests for each function. For now, that means calling your function with some values and printing out the answer. If you want to make Lloyd's life easier, print out the expected value as well.
Write a function that returns the area of a circle, given the radius. Hints: The area of a circle is "pi r 2". For pi, use Math.PI.
Given a string, create a function that returns the last character in that string. example: "cattywampus" --> "s"
Write a function that takes in one parameter "length" and prints out that many stars. example: 3 --> *** 5 --> *****
Now, write a function that takes in one parameter "length" and prints out a square of stars. examples:
3 --> *** *** ***
Given an array of integers, write a function that finds the average and returns it.
examples: [1,2,3] --> 2 [1,2,4] --> 2.3333
OPTIONAL CHALLENGE
Write a function that takes in two arrays of integers and returns the largest common integer. If there are no common integers, return 'undefined'.
example: [5, 10, 2], [3, 5, 7] returns 5 [8, 7, 6], [1, 2, 8, 200] returns 8
<!DOCTYPE html>
<html>
<head>
<title>CIA Website</title>
</head>
<body>
<p id="message">You are not supposed to be here</p>
<script src="http://code.jquery.com/jquery-3.1.0.min.js"></script>
<script>
$( document ).ready( function( ) {
$( '#message' ).html( 'You are very welcome' )
} )
</script>
<style>
p { color: red; }
#message { color: #ffffff; }
</style>
</body>
</html>
Recommended readings
- http://www.w3schools.com/html/default.asp (revisit HTML in general)
- http://www.w3schools.com/css/ (revisit css in general)
- https://jquery.com/
Project personal website
Personal Website
A personal site serves a similar, but distinct, role to your resume. Its primary purpose is to display your portfolio.
Website requirements
- a way to contact you
- a description of who you are
- a presentation your projects. Select only the work which has a high degree of polish, and secondarily showcases your most complex technical achievements
- guidelines for showcasing a project. Have the following:
- a screenshot(s) of the best part of the site
- description of the project / technologies used
- a link to the site
- a link to the source code
Process requirements
- use github
- commit often and with descriptive messages
Structure requirements
- position your html files in the root directory
- position css and js files in a folder called 'includes'
- comply with W3C code standards
- no not use external CDN resources, host everything yourself
Recommendations & challenges
- find a way to use the same head and footer sections without having duplicate code
- use a framework like Bootstrap or Materialize
- optimize your website for fast delivery
- consider page and resource size
- consider minification
- use Google page speed insights and gtmterix
Peripheral resources
- find out what is needed to have your website live on the internet
- consider domains
- consider servers and their software
- consider the specific needs for your website
- find out how to deal with deployment and changes in your website
Design guidelines and inspiration
- this page is one of your faces online, make it look good
- consider the needs and preferences of your target audience
My worst no-source-control horror was with a reasonably large PHP app. This thing was a monolithic beast - an API engine with maybe 15 files, all of which had line numbers that extended into the high tens of thousands. The level of commenting was anaemic at best, too. We'd discussed splitting it out into a more modular system, using OO to cut back on a lot of the duplication, but management (as always) didn't see the benefit of spending a month on the task.
We only had a few devs, and each had a copy of the whole project on their disk. Every time a change was to be pushed, we downloaded a copy of the lead dev's source (his live development code) and used diff to identify the changes, then updated them manually. Line by line. All by hand. The merged source was put it on his shared drive, along with our colleagues' copies. Before each test release, he'd go through all of the uploaded copies and merge them into a master branch. Usually it'd take a few iterations of diff-and-edit before we got a solid copy.
Of course, once we started hiring more devs, this process got more interesting. We had sub-teams, where each team leader had to merge to a team branch, which would then be merged with the master branch by the team leader. Line by line. All by hand. Ad infinitum.
Source: https://www.troyhunt.com/life-without-source-control-share-your/
Recommended readings
- https://www.youtube.com/watch?v=0fKg7e37bQE
- https://try.github.io ( dynamic tutorial )
Homework
Project Business Website
Work in groups of two or three. Note: each person will receive a separate grade based on their contributions on Github. Choose a business, then build a website for that business. The business can be real or imagined.
Design requirements: Prior to coding, spend time sketching out the site's layout. Scan in and submit your sketch as part of your submission. The primary importance of this is for future employers to see your thought process when designing the site.
Site requirements:
- A minimum of four separate pages
- Use photographs
- Using JavaScript and jQuery, add at least two interactive elements to the site. Options include, but are not limited to:
- animated drop down navigation bars
- a photo gallery that, on click, displays large versions of the photos
Git requirements:
- When creating each page, create a separate branch on git. Add your commits to that branch. Then, when the page is complete, issue a pull request. Your other team member(s) must review and then merge that branch into master. Branch names should be named after features. Do not push directly to master, aside from your initial commit.
Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.
npm init
npm install express --save
//require the `fs` library
var fs = require('fs');
//call `fs.readFile`
//`utf-8` is an encoding to ensure we get text
// This is a big movie
// THIS FILE FINISHES LOADING THIRD
fs.readFile('./hdmovie.mkv', 'utf-8', function(err, data){
//check for possible errors - more on this later
if (err) {
//log that an error happened
console.log(`an error occurred: ${err}`);
//throw the error for handling by the caller
throw err;
}
//otherwise, print the contents of the file
console.log(data);
});
// Small text file
// THIS FILE FINISHES LOADING FIRST
fs.readFile('./helloworld.txt', 'utf-8', function(err, data){
//check for possible errors - more on this later
if (err) {
//log that an error happened
console.log(`an error occurred: ${err}`);
//throw the error for handling by the caller
throw err;
}
//otherwise, print the contents of the file
console.log(data);
});
// Embarrass picture
// THIS FILE FINISHES LOADING SECOND
fs.readFile('./embarrassing.jpg', 'utf-8', function(err, data){
//check for possible errors - more on this later
if (err) {
//log that an error happened
console.log(`an error occurred: ${err}`);
//throw the error for handling by the caller
throw err;
}
//otherwise, print the contents of the file
console.log(data);
});
Recommended readings
- https://en.wikipedia.org/wiki/Node.js
- https://nodejs.org/en/foundation/
- https://nodejs.org/api/fs.html
Filestructure:
--node-modules (folder)
.gitignore
app.js
sayhello.js
npm init
npm install express --save
app.js:
var express = require( 'express' )
var sayhello = require( './sayhello' )
sayhello( process.argv[2] ) // Hello, I am Peter
sayhello.js:
var greeter = function ( name ) {
console.log( 'Hello, I am ' + name )
}
module.exports = greeter
Start commend for app:
node app.js Peter
Recommended readings
- https://nodejs.org/api/modules.html
- https://www.sitepoint.com/understanding-module-exports-exports-node-js/
Exercise
Country Information App
Part 1 Create a Node.js application that does the following:
- Takes in one parameter from the command line, the name of a country. Note: command line arguments can be read from the global array
process.argv
- Reads and parses the
countries.json
file. Note: you must use readFile and not readFileSync.- Outputs information about that specific country. Must be in the following format:
Country: Netherlands Top Level Domain: .nl
Part 2
- For the purposes of this exercise, you must create a separate module for reading and parsing the JSON file, named "json-file-reader".
- This module should have a function that takes in a filename and a callback function as a parameter. It should then read that file, then parse the JSON. Finally, it should call the callback function and pass the parsed JSON to it.
- One way to think of this module is as a helper that can read and parse any JSON file. It has nothing to do with 'countries', so to speak.
- Another way to think of it is as a small wrapper to fs.readFile, except that this function only works with JSON files.
Hints:
- Use JSON.parse (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse (Links to an external site.)) to parse JSON data from files into a JavaScript object.
- Try first completing the assignment without creating a separate module - Extracting the second module out is significantly more difficult.
// GET request
curl -v example.com// POST request
curl -v --data "param1=value1¶m2=value2" example.com/resource.cgi
// GET request with headers
curl -v example.com --header "Content-Type:application/json"
// Specify http command with -X
# the following two are the same: curl example.com curl -X GET example.com
Exercise
Important Notes
- Remember to add "node_modules" to your .gitignore file. Otherwise, a lot of other people's code is going to end up in your repository.
- If you did not originally create the repo, you must "fork" it on github, which will make a copy and put it on your github.
- express.static() looks for 'index.html' by default, so rename your home page to that. Alternatively, serve a different default file using the following syntax:
app.use(express.static('myStaticPath', { index: 'myNonDefaultHomepage.html' }));Instructions
- Take the website that you built previously, and create a new branch on git so the old version is still available for grading / reviewing.
- Put your website on a Node.js server, so that it can be reached at http://localhost:3000.
- Your Node.js server does not need any routes, since the entire website is static content.
- Check each of your links and images to ensure that they still work.
- Express by default looks for
index.html
for the first page.
<html>
<head></head>
<body>
<p>This might seem more complicated initially, but it will</p>
<br>
<p>save you time when you're developing larger projects.</p>
</body>
</html>
html
head
body
p This might seem more complicated initially, but it will
br
p save you time when you're developing larger projects.
br
p #{welcomemessage}
Recommended readings
Exercise
User Information App - Web Server
Create a Node.js application that is the beginning of a user management system. Your users are all saved in a "users.json" file, and you can currently do the following:
- search for users
- add new new users to your users file.
Part 0 Create one route:
- route 1: renders a page that displays all your users.
Part 1 Create two more routes:
- route 2: renders a page that displays a form which is your search bar.
- route 3: takes in the post request from your form, then displays matching users on a new page. Users should be matched based on whether either their first or last name contains the input string.
Part 2 Create two more routes:
- route 4: renders a page with three forms on it (first name, last name, and email) that allows you to add new users to the users.json file.
- route 5: takes in the post request from the 'create user' form, then adds the user to the users.json file. Once that is complete, redirects to the route that displays all your users (from part 0).
var menuId = $( "ul.nav" ).first().attr( "id" );
var request = $.ajax({
url: "script.php",
method: "POST",
data: { id : menuId },
dataType: "html"
});
request.done(function( msg ) {
$( "#log" ).html( msg );
});
request.fail(function( jqXHR, textStatus ) {
alert( "Request failed: " + textStatus );
});
$("button").click(function(){
$.get("demo_test.asp", function(data, status){
alert("Data: " + data + "\nStatus: " + status);
});
});
$("button").click(function(){
$.post("demo_test_post.asp",
{
name: "Donald Duck",
city: "Duckburg"
},
function(data, status){
alert("Data: " + data + "\nStatus: " + status);
});
});
Recommended readings
- https://api.jquery.com/category/ajax/
- https://api.jquery.com/jQuery.ajax/
- https://api.jquery.com/jQuery.get/
- https://api.jquery.com/jQuery.post/
- http://www.w3schools.com/jquery/jquery_ajax_get_post.asp
Exercise
User Information App - AJAX Server
Starting with your previous website, create a new branch to preserve the old site. Your site has a form on it that acts like a search bar. On click, it should retrieve a list of matching users and list them by name on the same page, similar to how the search bars on airbnb.com or hipmunk.com function.
Hints:
- use https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf
- you cannot send or render a response more than once per request.
- you must find a way to capture whenever the user's input changes in the search bar. This will trigger your Ajax request to your server.
Part 0: If you're having trouble finding matching users, solve this puzzle first:
// given an array of values, write a function that finds the index of where the value is located, and if nothing is found, returns -1. // example: for ['apple', 'orange', 'pineapple'] // 'orange' returns '1' // 'durian' returns '-1' // now, write a function that finds all the indexes of where the value is located and returns them in an array, and if nothing is found, returns -1 // example: ['apple', 'orange', 'orange', 'pineapple'] // 'orange' returns [1,2]Part 1: Autocomplete Modify your form so that every time the user enters a key, it makes an AJAX call that populates the search results. Do this work in a git branch called "autocomplete". Then, merge this branch into master with a pull request.
Part 2: Bandwidth optimization Modify your form again so that AJAX requests happen at most once every 300 milliseconds. Do this work in a git branch called "bandwidth-optimization". Then, merge this branch into master with a pull request.
Hints:
- use https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now
- test it by opening the Network tab in Chrome's Developer Tools by checking that fewer requests are going off.
drop table hats;
create table hats (
id serial primary key,
name text,
material text,
height integer,
brim boolean
);
insert into hats values ('sun hat', 'straw', 7, true);
insert into hats (name, material, height, brim) values
('top hat', 'buckram', 12, true);
insert into hats (name, material, height, brim) values
('cloche', 'felt', 6, false),
('chicken', 'bwuk bwuk bwuk', 12, false);
select * from hats;
select material from hats where name = 'top hat';
select count(*) from hats;
delete from hats where name = 'chicken';
alter table hats add column user_id integer references users;
Recommended readings
//include the node postgres library
var pg = require('pg');
//connect to a database
pg.connect('postgres://user:password@localhost/my_db', function(err, client, done) {
//add a new hat
client.query(`insert into hats
(name, material, height, brim)
values
('cowboy', 'straw', '4', true)`, function(err, result) {
//should print 'INSERT: 1'
console.log(`${result.command}: ${result.rowCount}`);
//call done and end, same as the read example
done();
pg.end();
});
});
Recommended readings
Exercise
Bulletin Board Application Create a website that allows people to post messages to a page. A message consists of a title and a body. The site should have two pages:
- The first page shows people a form where they can add a new message.
- The second page shows each of the messages people have posted. Make sure there's a way to navigate the site so users can access each page.
Messages must be stored in a postgres database. Create a "messages" table with three columns: column name / column data type:
- id: serial primary key
- title: text
- body: text
Additional Grading Criteria
As before, your package.json must include the correct dependencies.
Additionally, you must configure postgres as follows: Name your database "bulletinboard". Your postgres username must be read from an environment variable named "POSTGRES_USER". Your postgres password (if present) must be read from an environment variable named "POSTGRES_PASSWORD"
Thus, your connection string in the code will appear as follows:
var connectionString = 'postgres://' + process.env.POSTGRES_USER + ':' + process.env.POSTGRES_PASSWORD + '@localhost/bulletinboard';
set an environment variable by opening either ~/.bash_profile for OSX or ~/.bashrc for Linux and adding the line:
export POSTGRES_USER=jon export POSTGRES_PASSWORD=mypassword
After that, restart your terminal to propagate these changes to your shell.
This will allow your assignments to be graded without having to go into your code and change your connection string to his configuration.
var promise = Promise.resolve('hello')
.then(function(str) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(`${str} there`);
}, 1000);
});
})
.then(function(str) {
return `${str} world!`;
})
.then(function(str) {
//prints "hello there world!"
console.log(str);
//the `promise` variable above will eventually
//be a fulfilled promise with `str` as its value
return Promise.resolve(str);
});
// About sequelize
var Sequelize = require('sequelize');
var sequelize = new Sequelize('postgres://user:password@localhost/my_db');
//use the same hat definition as before
var Hat = sequelize.define('hat', {
name: Sequelize.STRING,
material: Sequelize.STRING,
height: Sequelize.INTEGER,
brim: Sequelize.BOOLEAN
});
//define a simple person model
var Person = sequelize.define('person', {
name: Sequelize.STRING
});
//a person can have many hats...
Person.hasMany(Hat);
//... but a hat belongs to a single person.
Hat.belongsTo(Person);
sequelize
//sync the models
.sync()
.then(function(){
//then create a person
//turns into INSERT INTO "people" ("id", "name") VALUES (DEFAULT, 'Jane Smith')
return Person.create({
name: 'Jane Smith'
})
})
.then(function(person){
//then create a hat for that person
//turns into INSERT INTO "hats" ("id", "name", "material", "height", "brim", "personId")
// VALUES (DEFAULT, 'cowboy', 'straw', 3, true, 1) RETURNING *;
return person.createHat({
name: 'cowboy',
material: 'straw',
height: 3,
brim:true
});
});
Recommended readings
- https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise
- http://www.javascriptkit.com/javatutors/javascriptpromises.shtml
Exercise
- Bulletin Board App
ORM-Lite module
Create a module called
orm-lite
that gives a user the following functions to work with:
- A function named
initialize
that takes in a connection string as a parameter. Save this to a global variable so that later function calls can connect to the designated postgres database.- A function named
getAll
that takes the name of a table as a parameter, as well as a 'callback' parameter. The function should connect to the postgres database and get the contents of that table in an array. Invoke the callback with the table contents.- A function named
findById
that behaves similarly togetAll
above, except that it additionally accepts an 'id' parameter. It should retrieve the row specified by the id and send it to the callback.Secondly, test this module: First, in psql, create a table:
create table test_user ( id serial primary key, firstname text, lastname text );
Now add a few entries to the table:
insert into test_user (firstname, lastname) values ('jackson', 'pollock'), ('sylvia', 'plath'), ('daenerys', 'targaryen');
Now, create an application that firstly requires the
orm-lite
module, then calls each of its methods, then prints the output. This will allow you to see that everything is in order.Bonus: Prototype practice
Create a
Table
class. The class should take in the name of a table in the constructor and the connection string and add them to thethis
object. Now, attach agetAll()
function attached to its prototype. ThegetAll()
function should now read the table name fromthis
's table name property. In other words,getAll("user")
would becomeUser.getAll()
. Do the same forfindById
.In this manner, users of your module can create instances of your class that represent their tables, which will automatically have methods on them that allow data retrieval from those tables.
var Sequelize = require('sequelize');
var express = require('express');
var bodyParser = require('body-parser');
var session = require('express-session');
var sequelize = new Sequelize('class_example', 'jon', null, {
host: 'localhost',
dialect: 'postgres',
define: {
timestamps: false
}
});
var User = sequelize.define('user', {
name: Sequelize.STRING,
email: Sequelize.STRING,
password: Sequelize.STRING
});
var app = express();
app.use(session({
secret: 'oh wow very secret much security',
resave: true,
saveUninitialized: false
}));
app.set('views', './src/views');
app.set('view engine', 'jade');
app.get('/', function (request, response) {
response.render('index', {
message: request.query.message,
user: request.session.user
});
});
app.get('/profile', function (request, response) {
var user = request.session.user;
if (user === undefined) {
response.redirect('/?message=' + encodeURIComponent("Please log in to view your profile."));
} else {
response.render('profile', {
user: user
});
}
});
app.post('/login', bodyParser.urlencoded({extended: true}), function (request, response) {
if(request.body.email.length === 0) {
response.redirect('/?message=' + encodeURIComponent("Please fill out your email address."));
return;
}
if(request.body.password.length === 0) {
response.redirect('/?message=' + encodeURIComponent("Please fill out your password."));
return;
}
User.findOne({
where: {
email: request.body.email
}
}).then(function (user) {
if (user !== null && request.body.password === user.password) {
request.session.user = user;
response.redirect('/profile');
} else {
response.redirect('/?message=' + encodeURIComponent("Invalid email or password."));
}
}, function (error) {
response.redirect('/?message=' + encodeURIComponent("Invalid email or password."));
});
});
app.get('/logout', function (request, response) {
request.session.destroy(function(error) {
if(error) {
throw error;
}
response.redirect('/?message=' + encodeURIComponent("Successfully logged out."));
})
});
sequelize.sync({force: true}).then(function () {
User.create({
name: "stabbins",
email: "yes@no",
password: "not_password"
}).then(function () {
var server = app.listen(3000, function () {
console.log('Example app listening on port: ' + server.address().port);
});
});
}, function (error) {
console.log('sync failed: ');
console.log(error);
});
Recommended readings
- https://github.com/expressjs/cookie-parser
- https://github.com/expressjs/session
Exercise
Basic Node Blog
Build a basic blogging app in Node.
There should be a User, Post, and Comment model.
The app should have similar functionality to Tumblr - users can login, write posts, comment on other users' posts, etc.
Work on this project with another student collaboratively, following the same process as with the micro-blogging app:
- Sketch out the way your app will look
- Create a basic repo, push to GitHub, create and assign issues
- Develop the software collaboratively!
Grading Criteria
User model sign up, in, login, edit, delete 5 Points
Post and Comment model allow current user to post 8 Points
Follow other users, follow and unfollow other users, join table 5 Points
Code is well commented and contains a README 2 Points
Total: 20 Points
bcrypt.hash("bacon", null, null, function(err, hash) {
// Store hash in your password DB.
});
// Load hash from your password DB.
bcrypt.compare("bacon", hash, function(err, res) {
// res == true
});
bcrypt.compare("veggies", hash, function(err, res) {
// res = false
});
Recommended readings
Exercise
Add encryption to your blog application so that your user's passwords are stored safely. Do this in a new branch called "encryption", then merge this back into your main branch.
Use the "bcrypt" library, and see: https://github.com/j7caiman/nodejs-sample-apps/tree/master/bcrypt_example for an example on how to use it.
Aside: Remember to use the input of type "password" so that the form field will appear as "*****" - otherwise, people looking over the shoulders of your users' screens will be able to steal their passwords.
Exercise
Consider this scenario: You are building an application that connects people who want to learn languages with each other. Each user is fluent in at least one language, and is trying to learn at least one other language. Your application matches compatible users with one another so that through an exchange, they can teach each other the languages they are good at.
Your matching algorithm is as follows:
For a user who is fluent in language X and wants to learn how to speak language Y, match them with all the users who are fluent in language Y and desire to speak language X. Note that users can be fluent in multiple languages, and can also desire to learn multiple languages. For example, say your site has the following users:
- Iris: fluent in English and Spanish | wants to learn French and German
- Finn: fluent in German | wants to learn Spanish
- Nathan: fluent in French | wants to learn English and Spanish
- Natasha: fluent in English | wants to learn Mandarin
When Iris signs on, she'll be matched with Finn and Nathan. When Finn or Nathan sign on, they'll be matched with Iris. Natasha will not be matched with anyone until the site has more users.
Part 1: You currently have two tables: Users and Languages. Draw a diagram that describes how you will store users' desired languages and users' fluent languages, including any added tables you need, as well as those tables' columns.
Part 2: When a user logs on to your site, describe the algorithm you will use to match that user with other users. Starting with the current user's id, how will you fetch his desired and fluent languages? What will you do after that?
Exercise
Install Bootstrap or another CSS framework like MaterializeCSS onto one of your applications. Use the grid system to make your site responsive and look appropriate on both desktop and mobile devices.
Exercise
Group Project
In groups of two to three, create a web application using the technologies covered so far. Use Git and Github to collaborate. Prior to coding, you must complete a design specification and technical specification, located here: Specification
This group project is a chance to expand your portfolio and demonstrate to future employers your ability to work on teams.
function validate()
{
if( document.myForm.Name.value == "" )
{
alert( "Please provide your name!" );
document.myForm.Name.focus() ;
return false;
}
if( document.myForm.EMail.value == "" )
{
alert( "Please provide your Email!" );
document.myForm.EMail.focus() ;
return false;
}
if( document.myForm.Zip.value == "" ||
isNaN( document.myForm.Zip.value ) ||
document.myForm.Zip.value.length != 5 )
{
alert( "Please provide a zip in the format #####." );
document.myForm.Zip.focus() ;
return false;
}
if( document.myForm.Country.value == "-1" )
{
alert( "Please provide your country!" );
return false;
}
return( true );
}
<input type="text" name="firstname" value="John" readonly>
<input type="text" name="firstname" value="John" disabled>
<input type="text" name="firstname" value="John" size="40">
<input type="text" name="firstname" maxlength="10">
<input type="email" name="email" autocomplete="off"><br>
<form action="action_page.php" novalidate>
<input type="text" name="fname" autofocus>
<input type="text" name="lname" form="form1">
Recommended readings
- http://www.w3schools.com/js/js_validation.asp
- https://www.owasp.org/index.php/Input_Validation_Cheat_Sheet
- https://www.smashingmagazine.com/2009/07/web-form-validation-best-practices-and-tutorials/
- http://www.w3schools.com/html/html_form_attributes.asp
Exercises
- Group project previously introduced
For your blog application, add validation such that the user registration and login routes behave like modern web applications. Make sure to put the validation on both the client and the server. Requirements:
- the username field cannot be empty and must be unique
- the password field cannot be empty and must contain at least 8 characters
- for registration, the 'confirm password' and 'password' fields must match each other
$primary-color-dark: #388E3C;
$primary-color: #4CAF50;
$primary-color-light: #C8E6C9;
$primary-color-text: #FFFFFF;
$accent-color: #FFC107;
$primary-text-color: #212121;
$secondary-text-color: #757575;
$divider-color: #BDBDBD;
@mixin border-radius($radius) {
-webkit-border-radius: $radius;
-moz-border-radius: $radius;
-ms-border-radius: $radius;
-o-border-radius: $radius;
border-radius: $radius;
}
.box {
@include border-radius(10px);
}
// Header intro
.header-intro {
width: 100%;
height: 300px;
background-color: $primary-color;
.valign-wrapper {
height: 100%;
margin-top: -32px;
}
#headertitle {
margin: -20px 0 10px 0;
}
#headersub {
margin: 0;
font-size: 20px;
font-style: italic;
}
}
Recommended readings
Exercise
- Group project previously introduced
Homework
Write a function that takes in an array of numbers and checks whether each number is less than the previous one.
Return true if all of them fit this condition, otherwise return false
Write comprehensive tests for this function.
// Write a function that fulfils the following tests: function test(methodToTest) { if(methodToTest(1,2,3) === 6) { console.log("test 1 passed"); } if(methodToTest(-1, 0, 1) === 0) { console.log("test 2 passed"); } if(methodToTest(10, 20, 1) === 31) { console.log("test 3 passed"); } }
These two weeks are dedicated to your final project. Consider it your cherry on tp, the one thing you can show potential clients and employers that will make them go: "Wow, this one really knows what they are doing".
Notes:
- These weeks will have lectures
- These weeks will have exercises
- These weeks will not have daily homework
Final Project
Design Brief / Project Specifications
Note: I have left the formatting to you.
State the purpose of your application clearly and concisely. Try to do it in a single sentence.
In a block, answer the following questions: What is the problem you are trying to solve? Who is your target audience? What are your specific goals?
In another block, answer the following: What is your business model? Where is your revenue coming from? What are the costs of your business?
Market research: Who is your current competition? How is your product different from currently available competitors? What is the current supply / demand for your product?
Technical Specifications: What data will you need to store? How will it be organized? Describe each table, its columns, and its relationships with other tables. What does your product look like? List each view, their purpose, and how they work Describe any complex business logic that is happening in your application. For example, how does data flow through your application
Have a timeline of milestones to reach: Create milestones that represent the discrete blocks of functionality. Give an estimate for how long each will take per engineer. Determine whether things can be built concurrently. Come up with a timeline of goals to stick to.