Sunday, September 30, 2012

Building a Bookmarklet

The video below shows how to build a bookmarklet.



Note: The code in the video does not set the host properly. Use the code below for your bookmarklet:

JavaScript DOM Manipulation

For the next homework you will be writing JavaScript that modifies the DOM (by getting images out then replacing the current page with a whole new page). The video below talks about the JavaScript methods that modify the DOM.

Thursday, September 27, 2012

REST

The webapp you are building follows (mostly, I took some liberties) a REST architecture.

Most modern webapps follow a REST-ful style, so, when you design your own webapp you should keep these principles in mind. I think that after you are done building our Pinboard app you will realize how this architecture saved you a lot of coding and confusion. In the video below I explain what REST is and how your Homework app implements REST principles.

JavaScript: Inheritance

And now, to the wonderful world of Prototype inheritance:


Wednesday, September 26, 2012

HW6: Bookmarklet

People will never use our Pinboard if they have to manuall cut-n-paste the URL for every image they want to add. What we need is a painless way for them to enter images from whatever page they are browsing directly into our Pinboard. Thus, we need a bookmarklet, or a browser extension (which are basically just bookmarklets with some extra browser-specific files added).

This week you will implement a bookmarklet that lets the user painlessly add img URLs to his pinboard. Specifically, you will:
  1. Add the bookmarklet to the / page, for logged-in users only.
  2. When the user clicks on your bookmarklet, your JavaScript code will erase the current page and show only the imgs in that page.
  3. Each image will be surrounded by a form that lets the user add a caption and then submit that image back to your server (the user can only submit one image)
  4. After submitting the user is re-directed to the page showing his new pin.

Required Reading

This is our first JavaScript homework. You will need to know quite a bit of JavaScript to do this. My videos cover the specific topics you need to know. But you should also use: When done, push your homework to your private github repo, and publish on appengine.com with Version: 6, by Monday, October 8 @9am. Note: My solution to this homework does not use jQuery (or any other library) and I recommend that neither should yours. If you do, you will be downloading a second script file whenever the user clicks on the bookmarklet (so, making the button a bit slower), and it is a good learning experience to write a bit of JavaScript using only the built-in DOM manipulators.

Tuesday, September 25, 2012

JavaScript: Variables and Functions

OK, we are now ready to start having fun with JavaScript. First, variables:



and then, functions:


Monday, September 24, 2012

Python, Indentation, and Eclipse


I'm noticing that many of you are not being careful about consistent indentation. In Python, indentation is code. So, while the program might work if the then-part of an if-else is over-indented, this will cause problems later on when you add more code.

Also, don't use tabs! You can tell eclipse to only use spaces (instead of tabs) by going to Preferences, as shown in the images.

Sunday, September 23, 2012

The Big Picture

By now you are all getting a good idea of what the big picture of webapp development looks like: that is all a bunch of GETs and POSTs, each of which you have to write an eventHandler for, or dispatch from a static file.

I thought I would summarize it in this video (I also talk about Ajax calls, which you will be doing in a couple of weeks).


Saturday, September 22, 2012

Many-to-Many Relationships

In the video below I show one way to setup a many-to-many relationship in the datastore: between Posts and Tags.

Friday, September 21, 2012

HW5: Boards

In this homework you will extend upon the previous database model by adding a Board. Basically, a user can create any number boards. Each board has a title, which the user can set. The user can add any number of his pins to any one of his boards (a pin can be in more than one board).

The user will also be able edit his board after creating it. He is able to edit the title, add and delete pins, and set it to private or not. If a board or pin is marked 'private' then only its owner can see it, if it is not marked private then everyone can see it (but still, only the owner can edit it).

A non-owner of a board can still see it, but cannot see the edit controls, nor can he edit it via direct POSTs (security).

The screenshots here provide a guide as to how your app will look like.

GET /when logged-in, shows links to "My Pins" (/pin) and "My Boards" (/board)
GET /pinlists all the users' pins and links us to each one, as before. Also, this page should let the user add a new pin.
POST /pincreates a new pin, as before
GET /pin/123shows pin 123, and a form for editing it, as before.
POST /pin/123updates pin 123 (caption or url), or deletes it, as before.
GET /boardlists all my boards. If not logged in re-direct to /, and do similarly for all the other URLs. Also, this page should let the user add a new board.
POST /boardCreates a new board and then redirects the user to it.
GET /board/123If my board then list all the pins in the board and a form for editing it. If not mine but public then list the pins in the board. If not mine and private then re-direct to /
POST /board/123Update board 123's information. The possible changes are: new title, add pin, delete pin, mark as private/public, delete board. Then redirect the user back to GET /board/123

Required Reading


This homework makes more use of the datastore, so you will need to continue using the datastore documenation

For storing the list of pins in a board I suggest you use the ListProperty on a Board. However, you can also use a mapping table, as is often done when one wants to implement a many-to-many relationship in a database (for those of you who have taken 520). In any case, you will need to be careful that when a pin is deleted from a board that the pin is no longer listed as belonging to that board.

As I will explain in class, these type of data-consistency checks are best implemented as methods to your Model class.

Push your final changes to your private github repo and publish your app to appspot.com by Monday, October 1 @9am.

Wednesday, September 19, 2012

Organizing Request Handlers

Below I give an example of how you might organize your Python code

Monday, September 17, 2012

Solutions and Lecture Code

I have just pushed my solutions to HW3. I also setup a repo with the code I write in the lecture, which I'll be updating after each lecture.

Saturday, September 15, 2012

Datastore Queries

The datastore supports a fairly complex query language (but, not as complex as full SQL). The two most often used operators are filter and order.

Datastore Keys

Every item (entity) in the datastore can be referenced by its Key, which works the same way as a key in a hash table (an index in an array). The keys can be generated from an item's ID and its entity type. I explain below:

The Datastore

Google app engine uses the datastore, which works a lot like a regular database (SQL) but is actually implemented as a gigantic distributed hash table, and is supposed to automatically scale to as many machine as you can pay for.

The video below give a quick introduction.


Tuesday, September 11, 2012

HW4: The Datastore


In this homework you will start using the datastore to store the pins that each user adds to his account and later displaying them. Note that you will not be storing the images themselves (the *.png or *.jpg). You will only be storing the URL to the image.

First, create a directory called /pic in your project and add a few of your favorite jpegs from the net. You will use these when debugging your app. They will save you time as your browser will not have to keep fetching images from the net (and, you can code offline).

You will then create a Pin(db.Model) with imgUrl, caption, date, and owner properties. That is, each Pin will have a URL, a caption, a date of creation, and an owner associated with it. Each pin will also have a unique id, but you can just use the built-in key. That is, the Pin's id will be given by self.key().id().

The way your app will work is as follows:
  1. As before, on 'GET *' if the user is not logged in he is shown the login page. If he is logged in then 'GET /' returns a form asking him for the img URL and caption. You do not need to check if it is a valid URL.
  2. When the user hits 'submit' on the form (for adding a image) you will generate a 'POST /pin/' that sends the information of the new pin to the server. Your server code will store this new pin information in the datastore and then forward the user (self.redirect()) to the new pin's page: /pin/1234 (or, whatever number you have the pin).
  3. '/pin/1234' will show pin 1234. It will also show the URL and caption values in text boxes, allowing the user to change this. If the user changes them and clicks on the 'update Pin info' button you will generate a 'POST /pin/1234' with the new information and update the info on the server accordingly, then come back to 'GET /pin/1234' which will then be updated.
  4. The '/pin/1234' will also have a 'delete this pin' button which does as it says.
  5. A 'GET /pin/' will return a page with thumbnails of all the pins owned by the user, each one linked to its pin page. In the header of all pages it will say 'My Pins' which is just a link to '/pin'.

What we are going for here is a fairly standard REST API for getting and editing your pins.

To summarize:


GET /when logged-in, shows a form for adding a pin
GET /pinlists all the users' pins and links us to each one.
POST /pincreates a new pin
GET /pin/123shows pin 123, and a form for editing it
POST /pin/123updates pin 123 (caption or url), or deletes it

Required Reading


  • You will need to read the Datastore example and consult the Datastore API for all the details of its operation (you only need to know the basics for this homework).
  • You will be using the users API to let users log in and determining if the person is logged-in or not. Almost everything you need from 'users' is covered in this Using Users Service example.



Deadline


As always, push it your github repo by Monday, September 24 @9am

A Note on Proper Googling

You will have notice that whenever you search for a web-related term like 'css font-family' your first results are always at w3chools.com. Now, I have nothing against that website but they are kinda sucky.

What I do is prepend every search with 'mdn', as in 'mdn css font-family'. That way I end up at the much nicer Mozilla Developer Network.

Monday, September 10, 2012

Static CSS Files in the App Engine

If you link to a CSS with, say href="/css/style.css" then the browser is going to do a GET /css/style.css. But, since you are running the app engine this means that, by default, this will go to your Python file where it will look to see if there is a handler defined for /css/style.css.

Since our CSS files are static we don't want the python code to be called to fetch them. We just want the webapp2 to serve these as old-fashioned static files. To do this you need to edit your app.yaml and tell it which files or directories you want to be static. Read the docs on Static File and Directory handlers for the details. Basically, you add something like:
- url: /css
  static_dir: css

to your app.yaml file.

My Solutions

I have pushed my solutions to HW2 to the pinboard github repo so you can take a look at how I did it. I added a link to this repo on the menu at the right. I will be pushing all future solutions to that repo.

Sunday, September 9, 2012

CSS Examples

At first, it is hard to imagine that significant visual effects can be achieved by using the CSS properties. But, that is only due to lack of imagination. The sites below showcase the power of CSS. Browse them for ideas, and CSS code.

  • CSS Zen Garden is the original CSS showcase site. Every time you click on a design on the right you will see a different design. But, note that all designs use the same HTML. The only thing that changes is the CSS file.
  • CSS Deck is a new site for showing off cool CSS tricks. Like, how to build a macbook pro entirely out of CSS.
  • The Shapes of CSS blog post shows how to generate geometric shapes with CSS.
  • Colour Lovers is just colors, but they have some pretty colors.
  • CSS3 generator will generate the CSS for shaded, rounded boxes.

Saturday, September 8, 2012

CSS Boxes

In the following video I explain a bit more about CSS margin, border, and padding.

Cascading Style Sheets

Below I give a quick introduction to CSS. You should read over the MDN CSS documentation to learn CSS.



Friday, September 7, 2012

HW3: CSS, users

For this homework you will add a CSS file to your webapp to make it look pretty, and you will use the app engine users library to provide login and logout capabilities.

That CSS Look


Your website should look like the screenshots you see here. Namely, it must have:
  1. A header which shows either the login button, or the email of the currently logged-in user and the logout button. Both of these must be right-justified.
  2. A title, as shown, more or less.
  3. A box that is centered on the page and shows either the login message or asks for input (same as the previous homework). The background of the box must be a different color from the rest of the page.
  4. The footer, with your name centered on it.

You can use the same colors I used, which are USC's colors, or choose your own color template. Note, if you don't know much about visual design (as I don't), the best thing to do is to use someone else's color scheme and try to pick one with fewer than six colors. The fewer colors you use the more professional it will look.

Login


The login and logout button should work, as expected: login and logout the user. When the user is logged in you should display his email address in the header. You will do this using the app engine's users library, which means that people will be logging in with their gmail/google credentials. Notice that with this method you do not need to store anything. Google takes care of the authentication process.

Required Reading


To do this homework you will to have read:

  1. Using the users service: getting started guide. More details in the users service API.
  2. MDN CSS Tutorial

You are free to google (or bing, or whatever you're into) for this and all homeworks as much as you want. However, be warned, you must understand what every line code in your program does! This is good to do not just for this class but for your whole career. If you cut-n-paste some piece of code from the interwebs into your program and you don't know exactly what it does you are asking for big-time trouble later on. When your app crashes the next day, is it because of the code you pasted? You have no idea! Blind pasting is the equivalent of agreeing to take in an international flight a suitcase that some stranger just gave you.

As always, push your code to your github repo by Monday, Sept. 17 @9am.

Tuesday, September 4, 2012

Jinja2 Templates

Below is a short intro to the Jinja2 templates as used in the app engine. You will need to consult the Jinja2 documentation to use them.


Monday, September 3, 2012

HTML Forms

Below I cover the basics of HTML forms.


HW1 Graded

I have graded HW1 and emailed you your grades. I am using your @email.sc.edu address. If you want me to email it somewhere just let me know.

I don't have a solution for this HW since it was mostly about making you have everything installed and know your way around chrome tools.

Saturday, September 1, 2012

Python

Below is a short introduction to the main features of Python.



Another fun way to learn python is by doing the codeacadempy Python track.