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; \
fi
index.html:
index.html: backbonestore.nw
@ $(ECHO) $(NOTANGLE) -c -R$@ $<
@ - $(NOTANGLE) -c -R$@ $< > $*.nw-html-tmp
@ if [ -s "$*.nw-html-tmp" ]; then \

View File

@ -137,16 +137,18 @@ product, but a reference to the products and a quantity.
One thing we will be doing is changing the quantity, so I have
provided a convenience function for the Item that allows you to do
that. Now, no client classes such as Views need to know how the
quantity is updated.
quantity is updated.
Also, it would be nice to know the total price of the Item.
<<cart models>>=
var Item = Backbone.Model.extend({
update: function(amount) {
this.set({'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');
}
});
@ -236,7 +238,7 @@ and remove tabs from the top of the viewport as needed.
<<base view>>=
var _BaseView = Backbone.View.extend({
parent: '#main',
parent: $('#main'),
className: 'viewport',
@
@ -313,8 +315,8 @@ for our one-page application:
</title>
<link rel="stylesheet" href="jsonstore.css" type="text/css">
<<product list template>>
<<product template>>
<<checkout template>>
<<product detail template>>
<<cart template>>
</head>
<body>
<div id="container">
@ -388,23 +390,23 @@ you should understand this fairly easily.
And here is the HTML:
<<product list template>>=
<script id="store_index_template" type="text/x-underscore-tmplate">
<h1>Product Catalog</h1>
<ul>
<% for(i=0,l=products.length;i<l;++i) { p = products[i]; %>
<li class="item">
<div class="item-image">
<a href="#item/<%= p.id %>">
<img alt="<%= p.title %>" src="<%= p.image %>" />
</a>
</div>
</li>
<div class="item-artist"><%= p.artist %></div>
<div class="item-title"><%= p.title %></div>
<div class="item-price">$<%= p.price %></div>
<% } %>
</ul>
</script>
<script id="store_index_template" type="text/x-underscore-tmplate">
<h1>Product Catalog</h1>
<ul>
<% for(i=0,l=products.length;i<l;++i) { p = products[i]; %>
<li class="item">
<div class="item-image">
<a href="#item/<%= p.id %>">
<img alt="<%= p.title %>" src="<%= p.image %>" />
</a>
</div>
<div class="item-artist"><%= p.artist %></div>
<div class="item-title"><%= p.title %></div>
<div class="item-price">$<%= p.price %></div>
</li>
<% } %>
</ul>
</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
and each item's relationship to its collection belongs in the
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>>=
update: function(e) {
e.preventDefault();
this.item.update(parseInt($('.uqf').val()));
this.item.update(parseInt(this.$('.uqf').val()));
},
updateOnEnter: function(e) {
@ -499,33 +509,33 @@ The product detail template is fairly straightforward. There is no
[[underscore]] magic because there are no loops.
<<product detail template>>=
<script id="store_item_template" type="text/x-underscore-template">
<div class="item-detail">
<div class="item-image">
<img alt="<%= title %>" src="<%= large_image %>" />
</div>
</div>
<div class="item-info">
<div class="item-artist"><%= artist %></div>
<div class="item-title"><%= title %></div>
<div class="item-price">$<%= price %></div>
<form action="#/cart" method="post">
<p>
<label>Quantity:</label>
<input class="uqf" name="quantity" size="2" type="text" value="1" />
</p>
<p>
<input class="uq" type="submit" value="Add to Cart" />
</p>
</form>
<div class="item-link">
<a href="<%= url %>">Buy this item on Amazon</a>
</div>
<div class="back-link">
<a href="#">&laquo; Back to Items</a>
</div>
</div>
</script>
<script id="store_item_template" type="text/x-underscore-template">
<div class="item-detail">
<div class="item-image">
<img alt="<%= title %>" src="<%= large_image %>" />
</div>
</div>
<div class="item-info">
<div class="item-artist"><%= artist %></div>
<div class="item-title"><%= title %></div>
<div class="item-price">$<%= price %></div>
<form action="#/cart" method="post">
<p>
<label>Quantity:</label>
<input class="uqf" name="quantity" size="2" type="text" value="1" />
</p>
<p>
<input class="uq" type="submit" value="Add to Cart" />
</p>
</form>
<div class="item-link">
<a href="<%= url %>">Buy this item on Amazon</a>
</div>
<div class="back-link">
<a href="#">&laquo; Back to Items</a>
</div>
</div>
</script>
@
So, let's talk about that shopping cart thing. We've been making the
@ -570,9 +580,9 @@ show that it did changed:
And the HTML for the template is dead simple:
<<cart template>>=
<script id="store_cart_template" type="text/x-underscore-template">
<p>Items: <%= count %> ($<%= cost %>)</p>
</script>
<script id="store_cart_template" type="text/x-underscore-template">
<p>Items: <%= count %> ($<%= cost %>)</p>
</script>
@
%$
@ -722,6 +732,8 @@ Here's the entirety of the program:
<<product detail view>>
<<cart widget>>
<<router>>
<<initialization>>

View File

@ -1,73 +1,75 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>The Backbone Store</title>
<link charset="utf-8" href="jsonstore.css" rel="stylesheet" type="text/css" />
<script id="store_index_template" type="text/x-underscore-tmplate">
<h1>Product Catalog</h1>
<ul>
<% for(i=0,l=products.length;i<l;++i) { p = products[i]; %>
<li class="item">
<div class="item-image">
<a href="#item/<%= p.id %>">
<img alt="<%= p.title %>" src="<%= p.image %>" />
</a>
<head>
<title>
The Backbone Store
</title>
<link rel="stylesheet" href="jsonstore.css" type="text/css">
<script id="store_index_template" type="text/x-underscore-tmplate">
<h1>Product Catalog</h1>
<ul>
<% for(i=0,l=products.length;i<l;++i) { p = products[i]; %>
<li class="item">
<div class="item-image">
<a href="#item/<%= p.id %>">
<img alt="<%= p.title %>" src="<%= p.image %>" />
</a>
</div>
<div class="item-artist"><%= p.artist %></div>
<div class="item-title"><%= p.title %></div>
<div class="item-price">$<%= p.price %></div>
</li>
<% } %>
</ul>
</script>
<script id="store_item_template" type="text/x-underscore-template">
<div class="item-detail">
<div class="item-image">
<img alt="<%= title %>" src="<%= large_image %>" />
</div>
</div>
</li>
<div class="item-artist"><%= p.artist %></div>
<div class="item-title"><%= p.title %></div>
<div class="item-price">$<%= p.price %></div>
<% } %>
</ul>
</script>
<div class="item-info">
<div class="item-artist"><%= artist %></div>
<div class="item-title"><%= title %></div>
<div class="item-price">$<%= price %></div>
<form action="#/cart" method="post">
<p>
<label>Quantity:</label>
<input class="uqf" name="quantity" size="2" type="text" value="1" />
</p>
<p>
<input class="uq" type="submit" value="Add to Cart" />
</p>
</form>
<div class="item-link">
<a href="<%= url %>">Buy this item on Amazon</a>
</div>
<div class="back-link">
<a href="#">&laquo; Back to Items</a>
</div>
</div>
</script>
<script id="store_cart_template" type="text/x-underscore-template">
<p>Items: <%= count %> ($<%= cost %>)</p>
</script>
<script id="store_item_template" type="text/x-underscore-template">
<div class="item-detail"></div>
<div class="item-image">
<img alt="<%= title %>" src="<%= large_image %>" />
</div>
<div class="item-info"></div>
<div class="item-artist"><%= artist %></div>
<div class="item-title"><%= title %></div>
<div class="item-price">$<%= price %></div>
<div class="item-form"></div>
<form action="#/cart" method="post">
<p>
<label>Quantity:</label>
<input class="uqf" name="quantity" size="2" type="text" value="1" />
</p>
<p>
<input class="uq" type="submit" value="Add to Cart" />
</p>
</form>
<div class="item-link">
<a href="<%= url %>">Buy this item on Amazon</a>
</div>
<div class="back-link">
<a href="#">&laquo; Back to Items</a>
</div>
</script>
</head>
<body>
<div id="container">
<div id="header">
<h1>
The Backbone Store
</h1>
<script id="store_cart_template" type="text/x-underscore-template">
<p>Items: <%= count %> ($<%= cost %>)</p>
</script>
<div class="cart-info">
</div>
</div>
</head>
<body>
<div id="container">
<div id="header">
<h1>
The Backbone Store
</h1>
<div class="cart-info"></div>
</div>
<div id="main"></div>
</div>
<script src="jquery-1.6.2.min.js" type="text/javascript"></script>
<script src="underscore.js" type="text/javascript"></script>
<script src="backbone.js" type="text/javascript"></script>
<script src="store.js" type="text/javascript"></script>
</body>
<div id="main"> </div>
</div>
<script src="jquery-1.6.2.min.js" type="text/javascript"></script>
<script src="underscore.js" type="text/javascript"></script>
<script src="backbone.js" type="text/javascript"></script>
<script src="store.js" type="text/javascript"></script>
</body>
</html>

View File

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

View File

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