BackboneJS在一个集合中重新排列模型的最佳方式,同时为每个模型维护0个索引的序数属性 [英] BackboneJS best way to rearrange models in a collection while maintaining 0-indexed ordinal property for each model

查看:215
本文介绍了BackboneJS在一个集合中重新排列模型的最佳方式,同时为每个模型维护0个索引的序数属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题,我在这里玩,我有一个BackboneJS模型的集合,每个模型有一个'ordinal'属性,它跟踪其在集合中的顺序。

I have a problem I'm playing with here, I have a collection of BackboneJS models, each model has a 'ordinal' property that tracks its order in the collection.

这里是我的播放数据

var ex_group_test_data = [{

            title: 'PRE EXERCISE',
            id:         0,
            ordinal:    1,

            group_items: [{
                id:         0,
                ordinal:    0,
                title: 'item 1'
            },{
                id:         1,
                ordinal:    1,
                title: 'item 2'
            }]

        },{

            title: 'MAIN PART',
            id:         1,
            ordinal:    0,

            group_items: [{
                id:             2,
                ordinal:        0,
                title:          'item 3',
                description:    'testing descrip'
            },{
                id:         3,
                ordinal:    1,
                title: 'item 4'
            }]

        },{

            title: 'POST EXERCISE BS',
            id:         2,
            ordinal:    2,

            group_items: [{
                id:             2,
                ordinal:        0,
                title:          'item 5',
                description:    'testing descrip'
            },{
                id:         3,
                ordinal:    1,
                title: 'item 6'
            }]

        }];

这里是我骨干集合的精髓

        Collections.Exercise_Groups = Backbone.Collection.extend({
            model: Models.Exercise_Group,
            comparator: function(model){
                return model.get('ordinal');
            },
            initialize: function(){

                return this;
            }

从简单的开始,我想要一个模型,并移动它+1或-1序数,并保持0 - 集合中所有模型的索引。

Eventually I want to bring this to a level where I can drop in models or remove them from any position and still maintain my 0-indexing, or take a model and move it +/- X positions.

最后,我想把这个水平放到模型中或从任何位置删除它们,并保持我的0 -indexing,or take a model and move it +/- X positions。

Anyone have an recommended ways of accomplishing this?

任何人都有推荐的方法来完成这项工作?

EDIT 1

编辑1

我已经制定了一个解决方案,我可能想在明天进行优化, 。它保持我的模型的'ordinals'的0索引在我的集合,无论我是相对于它的原始位置向前或向后移动模型。

EDIT 2 Err actually it has errors on fringe-cases.

EDIT 2
Err实际上在边缘情况下有错误。

/** * Move model to a specified location. * * @param int [model id] * @param int [mew item position] * @return this */ move_to: function(m_id, new_pos){ //keep within range if(new_pos < 0) new_pos = 0; else if(new_pos > (this.length - 1)) new_pos = this.length - 1; var model = this.get(m_id), old_pos = model.get('ordinal'); model.set({ ordinal: new_pos }); if(new_pos == old_pos){ //trigger associated events this.sort(); return this; } //update indexes of affected models this.each(function(m){ //ordinal of current model in loop var m_ordinal = m.get('ordinal'); //skip if this is the model we just updated if(m.get('id') == m_id) return; if(old_pos < new_pos){ //moving down, ordinal is increasing if(m_ordinal <= new_pos && m_ordinal != 0){ //this is in the range we care about m.set({ ordinal: m.get('ordinal') - 1 }); } }else if(old_pos > new_pos){ //moving up, ordinal is decreasing if(m_ordinal >= new_pos && (m_ordinal != (this.length - 1))){ //this is in the range we care about m.set({ ordinal: m.get('ordinal') + 1 }); } } }); this.sort(); return this; }

EDIT 3
Okay I think I've fixed all the problems, some simple scope stuff. Here's some code I've tested pretty thoroughly and I believe it works.

EDIT 3
好吧,我想我已经解决了所有的问题,一些简单的范围的东西。这里有一些代码我已经测试得很彻底,我相信它的工作原理。

/** * Move model to a specified location. * * @param int [model id] * @param int [mew item position] * @return this */ move_to: function(m_id, new_pos){ //keep within range if(new_pos < 0) new_pos = 0; else if(new_pos > (this.length - 1)) new_pos = this.length - 1; var model = this.get(m_id), old_pos = model.get('ordinal'); log('old_pos ' + old_pos); log('new_pos ' + new_pos); model.set({ ordinal: new_pos }); if(old_pos == new_pos){ //trigger associated events this.sort(); return this; } var _this = this; //update indexes of affected models this.each(function(m){ //ordinal of current model in loop var m_ordinal = m.get('ordinal'); //skip if this is the model we just updated if(m.get('id') == m_id) return; if(old_pos < new_pos){ //moving down, ordinal is increasing if(m_ordinal <= new_pos && !(m_ordinal <= 0)){ //this is in the range we care about m.set({ ordinal: m.get('ordinal') - 1 }); } }else if(old_pos > new_pos){ //moving up, ordinal is decreasing log('p1'); if(m_ordinal >= new_pos && !(m_ordinal >= (_this.length - 1))){ //this is in the range we care about m.set({ ordinal: m.get('ordinal') + 1 }); } } }); this.sort(); return this; }

EDIT 4

编辑4 >

发现另一个错误,修补它。

Found another bug, patched it.

Backbone.Collection.prototype.move_to = function(m_id, new_pos) {

    //keep within range
    if(new_pos < 0)
        new_pos = 0;
    else if(new_pos > (this.length - 1))
        new_pos = this.length - 1;


    var model = this.get(m_id),
        old_pos = model.get('ordinal');

    log('old_pos ' + old_pos);
    log('new_pos ' + new_pos);

    model.set({
        ordinal: new_pos
    });
    if(old_pos == new_pos){
        //trigger associated events
        this.sort();
        return this;
    }

    var _this = this;
    //update indexes of affected models
    this.each(function(m){

        log(m.id);

        //ordinal of current model in loop
        var m_ordinal = m.get('ordinal');

        //skip if this is the model we just updated
        if(m.get('id') == m_id)
            return;

        if(old_pos < new_pos){
            //moving down, ordinal is increasing

            if(m_ordinal <= new_pos && m_ordinal >= old_pos && !(m_ordinal <= 0)){
                //this is in the range we care about
                m.set({
                    ordinal: m.get('ordinal') - 1
                }, {
                    silent: true
                });

            }

        }else if(old_pos > new_pos){
            //moving up, ordinal is decreasing                  
             log('p1');

            if(m_ordinal >= new_pos && m_ordinal <= old_pos && !(m_ordinal >= (_this.length - 1))){
                //this is in the range we care about
                m.set({
                    ordinal: m.get('ordinal') + 1
                }, {
                    silent: true
                });

            }

        }

    });

    this.sort();                    
    return this;
};


推荐答案

如果你看一下backbone.js的源代码,你会发现,例如,add方法支持使用

If you look at the backbone.js source code, you'll find out that for example the add method supports adding models to certain indexes with

向集合中添加模型到collectionName.add(model,{at:index} );

从位置移除可能需要您为集合创建自定义函数,如:

removing from position might need you to make a custom function to the collection, like:

// Your Collection

removeAt: function(options) {
  if (options.at) {
    this.remove(this.at(options.at));
  }
}

函数并使用内置下划线indexOf函数

for +1 / -1 you can make a custom function and make use of the built-in underscore indexOf-function

// Your Collection

moveUp: function(model) { // I see move up as the -1
  var index = this.indexOf(model);
  if (index > 0) {
    this.remove(model, {silent: true}); // silence this to stop excess event triggers
    this.add(model, {at: index-1});
  }
}

moveDown: function(model) { // I see move up as the -1
  var index = this.indexOf(model);
  if (index < this.models.length) {
    this.remove(model, {silent: true}); // silence this to stop excess event triggers
    this.add(model, {at: index+1});
  }
}

这样你也可以实现moveUp和moveDown

This way you can also implement the moveUp and moveDown to the models themselves for more easily readable code!

// Your Model

moveUp: function() {
  this.collection.moveUp(this);
}

// And the same for moveDown

但是现在索引属性不会保存在模型本身中。要读取索引,只需使用 collection.indexOf(model),但是如果要在模型中始终存储该信息,则可以绑定到添加删除事件以更新所有索引:

But now the index property is not saved in the models themselves. To read the index just use collection.indexOf(model), but if you want to store that information in the models at all times, you could bind to the add and remove events to update all indexes when changes to the collection are made:

// Your collection

initialize: function(options?) {
  ...
  this.on('add remove', this.updateModelOrdinals);
  ...
},

...

updateModelOrdinals: function() {
  this.each(function(model, index) {
    this.model.set('ordinal', index);
  });
}

etvoilà!现在你应该有你需要的功能,而不需要重新发明的轮,仍然保持0索引与Backbone自己的功能到位!对不起,有点被带走,问我是否走过你的头。并阅读 backbone.js来源,您可以在那里找到真正有用的内容!

et voilà! Now you should have the functionality you need without reinventing the wheel and still keeping the 0-indexing in place with Backbone's own functionality! Sorry for getting a bit carried off, ask if I went over your head. And read the backbone.js source, you can find seriously useful stuff there!

希望这有助于!

这篇关于BackboneJS在一个集合中重新排列模型的最佳方式,同时为每个模型维护0个索引的序数属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆