Fixed a bug with the updater.
This commit is contained in:
		
							parent
							
								
									e7625991a1
								
							
						
					
					
						commit
						58c3d50bce
					
				
							
								
								
									
										2
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										2
									
								
								Makefile
								
								
								
								
							|  | @ -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 \
 | ||||||
|  |  | ||||||
							
								
								
									
										116
									
								
								backbonestore.nw
								
								
								
								
							
							
						
						
									
										116
									
								
								backbonestore.nw
								
								
								
								
							|  | @ -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"> | ||||||
|  | @ -388,23 +390,23 @@ you should understand this fairly easily. | ||||||
| And here is the HTML: | And here is the HTML: | ||||||
| 
 | 
 | ||||||
| <<product list template>>= | <<product list template>>= | ||||||
|     <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> | ||||||
|         <% for(i=0,l=products.length;i<l;++i) { p = products[i]; %> |     <% for(i=0,l=products.length;i<l;++i) { p = products[i]; %> | ||||||
|         <li class="item"> |     <li class="item"> | ||||||
|           <div class="item-image"> |       <div class="item-image"> | ||||||
|             <a href="#item/<%= p.id %>"> |         <a href="#item/<%= p.id %>"> | ||||||
|               <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) { | ||||||
|  | @ -499,33 +509,33 @@ The product detail template is fairly straightforward.  There is no | ||||||
| [[underscore]] magic because there are no loops. | [[underscore]] magic because there are no loops. | ||||||
| 
 | 
 | ||||||
| <<product detail template>>= | <<product detail template>>= | ||||||
|     <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 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> |   </div> | ||||||
|       <div class="item-info"> |   <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> | ||||||
|         <form action="#/cart" method="post"> |     <form action="#/cart" method="post"> | ||||||
|           <p> |       <p> | ||||||
|             <label>Quantity:</label> |         <label>Quantity:</label> | ||||||
|             <input class="uqf" name="quantity" size="2" type="text" value="1" /> |         <input class="uqf" name="quantity" size="2" type="text" value="1" /> | ||||||
|           </p> |       </p> | ||||||
|           <p> |       <p> | ||||||
|             <input class="uq" type="submit" value="Add to Cart" /> |         <input class="uq" type="submit" value="Add to Cart" /> | ||||||
|           </p> |       </p> | ||||||
|         </form> |     </form> | ||||||
|         <div class="item-link"> |     <div class="item-link"> | ||||||
|           <a href="<%= url %>">Buy this item on Amazon</a> |       <a href="<%= url %>">Buy this item on Amazon</a> | ||||||
|         </div> |     </div> | ||||||
|         <div class="back-link"> |     <div class="back-link"> | ||||||
|           <a href="#">« Back to Items</a> |       <a href="#">« Back to Items</a> | ||||||
|         </div> |     </div> | ||||||
|       </div> |   </div> | ||||||
|     </script> | </script> | ||||||
| @  | @  | ||||||
| 
 | 
 | ||||||
| So, let's talk about that shopping cart thing.  We've been making the | 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: | And the HTML for the template is dead simple: | ||||||
| 
 | 
 | ||||||
| <<cart template>>= | <<cart template>>= | ||||||
|     <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> | ||||||
| 
 | 
 | ||||||
| @  | @  | ||||||
| %$ | %$ | ||||||
|  | @ -722,6 +732,8 @@ Here's the entirety of the program: | ||||||
| 
 | 
 | ||||||
| <<product detail view>> | <<product detail view>> | ||||||
| 
 | 
 | ||||||
|  | <<cart widget>> | ||||||
|  | 
 | ||||||
| <<router>> | <<router>> | ||||||
| 
 | 
 | ||||||
| <<initialization>> | <<initialization>> | ||||||
|  |  | ||||||
							
								
								
									
										134
									
								
								index.html
								
								
								
								
							
							
						
						
									
										134
									
								
								index.html
								
								
								
								
							|  | @ -1,73 +1,75 @@ | ||||||
| <!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> | ||||||
|     <script id="store_index_template" type="text/x-underscore-tmplate"> |         <link rel="stylesheet" href="jsonstore.css" type="text/css"> | ||||||
|       <h1>Product Catalog</h1> |         <script id="store_index_template" type="text/x-underscore-tmplate"> | ||||||
|       <ul> |           <h1>Product Catalog</h1> | ||||||
|         <% for(i=0,l=products.length;i<l;++i) { p = products[i]; %> |           <ul> | ||||||
|         <li class="item"> |             <% for(i=0,l=products.length;i<l;++i) { p = products[i]; %> | ||||||
|           <div class="item-image"> |             <li class="item"> | ||||||
|             <a href="#item/<%= p.id %>"> |               <div class="item-image"> | ||||||
|               <img alt="<%= p.title %>" src="<%= p.image %>" /> |                 <a href="#item/<%= p.id %>"> | ||||||
|             </a> |                   <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> |           </div> | ||||||
|         </li> |           <div class="item-info"> | ||||||
|         <div class="item-artist"><%= p.artist %></div> |             <div class="item-artist"><%= artist %></div> | ||||||
|         <div class="item-title"><%= p.title %></div> |             <div class="item-title"><%= title %></div> | ||||||
|         <div class="item-price">$<%= p.price %></div> |             <div class="item-price">$<%= price %></div> | ||||||
|         <% } %> |             <form action="#/cart" method="post"> | ||||||
|       </ul> |               <p> | ||||||
|     </script> |                 <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="#">« 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"> |     </head> | ||||||
|       <div class="item-detail"></div> |     <body> | ||||||
|       <div class="item-image"> |         <div id="container"> | ||||||
|         <img alt="<%= title %>" src="<%= large_image %>" /> |             <div id="header"> | ||||||
|       </div> |                 <h1> | ||||||
|       <div class="item-info"></div> |                     The Backbone Store | ||||||
|       <div class="item-artist"><%= artist %></div> |                 </h1> | ||||||
|       <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="#">« Back to Items</a> |  | ||||||
|       </div> |  | ||||||
|     </script> |  | ||||||
| 
 | 
 | ||||||
|     <script id="store_cart_template" type="text/x-underscore-template"> |                 <div class="cart-info"> | ||||||
|       <p>Items: <%= count %> ($<%= cost %>)</p> |                 </div> | ||||||
|     </script> |             </div> | ||||||
| 
 | 
 | ||||||
|   </head> |             <div id="main"> </div> | ||||||
| 
 |         </div> | ||||||
|   <body> |         <script src="jquery-1.6.2.min.js" type="text/javascript"></script> | ||||||
|     <div id="container"> |         <script src="underscore.js" type="text/javascript"></script> | ||||||
|       <div id="header"> |         <script src="backbone.js" type="text/javascript"></script> | ||||||
|         <h1> |         <script src="store.js" type="text/javascript"></script> | ||||||
|           The Backbone Store |     </body> | ||||||
|         </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> |  | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
							
								
								
									
										34
									
								
								store.js
								
								
								
								
							
							
						
						
									
										34
									
								
								store.js
								
								
								
								
							|  | @ -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); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue