Skip to content

Instantly share code, notes, and snippets.

@amysimmons
Last active December 26, 2017 06:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amysimmons/42289b695062a11b3ebd to your computer and use it in GitHub Desktop.
Save amysimmons/42289b695062a11b3ebd to your computer and use it in GitHub Desktop.
WDI Week 9 Notes

#WDI Week 9 Notes

##Sunday

###Code School: The Anatomy of Backbone.js

Source:

http://backbone.codeschool.com/levels/1

http://courseware.codeschool.com/The_Anatomy_of_BackboneJS.pdf

##Monday

###Warmup

Regular expressions calculator:

https://gist.github.com/anonymous-wolf/9dd62f862b65324a034d

http://rubylearning.com/satishtalim/ruby_regular_expressions.html

class Calculator

  def initialize
  end

  def ask(question)
    question.match(/What is (-?\d+) plus (-?\d+)?/) do |m|
        m[1].to_i + m[2].to_i
    end
  end

end

###Retro

###TDD

####TDD Homework

###Coffeescript

console.log 'hello world'

# no semicolons
items = ['beer', 'wine', 'spirits']

# backwards conditionals 
beerLover = true if items.length > 0

# while items.length > 0 then drinkBeer()

# sort of iterators 
for item in items
  console.log item

for i in [5..0]
  console.log i
console.log 'blast off'

nums = [0..20]
console.log nums
# generates this in one way

nums = [0..21]
console.log nums
# generates this in another way, to save space 

for drink in items 
  console.log drink if drink != 'spirits'

# trickier conditionals
for drink in items when drink isnt 'spirits'
  console.log drink

# this is the syntax for a function 
drinkBeer = -> 
  console.log 'Glug glug'

drinkBeer()

# this is the syntax for a function 
drinkBeer = -> 
  console.log 'Glug glug'
  items.pop()
  
while items.length > 0 then drinkBeer()

#a function with an argument
hello = (target)->
  console.log 'hello ' + target

hello 'world'

#obejcts

#the js way
# fridge = {
#   beer: [],
#   chips: [],
#   consume: function(){

#   }
# }

fridge = 
  beer: ['cider', 'vb', 'tooheys', 'guiness']
  chips: ['potato chips', 'corn chips']
  consume: -> 
    console.log('nom nom nom')
    @beer.pop()
    # @beer means this.beer
fridge.consume()
fridge.consume()
console.log fridge


# jquery 

# $ ->
#can also write document.ready as above 

$(document).ready ->
  $('#wonderland').on 'click', -> 
    console.log 'there was a click' 


# you can  do up to and includin as well as up to 
nums = [0...5]
console.log nums

nums = [0..5]
console.log nums

# you can alos use interpolation, or something similar 

####Homework

https://www.codeschool.com/courses/coffeescript

##Tuesday

###Warmup

https://gist.github.com/anonymous-wolf/688b3ffa222af9bd03e6

https://gist.github.com/anonymous-wolf/b74c2f2ac5afcee8b783

###Backbone Intro

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Backbone zoo</title>
  <script src="js/jquery.js"></script>
  <script src="js/underscore.js"></script>
  <script src="js/backbone.js"></script>
  <script src="js/intro.js"></script>
</head>
<body>
  <div id="main"></div>
  <script type="text/x-underscore-template" id="animal-template">
    <p><%= type %> lives in the <%=ecosystem%> and has <%=stripes%> stipes.</p>
  </script>
<!--   it doesnt matter what the type is as long as its not js
  but at least calling it x-underscore-template somebody reading
  will know that its not javascript -->
  <!-- so this will be my template that knows how to print out an animal -->
</body>
</html>
// console.log(_, Backbone);

var Animal = Backbone.Model.extend({

  defaults: {
    type: 'animal',
    ecosystem: '',
    stripes: 0
  },

  initialize: function() {
    console.log('I am a new animal');

    this.on('change:type', function(model){
      var type = model.get('type');
        console.log('I am now ' + type)
    });
  }

});

var Zoo = Backbone.Collection.extend({
  model: Animal
});

var animal1 = new Animal({type: 'frog', ecosystem: 'pond', stripes: 30})
var animal2 = new Animal({type: 'dog', ecosystem: 'house', stripes: 40})
var animal3 = new Animal({type: 'bat', ecosystem: 'cave'})

var gaZoo = new Zoo([animal1, animal2, animal3]);

var ZooView = Backbone.View.extend({
  el: '#main',
  initialize: function(){
    console.log('ZooView init');
  },
  events:{
    'click p': 'animalClick'
  },
  render: function(){
    // this.$el.html('blah blah blah');
        // gets me the jquery version of this 
    // console.log('Associated collection', this.collection);
    var view = this;
    var animalTemplate = $('#animal-template').html();
    // this line gets me the html inside of my template
    var animalHTML = _.template(animalTemplate);

    this.collection.each(function(animal){
      // var $p = $('<p/>');
      // $p.text(animal.get('type'));
      view.$el.append(animalHTML(animal.toJSON()));
    })
  },
  animalClick: function(){
    console.log('you clicked on an animal');
  }
});

// need to set the value of this to view, and then refer to view,
// because the value of this gets clobbered when you go into an each loop
// so i hang onto the value of this when it is what i want it to be

var AppRouter = Backbone.Router.extend({
  routes: {
    '': 'index',
    'animals/:id': 'viewAnimal'
  },
  index: function(){
    console.log('you found the home page');

    var zooView = new ZooView({collection: gaZoo});
    // this is saying
    // create me a new view for this collection andnow 
    // i will ahve access to the view within this collection 
    zooView.render();
  },
  viewAnimal: function(){
    console.log('you are viewing an anaimal');
  }
});

$(document).ready(function(){
  var router = new AppRouter();
  Backbone.history.start();
  // the above two lines r rquired to start the router


});


// The first thing we do with backbone is our models
// when we load the page its going to fetch underscore and backbone 
// and then  my intro js code
// then its goign ot define this class of Animal
// what we are going to end up building is a zoo, 
// and the thing that we have inside of a zoo is animals, so 
// i've created a class of animals

// ive made a zoo Collection
// you can think of a collection as being similar to an array
// but it has some extra features you can play with


// in the console:

// var zebra = new Animal ({type: 'zebra', ecosystem: 'savanna', stripes: 100})
// I am a new animal
// undefined
// zebra.attributes
// Object {type: "zebra", ecosystem: "savanna", stripes: 100}
// zebra.set('type', 'butterfly')
// I am now butterfly
// child {cid: "c1", attributes: Object, _changing: false, _previousAttributes: Object, changed: Object…}
// zebra.attributes
// Object {type: "butterfly", ecosystem: "savanna", stripes: 100}

// gaZoo.each(function(a){
//   console.log(a.get('ecosystem'));
// });

// gaZoo.toJSON();

// gaZoo.sortBy(function(model){
//   return model.get('stripes');
// });
// returns a list of animals in ascending order by number of stripes

// we can find things with our underscore methods: http://underscorejs.org/#collections


// var ZooView = Backbone.View.extend({
//   el: '#main',
//   this is telling the view where to appear on the page
// });

// need to initiate a view
// and call the render function

// animal.type
// animal.attributes
// animal.toJSON()
// typeof animal.toJSON()


// the view is the thing that knows how to show the collection on the page
// if theyre to do with this view, all of the events will be grouped toegther in the view

###Blog

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Backbone Blog</title>
  <script src="js/jquery.js"></script>
  <script src="js/underscore.js"></script>
  <script src="js/backbone.js"></script>
  <script src="js/blog.js"></script>
</head>
<body>

  <a href="#">Home</a>
  <a href="#posts/post-about-chico">Featured post</a>
  
  <div id="main"></div>
  <script id="appView-template" type="text/x-template">
    <h2>Recent posts</h2>
    <ul id="posts"></ul>
  </script>

  <script id="postListView-template" type="text/x-underscore-template">
    <h3><%= title %></h3>
  </script>

  <script id="postView-template" type="text/x-underscore-template">
    <h2><%= title %></h2>
    <p><%= content %></p>
  </script>

</body>
</html>
// console.log(_, Backbone, jQuery);

// kind of like the rails router with embedded actions
// makes the application have meaningful urls
var AppRouter = Backbone.Router.extend({

  routes: {
    '':'index',
    'posts/:id':'viewPost'
  },

  index: function(){
    // if (today === "Sunday"){
    //   var appView = new AppView({collection: blogPosts});
    // }else{
    //   var appView = new AppView({collection: funnyPosts});
    // }

    // console.log('routed to index');
    var appView = new AppView({collection: blogPosts});
    appView.render();
  },

  viewPost:function(slug){
    // console.log('viewing post', id);
    var post = blogPosts.get(slug);
    console.log(post.toJSON());
    var postView = new PostView({model: post});
    postView.render();
  }

});

// our models as per rails
// the defaults are similar to a schema
var Post = Backbone.Model.extend({
  idAttribute: 'slug',
  defaults: {
    title: 'New Post',
    content: 'New post content'
  }
});

// this is really just part of our model, but is like a fancy array
// for storying a collection of models
// uses underscore.js to give us activerecordish methods like .get 
var Posts = Backbone.Collection.extend({
  model: Post
});

// seed data -- later we will retreive these from the server via ajax instead
var blogPosts = new Posts([
  new Post({id: 1, slug: 'post-about-hotdogs', title: 'Post 1', content: 'Post 1 Content'}),
  new Post({id: 2, slug: 'post-about-chico', title: 'Post 2', content: 'Post 2 Content'}),
  new Post({id: 3, slug: 'post-about-harpo', title: 'Post 3', content: 'Post 3 Content'}),
  new Post({id: 4, slug: 'post-about-groucho', title: 'Post 4', content: 'Post 4 Content'})
]);

// like rails views, but with the event handling stored here as well
// responsible for showing data on the page, but also allowing interaction 
var AppView = Backbone.View.extend({
  // defines the selector which this view is associated with
  el: '#main', 
  render: function(){
    console.log('rendering AppView', this.collection);
    var appViewHTML = $('#appView-template').html();
    this.$el.html(appViewHTML);
    this.collection.each(function(post){
      // console.log(post);
      var postListView = new PostListView({model: post});
      postListView.render();
    });
  }
});

var PostListView = Backbone.View.extend({
  // new post list view will use this to create a new li
  tagName: 'li',
  events: {
    'click': 'showPost'
    // anytime there is a click anywehre in this view, call a method called showPost
  },
  render: function() {
    // console.log('rendering post list view', this.model);

    // fetch and compile the template 
    var postListViewTemplate = $('#postListView-template').html();
    var postListViewHTML = _.template(postListViewTemplate); 

    // set the content of this views element to be the template for this model
    this.$el.html(postListViewHTML(this.model.toJSON()));

    // append this view's element to the posts ul 
    $('#posts').append(this.$el); 
  },
  showPost: function(){
    console.log('showing post', this.model.get('title'));
    appRouter.navigate('posts/' + this.model.get('slug'), true);
  }
});

var PostView = Backbone.View.extend({
  el: '#main',
  render: function(){
    var postViewTemplate = $('#postView-template').html();
    var postViewHTML = _.template(postViewTemplate);
    this.$el.html(postViewHTML(this.model.toJSON()));
  }
});

// this is global so we can access it inside certain views
var appRouter = new AppRouter();

$(document).ready(function(){
  // this kicks off the router and makes the back button and fwd button work
  Backbone.history.start();
});

// when we visit the route with no text in it
// that goes to the index function
// which jsut sasy go and get me a new view
// and rendew appview in it

// the lower case appView is the instance of the new AppView


// ====

// in the console:

// p1 = new Post()
// child {cid: "c2", attributes: Object, _changing: false, _previousAttributes: Object, changed: Object…}
// p1.attributes
// Object {title: "New Post", content: "New post content"}


// there are two ways of assicationg a view with a selector on the page
// el: '#main'
// taganme li means everytime we create a new instance of the post list view it will create a new li

###Addy's Todos

###RORO

###Homework

##Wednesday

###Warmup

PlingPlangPlong:

https://gist.github.com/anonymous-wolf/89c0abb1dae801d7cab9

https://gist.github.com/anonymous-wolf/a91806ceea2980308751

###Backbone Folders

###Backbone Ajax fetch()

Animals example:

To make an animal have web stuff behind it all you need to do is specify a url root.

urlRoot: '/animals',

If I Create a new animal in the console

butterfly = new Animal({id: 75});

All I need to do is say butterfly.fetch()

spider = new Animal()

spider.set({type: 'hunchback', ecosystem: 'belltower'})

spider.save();

You can jsut call the fetch and save methods and you can just get back whatever data you need

###Backbone blog + Rails

rails new backboneblog-rails -T

the first thing to do is get rid of turbolinks from the Gemfile and the application.js

bundle

rails generate scaffold Posts title:string content:text

rake db:migrate

annotate

we can request http://localhost:3000/posts.json

the scaffolding magic makes this work

it goes to the views folder and looks for index.json.jBuilder file

but we deleted this file and included it ourselves in the posts controller, because joel prefers this way!

  def index
    @posts = Post.all
    respond_to do |format|
      format.html {}
      format.json {render :json => @posts}
    end
  end

this enables me to request the html version or the json version and it gives it back to me

burning airlines pro-tip: backbone gem for rails

https://github.com/codebrew/backbone-rails

this will go and scaffold out the backbone code from the beginning

because this is going to be a single page application i want a single page

root :to => 'posts#landing' in my routes

in my controller

def landing
end

create landing.html.erb in my views

included this in our blog.js file:

_.templateSettings = { interpolate: /{{(.+?)}}/g };

and changed our landing.html.erb file from erb tags to handlebars curly brackets

app.Posts = Backbone.Collection.extend({
  url: '/posts',
  model: app.Post
});

addded the url to the posts.js file so that it knows where to make the request on the server

removed the seed data

in blog.js, we moved the router into a .done function to happen after the posts are loaded

when we are d0ing burning airlines we will need to make fetch requests to flights and seats etc

--

changed the slugs to ids

in post.js and postListView

How to remove the # from the url - best not to do this:

In the blog.js file add pushState: true

Backbone.history.start({pushState: true});

this makes the url prettier, but when i send this link to someone and they open it in a new tab

what happens is that they see it in a completely different page

if you use pushState navigation, it makes it look like a regular url, but when sent to a friend, the request that comes into the server it just posts/3, so somebody loading the page is no longer inside the backbone app, and they have the ability to edit, delete, etc

have to look up tutorials to make sure this doesnt happen, but it's a lot of effort to get rid of a hash!

also, pushState is also only supported by some brosers

to get browser support for pushState:

pushState: Modernizr.history

include this in application.html.erb

<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>


we will look at polling requests for buringin airlines, where we make the fetch request happen every second, as opposed to every time the page loads

###Homework

http://jsfiddle.net/9d659trn/

exercise 2:

http://addyosmani.github.io/backbone-fundamentals/#Exercise 2: Book Library - Your First RESTful Backbone.js App

##Thursday

###Warmup

Prime Factors:

https://gist.github.com/anonymous-wolf/53bf5af6f4df75bf882c

https://gist.github.com/anonymous-wolf/056364f6f783123ab43d

https://github.com/wofockham/wdi-8/blob/master/0x-bonus/prime_factors/prime_factors.rb

###Backbone Ajax Post

Backbone forms:

https://github.com/powmedia/backbone-forms

In our intro / animals app:

<script src="js/backbone-forms.js"></script>

curl https://raw.githubusercontent.com/powmedia/backbone-forms/master/distribution/backbone-forms.js > js/backbone-forms.js

add into intro.js

  schema: {
  type: 'Text'
  ecosystem: 'Text',
  stripes: 'Number'
  // in the animal model there will be this schema key, its only the form that
  // cares about it 
},

Creating a new form and appending to the page:

In the console:

 var animal = new Animal()
intro.js:14 I am a new animal
undefined
var form = new Backbone.Form({model: animal})
undefined
form.render()
child {cid: "view6", model: child, $el: jQuery.fn.init[1], el: form, options: Object…}$el: jQuery.fn.init[1]Field: function (){ return parent.apply(this, arguments); }Fieldset: function (){ return parent.apply(this, arguments); }NestedField: function (){ return parent.apply(this, arguments); }cid: "view6"el: formfields: Objectfieldsets: Array[1]model: childoptions: Objectschema: ObjectselectedFields: Array[0]template: function (data) {__proto__: Surrogate
form.el

$('body').append(form.el)
[]

```

```
var form  = new Backbone.Form({model: animal})
undefined
form.render()
child {cid: "view8", model: child, $el: jQuery.fn.init[1], el: form, options: Object…}
$('body').append(form.el)
[]
```

**Event listen to ... comments can be appended to the page three times - watch out for this with burning arlines.**

####Generating a Comment model in backbone blog

 rails generate model Comment post_id:integer author:string :content:text

c1 = Comment.create :author => 'Bilbo', :content => 'Cool post dude'

then set association

or to set up the association from the start:

p1 = Post.find(1)

 p1.comments.create :author => 'Bilbo', :content => 'Cool post dude'

then create the comment js collection and comment js model

now we need to render the views

then we need a comment view and a template


###JS Ecosystem

http://coldhead.ninth.su/jsecosystem/#/

###Georgina from Lookahead Search 

###Backbone flow

the js files jquery, backbone and underscore are loaded before any of our js files are loaded

those all need to appear first in my head

underscore needs to appear first because the others depend on it

the next thing we do is load in our models, collections and views

because of the way we start it with var app = app || {}, we can load them in any order

but good way is to group all models, collections, then views together

then by the time we get down to our blog js, which is where our code actually starts, we have defined our entire app object

so app now has some things hanging off it:

- it has Post and 
- Posts (collection - which knows where to fetch the instance)
- comment
- appview
- postview

so we now have all the things that we actually need loaded in memory 

then the way we actually make things start happening is by starting the router, the backbone history line

so in our blog.js file 

we know we actually need a tangible collection, not a class of posts, but an instance of the posts collection 

the browser will take note of this function, finish loading other js files, run the html, leave the templates alone, get to the bottom of the body, and at that point the document ready fires

the document ready function says if the number of elements on the page with the id of main is 0, abandon everything

but if we do have the right div, it will keep running

(note - use handlebars template for burning airlines)

then we say this app is going to depend on some blog posts

in our app.posts, we have a url where it knows it can go and get its posts from, on line 6 of posts.js it says this ur '/posts', which matches up with the routes.. if you make a get request to /posts, that gives you all of the posts

so we say go and fetch me the blog posts, and only when it is done, should the next thing happen

so once the document is ready, it fires off the fetch request. once the request comes back and the fetch is done, we create the app router, because we now have something which is useful to the user, we have the blog posts

so the app router is ready to go, we have an instance of it, we can do routing as soon as backbone starts listening to changes in the hash, which is what backbone.history.start does

 when the document ready is finished, the main container will be empty
 
 the first thing that the approuter does is it looks for the route, which is '', and it will run the code in the index action (this is specified in the approuter)
 
 so at this point, we have the route, and we have fetched the blog posts from the server
 
 so we are in the index action and it says my job is to show the view on the page. first it creates an instance of the view, and then renders that view
 
 when we created an instance of this view, it ran everything in our initiilize method (in the appview.js file), then everything in the render method for this view will happen.
 
 this is the point at which it is getting the collection, going through each of the posts in the collection, and running the render chunk of code.
 
 so each post is going to have its own view on the page, so the render for the postListView then gets called, which shoves it onto the page
 
 the reason we had a postListView on its own was so that we could listen to something
 
so we now have a global appview, with our postlistviews 

it has the ability to listen for an event, which is a click on a particular view

so as soon as you click on a view, the postlistview.js file tells it to showPost

and the showPost function uses the approuter to take us to the post/id url

the js says if someone clicks on this post item, go to /posts/4

so if i click on this the only thing that happens is it updates the url

so now we have said navigate to /posts/id

and the showpost function says , when this is true, it will take us back to the router

the router sees that we have changed the url, so the viewpost function is then called from the approuter

so the viewpost action runs, and any dynamic part gets passed in to the function (the id is dynamic because it is written ':id' with colon in front of it)

this function viewPost gets the post, creates an instance of the post view, and renders that post on the page

so then we go to the postview

the postView tells it where on the page it is going to go. 

it replaces everything in the div with a main id

because we created a model, inside of here we have access to the model

so we go and find one of our templates, compile it using underscore, and pass in the json object for that model

we say for this view, go and get its element and make its html whatever the object gets back 

so at this point we can see the single post on its own

now we are at the point where we want to see the comments underneath

this is where we make a second ajax request

we want to create a new instance of the comments collection for a particualr post

we say go and make this ajax request for the comments, and then the rest is dealt with in the comments collection itself

the comments collection says when someone initializes or instantiates a new comments collection, save the id so we can remember where it is getting its posts from

then we sya every time a new add event fires, we should run a function, which creates a view for that single comment, and renders that view 

then we look at the comment view, which goes and compiles the template, uses that template for this model, and shoves the comment on the page

the final piece of ajax is when someone clicks on the submit comment button, we call the submit comment function, 

we save the values of the author and content, we create a new comment objct that lives in backbones memory that knows the comment author and which post it belongs to 

this comment now exists in backbone memory but the server has no idea about my comment and what it says

so now i need to persist this to the server

once we have created it in memory, we say save this comment for me

because save has a url associated with it, the comment is forever goign to be associated with this particular post

so that the user can see it on the page, we say once we are done saving this function, go and load all of the comments again, fetch them

so the fetch is called when you first render the comments on the post, but we call fetch a second time when a comment is saved

so my comment will appear at the bottom, and anybody elses comments that may have happened in the last couple of moments will also appear in there

the differnce between get and fetch:

- get is getting someting from the collection in the browser 

- fetch goes and updates the array with whatever is on the server

if we then go to a specific blog post we want ot know whcih comments they have

AJAX - blog posts().fetch

AJAx - posts/3/comments

AJAX - .save

so the rails app really only has to do one thing 

it serves up the very first page

and after that this has everyting we need to show us 

after the first page is loaded, all of the interaction with rails is just through json

it's a single page app because this is a single page, and it goes and gets dynamic data by making requests to json

so the only html page that we have used is the root, thats the only html page that we serve up

##Friday

###Burning Airlines Lab

the admin thing 

models associations seed data

one person do admin

one person do search

one person do the flight booking

https://gist.github.com/wofockham/7d9ef83a3362c8d4d8af




Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment