2

I have a TR's ( or divs with class - it doesnt matter ) like that

I want to sort the lines by SCORE.

Name     |     Age        |Score 
-----------------------------------
John           26           90
paul           25           75
ringo          25           77

I know there is already a plugin for jquery that sorts tables but i want to build my own.

I dont have a problem finding the values in the score column - thats easy.

my question is how to sort and display the new results ? i have thought of something

1) take all the tr's elements to array of jQuery elements .

2) by .each sort the array

3) delete the old content

4)by .each loop - 'append' each TR by the order of the appearence in the array.

Is there a better way ?

Royi Namir
  • 144,742
  • 138
  • 468
  • 792
  • @RobW: Perfectly acceptable to make that an answer. Since it's a link within Stack Overflow itself, it's not a [link-only answer](http://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers). – T.J. Crowder Sep 27 '11 at 14:05

2 Answers2

4

I've previously written an efficient algorithm for sorting tables (answer). I've adjusted the function for this case:

function sortTable(){
    var tbl = document.getElementById("myTable").tBodies[0];
    var store = [];
    for(var i=0, len=tbl.rows.length; i<len; i++){
        var row = tbl.rows[i];
        var sortnr = parseFloat(row.cells[2].textContent || row.cells[2].innerText);
        if(!isNaN(sortnr)) store.push([sortnr, row]);
    }
    store.sort(function(x,y){
        return x[0] - y[0];
    });
    for(var i=0, len=store.length; i<len; i++){
        tbl.appendChild(store[i][1]);
    }
    store = null;
}

To sort the table, use `sortTable();

Explanation of code:

  1. Two variables are created: HTMLTableSectionElement tbl and Array store.
  2. A loop walks through all elements of the tBody (=rows), and pushes a new array in store, consisting of two elements: [sortnr, row].
    sortnr holds the numeric value of the second cell of the row, which is used for the sort function (look ahead)
    row is a reference to HTMLTableRowElement, used later to move the rows.
  3. store.sort(..) sorts the array store according to sortnr (as defined above, #2 of this explanation).
  4. A loop walks through the sorted array, and appends the rows at the end of the table (tbl.appendChild moves the node from the previous location)

Note that elements which don't have a valid number at the 3rd column (cell index 2) aren't moved at all. These stay at the top of the table.

If you want to have the invalid rows located at the end, use:

for(var i=store.length-1; i>=0; i--){
    tbl.insertBefore(store[i][1], tbl.rows[0]);
}

Question by Royi Namir (at comments)

youre the man. just one more question : you wrote 'tbl.appendChild moves the node from the previous location' , and i thoguth to my self that the action is appendChild - but behind the scenes it moves(!) the element. I read about it and they said that if its the same object then it moved. but how dows he knows that its the same object? he doesnt have any ID or something to recognize ...

Answer:
(Real life example:) Say, you see a apple laying on the table. If you want that same apple to be at the floor, what would you do? pick up the apple and put it at the floor.

The same applies to appendChild: When you request the node to be appended, the script engine wants to place the node to be placed in the tree. Consequently, the previous node will be removed, because » appendChild does not copy nodes. «
To copy nodes, the function element.cloneNode() exists.

Community
  • 1
  • 1
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • listen , you are great. p.s. i need to convert it to jQuery. but i will do it . thanks. ":) ( in 9 min i'll check the ans) – Royi Namir Sep 27 '11 at 14:07
  • Do NOT, NOT, I mean NOT convert this to JQuery. For such a heavy operation like sorting HTML nodes, you should use native JavaScript when possible. See the link within my answer. The JQuery (question) approach tooks several seconds to execute, while my function achieved the same results within a second. – Rob W Sep 27 '11 at 14:09
  • at the end you wrote ' tbl.appendChild(store[i][1]);' - so what do you do with the old data ? you erase it ? where do you add the whole (!!) row data ? – Royi Namir Sep 27 '11 at 14:12
  • Rob W , i got it - this is the second data in the array. thanks – Royi Namir Sep 27 '11 at 14:18
  • @RoyiNamir I edited my answer to answer the question you asked 10 minutes below. – Rob W Sep 27 '11 at 14:23
  • youre the man. just one more question : you wrote 'tbl.appendChild moves the node from the previous location' , and i thoguth to my self that the action is appendChild - but behind the scenes it moves(!) the element. I read about it and they said that if its the same object then it moved. but how dows he knows that its the same object? he doesnt have any ID or something to recognize ... – Royi Namir Sep 27 '11 at 19:32
  • @RoyiNamir See my updated answer for the detailled answer to that question/comment. – Rob W Sep 27 '11 at 19:53
  • , Let's say this apple is '

    ' which is currently in the document. Now im getting by Ajax a new(!!)

    from server. now i appendChild this new 'p' into some div. how does JS knows which 'p' to move ? the new 'p' is no different than the current 'p' ...

    – Royi Namir Sep 27 '11 at 20:57
  • You may not see the difference between `

    ` and `

    `, but the JavaScript interpreter **does** know the difference between `document.createElement("p");document.createElement("p")` (TWO `

    ` elements are created).

    – Rob W Sep 27 '11 at 21:19
  • http://stackoverflow.com/questions/7575842/how-does-javascript-distincts-between-objects – Royi Namir Sep 27 '11 at 21:23
1

If for example you wanted to have your table ordered alphabetically by rows, and every second row was a non-useful partner of the previous (or didn't contain appropriate data) - you could do this (variation on Rob W's answer).

function sortTable(){
    var tbl = document.getElementsByTagName('table')[1].tBodies[1]; // magic numbers are bad
    var store = [];
    var len = tbl.rows.length / 2; // Assumes even rows. Loops become invalid otherwise.

    for(var i=0; i<len; i++){
        var row = tbl.rows[2*i];
        var sortnr = (row.cells[1].textContent || row.cells[1].innerText || row.cells[1].innerHTML);
        store.push([sortnr, row, tbl.rows[(2*i) + 1]]);
    }

    store.sort(function(a, b){
        a = a[0].toLowerCase(); // make sort case insensitive (waste resources?)
        b = b[0].toLowerCase();
        if (a < b)
           return -1 
        if (a > b)
           return 1
        return 0
    });

    for(var i=0, len=store.length; i<len; i++){
        tbl.appendChild(store[i][1]); // sorted line
        tbl.appendChild(store[i][2]); // its partner
    }

    store = null;
}

sortTable();
Supernovah
  • 1,946
  • 12
  • 34
  • 50