VA wrote:

Thanks.

One more question:

How can I extend this concept to, say, take in a list of column indexes

(or TH ids) and re-order the columns according to that order?

Thanks

There was an error in my earlier script, this line:

row.insertBefore(cell1, row.cells[colIndex2]);

should be:

row.insertBefore(cell1, row.cells[colIndex2].nextSibling);

The nextSibling bit is important when swapping non-adjacent rows.

Ordering columns is a fish of a different feather.

You first must decide which columns to swap, then swap them. Here are

some general solutions (if RC is reading this, I make no apologies for

qualifying 'solution'):

1. Determine which columns need to be swapped and do that - probably

more than one swap will be required and hopefully you have an

algorithm that lets you do it in as few as possible

2. Break the table into fragments and re-construct it in the new order

3. Clone the cells of the existing table, add them to a new table in

the new order then replace the existing table with the new one

4. Inspect the new order, wherever a column is out of order, move it to

its new position.

Which one is more efficient than the other will likely depend on the

situation, I think the last is the best as a general solution (i.e. will

work in all situations and it is sufficiently fast in most).

For example, if the columns are in the order ABCD and you are given the

order ACDB, you can do two swaps or one move. To get ACBD requires one

swap or one move, and DCBA requires two swaps or 3 moves.

Fragmenting/cloning will take the same amount of time every time, those

methods may come into their own if the tables are large and the

re-ordering is extensive.

The difference in time taken for one method compared to another may be

significant and probably varies depending on the browser and internal

algorithm for each method - e.g. DOM move versus some innerHTML/text

munging method.

Will the user want re-order the columns manually (say moving individual

columns left or right)? Will they want to prescribe the new order then

press a button to 'make it so'.

Below is a script that uses keys for the old order and the new order,

e.g. for a four column table, changing ABCD to ADBC requires 2 moves.

The maximum number of moves ever required is one less that the number of

columns (I think). It only searches through the keys, so even if a large

number of columns need lots of changes, the number of moves should be

kept close to the minimum number (though likely not often *the* minimum

number) required.

I've left out feature detection etc. The use of concat, splice etc.

means JavaScript 1.2 or better is required. It needs DOM anyway, so

what the heck. Not all browsers support the cells collection properly

(e.g. Safari 1.0.3 but fixed thereafter).

There is also very little error detection or correction, you may want to

add some.

<html><head>

<title>reorder columns</title>

</head>

<body >

<script type="text/javascript">

// Re-order table

function reorderColumn(table, order0, order1)

{

// Turn order keys into arrays

order0 = order0.split('');

order1 = order1.split('');

// Check arrays are same length

if (order0.length != order1.length) return;

// Check arrays have same elements

var x = order0.concat().sort().join('');

var y = order1.concat().sort().join('');

if (x != y) return;

// Re-order the columns

var j, k = i = order0.length;

while (i--) { // Compare each key

if (order0[i] != order1[i]){ // If one out of order

j = newIdx(order0[i], order1) // Find new spot

moveColumn(table, i, j); // Move the column

moveEl(order0, i, j); // Move the key

i = k; // Start key comparison again

}

}

}

// returns the position of element el in array ar

// Assumes el is in ar

function newIdx(el, ar)

{

var i = ar.length;

while( ar[--i] != el){}

return i;

}

// Move a column of table from start index to finish index

// Assumes there are columns at sIdx and fIdx

function moveColumn(table, sIdx, fIdx)

{

var row, cA;

var i=table.rows.length;

while (i--){

row = table.rows[i]

var x = row.removeChild(row.cells[sIdx]);

row.insertBefore(x, row.cells[fIdx]);

}

}

// Move element in array ar from index i to index j

// Assumes array has indexes i and j

function moveEl(ar, i, j)

{

var x = ar.splice(i,1);

ar.splice(j,0,x);

return ar; // Not needed, handy for debug

}

</script>

<input type="button" value="re-order ABCD to DCBA" onClick="

reorderColumn(document.getElementById('tableA'),'A BCD','DCBA');

"><br>

<table id="tableA" cellpadding="5" border="1"

cellspacing="5">

<tr><th>HC0</th><th>HC1</th><th>HC2</th><th>HC3</th></tr>

<tr><td>R0 C0</td><td>R0 C1</td><td>R0 C2</td><td>R0 C3</td></tr>

<tr><td>R1 C0</td><td>R1 C1</td><td>R1 C2</td><td>R1 C3</td></tr>

<tr><td>R2 C0</td><td>R2 C1</td><td>R2 C2</td><td>R2 C3</td></tr>

<tr><td>R3 C0</td><td>R3 C1</td><td>R3 C2</td><td>R3 C3</td></tr>

</table>

</body>

</html>

--

Rob