Scott Baker | 7ee32a0 | 2014-07-13 09:52:15 -0700 | [diff] [blame^] | 1 | MyApp = new Backbone.Marionette.Application(); |
| 2 | |
| 3 | MyApp.addRegions({ |
| 4 | mainRegion: "#content" |
| 5 | }); |
| 6 | |
| 7 | AngryCat = Backbone.Model.extend({ |
| 8 | defaults: { |
| 9 | votes: 0 |
| 10 | }, |
| 11 | |
| 12 | addVote: function(){ |
| 13 | this.set('votes', this.get('votes') + 1); |
| 14 | }, |
| 15 | |
| 16 | rankUp: function() { |
| 17 | this.set({rank: this.get('rank') - 1}); |
| 18 | }, |
| 19 | |
| 20 | rankDown: function() { |
| 21 | this.set({rank: this.get('rank') + 1}); |
| 22 | } |
| 23 | }); |
| 24 | |
| 25 | AngryCats = Backbone.Collection.extend({ |
| 26 | model: AngryCat, |
| 27 | |
| 28 | initialize: function(cats){ |
| 29 | var rank = 1; |
| 30 | _.each(cats, function(cat) { |
| 31 | cat.set('rank', rank); |
| 32 | ++rank; |
| 33 | }); |
| 34 | |
| 35 | this.on('add', function(cat){ |
| 36 | if( ! cat.get('rank') ){ |
| 37 | var error = Error("Cat must have a rank defined before being added to the collection"); |
| 38 | error.name = "NoRankError"; |
| 39 | throw error; |
| 40 | } |
| 41 | }); |
| 42 | |
| 43 | var self = this; |
| 44 | |
| 45 | MyApp.on("rank:up", function(cat){ |
| 46 | if (cat.get('rank') === 1) { |
| 47 | // can't increase rank of top-ranked cat |
| 48 | return true; |
| 49 | } |
| 50 | self.rankUp(cat); |
| 51 | self.sort(); |
| 52 | self.trigger("reset"); |
| 53 | }); |
| 54 | |
| 55 | MyApp.on("rank:down", function(cat){ |
| 56 | if (cat.get('rank') === self.size()) { |
| 57 | // can't decrease rank of lowest ranked cat |
| 58 | return true; |
| 59 | } |
| 60 | self.rankDown(cat); |
| 61 | self.sort(); |
| 62 | self.trigger("reset"); |
| 63 | }); |
| 64 | |
| 65 | MyApp.on("cat:disqualify", function(cat){ |
| 66 | var disqualifiedRank = cat.get('rank'); |
| 67 | var catsToUprank = self.filter( |
| 68 | function(cat){ return cat.get('rank') > disqualifiedRank; } |
| 69 | ); |
| 70 | catsToUprank.forEach(function(cat){ |
| 71 | cat.rankUp(); |
| 72 | }); |
| 73 | self.trigger('reset'); |
| 74 | }); |
| 75 | }, |
| 76 | |
| 77 | comparator: function(cat) { |
| 78 | return cat.get('rank'); |
| 79 | }, |
| 80 | |
| 81 | rankUp: function(cat) { |
| 82 | // find the cat we're going to swap ranks with |
| 83 | var rankToSwap = cat.get('rank') - 1; |
| 84 | var otherCat = this.at(rankToSwap - 1); |
| 85 | |
| 86 | // swap ranks |
| 87 | cat.rankUp(); |
| 88 | otherCat.rankDown(); |
| 89 | }, |
| 90 | |
| 91 | rankDown: function(cat) { |
| 92 | // find the cat we're going to swap ranks with |
| 93 | var rankToSwap = cat.get('rank') + 1; |
| 94 | var otherCat = this.at(rankToSwap - 1); |
| 95 | |
| 96 | // swap ranks |
| 97 | cat.rankDown(); |
| 98 | otherCat.rankUp(); |
| 99 | } |
| 100 | }); |
| 101 | |
| 102 | AngryCatView = Backbone.Marionette.ItemView.extend({ |
| 103 | template: "#angry_cat-template", |
| 104 | tagName: 'tr', |
| 105 | className: 'angry_cat', |
| 106 | |
| 107 | events: { |
| 108 | 'click .rank_up img': 'rankUp', |
| 109 | 'click .rank_down img': 'rankDown', |
| 110 | 'click a.disqualify': 'disqualify' |
| 111 | }, |
| 112 | |
| 113 | initialize: function(){ |
| 114 | this.listenTo(this.model, "change:votes", this.render); |
| 115 | }, |
| 116 | |
| 117 | rankUp: function(){ |
| 118 | this.model.addVote(); |
| 119 | MyApp.trigger("rank:up", this.model); |
| 120 | }, |
| 121 | |
| 122 | rankDown: function(){ |
| 123 | this.model.addVote(); |
| 124 | MyApp.trigger("rank:down", this.model); |
| 125 | }, |
| 126 | |
| 127 | disqualify: function(){ |
| 128 | MyApp.trigger("cat:disqualify", this.model); |
| 129 | this.model.destroy(); |
| 130 | } |
| 131 | }); |
| 132 | |
| 133 | AngryCatsView = Backbone.Marionette.CompositeView.extend({ |
| 134 | tagName: "table", |
| 135 | id: "angry_cats", |
| 136 | className: "table-striped table-bordered", |
| 137 | template: "#angry_cats-template", |
| 138 | itemView: AngryCatView, |
| 139 | |
| 140 | initialize: function(){ |
| 141 | this.listenTo(this.collection, "sort", this.renderCollection); |
| 142 | }, |
| 143 | |
| 144 | appendHtml: function(collectionView, itemView){ |
| 145 | collectionView.$("tbody").append(itemView.el); |
| 146 | } |
| 147 | }); |
| 148 | |
| 149 | MyApp.addInitializer(function(options){ |
| 150 | var angryCatsView = new AngryCatsView({ |
| 151 | collection: options.cats |
| 152 | }); |
| 153 | MyApp.mainRegion.show(angryCatsView); |
| 154 | }); |
| 155 | |
| 156 | $(document).ready(function(){ |
| 157 | var cats = new AngryCats([ |
| 158 | new AngryCat({ name: 'Wet Cat', image_path: 'assets/images/cat2.jpg' }), |
| 159 | new AngryCat({ name: 'Bitey Cat', image_path: 'assets/images/cat1.jpg' }), |
| 160 | new AngryCat({ name: 'Surprised Cat', image_path: 'assets/images/cat3.jpg' }) |
| 161 | ]); |
| 162 | |
| 163 | MyApp.start({cats: cats}); |
| 164 | |
| 165 | cats.add(new AngryCat({ |
| 166 | name: 'Cranky Cat', |
| 167 | image_path: 'assets/images/cat4.jpg', |
| 168 | rank: cats.size() + 1 |
| 169 | })); |
| 170 | }); |