2014-09-25 17 views
0

我有一個小應用程序,我想通過點擊它們編輯跨度。我有兩個跨度,但是當我編輯第二跨度時,第一個跨度會自動更改爲與第二個跨度相同的值。我也無法改變至跨度第一的價值,因爲通過點擊撤消第一個值是Backbone.undo.js不跟蹤我的第二個跨度並且不保存起始值

<!doctype html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title>Backbone.Undo sample</title> 
    <style> 
     body { 
      font-family: sans-serif; 
      line-height: 140%; 
     } 

     #centered { 
      position: absolute; 
      top: 50%; 
      left: 50%; 
      margin-left: -180px; 
      margin-top: -120px; 
     } 
    </style> 
</head> 
<body> 
    <ol id="centered"> 
     <li> 
      <span type="text" id="input" value="foo">span1 </span> 
      <button id="set">set</button> 
     </li> 
     <li> 
      <span type="text" id="input2" value="foo">span2 </span> 
      <button id="Button1">set</button> 
     </li> 
     <li> 
      <button id="undo">undo</button> 
      <button id="redo">redo</button> 
     </li> 
    </ol> 
    <script src="jquery-1.9.1.js"></script> 
    <script src="underscore.js"></script> 
    <script src="backbone.js"></script> 
    <script src="../Backbone.Undo.js"></script> 
    <script> 
     $(function() { 
      var model = new Backbone.Model({ "text": "foo" }), 
      View = Backbone.View.extend({ 
       initialize: function() { 
        // If the model's text changes, update the view 
        this.model.on("change:text", function (model, text, options) { 
         if (text != this.$el.text()) { 
          this.$el.text(text); 
         } 
        }, this); 
       } 
      }) 
      view = new View({ 
       model: model, 
       el: $("#input") 
      }) 
      // Now: The undo/redo part 
      var undoManager = new Backbone.UndoManager; 
      undoManager.register(model); 
      undoManager.startTracking(); 

      $("#undo").on("click", function() { 
       undoManager.undo(); 
      }) 
      $("#redo").on("click", function() { 
       undoManager.redo(); 
      }) 
      $("#input").on("click", function() { 
       var element = document.getElementById("input"); 
       element.innerHTML = prompt("#input", element.innerHTML); 
       model.set("text", $("#input").text()); 
      }) 
      $("#input2").on("click", function() { 
       var element = document.getElementById("input2"); 
       element.innerHTML = prompt("#input2", element.innerHTML); 
       model.set("text", $("#input2").text()); 
      }) 
     }) 
    </script> 
</body> 
</html> 

回答

2

從我所使用的是1個模型和1個視圖中看到,但你希望他們獨立行事。所以當你點擊span2時,你仍然在設置相同的模型,這就是它們都改變的原因。

爲此,我將使用單獨的模型和獨立意見爲這兩個範圍這樣

var model = new Backbone.Model({ 
    "text": "span1" 
}); 
var model2 = new Backbone.Model({ 
    "text": "span2" 
}); 
var View = Backbone.View.extend({ 
    initialize: function() { 
     // If the model's text changes, update the view 
     this.model.on("change:text", function (model, text, options) { 
      if (text != this.$el.text()) { 
       this.$el.text(text); 
      } 
     }, this); 
    } 
}); 
var view1 = new View({ 
    model: model, 
    el: $("#input") 
}); 

var view2 = new View({ 
    model: model2, 
    el: $("#input2") 
}); 

然後在撤消登記註冊您的其他型號

// Now: The undo/redo part 
var undoManager = new Backbone.UndoManager; 
undoManager.register(model); 
undoManager.register(model2); 
undoManager.startTracking(); 

終於在改變你的點擊處理程序span2編輯新模型

$("#input2").on("click", function() { 
    var element = document.getElementById("input2"); 
    element.innerHTML = prompt("#input2", element.innerHTML); 
    model2.set("text", $("#input2").text()); 
}) 

here is a fiddle with it all together

你也可以通過讓視圖處理事件而不是在外面做這件事來更多地利用骨幹。這裏有一個例子

var View = Backbone.View.extend({ 
    initialize: function() { 
     // If the model's text changes, update the view 
     this.model.on("change:text", function (model, text, options) { 
      if (text != this.$el.text()) { 
       this.$el.text(text); 
      } 
     }, this); 
    }, 

    events: { 
     'click': 'editValue' 
    }, 
    editValue: function() { 
     var data = prompt("#input2", this.model.get("text")); 
     if(data) 
     { 
      this.model.set("text", data); 
     } 
    } 
    }); 

現在視圖處理這一變化的模型,我們也不要;噸不得不從我們保持它在任何時候模型中的HTML獲取數據。這裏是一個更新的小提琴顯示這種技術http://fiddle.jshell.net/leighking2/2vx00s4b/9/


一個更Backboney方法利用模板的每個模型,收集保存您的模型,然後在視圖顯示了收集和顯示每個模型的視圖。我試圖添加註釋,以顯示不同部分在做什麼,問你要什麼清理

Fiddle of this example

HTML

<script type="text/template" id="model-template"> 
    <span type="text" class="input" value="foo"><%= text %></span> 
     <button class="remove">remove</button> 
</script> 
<div id="centered"> 
    <ol id="collection-hook"> 
    </ol> 
    <button id="undo">undo</button> 
    <button id="redo">redo</button> 
    <button id="add">add</button> 
</div> 

JS

var Model = Backbone.Model.extend({ 
    defaults: { 
     text: "Click To Edit Text" 
    } 
}); 
var Collection = Backbone.Collection.extend({ 
    model: Model 
}); 

var ModelView = Backbone.View.extend({ 
    tagName: "li", 
    className: "model", 

    //get the template and cache it for future use 
    template:_.template($('#model-template').html()), 
    initialize: function() { 
     // If the model's text changes, update the view 
     this.listenTo(this.model, "change:text", this.render, this); 
     //if the model is removed from the collection close this view 
     this.listenTo(this.model, 'remove', this.close, this); 
    }, 

    //events this view will be listening for 
    events: { 
     'click span.input': 'editValue', 
     'click button.remove': 'removeModel', 
    }, 

    //get the models collection from it's self and tell the collection to remove the model 
    removeModel: function() { 
     this.model.collection.remove(this.model); 
    }, 

    //ensure model and all events are destroyed and remove this view from the DOM 
    close: function() { 
     this.model.destroy(); 
     this.remove(); 
     this.unbind(); 
     this.stopListening(); 
    }, 

    //render this view with the models data 
    render: function() { 

     //attach the generated template to this views $el 
     this.$el.html(this.template({ 
      text: this.model.get("text") 
     })); 

     //return this view so collection view can decided where to place it on the DOM 
     return this; 
    }, 

    editValue: function() { 
     var data = prompt("Change text", this.model.get("text")); 
     if (data) { 
      this.model.set("text", data); 
     } 
    } 
}); 

var CollectionView = Backbone.View.extend({ 
    el: $("#centered"), 
    //store a refrence to where you would like to add your models 
    collectinoHook: $("#collection-hook", this.$el), 

    initialize: function() { 
     this.undoManager = new Backbone.UndoManager; 

     this.undoManager.startTracking(); 

     //when ever a new model is added to the collection call the function 
     //to render it 
     this.listenTo(this.collection, 'add', this.renderOne, this); 

    }, 

    events: { 
     'click #add': 'addModel', 
     'click #redo': 'redo', 
     'click #undo': 'undo', 
    }, 

    //render the collection items one at a time 
    renderOne: function(model) { 
     this.undoManager.register(model); 
     //create a new view using this model 
     var view = new ModelView({ 
      model: model 
     }); 

     //append the new view to you list 
     this.collectinoHook.append(view.render().el); 
    }, 

    //use this to render the view with existing models in the collection 
    render: function() { 
     //clear the current views that have been rendered not the cleanest method as 
     //those views will still exist but this is a quick example 
     this.collectinoHook.html(''); 
     this.collection.each(_.bind(function(model) { 
      this.renderOne(model); 
     },this)); 
    }, 


    undo: function() { 
     this.undoManager.undo(); 
    }, 
    redo: function() { 
     this.undoManager.redo(); 
    }, 
    addModel: function() { 

     //create a new model and add it to the collection 
     var model = new Model(); 
     this.collection.add(model); 
    }, 

}); 

var collection = new Collection(); 
var collectionView = new CollectionView({ 
    collection: collection 
}); 
+0

保護你。我怎樣才能設法動態地創建我的模型依賴於我有多少跨度?我希望能夠編輯所有跨度並輕鬆添加新跨度。 – Volz 2014-09-25 10:14:23

+1

因此,您需要開始使用模板(用於保存模型的標記),集合(用於容納所有模型),並使用一個視圖作爲模型視圖,另一個視圖用作集合視圖。然後在集合視圖中,您可以添加一些鏈接到按鈕的處理程序以添加新模型。在ToDo應用教程的幌子下可以找到很多這樣的例子,這是我在學習骨幹時開始的地方 – Quince 2014-09-25 10:17:11

+0

我還有一個問題。是否可以在我的模型中創建**「text」**位置等於它的跨度**。text()**? 我的意思是,如果我有' example'我想'var model = new Backbone.Model({text:「span1 「//這裏是我的$(」#input「)。text() });' – Volz 2014-09-25 10:29:46