text: // Load the application once the DOM is ready, using `jQuery.ready`:
  
  $(function(){
  
  
  
    // Note Model
  
    // ----------
  
  
  
    var Note = Backbone.Model.extend({
  
  
  
      // Default attributes for the item.
  
      defaults: function() {
  
        return {
  
          id   :  Notes.nextId(),
  
          name :  "New note",
  
          description :  "",
  
          date :  Date.now()
  
        };
  
      }
  
  
  
    });
  
  
  
    // Note Collection
  
    // ---------------
  
  
  
    // The collection of notes is backed by *localStorage* instead of a remote server
  
  
  
    var NoteList = Backbone.Collection.extend({
  
  
  
      // Reference to this collection's model.
  
      model: Note,
  
  
  
      // Save all of the items to local storage under namespace.
  
      localStorage: new Backbone.LocalStorage("notes-app"),
  
  
  
      // Save data to database.
  
      //url: 'api/notes',
  
  
  
      // We keep in sequential id, despite being saved by unordered
  
      // GUID in the database. This generates the next id number for new items.
  
      nextId: function() {
  
        if (this.url) return null;
  
        if (!this.length) return 1;
  
        return this.last().get('id') + 1;
  
      },
  
  
  
      // sorted by their original insertion id.
  
      comparator: function(note) {
  
        return parseInt(note.get("id"));
  
      },
  
  
  
      search : function(str){
  
        // if(str == "") return this;
  
        
  
        var pattern = new RegExp(str, "gi");
  
        return _(this.filter(function(data) {
  
            data.trigger('show');
  
            if (pattern.test(data.get("description")) == false) {
  
              data.trigger('hide');
  
            };
  
        }));
  
  
  
      }
  
  
  
    });
  
  
  
    // Create our global collection.
  
    var Notes = new NoteList;
  
  
  
    // Item View
  
    // --------------
  
  
  
    // The DOM element for a item...
  
    var NoteItemView = Backbone.View.extend({
  
  
  
      //... is a list tag.
  
      tagName:  "li",
  
      className: "list-group-item hover",
  
  
  
      // Cache the template function for a single item.
  
      template: _.template($('#item-template').html()),
  
  
  
      // The DOM events specific to an item.
  
      events: {
  
        "click .destroy": "clear",
  
        "click"         : "select"
  
      },
  
  
  
      // The View listens for changes to its model, re-rendering. 
  
      initialize: function() {
  
        this.listenTo(this.model, 'change', this.render);
  
        this.listenTo(this.model, 'destroy', this.remove);
  
        this.listenTo(this.model, 'select', this.select);
  
        this.listenTo(this.model, 'active', this.active);
  
        this.listenTo(this.model, 'hide', this.hide);
  
        this.listenTo(this.model, 'show', this.show);
  
      },
  
  
  
      // Re-render the titles of the item.
  
      render: function() {
  
        this.$el.html(this.template(this.model.toJSON()));
  
        return this;
  
      },
  
  
  
      // Remove the item, destroy the model.
  
      clear: function(e) {
  
        this.model.destroy();
  
        window.history.back();
  
      },
  
  
  
      // Click to select
  
      select: function(){
  
        this.active();
  
        app.navigate("notes/"+this.model.get('id'), {trigger: true});
  
      },
  
  
  
      // Active
  
      active: function(){
  
        this.$el.parent().find('.active').removeClass('active');
  
        this.$el.addClass('active');
  
      },
  
  
  
      hide: function(){
  
        this.$el.addClass('hide');
  
      },
  
  
  
      show: function(){
  
        this.$el.removeClass('hide');
  
      }
  
  
  
    });
  
  
  
  
  
    // list view
  
  
  
    var NoteListView = Backbone.View.extend({
  
  
  
      // Instead of generating a new element, bind to the existing skeleton of
  
      el: $("#note-list"),
  
  
  
      // Delegated events for creating new items, and clearing completed ones.
  
      events: {
  
        "click #new-note"   : "create",
  
        "keyup #search-note": "search"
  
      },
  
      // At initialization we bind to the relevant events on the 
  
      // collection, when items are added or changed. Kick things off by
  
      // loading any preexistings that might be saved in *localStorage*.
  
      initialize: function() {
  
        this.listenTo(Notes, 'add', this.addOne);
  
        this.listenTo(Notes, 'reset', this.addAll);
  
        this.listenTo(Notes, 'all', this.render);      
  
      },
  
  
  
      // Re-rendering the App just means refreshing the statistics -- the rest
  
      // of the app doesn't change.
  
      render: function() {
  
  
  
      },
  
  
  
      // Add a single item to the list by creating a view for it, and
  
      // appending its element to the `<ul>`.
  
      addOne: function(note) {
  
        var view = new NoteItemView({model: note});
  
        this.$el.find('#note-items').prepend(view.render().el);
  
      },
  
  
  
      // Add all items in the collection at once.
  
      addAll: function() {
  
        Notes.each(this.addOne, this);      
  
      },
  
  
  
      create: function(e) {
  
        var note = new Note;
  
        Notes.create(note, {
  
          success:function () {
  
              note.trigger('select');
  
          }
  
        });
  
      },
  
  
  
      search: function(){
  
        Notes.search($('#search-note').val());
  
      }
  
  
  
    });
  
  
  
    // note detail
  
    var NoteView = Backbone.View.extend({
  
      el: $("#note-detail"),
  
  
  
      // Cache the template function
  
      template: _.template($('#note-template').html()),
  
  
  
      // The DOM events specific to the textarea.
  
      events: {
  
        "keyup textarea"  : "updateOnKeyup",
  
      },
  
  
  
      initialize:function () {
  
        this.$el.html(this.template(this.model.toJSON()));
  
      },
  
  
  
      // update the model when update
  
      updateOnKeyup: function(e){
  
        var name = '',
  
            description = $(e.target).val(),
  
            arr  = description.split(/\r\n|\r|\n/g);
  
        arr.length && ( name = _.first( _.filter(arr, function(item){ return !!$.trim(item); }) ) );
  
        this.model.save({name: name, description: description});
  
      },
  
  
  
      close:function () {
  
        this.$el.unbind();
  
        this.$el.empty();
  
      }
  
  
  
    });
  
  
  
  
  
    var AppRouter = Backbone.Router.extend({
  
      routes: {
  
        "" : "list",
  
        "notes/:id" : "details"
  
      },
  
  
  
      initialize: function () {
  
        
  
      },
  
  
  
      list: function() {
  
        if(this.noteListView) return;
  
        this.noteListView = new NoteListView;
  
        var self = this;
  
        Notes.fetch({
  
          success: function(){
  
            var id = app.requiredId || (Notes.length && Notes.at(Notes.length - 1).get('id'));
  
            Notes.length && self.details(id) && app.navigate('notes/'+id);
  
            !Notes.length && $('#new-note').trigger('click');
  
          }
  
        });
  
      },
  
      
  
      details: function(id) {
  
        app.requiredId = id;
  
        this.list();
  
        // close the note detail view
  
        if (this.noteView) this.noteView.close();
  
        // get the note
  
        this.note = Notes.get(id);
  
        if(this.note){
  
          this.note.trigger('active');
  
          this.noteView = new NoteView({model: this.note});
  
        }
  
        return this;
  
      }
  
  
  
    });
  
  
  
    // Finally, we kick things off by creating the **App**.
  
    
  
    var app = new AppRouter();
  
    Backbone.history.start();
  
    
  
  });
  
  