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.
Here are my game data
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' }] }];
And here is the gist of my core network
Collections.Exercise_Groups = Backbone.Collection.extend({ model: Models.Exercise_Group, comparator: function(model){ return model.get('ordinal'); }, initialize: function(){ return this; }
The launch is simple, I want to be able to take the model and transfer its +1 or -1 serial number and support 0-indexing of all models in the collection.
In the end, I want to bring this to the level where I can fall into models or remove them from any position and still maintain my 0-indexing, or take the model and move it +/- X positions.
Does anyone have recommended ways to accomplish this?
EDIT 1
I developed a solution, maybe I want to optimize it tomorrow after I really get some sleep. It supports 0-indexing the โordinals" of my models in my collection, regardless of whether I move the model forward or backward relative to its original position.
EDIT 2 Err actually has errors in fringes.
/** * 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 Well, I think I fixed all the problems, some simple things. Here is some code that I tested quite carefully, and I believe that it works.
/** * 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
Found another mistake, fixed 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; };