PageRenderTime 27ms CodeModel.GetById 11ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/js/app.js

https://bitbucket.org/tariel/contacts
JavaScript | 208 lines | 151 code | 42 blank | 15 comment | 8 complexity | c6ed335fab03ae5f40ea1455ebd20fb3 MD5 | raw file
  1/*
  2http://net.tutsplus.com/tutorials/javascript-ajax/build-a-contacts-manager-using-backbone-js-part-1/
  3http://net.tutsplus.com/tutorials/javascript-ajax/build-a-contacts-manager-using-backbone-js-part-2/
  4*/
  5
  6(function ($) {
  7  var contacts = [
  8    { name: "Contact 1", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "family" },
  9    { name: "Contact 2", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "family" },
 10    { name: "Contact 3", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "friend" },
 11    { name: "Contact 4", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "colleague" },
 12    { name: "Contact 5", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "family" },
 13    { name: "Contact 6", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "colleague" },
 14    { name: "Contact 7", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "friend" },
 15    { name: "Contact 8", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "family" }
 16  ];
 17  
 18  var Contact = Backbone.Model.extend({
 19    defaults: {
 20      photo: "img/placeholder.png",
 21      name: "",
 22      address: "",
 23      tel: "",
 24      email: "",
 25      type: ""
 26    }
 27  });
 28  
 29  // Define directory collection
 30  var Directory = Backbone.Collection.extend({
 31    model: Contact
 32  });
 33  
 34  var ContactView = Backbone.View.extend({
 35    tagName: "article",
 36    className: "contact-container",
 37    template: _.template($("#contactTemplate").html()),
 38    
 39    render: function () {      
 40      this.$el.html(this.template(this.model.toJSON()));      
 41      return this;
 42    },
 43    
 44    events: {
 45      "click button.delete": "deleteContact"
 46    },
 47    
 48    deleteContact: function () {
 49      var removedType = this.model.get("type").toLowerCase();
 50      
 51      // remove model
 52      this.model.destroy();
 53      
 54      // remove view
 55      this.remove();
 56      
 57      if (_.indexOf(directory.getTypes(), removedType) === -1) {
 58        directory.$el.find("#filter select").children("[value='" + removedType + "']").remove();
 59      }
 60    }
 61  });
 62  
 63  // Master view
 64  var DirectoryView = Backbone.View.extend({
 65    el: $("#contacts"),
 66    
 67    initialize: function () {
 68      this.collection = new Directory(contacts);
 69      
 70      this.render();
 71      this.$el.find('#filter').append(this.createSelect());
 72      
 73      this.on("change:filterType", this.filterByType, this);
 74      this.collection.on("reset", this.render, this);
 75      
 76      this.collection.on("add", this.renderContact, this);
 77      
 78      this.collection.on("remove", this.removeContact, this);
 79    },
 80    
 81    render: function () {
 82      this.$el.find("article").remove();
 83      
 84      _.each(this.collection.models, function (item) {
 85        this.renderContact(item);
 86      }, this);
 87    },
 88    
 89    renderContact: function (item) {
 90      var contactView = new ContactView({
 91        model: item  
 92      });
 93      
 94      // $el property is cached jQuery object
 95      // that Backbone creates automatically
 96      this.$el.append(contactView.render().el);
 97    },
 98    
 99    getTypes: function () {
100      return _.uniq(this.collection.pluck("type"), false, function (type) {
101        return type.toLowerCase();
102      });
103    },
104    
105    // Build types filter list
106    createSelect: function () {
107      var select = $("<select/>", {
108          html: "<option>All</option>"
109        });
110      
111      _.each(this.getTypes(), function (item) {
112        var option = $("<option/>", {
113          value: item.toLowerCase(),
114          text: item.toLowerCase()
115        }).appendTo(select);
116      });
117      return select;
118    },
119    
120    // Define ui events
121    events: {
122      "change #filter select": "setFilter",
123      "click #add": "addContact",
124      "click #showForm": "showForm"
125    },
126    
127    // Define filter handler
128    setFilter: function (e) {
129      this.filterType = e.currentTarget.value;
130      this.trigger("change:filterType");
131    },
132    
133    filterByType: function () {
134      if (this.filterType === "all") {
135        this.collection.reset(contacts);
136        
137        contactsRouter.navigate("filter/all");
138      } else {
139        this.collection.reset(contacts, { silent: true });
140        
141        var filterType = this.filterType,
142            filtered = _.filter(this.collection.models, function (item) {
143              return item.get("type") === filterType; 
144        });
145            
146        this.collection.reset(filtered);
147        
148        contactsRouter.navigate("filter/" + filterType);
149      }
150    },
151    
152    // Define method for adding contacts
153    addContact: function (e) {
154      e.preventDefault();
155      
156      var newModel = {};
157      $("#addContact").children("input").each(function (i, el) {
158        if ($(el).val() !== "") {
159          newModel[el.id] = $(el).val();
160        }
161      });
162      
163      contacts.push(newModel);
164      
165      if (_.indexOf(this.getTypes(), newModel.type) === -1) {
166        this.collection.add(new Contact(newModel));
167        this.$el.find("#filter").find("select").remove().end().append(this.createSelect());
168      } else {
169        this.collection.add(new Contact(newModel));
170      }
171    },
172    
173    removeContact: function (removedModel) {
174      var removed = removedModel.attributes;
175       
176      if (removed.photo === "/img/placeholder.png") {
177        delete removed.photo;
178      }
179      
180      _.each(contacts, function (contact) {
181        if (_.isEqual(contact, removed)) {
182          contacts.splice(_.indexOf(contacts, contact), 1);  
183        }  
184      });
185    },
186    
187    showForm: function () {
188      this.$el.find("#addContact").slideToggle();
189    }
190  });
191  
192  // Define routes
193  var ContactsRouter = Backbone.Router.extend({
194    routes: {
195      "filter/:type": "urlFilter"
196    },
197    
198    urlFilter: function (type) {
199      directory.filterType = type;
200      directory.trigger("change:filterType");
201    }
202  });
203  
204  var directory = new DirectoryView();
205  var contactsRouter = new ContactsRouter();
206  Backbone.history.start();
207  
208} (jQuery));