将jQuery UI Sortable的顺序保存到Backbone.js集合

我有一个Backbone.js集合,我希望能够使用jQuery UI的Sortable进行sorting。 没有什么奇特的,我只是有一个清单,我希望能够sorting。

问题是,我不知道如何获得项目的当前顺序sorting后,并传达给收集。 Sortable可以序列化自己,但是这不会给我需要给集合的模型数据。

理想情况下,我希望能够获得集合中模型的当前顺序的数组,并使用重置方法进行收集,但是我不确定如何获取当前顺序。 请分享任何想法或例子获取当前的模型订单数组。

我已经通过使用jQuery UI Sortable在项目视图中删除项目时触发事件。 然后,我可以在包含模型的项目视图上触发另一个事件作为集合视图绑定的数据。 集合视图然后可以负责更新sorting顺序。

工作示例

http://jsfiddle.net/7X4PX/260/

jQuery UI可sorting

$(document).ready(function() { $('#collection-view').sortable({ // consider using update instead of stop stop: function(event, ui) { ui.item.trigger('drop', ui.item.index()); } }); }); 

停止事件被绑定到一个函数,该函数会触发DOM节点上的项目索引(由jQuery UI提供)作为数据的项目。

项目视图

 Application.View.Item = Backbone.View.extend({ tagName: 'li', className: 'item-view', events: { 'drop' : 'drop' }, drop: function(event, index) { this.$el.trigger('update-sort', [this.model, index]); }, render: function() { $(this.el).html(this.model.get('name') + ' (' + this.model.get('id') + ')'); return this; } }); 

drop事件绑定到drop函数,该函数使用data [this.model, index]触发项目视图的DOM节点上的update-sort事件。 这意味着我们正在传递当前模型,它的索引(从jQuery UIsorting)到绑定到update-sort事件的任何人。

项目(集合)视图

 Application.View.Items = Backbone.View.extend({ events: { 'update-sort': 'updateSort' }, render: function() { this.$el.children().remove(); this.collection.each(this.appendModelView, this); return this; }, appendModelView: function(model) { var el = new Application.View.Item({model: model}).render().el; this.$el.append(el); }, updateSort: function(event, model, position) { this.collection.remove(model); this.collection.each(function (model, index) { var ordinal = index; if (index >= position) { ordinal += 1; } model.set('ordinal', ordinal); }); model.set('ordinal', position); this.collection.add(model, {at: position}); // to update ordinals on server: var ids = this.collection.pluck('id'); $('#post-data').html('post ids to server: ' + ids.join(', ')); this.render(); } }); 

Items视图绑定到update-sort事件,函数使用事件(模型和索引)传递的数据。 将模型从集合中移除,对每个剩余的项目更新ordinal属性,并将按idsorting的项目发送到服务器以存储状态。

采集

 Application.Collection.Items = Backbone.Collection.extend({ model: Application.Model.Item, comparator: function(model) { return model.get('ordinal'); }, }); 

该集合具有定义的比较器function,按ordinal对集合进行ordinal 。 这将保持项目的呈现顺序同步,因为集合的“默认顺序”现在是ordinal属性的值。

注意这里有一些重复的工作:如果一个集合具有jsfiddle的比较函数,那么模型不需要被移除并添加回集合。 而且这个视图可能不需要重新渲染自己。

注意 :与其他答案相比,我的感觉是,通知项目的模型实例需要更新而不是直接收集是更正确的。 两种方法都是有效的。 这里的另一个答案是直接到收集,而不是采取模型优先的方法。 select哪一个对你更有意义。

http://jsfiddle.net/aJjW6/2/

HTML:

 `<div class="test-class"> <h1>Backbone and jQuery sortable - test</h1> <div id="items-collection-warper"></div> </div>` 

JavaScript的:

 $(document).ready(function(){ var collection = [ {name: "Item ", order: 0}, {name: "Item 1", order: 1}, {name: "Item 2", order: 2}, {name: "Item 3", order: 3}, {name: "Item 4", order: 4} ]; var app = {}; app.Item = Backbone.Model.extend({}); app.Items = Backbone.Collection.extend({ model: app.Item, comparator: 'order', }); app.ItemView = Backbone.View.extend({ tagName: 'li', template: _.template('<span><%= name %> - <b><%= order %></b></span>'), initialize: function(){ }, render: function(){ var oneItem = this.$el.html(this.template(this.model.attributes)); return this; } }); app.AppView = Backbone.View.extend({ el: "#items-collection-warper", tagName: 'ul', viewItems: [], events:{ 'listupdate': 'listUpdate' }, initialize: function(){ var that = this; this.$el.sortable({ placeholder: "sortable-placeholder", update: function(ev, ui){ that.listUpdate(); } }); }, render: function(){ var that= this; this.collection.each(function(item){ that.viewItems.push(that.addOneItem(item)); return this; }); }, addOneItem: function(item){ var itemView = new app.ItemView({model: item}); this.$el.append(itemView.render().el); return itemView; }, listUpdate: function(){ _.each(this.viewItems, function(item){ item.model.set('order', item.$el.index()); }); this.collection.sort({silent: true}) _.invoke(this.viewItems, 'remove'); this.render(); } }); var Items = new app.Items(collection) var appView = new app.AppView({collection: Items}); appView.render(); }); 

CSS:

 .test-class{ font-family: Arial; } .test-class li{ list-style:none; height:20px; } .test-class h1{ font-size: 12px; } .ui-sortable-helper{ opacity:0.4; } .sortable-placeholder{ background: #ddd; border:1px dotted #ccc; } 

只要使用Backbone.CollectionView !

 var collectionView = new Backbone.CollectionView( { sortable : true, collection : new Backbone.Collection } ); 

瞧!