Updating to post-modern standards.
This commit is contained in:
parent
7678aa3e16
commit
88cf744296
|
@ -0,0 +1,54 @@
|
|||
!!! 5
|
||||
%html{:xmlns => "http://www.w3.org/1999/xhtml"}
|
||||
%head
|
||||
%title The Backbone Store
|
||||
%link{:charset => "utf-8", :href => "jsonstore.css", :rel => "stylesheet", :type => "text/css"}/
|
||||
|
||||
%script#store_index_template(type="text/x-underscore-tmplate")
|
||||
%h1 Product Catalog
|
||||
%ul
|
||||
<% for(i=0,l=products.length;i<l;++i) { p = products[i]; %>
|
||||
%li.item
|
||||
.item-image
|
||||
%a{:href => "#item/<%= p.id %>"}
|
||||
%img{:src => "<%= p.image %>", :alt => "<%= p.title %>"}/
|
||||
.item-artist <%= p.artist %>
|
||||
.item-title <%= p.title %>
|
||||
.item-price $<%= p.price %>
|
||||
<% } %>
|
||||
|
||||
%script#store_item_template(type= "text/x-underscore-template")
|
||||
.item-detail
|
||||
.item-image
|
||||
%img(src="<%= large_image %>" alt="<%= title %>")/
|
||||
.item-info
|
||||
.item-artist <%= artist %>
|
||||
.item-title <%= title %>
|
||||
.item-price $<%= price %>
|
||||
.item-form
|
||||
%form(action="#/cart" method="post")
|
||||
%p
|
||||
%label Quantity:
|
||||
%input(type="text" size="2" name="quantity" value="1" class="uqf")/
|
||||
%p
|
||||
%input(type="submit" value="Add to Cart" class="uq")/
|
||||
|
||||
.item-link
|
||||
%a(href="<%= url %>") Buy this item on Amazon
|
||||
.back-link
|
||||
%a(href="#") « Back to Items
|
||||
|
||||
%script#store_cart_template(type="text/x-underscore-template")
|
||||
%p Items: <%= count %> ($<%= cost %>)
|
||||
|
||||
%body
|
||||
#container
|
||||
#header
|
||||
%h1
|
||||
The Backbone Store
|
||||
.cart-info
|
||||
#main
|
||||
%script{:src => "jquery-1.6.2.min.js", :type => "text/javascript"}
|
||||
%script{:src => "underscore.js", :type => "text/javascript"}
|
||||
%script{:src => "backbone.js", :type => "text/javascript"}
|
||||
%script{:src => "store.js", :type => "text/javascript"}
|
|
@ -0,0 +1,164 @@
|
|||
class Product extends Backbone.Model
|
||||
|
||||
class ProductCollection extends Backbone.Collection
|
||||
model: Product
|
||||
|
||||
initialize: (models, options) ->
|
||||
@url = options.url
|
||||
@
|
||||
|
||||
comparator: (item) ->
|
||||
item.get('title')
|
||||
|
||||
|
||||
class Item extends Backbone.Model
|
||||
update: (amount) ->
|
||||
@set {quantity: @get('quantity') + amount}
|
||||
|
||||
class ItemCollection extends Backbone.Collection
|
||||
model: Item
|
||||
|
||||
getOrCreateItemForProduct: (product) ->
|
||||
pid = product.get('id')
|
||||
i = this.detect (obj) -> (obj.get('product').get('id') == pid)
|
||||
if (i)
|
||||
return i
|
||||
i = new Item
|
||||
product: product
|
||||
quantity: 0
|
||||
@add i, {silent: true}
|
||||
i
|
||||
|
||||
getTotalCount: () ->
|
||||
addup = (memo, obj) -> obj.get('quantity') + memo
|
||||
@reduce addup, 0
|
||||
|
||||
getTotalCost: () ->
|
||||
addup = (memo, obj) ->
|
||||
(obj.get('product').get('price') *
|
||||
obj.get('quantity')) + memo
|
||||
@reduce addup, 0
|
||||
|
||||
class _BaseView extends Backbone.View
|
||||
parent: $('#main')
|
||||
className: 'viewport'
|
||||
|
||||
initialize: () ->
|
||||
@el = $(@el)
|
||||
@el.hide()
|
||||
@parent.append(@el)
|
||||
@
|
||||
|
||||
hide: () ->
|
||||
if not @el.is(':visible')
|
||||
return null
|
||||
|
||||
# Make a note here about how the => operator replaces the need for
|
||||
# _.bind()
|
||||
promise = $.Deferred (dfd) => @el.fadeOut('fast', dfd.resolve)
|
||||
@trigger 'hide', @
|
||||
promise.promise()
|
||||
|
||||
show: () ->
|
||||
if @el.is(':visible')
|
||||
return
|
||||
|
||||
promise = $.Deferred (dfd) => @el.fadeIn('fast', dfd.resolve)
|
||||
@trigger 'show', @
|
||||
promise.promise()
|
||||
|
||||
|
||||
class ProductListView extends _BaseView
|
||||
id: 'productlistview'
|
||||
template: $("#store_index_template").html()
|
||||
|
||||
initialize: (options) ->
|
||||
@constructor.__super__.initialize.apply @, [options]
|
||||
@collection.bind 'reset', _.bind(@render, @)
|
||||
|
||||
render: () ->
|
||||
@el.html(_.template(@template, {'products': @collection.toJSON()}))
|
||||
@
|
||||
|
||||
class ProductView extends _BaseView
|
||||
id: 'productitemview'
|
||||
template: $("#store_item_template").html()
|
||||
initialize: (options) ->
|
||||
@constructor.__super__.initialize.apply @, [options]
|
||||
@itemcollection = options.itemcollection
|
||||
@item = @itemcollection.getOrCreateItemForProduct @model
|
||||
@
|
||||
|
||||
events:
|
||||
"keypress .uqf" : "updateOnEnter"
|
||||
"click .uq" : "update"
|
||||
|
||||
update: (e) ->
|
||||
e.preventDefault()
|
||||
@item.update parseInt($('.uqf').val())
|
||||
|
||||
updateOnEnter: (e) ->
|
||||
if (e.keyCode == 13)
|
||||
@update e
|
||||
|
||||
render: () ->
|
||||
@el.html(_.template(@template, @model.toJSON()));
|
||||
@
|
||||
|
||||
class CartWidget extends Backbone.View
|
||||
el: $('.cart-info')
|
||||
template: $('#store_cart_template').html()
|
||||
|
||||
initialize: () ->
|
||||
@collection.bind('change', _.bind(@render, @));
|
||||
|
||||
render: () ->
|
||||
tel = @el.html _.template @template,
|
||||
'count': @collection.getTotalCount()
|
||||
'cost': @collection.getTotalCost()
|
||||
tel.animate({paddingTop: '30px'}).animate({paddingTop: '10px'})
|
||||
@
|
||||
|
||||
class BackboneStore extends Backbone.Router
|
||||
views: {}
|
||||
products: null
|
||||
cart: null
|
||||
|
||||
routes:
|
||||
"": "index"
|
||||
"item/:id": "product"
|
||||
|
||||
initialize: (data) ->
|
||||
@cart = new ItemCollection()
|
||||
new CartWidget
|
||||
collection: @cart
|
||||
|
||||
@products = new ProductCollection [],
|
||||
url: 'data/items.json'
|
||||
@views =
|
||||
'_index': new ProductListView
|
||||
collection: @products
|
||||
$.when(@products.fetch({reset: true}))
|
||||
.then(() -> window.location.hash = '')
|
||||
@
|
||||
|
||||
hideAllViews: () ->
|
||||
_.select(_.map(@views, (v) -> return v.hide()),
|
||||
(t) -> t != null)
|
||||
|
||||
index: () ->
|
||||
view = @views['_index']
|
||||
$.when(@hideAllViews()).then(() -> view.show())
|
||||
|
||||
product: (id) ->
|
||||
product = @products.detect (p) -> p.get('id') == (id)
|
||||
view = (@views['item.' + id] ||= new ProductView(
|
||||
model: product,
|
||||
itemcollection: @cart
|
||||
).render())
|
||||
$.when(@hideAllViews()).then(
|
||||
() -> view.show())
|
||||
|
||||
$(document).ready () ->
|
||||
new BackboneStore();
|
||||
Backbone.history.start();
|
Loading…
Reference in New Issue