WebFund 2015W Lecture 10

From Soma-notes
Jump to navigation Jump to search

Resources


Video

The video from the lecture given on February 4, 2015 is available now as an MP4.


Notes

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")
      
  • 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 function
    • typeof(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
    

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(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()!

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.