Fixed a bug with the updater.

This commit is contained in:
Elf M. Sternberg 2011-08-07 17:44:17 -07:00
parent e7625991a1
commit 58c3d50bce
5 changed files with 162 additions and 135 deletions

View File

@ -39,7 +39,7 @@ store.js: backbonestore.nw
rm $*.nw-tmp; \ rm $*.nw-tmp; \
fi fi
index.html: index.html: backbonestore.nw
@ $(ECHO) $(NOTANGLE) -c -R$@ $< @ $(ECHO) $(NOTANGLE) -c -R$@ $<
@ - $(NOTANGLE) -c -R$@ $< > $*.nw-html-tmp @ - $(NOTANGLE) -c -R$@ $< > $*.nw-html-tmp
@ if [ -s "$*.nw-html-tmp" ]; then \ @ if [ -s "$*.nw-html-tmp" ]; then \

View File

@ -144,9 +144,11 @@ Also, it would be nice to know the total price of the Item.
<<cart models>>= <<cart models>>=
var Item = Backbone.Model.extend({ var Item = Backbone.Model.extend({
update: function(amount) { update: function(amount) {
this.set({'quantity': amount}); this.set({'quantity': amount}, {silent: true});
this.collection.trigger('change', this);
}, },
price: function() { price: function() {
console.log(this.get('product').get('title'), this.get('quantity'));
return this.get('product').get('price') * this.get('quantity'); return this.get('product').get('price') * this.get('quantity');
} }
}); });
@ -236,7 +238,7 @@ and remove tabs from the top of the viewport as needed.
<<base view>>= <<base view>>=
var _BaseView = Backbone.View.extend({ var _BaseView = Backbone.View.extend({
parent: '#main', parent: $('#main'),
className: 'viewport', className: 'viewport',
@ @
@ -313,8 +315,8 @@ for our one-page application:
</title> </title>
<link rel="stylesheet" href="jsonstore.css" type="text/css"> <link rel="stylesheet" href="jsonstore.css" type="text/css">
<<product list template>> <<product list template>>
<<product template>> <<product detail template>>
<<checkout template>> <<cart template>>
</head> </head>
<body> <body>
<div id="container"> <div id="container">
@ -398,10 +400,10 @@ And here is the HTML:
<img alt="<%= p.title %>" src="<%= p.image %>" /> <img alt="<%= p.title %>" src="<%= p.image %>" />
</a> </a>
</div> </div>
</li>
<div class="item-artist"><%= p.artist %></div> <div class="item-artist"><%= p.artist %></div>
<div class="item-title"><%= p.title %></div> <div class="item-title"><%= p.title %></div>
<div class="item-price">$<%= p.price %></div> <div class="item-price">$<%= p.price %></div>
</li>
<% } %> <% } %>
</ul> </ul>
</script> </script>
@ -467,12 +469,20 @@ get its id and so forth. All of that has been put into the shopping
cart model, which is where it belongs: \textit{knowledge about items cart model, which is where it belongs: \textit{knowledge about items
and each item's relationship to its collection belongs in the and each item's relationship to its collection belongs in the
collection}. collection}.
Look closely at the [[update()]] method. The reference [[this.\$]] is
a special Backbone object that limits selectors to objects inside the
element of the view. Without it, jQuery would have found the first
input field of class 'uqf' in the DOM, not the one for this specific
view. [[this.\$('.uqf')]] is shorthand for [[$('uqf', this.el)]], and
helps clarify what it is you're looking for.
%' %'
<<product detail view>>= <<product detail view>>=
update: function(e) { update: function(e) {
e.preventDefault(); e.preventDefault();
this.item.update(parseInt($('.uqf').val())); this.item.update(parseInt(this.$('.uqf').val()));
}, },
updateOnEnter: function(e) { updateOnEnter: function(e) {
@ -722,6 +732,8 @@ Here's the entirety of the program:
<<product detail view>> <<product detail view>>
<<cart widget>>
<<router>> <<router>>
<<initialization>> <<initialization>>

View File

@ -1,9 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<head> <head>
<title>The Backbone Store</title> <title>
<link charset="utf-8" href="jsonstore.css" rel="stylesheet" type="text/css" /> The Backbone Store
</title>
<link rel="stylesheet" href="jsonstore.css" type="text/css">
<script id="store_index_template" type="text/x-underscore-tmplate"> <script id="store_index_template" type="text/x-underscore-tmplate">
<h1>Product Catalog</h1> <h1>Product Catalog</h1>
<ul> <ul>
@ -14,24 +15,23 @@
<img alt="<%= p.title %>" src="<%= p.image %>" /> <img alt="<%= p.title %>" src="<%= p.image %>" />
</a> </a>
</div> </div>
</li>
<div class="item-artist"><%= p.artist %></div> <div class="item-artist"><%= p.artist %></div>
<div class="item-title"><%= p.title %></div> <div class="item-title"><%= p.title %></div>
<div class="item-price">$<%= p.price %></div> <div class="item-price">$<%= p.price %></div>
</li>
<% } %> <% } %>
</ul> </ul>
</script> </script>
<script id="store_item_template" type="text/x-underscore-template"> <script id="store_item_template" type="text/x-underscore-template">
<div class="item-detail"></div> <div class="item-detail">
<div class="item-image"> <div class="item-image">
<img alt="<%= title %>" src="<%= large_image %>" /> <img alt="<%= title %>" src="<%= large_image %>" />
</div> </div>
<div class="item-info"></div> </div>
<div class="item-info">
<div class="item-artist"><%= artist %></div> <div class="item-artist"><%= artist %></div>
<div class="item-title"><%= title %></div> <div class="item-title"><%= title %></div>
<div class="item-price">$<%= price %></div> <div class="item-price">$<%= price %></div>
<div class="item-form"></div>
<form action="#/cart" method="post"> <form action="#/cart" method="post">
<p> <p>
<label>Quantity:</label> <label>Quantity:</label>
@ -47,22 +47,24 @@
<div class="back-link"> <div class="back-link">
<a href="#">&laquo; Back to Items</a> <a href="#">&laquo; Back to Items</a>
</div> </div>
</div>
</script> </script>
<script id="store_cart_template" type="text/x-underscore-template"> <script id="store_cart_template" type="text/x-underscore-template">
<p>Items: <%= count %> ($<%= cost %>)</p> <p>Items: <%= count %> ($<%= cost %>)</p>
</script> </script>
</head> </head>
<body> <body>
<div id="container"> <div id="container">
<div id="header"> <div id="header">
<h1> <h1>
The Backbone Store The Backbone Store
</h1> </h1>
<div class="cart-info"></div>
<div class="cart-info">
</div> </div>
</div>
<div id="main"> </div> <div id="main"> </div>
</div> </div>
<script src="jquery-1.6.2.min.js" type="text/javascript"></script> <script src="jquery-1.6.2.min.js" type="text/javascript"></script>

View File

@ -33,12 +33,17 @@ body {
img { img {
border: 0; border: 0;
} }
#productlistview ul {
list-style: none;
}
.item { .item {
display: border;
float:left; float:left;
width: 250px; width: 250px;
margin-right: 3px; margin-right: 10px;
padding: 2px; margin-bottom: 10px;
padding: 10px;
border: 1px solid #ccc; border: 1px solid #ccc;
text-align:center; text-align:center;
font-size: 12px; font-size: 12px;

View File

@ -16,12 +16,18 @@
var Item = Backbone.Model.extend({ var Item = Backbone.Model.extend({
update: function(amount) { update: function(amount) {
this.set({'quantity': this.get('quantity') + amount}); this.set({'quantity': amount}, {silent: true});
this.collection.trigger('change', this);
},
price: function() {
console.log(this.get('product').get('title'), this.get('quantity'));
return this.get('product').get('price') * this.get('quantity');
} }
}); });
var ItemCollection = Backbone.Collection.extend({ var ItemCollection = Backbone.Collection.extend({
model: Item, model: Item,
getOrCreateItemForProduct: function(product) { getOrCreateItemForProduct: function(product) {
var i, var i,
pid = product.get('id'), pid = product.get('id'),
@ -35,18 +41,19 @@
this.add(i, {silent: true}) this.add(i, {silent: true})
return i; return i;
}, },
getTotalCount: function() { getTotalCount: function() {
return this.reduce(function(memo, obj) { return this.reduce(function(memo, obj) {
return obj.get('quantity') + memo; }, 0); return obj.get('quantity') + memo; }, 0);
}, },
getTotalCost: function() { getTotalCost: function() {
return this.reduce(function(memo, obj) { return this.reduce(function(memo, obj) {
return (obj.get('product').get('price') * return obj.price() + memo; }, 0);
obj.get('quantity')) + memo; }, 0);
} }
}); });
var _BaseView = Backbone.View.extend({ var _BaseView = Backbone.View.extend({
parent: $('#main'), parent: $('#main'),
className: 'viewport', className: 'viewport',
@ -63,9 +70,8 @@
return null; return null;
} }
promise = $.Deferred(_.bind(function(dfd) { promise = $.Deferred(_.bind(function(dfd) {
this.el.fadeOut('fast', dfd.resolve)}, this)).promise(); this.el.fadeOut('fast', dfd.resolve)}, this));
this.trigger('hide', this); return promise.promise();
return promise;
}, },
show: function() { show: function() {
@ -73,13 +79,12 @@
return; return;
} }
promise = $.Deferred(_.bind(function(dfd) { promise = $.Deferred(_.bind(function(dfd) {
this.el.fadeIn('fast', dfd.resolve) }, this)).promise(); this.el.fadeIn('fast', dfd.resolve) }, this))
return promise.promise();
this.trigger('show', this);
return promise;
} }
}); });
var ProductListView = _BaseView.extend({ var ProductListView = _BaseView.extend({
id: 'productlistview', id: 'productlistview',
template: $("#store_index_template").html(), template: $("#store_index_template").html(),
@ -96,6 +101,7 @@
} }
}); });
var ProductView = _BaseView.extend({ var ProductView = _BaseView.extend({
id: 'productitemview', id: 'productitemview',
template: $("#store_item_template").html(), template: $("#store_item_template").html(),
@ -113,7 +119,7 @@
update: function(e) { update: function(e) {
e.preventDefault(); e.preventDefault();
this.item.update(parseInt($('.uqf').val())); this.item.update(parseInt(this.$('.uqf').val()));
}, },
updateOnEnter: function(e) { updateOnEnter: function(e) {
@ -128,6 +134,7 @@
} }
}); });
var CartWidget = Backbone.View.extend({ var CartWidget = Backbone.View.extend({
el: $('.cart-info'), el: $('.cart-info'),
template: $('#store_cart_template').html(), template: $('#store_cart_template').html(),
@ -137,7 +144,6 @@
}, },
render: function() { render: function() {
console.log(arguments);
this.el.html( this.el.html(
_.template(this.template, { _.template(this.template, {
'count': this.collection.getTotalCount(), 'count': this.collection.getTotalCount(),
@ -147,6 +153,7 @@
} }
}); });
var BackboneStore = Backbone.Router.extend({ var BackboneStore = Backbone.Router.extend({
views: {}, views: {},
products: null, products: null,
@ -200,4 +207,5 @@
new BackboneStore(); new BackboneStore();
Backbone.history.start(); Backbone.history.start();
}); });
}).call(this); }).call(this);