PageRenderTime 53ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/store.js

https://github.com/elfsternberg/The-Backbone-Store
JavaScript | 227 lines | 187 code | 40 blank | 0 comment | 7 complexity | e1f684b9a411badc459945d7c4c1c266 MD5 | raw file
  1. var Product = Backbone.Model.extend({});
  2. var Item = Backbone.Model.extend({
  3. update: function(amount) {
  4. if (amount === this.get('quantity')) {
  5. return this;
  6. }
  7. this.set({quantity: amount}, {silent: true});
  8. this.collection.trigger('update', this);
  9. return this;
  10. },
  11. price: function() {
  12. return this.get('product').get('price') * this.get('quantity');
  13. }
  14. });
  15. var ProductCollection = Backbone.Collection.extend({
  16. model: Product,
  17. initialize: function(models, options) {
  18. this.url = options.url;
  19. },
  20. comparator: function(item) {
  21. return item.get('title');
  22. }
  23. });
  24. var ItemCollection = Backbone.Collection.extend({
  25. model: Item,
  26. updateItemForProduct: function(product, amount) {
  27. amount = amount != null ? amount : 0;
  28. var pid = product.get('id');
  29. var item = this.detect(function(obj) {
  30. return obj.get('product').get('id') === pid;
  31. });
  32. if (item) {
  33. item.update(amount);
  34. return item;
  35. }
  36. return this.add({
  37. product: product,
  38. quantity: amount
  39. });
  40. },
  41. getTotalCount: function() {
  42. var addup = function(memo, obj) {
  43. return memo + obj.get('quantity');
  44. };
  45. return this.reduce(addup, 0);
  46. },
  47. getTotalCost: function() {
  48. var addup = function(memo, obj) {
  49. return memo + obj.price();
  50. };
  51. return this.reduce(addup, 0);
  52. }
  53. });
  54. var BaseView = Backbone.View.extend({
  55. parent: $('#main'),
  56. className: 'viewport',
  57. initialize: function(options) {
  58. Backbone.View.prototype.initialize.apply(this, arguments);
  59. this.$el.hide();
  60. this.parent.append(this.el);
  61. },
  62. hide: function() {
  63. var dfd = $.Deferred();
  64. if (!this.$el.is(':visible')) {
  65. return dfd.resolve();
  66. }
  67. this.$el.fadeOut('fast', function() {
  68. return dfd.resolve();
  69. });
  70. return dfd.promise();
  71. },
  72. show: function() {
  73. var dfd = $.Deferred();
  74. if (this.$el.is(':visible')) {
  75. return dfd.resolve();
  76. }
  77. this.$el.fadeIn('fast', function() {
  78. return dfd.resolve();
  79. });
  80. return dfd.promise();
  81. }
  82. });
  83. var ProductListView = BaseView.extend({
  84. id: 'productlistview',
  85. template: _.template($("#store_index_template").html()),
  86. initialize: function(options) {
  87. BaseView.prototype.initialize.apply(this, arguments);
  88. this.collection.bind('reset', this.render.bind(this));
  89. },
  90. render: function() {
  91. this.$el.html(this.template({
  92. 'products': this.collection.toJSON()
  93. }));
  94. return this;
  95. }
  96. });
  97. var ProductView = BaseView.extend({
  98. className: 'productitemview',
  99. template: _.template($("#store_item_template").html()),
  100. initialize: function(options) {
  101. BaseView.prototype.initialize.apply(this, [options]);
  102. this.itemcollection = options.itemcollection;
  103. },
  104. events: {
  105. "keypress .uqf" : "updateOnEnter",
  106. "click .uq" : "update"
  107. },
  108. update: function(e) {
  109. e.preventDefault();
  110. return this.itemcollection.updateItemForProduct(this.model, parseInt(this.$('.uqf').val()));
  111. },
  112. updateOnEnter: function(e) {
  113. if (e.keyCode === 13) {
  114. this.update(e);
  115. }
  116. },
  117. render: function() {
  118. this.$el.html(this.template(this.model.toJSON()));
  119. return this;
  120. }
  121. });
  122. var CartWidget = Backbone.View.extend({
  123. el: $('.cart-info'),
  124. template: _.template($('#store_cart_template').html()),
  125. initialize: function() {
  126. Backbone.View.prototype.initialize.apply(this, arguments);
  127. this.collection.bind('update', this.render.bind(this));
  128. },
  129. render: function() {
  130. var tel = this.$el.html(this.template({
  131. 'count': this.collection.getTotalCount(),
  132. 'cost': this.collection.getTotalCost()
  133. }));
  134. tel.animate({ paddingTop: '30px' }).animate({ paddingTop: '10px' });
  135. return this;
  136. }
  137. });
  138. var BackboneStore = Backbone.Router.extend({
  139. views: {},
  140. products: null,
  141. cart: null,
  142. routes: {
  143. "": "index",
  144. "item/:id": "product"
  145. },
  146. initialize: function(data) {
  147. Backbone.Router.prototype.initialize.apply(this, arguments);
  148. this.cart = new ItemCollection();
  149. new CartWidget({ collection: this.cart });
  150. this.products = new ProductCollection([], { url: 'data/items.json' });
  151. this.views = {
  152. '_index': new ProductListView({ collection: this.products })
  153. };
  154. $.when(this.products.fetch({ reset: true })).then(function() {
  155. return window.location.hash = '';
  156. });
  157. },
  158. hideAllViews: function() {
  159. return _.filter(_.map(this.views, function(v) { return v.hide(); }),
  160. function(t) { return t !== null; });
  161. },
  162. index: function() {
  163. var view = this.views['_index'];
  164. return $.when.apply($, this.hideAllViews()).then(function() {
  165. return view.show();
  166. });
  167. },
  168. product: function(id) {
  169. var view = this.views[id];
  170. if (!view) {
  171. var product = this.products.detect(function(p) {
  172. return p.get('id') === id;
  173. });
  174. view = this.views[id] = new ProductView({
  175. model: product,
  176. itemcollection: this.cart
  177. }).render();
  178. }
  179. return $.when(this.hideAllViews()).then(function() {
  180. return view.show();
  181. });
  182. }
  183. });
  184. $(document).ready(function() {
  185. new BackboneStore();
  186. return Backbone.history.start();
  187. });