Most efficient way to insert into ordered sequence I have a dashboard like interface, that can have many tabs. There can be as many or as few tabs as the user likes, with the user being allowed to re order them as they wish. Exactly like browsers do.

My problem is moving the tabs position, for example, look at these tabs: 

[Sales] [Admin] [Finance] [Development]


If the user wants to move the [Development](index 3) tag to be after [Sales], giving it a new index of 1, how should I bump Finance and Development along to 2 and 3 respectively?

I am using JSON to store it so data.dashboard[0].sequence merely means the sequence value for the first dashboard.

At the moment I am using the following bit of code, which seems a bit hacky and not as efficient as it could be. The function is called with the start index(3 in this case) and the desired or end index (1 in this case). I've tried my best to explain with the comments, but feel free to ask anything you don't understand:

function changeSequence(start, end){
  var newVal = 999;
  for(d=0;d&lt;data.dashboards.length;d++){
    if(data.dashboards[d].sequence == start){    // set [Development] to 999 temporarily
      data.dashboards[d].sequence = newVal;
    } 
  }
  if(start &gt; end){ 
    for(i=start; i&gt;end; i--){
      var d = i;
      d--;
      for(j=0;j&lt;data.dashboards.length;j++){     // if [Development] (index3) is after 
        if(data.dashboards[j].sequence == d){    // [Admin] (index1), bump indexes 
          data.dashboards[j].sequence = i;       // 1 and 2 along one (to 2 and 3)
        } 
      }
    }
  } else {
    for(i=start; i&lt;end; i++){
      var d = i;
      d++;
      for(j=0;j&lt;data.dashboards.length;j++){     // else if [Development] (index3) is
        if(data.dashboards[j].sequence == d){    // before [Admin] (index1), which it
          data.dashboards[j].sequence = i;       // isn't in this case, bump them all
        }                                        // down one
      }
    }
  }
  for(d=0;d&lt;data.dashboards.length;d++){
    if(data.dashboards[d].sequence == newVal){   // then set [Development]'s new
      data.dashboards[d].sequence = end;         // index to what its meant to be
    } 
  } 
}


This code works, but I feel like I've gone the long way and simply going from

[Sales] [Admin] [Finance] [Development]


to

[Sales] [Development] [Admin] [Finance]


Should be that hard

Edit: Still learning, so even unrelated ways to improve my code would be great
Fundamentally, you should probably use the array's own ordering. It'd remove the need for a sequence number that you manually have to track and update. Instead, you can simply pluck index 3 out of the array, and splice it in at index 1, and not worry about sequence numbers at all.

But if you can't/won't get the data.dashboards array to behave like that, you can take a detour.

Now, I highly, highly doubt this is the most efficient way of doing things - it's certainly not elegant - but it's straightforward to follow.

Say you have this:

var data = {
    dashboards: [ // random ordering
        {name: "Development", sequence: 3},
        {name: "Sales", sequence: 0},
        {name: "Finance", sequence: 2},
        {name: "Admin", sequence: 1}
    ]
};


Get everything sorted first:

var sorted = data.dashboards.sort(function(a, b) {
    return a.sequence - b.sequence;
});


So now we have an array where the objects are ordered according to their sequence

seq | name
------------------
0   | Sales
1   | Admin
2   | Finance
3   | Development


Then, if we can assume that the sequence numbers are indeed sequential with no gaps or repeats, we could (again) just splice &amp; splice to get the right order.
But let's say we can be sure that index equals sequence number. In that case, loop until we find it, pluck it, and reinsert it:

var currSequence = 3, // the target's current number
    newSequence  = 1, // the target's desired number
    dashboard;

// find and move the target
for( var i = 0, l = sorted.length ; i &lt; l ; i++ ) {
    if( sorted[i].sequence === currSequence ) {
        dashboard = sorted[i];
        sorted.splice(i, 1); // remove the target
        sorted.splice(newSequence, 0, dashboard); // re-insert it at its new position
        break;
    }
}


Now, we have the right order, but not the right sequence numbers:

seq | name
------------------
0   | Sales
3   | Development
1   | Admin
2   | Finance 


Finally, reset the sequence numbers

for( i = 0, l = sorted.length ; i &lt; l ; i++ ) {
    sorted[i].sequence = i;
}


And we get

seq | name
------------------
0   | Sales
1   | Development
2   | Admin
3   | Finance


Neatly sequential numbering and ordering, regardless of the original array's order and sequence values. The original data.dashboards array is still in the same scrambled order as before, but the sequence number of each object is now correct.

Here a jsfiddle



Actually, here's a simpler one that I believe works in all cases, regardless of array ordering, as long as the sequence numbers are sequential already:

var currSequence = 3, // the target's current number
    newSequence  = 1, // the target's desired number
    correction = currSequence &gt; newSequence ? 1 : -1,
    lower = Math.min(currSequence, newSequence),
    upper = Math.max(currSequence, newSequence),
    dashboard;

for( var i = 0, l = data.dashboards.length ; i &lt; l ; i++ ) {
    dashboard = data.dashboards[i];
    if( dashboard.sequence == currSequence ) {
        dashboard.sequence = newSequence;
    } else if( dashboard.sequence &gt;= lower &amp;&amp; dashboard.sequence &lt;= upper ) {
        dashboard.sequence += correction;
    }
}


Here's a demo