2013-01-21 48 views
2

我正在学习backbone.js,并且在this tutorial之后出现问题。我有一个名为HistoryEra的集合。当试图app.History.create({ from: 0, until: 1, stash: {from: null, until: null}, _enabled: true})我得到标题中的错误。Backbone.js:TypeError:Object#<Object> has no method'parse'

这里是我的代码:

示范

var app = app || {}; 

app.Era = Backbone.Model.extend({ 

    defaults: { 
     from: Number.NEGATIVE_INFINITY, 
     until: Number.POSITIVE_INFINITY, 
     stash: { 
      from: null, 
      until: null 
     }, 
     _enabled: true 
    }, 

    toggle: function(){ 
     if(this.get('_enabled')){ 
      this.disable(); 
     }else{ 
      this.enable(); 
     } 

     this.save(); 
    }, 

    enable: function(){ 
     this.from = this.stash.from; 
     this.until = this.stash.until; 

     this.stash.from = null; // strictly speaking unnecssary 
     this.stash.until = null; 

     this._enabled = true; 
    }, 

    disable: function(){ 
     this.stash.from = this.from; 
     this.stash.until = this.until; 

     this.from = null; 
     this.until = null; 

     this._enabled = false; 
    }, 

    enabled: function(){ 
     return this._enabled; 
    }, 

}); 

var History = Backbone.Collection.extend({ 

    model: app.Era, 

    localStorage: new Backbone.LocalStorage('karass-history'), 

    enabled: function(){ 
     return this.filter(function(era){ 
      return era.enabled(); 
     }); 
    }, 

    nextOrder: function(){ 
     if(!this.length){ 
      return 1; 
     } 

     return this.last().get('order') + 1; 
    }, 

    comparator: function(era) { 
     return era.get('order'); 
    }, 

    comparatorFrom: function(era){ 
     return era.get('from'); 
    }, 

    comparatorUntil: function(era){ 
     return era.get('until'); 
    }, 

    getFirstFrom: function(){ 
     // todo 
    }, 

    getLastUntil: function(){ 
     // todo 
    }, 

    getEraAt: function(time){ 
     // todo 
    }, 

}); 

app.History = new History(); 

app.AppView = Backbone.View.extend({ 

    // bind to the karassApp div we set up in the html file 
    el: "#karassApp", 

    // Our template for the line of statistics at the bottom of the app. 
    statsTemplate: _.template($('#stats-template').html()), 

    // delegated events for creating new items, and clearing completed ones 
    events: { 
     'keypress #new-era-start': 'focusOnEnd', 
     'keypress #new-era-end': 'createEraOnEnter', 
     'click #disable-history': 'toggleEnabledAllEras' 
    }, 

    // At initialization we bind to the relevant events on the 'eras' 
    // collection, when items are added or changed. Kick things off by 
    // loading any preexisting todos that might be saved in *localStorage* 
    initialize: function(){ 
     //_.bindAll(this); 

     this.era_start = this.$('#new-era-start'); 
     this.era_end = this.$('#new-era-end'); 
     this.disableHistory = this.$('#disable-history'); 
     this.$footer = this.$('#footer'); 
     this.$main = this.$('#main'); 

     window.app.History.on('add', this.addOneEra, this); 
     window.app.History.on('reset', this.addAllEras, this); 
     // window.app.History.on('add:true', this.addAllEras, this); 
     window.app.History.on('change:_enabled', this.filterOneEra, this); 
     window.app.History.on('filter', this.filterAllEras, this); 

     window.app.History.on('all', this.renderHistory, this); 

     app.History.fetch(); 
    }, 

    // Re-rendering the App just means refreshing the statistics -- the rest 
    // of the app doesn't change. 
    renderHistory: function(){ 
     var era_count = app.History.length(); 

     if(app.History.length){ 
      this.$main.show(); 
      this.$footer.show(); 

      this.$footer.html(this.statsTemplate({ 
       era_count: era_count, 
      })); 

      this.$('#filters li a') 
       .removeClass('selected') 
       .filter('[href=#/' + (app.EraFilter || '') + '"]') 
       .addClass('selected'); 

     }else{ 
      this.$main.hide(); 
      this.$footer.hide(); 
     } 

     this.disableHistory = !app.History.enabled(); 
    }, 

    // Add a single era item to the list by creating a view for it, and 
    // appending its element to the `<ul>`. 
    addOneEra: function(era){ 
     var view = new app.EraView({ model: era }); 
     $('#history').append(view.render().el); 
    }, 

    addAllEras: function(){ 
     this.$('#history').html(''); 
     app.History.each(this.addOneEra, this); 
    }, 

    filterOneEra: function(era){ 
     era.trigger('visible'); 
    }, 

    filterAllEras: function(){ 
     app.History.each(this.filterOne, this); 
    }, 

    // Generate the attributes for the new Era Item 
    newEraAttributes: function(){ 
     return { 
      from: this.era_start.val().trim(), // validation logic should probably go here: make sure it's a date that can be saved 
      until: this.era_end.val().trim(), // ditto 
      stash: { 
       from: null, 
       until: null 
      }, 
      order: app.History.nextOrder(), 
      _enabled: true, 
     } 
    }, 

    focusOnEnd: function(e){ 
     if(e.which !== ENTER_KEY || !this.era_start.val().trim()){ 
      return; 
     } 

     this.era_end.focus(); 
    }, 

    createEraOnEnter: function(e){ 
     if(e.which !== ENTER_KEY || !this.era_start.val().trim()){ 
      return; 
     } 

     app.History.create(this.newEraAttributes()); 
     this.era_start.val(''); 
     this.era_end.val(''); 
    }, 

    toggleEnabledAllEras: function(){ 
     var enabled = !this.disableHistory.checked; 

     app.History.each(function(era){ 
      era.toggle(); 
      era.save(); 
     }); 
    } 
}); 

app.EraView = Backbone.View.extend({ 
    tagName: 'li', 
    template: _.template($('#era-template').html()), 

    // The DOM events specified to an item 
    events: { 
     'dblclick label': 'edit', 
     'keypress .edit .start': 'focusOnEnd', 
     'keypress .edit .end': 'updateOnEnter', 
     'blur .edit': 'close', 
    }, 

    // The EraView listens for changes to its model, re-rendering. Since there's 
    // a one-to-one correspondence between an era and a EraView in this app, 
    // we set a direct reference on the model for convenience. 
    initialize: function(){ 
     //_.bindAll(this); 
     this.model.on('change', this.render, this); 
    }, 

    // Re-renders the era item to the current state of the model and 
    // updates the reference to the era's edit input within the view 
    render: function(){ 
     this.$el.html(this.template(this.model.toJSON())); 
     this.era_start = this.$('.era-start'); 
     this.era_end = this.$('.era-end'); 
     return this; 
    }, 

    // Switch this view into editing mode, displaying the input field 
    edit: function(){ 
     this.$el.addClass('editing'); 
     this.era_start.focus(); 
    }, 

    // Close the editing mode, saving changes to the era 
    close: function(){ 
     var start = this.era_start.val().trim(); 
     var end = this.era_end.val().trim(); 

     if(start && end){ 
      this.model.save({from: start, until: end}); 
     } 

     this.$el.removeClass('editing'); 
    }, 

    focusOnEnd: function(e){ 
     if(e.which !== ENTER_KEY || !this.era_start.val().trim()){ 
      return; 
     } 

     this.era_end.focus(); 
    }, 

    updateOnEnter: function(e){ 
     if(e.which !== ENTER_KEY || !this.era_end.val().trim()){ 
      return; 
     } 

     this.close(); 
    } 
}); 

最后但并非最不重要的:

的HTML

<!doctype html> 
<html lang="en"> 
<head> 
    <meta charset="utf-8"> 
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 
    <title>Backbone.js • HistoryMVC</title> 
</head> 
<body> 
    <section id="karassApp"> 
     <header id="header"> 
      <h1>Karass</h1> 
      <input id="new-era-start" placeholder="Since when?" autofocus> 
      <input id="new-era-end" placeholder="Until when?" > 
     </header> 
     <section id="main"> 
      <input id="disable-history" type="checkbox"> 
      <label for="disable-history">Disable History, work on Snapshot instead</label> 
      <ul id="history"></ul> 
     </section> 
     <footer id="footer"></footer> 
    </section> 
    <div id="info"> 
     No info here, traveller! 
    </div> 

    <script type="text/template" id="era-template"> 
     <li> 
      <input class="era-start" placeholder="Since when?" value="<%= from %>"> 
      <input class="era-end" placeholder="Until when?" value="<%= until %>"> 
      <label>Edit</label> 
     </li> 
    </script> 

    <script type="text/template" id="stats-template"> 
     <% if (era_count) { %> 
      <p>There are <%= era_count %> eras to display</p> 
     <% }else{ %> 
      <p>There are no eras to display, yet.</p> 
     <% } %> 
    </script> 

    <script src="js/lib/jquery-1.9.0.min.js"></script> 
    <script src="js/lib/underscore-min.js"></script> 
    <script src="js/lib/backbone.js"></script> 
    <script src="js/lib/backbone.localStorage-min.js"></script> 
    <script src="js/models/era.js"></script> 
    <script src="js/models/history.js"></script> 
    <script src="js/views/app.js"></script> 
    <script src="js/views/era.js"></script> 
</html> 

调试

我可以在使用era = new app.Era({ from: 0, until: 1, stash: {from: null, until: null}, _enabled: true});Era,但调用app.History.create(...)使用相同参数的实例引发错误。

问题 这里有什么错误?我试着做了与本教程相同的所有内容,并且现在已经遍历了代码的所有部分,以查看是否会发现错误。

谢谢!

哦,是的,信贷去Nyxynyx,他的问题我没有找到我的答案后无耻地扯掉。

回答

相关问题