...which we'll review!
...and we'll have exercises for each!
// The object "constructor"
var Product = function(config) {
// The object "properties"
this.name = config.name;
this.type = config.type;
this.inventory = config.inventory || 0;
};
// An object "method"
Product.prototype.buy = function() {
this.inventory--;
console.log("We now have " + this.inventory + " of " + this.name);
};
// Instantiating a new object
var product = new Product({
name: "BetaBrand Disco FannyPack",
type: "Accessory",
inventory: 20
});
// Calling a method on a new object
product.buy();
var Shirt = function(config) {
// Re-using the Product constructor
Product.call(this, config);
this.colors = config.colors;
}
// Inheriting the Product methods
Shirt.prototype = Object.create(Product.prototype);
// Defining a new method on this object
Shirt.prototype.addColor = function(color) {
this.colors.push(color);
console.log("We now stock " + color);
};
// Instantiating a new object
var shirt = new Shirt({
name: "Three Wolves Shirt",
type: "T-Shirt",
inventory: 33,
colors: ["black"]
});
shirt.buy();
shirt.addColor("teal");
<script src="http://imagine-it.org/math.js"></script>
<script>
var answer = math.sum(2, 2);
alert(answer);
</script>
// Finding elements
var code = $('code.javascript');
// Reading elements
alert(code.text());
// Changing elements
code.css('background-color', 'pink');
// Creating elements
var newCode = $('<code>// Whee!</code>');
$('#jquery-review').append(newCode);
You can define a basic Backbone Model with .extend()
var Product = Backbone.Model.extend();
You can also pass in an object for more configuration...
var Product = Backbone.Model.extend({
defaults: {
name: "California",
type: "T-shirt",
colors: ["light gray"],
tagline: "Cali says relax",
newProduct: true,
inventory: 28
}
});
Note that an object literal is being passed into .extend()
Consider: Where else have we seen objects as arguments?
Create an empty model that inherits all the defaults
var shirt = new Product();
You can also override the defaults with an object
var shirt = new Product({
name: "Roma",
colors: ["green", "white", "red"],
onSale: true,
freeShippingEligible: false
});
Use .set()
and .get()
for Backbone Models
shirt.set('tagline', 'sempre ad maiora');
shirt.set('newProduct', false);
shirt.set('inventory', 1);
shirt.get('tagline'); //returns 'sempre ad maiora'
shirt.get('newProduct'); // returns false
shirt.get('inventory'); // returns 1
If you try to access Model properties via dot/bracket notation, they'll be undefined
shirt.tagline; // undefined
shirt['tagline']; // undefined
var Product = Backbone.Model.extend({
initialize: function() {
this.set('url', 'http://products.com/' + this.get("id"));
}
});
var Product = Backbone.Model.extend({
makeSentence: function() {
console.log("Check out our very special " + this.get('type') + ".");
}
});
You can define a basic Backbone Collection with .extend()
var Products = Backbone.Collection.extend();
You can also pass in an object for more configuration...
var Products = Backbone.Collection.extend({
model: Product
});
Pass an array of models:
var products = new Products([product1, product2, product3]);
Or pass a JSON array:
var products = new Products([
{name: "I Love JS",
colors: ["yellow", "black"]
},
{name: "Three Wolves",
colors: ["blue"]
}]);
Use comparator
as a property to sort a Collection
var Products = Backbone.Collection.extend({
comparator: 'inventory'
});
Or for something more complex, use .comparator()
as a method that returns a value to sort by
var Products = Backbone.Collection.extend({
comparator: function(model) {
return model.get("name").toLowerCase();
}
});
Adding models:
products.add([product4, product5]);
Removing models:
products.remove(product1);
You can define a basic Backbone View with .extend()
var ProductListing = Backbone.View.extend();
You can also pass in an object for more configuration...
var ProductListing = Backbone.View.extend({
tagName: "div", // default
className: "product"
});
var ProductListing = Backbone.View.extend({
className: "product",
render: function() {
this.$el.append('<img src="http://placepuppy.it/200/200">');
return this;
}
});
var ProductListing = Backbone.View.extend({
className: "product",
render: function() {
var imgUrl = this.model.get('imgUrl');
var newNode = $('<img src="' + imgUrl + '">');
this.$el.append(newNode);
return this;
}
});
var product = new Product({imgUrl: "http://placekitten.com/200/100"});
var listing = new ProductListing({
model: product
});
Create the view:
var listing = new ProductListing({
model: product
});
Then append it:
listing.render();
$('#products').append(listing.$el);
..or...
var listingEl = listing.render().$el;
$('#products').append(listingEl);
...or...
$('#products').append(listing.render().$el);
var ProductListing = Backbone.View.extend({
events: {
'mouseover img' : 'showTooltip',
'mouseout img': 'hideTooltip'
},
showTooltip: function(e) {
var tooltipDiv = $('<div class="product-tooltip">');
tooltipDiv.html('<strong>' + this.model.get('review') + ' stars: </strong>');
tooltipDiv.css({'position': 'absolute', 'top': e.pageY, 'left': e.pageX});
this.$el.append(tooltipDiv);
},
hideTooltip: function(e) {
this.$('.product-tooltip').remove();
}
});
Listen to Backbone events with .listenTo()
var ProductListing = Backbone.View.extend({
initialize: function() {
this.listenTo(this.model, 'change', this.render)
},
render: function() {
// ...
}
});
'add' 'remove' 'sort' 'change'
and more...
Trigger custom events with .trigger()
var ProductModel = Backbone.Model.extend({
initialize: function() {
this.trigger('ready');
}
});
You can listen to these events, too
var ProductView = Backbone.View.extend({
initialize: function() {
this.listenTo(this.model, 'ready', this.render)
},
render: function() {
// ...
}
});
Handlebars is an HTML templating library. To use it:
1. Include handlebars.js on your page
2. Make a template script tag:
<script id="product-template" type="text/x-handlebars-template">
<strong>{{ product.name }}</strong>: {{ product.inventory }} in stock
</script>
3. Compile the template and render it with your data:
var source = $("#product-template").html();
var template = Handlebars.compile(source);
var litterRobot = {"name": "Litter Robot", "inventory": 20};
var rendered = template({product: litterRobot});
In the HTML:
<script id="products-template" type="text/x-handlebars-template">
{{#each products}}
<div class="product">
<strong>{{ name }}</strong>: {{ inventory }} in stock
</div>
{{/each}}
</script>
In the JS:
var ProductsListing = Backbone.View.extend({
className: 'products',
render: function() {
var template = Handlebars.compile($("#products-template").html());
var rendered = template({products: this.collection.toJSON()});
this.$el.append(rendered);
return this;
}
});
var products = new Products([product1, product2]);
var listings = new ProductsListing({collection: products});
Operation name | HTTP method | Backbone Model | Backbone Collection |
CREATE | POST | model.save() | |
READ | GET | model.fetch() | collection.fetch() |
UPDATE | PUT | model.save() | |
DELETE | DELETE | model.destroy() |
.save()
var Product = Backbone.Model.extend({
urlRoot: 'http://gdibb.herokuapp.com/products'
});
var shirt = new Product({
desc: "GDISF Backbone.js",
category: "t-shirt",
price: "20",
inventory: 10
});
shirt.save();
HTTP POST http://gdibb.herokuapp.com/products
.save()
shirt.set('inStock', true);
shirt.save();
HTTP PUT http://gdibb.herokuapp.com/products/<id>
.destroy()
shirt.destroy();
HTTP DELETE http://gdibb.herokuapp.com/products/<id>
.fetch()
var ProductCollection = Backbone.Collection.extend({
url: "http://gdibb.herokuapp.com/products",
model: Product
});
var products = new ProductCollection();
products.fetch(); // sets models on the collection from the response
HTTP GET http://gdibb.herokuapp.com/products
var BookShelfView = Backbone.View.extend({
initialize: function() {
this.listenTo(this.collection, 'reset', this.render);
this.fetch();
},
render: function() {
// ...
}
});
Figure out what's important to you:
modularity? data binding? testability? persistance?
Review your options:
Ember? Spine? AngularJS? Enyo? and many more...