我在这里遇到了一个问题,我有一个 BackboneJS 模型的集合,每个模型都有一个“序数”属性来跟踪它在集合中的顺序。
这是我的播放数据
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 索引。
最终我想把它带到一个水平,我可以放入模型或从任何位置删除它们,并且仍然保持我的 0 索引,或者取一个模型并将其移动 +/- X 位置。
有人有推荐的方法来完成这个吗?
编辑 1
我已经制定了一个解决方案,我可能想在明天真正睡一觉后对其进行优化。它维护我的集合中我的模型的“序数”的 0 索引,无论我是相对于它的原始位置向前还是向后移动模型。
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;
}
编辑 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;
}
编辑 4
又发现一个bug,补上。
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;
};