WebFund 2015W Lecture 10
Resources
Video
The video from the lecture given on February 4, 2015 is available now as an MP4.
Notes
CORRECTION regarding hasOwnProperty()
In lecture we saw that we could break notes-demo by giving hasOwnProperty as a username. This error is because the following code in the login post handler is incorrect:
if (!userNotes[username]) { userNotes[username] = []; }
This code should instead say:
if (!Object.hasOwnProperty.apply(userNotes, [username])) { userNotes[username] = []; }
If you are treating a JavaScript object as an associative array you must explicitly check whether a given key value (property) is present using the hasOwnProperty() method inherited by every object.
Note you can create an object x with no prototype by doing the following:
x = Object.create(null);
However, this is not normally done. Indeed, even if you use a JSON parser objects will have a non-null prototype.
Thus, use hasOwnProperty()!
Breaking a few things in notes-demo
In app.js, remove var app = express();
- If you delete this line, app is going to be undefined.
- This becomes a problem because you’d be trying to access parts of an undefined object.
- You get a reference error when doing this.
In app.js, remove var session = require('express-session');
- If this line is deleted you get an error: session is not defined.
- This error comes from the calls in index.js to get the username (
req.session.username
). - Since the session module is not loaded, this code cannot execute correctly.
In index.js, inside the router.get('/', ...)
function, remove error: req.query.error
- This causes problems when the user tries to access pages which require them to be logged in such as /notes and /edit.
- The 'not logged in' error will still show up in the URL but not display the error message on the page itself anymore.
JavaScript in Jade
In index.jade, does the -if(error)
get seen by the browser?
No: take a look at the page source and you will see that there is only the div tag and not the condition.
You must realize:
- When you add any JavaScript into the body of a jade template, it is executed on the server (server side JavaScript) and is not seen by the web browser.
- This idea applies to all JavaScript (that is not contained in a script tag).
- The web browser just gets the result.
Making a pop up box when the web page is loaded
- The
res.render()
calls render a Jade template and and then send them to the browser as an HTML page. - It is inside these Jade templates that code can be added to ensure that JavaScript code is sent along with the HTML to be executed on the client-side.
- Add in a
block header
into index.jade.block header script alert(“Hi there”)
- Most of the time you want to put your JavaScript in a separate file (in the public/
JavaScripts folder) so instead you can do the following:
- In public/JavaScripts create a file called alert.js with contents:
alert(“Hello there again”);
- Change the code in index.jade to be:
block header script(src="javascripts/alert.js")
- In public/JavaScripts create a file called alert.js with contents:
- If we want this script to also be able to run in a terminal, it must be modified.
- We need to check if alert is defined (as it is not defined in a regular terminal running Node) to determine whether or not we are in the browser and have access to the
alert()
function. - If there are no alert boxes, we must display to the console instead.
if (typeof(alert)==="undefined") { myalert = function(s) { console.log(s); // this will output to the console instead of pop up in browser } } for(i=0; i<5; i++) { alert(“Hello there again”); }
typeof()
is a useful functiontypeof(5)
gives you ‘number’.typeof(“hello”)
gives you ‘string’.typeof(foo)
gives you ‘undefined’.- You have to remember that it returns a string.
- When trying to read the source code for scripts on other pages, some are very hard to read.
- Any idea why the code from Google might be really hard to read?
- The JavaScript inside of a page is what powers advertisements.
- If you can figure out the JavaScript you can engineer fake clicks.
- Google obscures the JavaScript to prevent click fraud.
Why do you get an error when you try to log in with ‘hasOwnProperty’?
- In the
router.post('/login',...)
function in index.js, we check for the username in userNotes. - The fact that the userNotes object has a function called
hasOwnProperty
is causing a problem. - We can see that this is an inherited function through the following code example:
> x = {} {} > x.hasOwnProperty() [Function: hasOwnProperty] > y = Object.create(null); {} > y {} > y.hasOwnProperty() undefined
Adding tags in notes-demo
- We want another field for the notes to hold tags (information about the notes).
- Add a field to display tags in notes.jade:
i= userNotes[i].tags
- Appropriate tag data must be added for Alice in the data structure in index.js to view the change.
- Why didn't we have to pass the tags directly to the jade file?
- Because we just passed in the whole notes object, in this case its called userNotes.
- Since the entire object is passed in, the tags get passed in with it.
- If “tags” was a separate data structure, it would need to be added to index.js to be passed in also.
- To be able to edit the tags we need to go to edit.jade and add
div input#title(type=”text”, name=”tags”, value=note.tags)
- To make sure there is a default tag when we create a new note we look at the
router.get('/new', ...
function in index.js and add an additional attribute to the notes object:tags: “Add tags here”
- But we also need to make sure the tag field actually gets the value when you create
a new note or update one. In index.js, in the
router.post('/update', ...
function we also need to add in:note.tags = req.body.tags
Adding jQuery to a page
- In the header of a Jade file, link the script using
script(src="...")
- You would either have to download the jQuery file to your web app and put it in the
JavaScripts directory or you could make the src a full URL and link it from another
place on the web, ex:
<script src=”//code.jquery.com/jquery-1.11.2.min.js”></script> <script src=”//code.jquery.com/jquery-migrate-1.2.1.min.js></script>
- Why would it be better to use the longer URL?
- It saves bandwidth on your server because you don’t have to serve the file; another website does.
- Users may already have the file cached from other websites so it can save bandwidth for them as well.