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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10147969/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 08:50:24  来源:igfitidea点击:

Saving jQuery UI Sortable's order to Backbone.js Collection

javascriptjquery-uibackbone.jsbackbone.js-collections

提问by VirtuosiMedia

I have a Backbone.js collection that I would like to be able to sort using jQuery UI's Sortable. Nothing fancy, I just have a list that I would like to be able to sort.

我有一个 Backbone.js 集合,我希望能够使用 jQuery UI 的 Sortable 对其进行排序。没什么特别的,我只有一个列表,我希望能够对其进行排序。

The problem is that I'm not sure how to get the current order of items after being sorted and communicate that to the collection. Sortable can serialize itself, but that won't give me the model data I need to give to the collection.

问题是我不确定如何在排序后获取项目的当前顺序并将其传达给集合。Sortable 可以序列化自身,但这不会给我需要提供给集合的模型数据。

Ideally, I'd like to be able to just get an array of the current order of the models in the collection and use the reset method for the collection, but I'm not sure how to get the current order. Please share any ideas or examples for getting an array with the current model order.

理想情况下,我希望能够获取集合中模型当前顺序的数组,并使用该集合的 reset 方法,但我不确定如何获取当前顺序。请分享使用当前模型顺序获取数组的任何想法或示例。

回答by Cymen

I've done this by using jQuery UI Sortable to trigger an event on the item view when an item is dropped. I can then trigger another event on the item view that includes the model as data which the collection view is bound to. The collection view can then be responsible for updating the sort order.

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

Working example

工作示例

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

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

jQuery UI Sortable

jQuery UI 可排序

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

The stopevent is bound to a function that triggers dropon the DOM node for the item with the item's index (provided by jQuery UI) as data.

所述止挡事件被绑定到一个函数,触发器drop,用于与项目的索引(由jQuery的用户界面提供)作为数据项的DOM节点上。

Item view

项目视图

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;
    }
});

The drop event is bound to the dropfunction which triggers an update-sortevent on the item view's DOM node with the data [this.model, index]. That means we are passing the current model and it's index (from jQuery UI sortable) to whomever is bound to the update-sortevent.

drop 事件绑定到使用 data 在项目视图的 DOM 节点上drop触发update-sort事件的函数[this.model, index]。这意味着我们将当前模型及其索引(来自 jQuery UI 可排序)传递给绑定到update-sort事件的任何人。

Items (collection) view

项目(集合)视图

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();
    }
}); 

The Itemsview is bound to the update-sortevent and the function uses the data passed by the event (model and index). The model is removed from the collection, the ordinalattribute is updated on each remaining item and the order of items by id is sent to the server to store state.

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

Collection

收藏

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

The collection has a comparatorfunction defined which orders the collection by ordinal. This keeps the rendered order of items in sync as the "default order" of the collection is now by the value of the ordinalattribute.

该集合定义了一个比较器函数,该函数按 对集合进行排序ordinal。这使项目的呈现顺序保持同步,因为集合的“默认顺序”现在由ordinal属性值决定。

Note there is some duplication of effort: the model doesn't need to be removed and added back to the collection if a collection has a comparator function as the jsfiddle does. Also the view may not need to re-render itself.

请注意,有一些重复的工作:如果集合具有比较器功能,则不需要删除模型并将其添加回集合,就像 jsfiddle 那样。此外,视图可能不需要重新渲染自身。

Note: compared to the other answer, my feeling was that it was more correct to notify the model instance of the item that it needed to be updated instead of the collection directly. Both approaches are valid. The other answer here goes directly to the collection instead of taking the model-first approach. Pick whichever makes more sense to you.

注意:与其他答案相比,我的感觉是通知项目的模型实例它需要更新而不是直接通知集合更正确。这两种方法都是有效的。这里的另一个答案直接指向集合,而不是采用模型优先的方法。选择对您更有意义的那个。

回答by Mateusz Godlewski

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

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

HTML:

HTML:

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

JavaScript:

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:

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;
}

回答by Brave Dave

Just use Backbone.CollectionView!

只需使用Backbone.CollectionView

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

Voila!

瞧!