1

I am trying to sort a dynamically constructed table on the client side. So far I have done my research to discover JavaScript's sort() method will take a callback. Here is what I have so far:

function retrvCatalog(e){
var merch = document.getElementById('merch');
var tRows = merch.rows;
var tBody = merch.tBodies;
var rowArr = [];
for (x in tRows){
    rowArr[x] = tRows[x];
}
rowArr.sort(function(a, b){
    if (a.cells.textContent < b.cells.textContent){
        return -1;
    }
    if(a.cells.textContent > b.cells.textContent){
        return 1;
    }
    return 0;
});
}

Stepping through it in Firebug, it appears to not change the order of the rows. Can someone please help me figure out what I am missing?

FINAL ALGORITHM

function retrvCatalog(e){
var fltr = e.id;
var merch = document.getElementById('merch');
var tblHead = merch.tHead;
merch.deleteTHead();
var tRows = merch.rows;
var rowArr = [];
for (var i=0; i<tRows.length; i++){
    rowArr[i] = tRows[i];
}
rowArr = rowArr.sort(function(a, b){
    if (fltr > 3){
        a = parseFloat(a.cells[fltr].innerHTML);
        b = parseFloat(b.cells[fltr].innerHTML);
    }
    else{
        a = a.cells[fltr].innerHTML;
        b = b.cells[fltr].innerHTML;
    }
    if (a>b){
        return 1;
    }
    if(a<b){
        return -1;
    }
    return 0;
});
while(merch.hasChildNodes()) {
    merch.removeChild(merch.firstChild);
}
merch.appendChild(tblHead);
for (i=0;i<rowArr.length;i++){
    merch.appendChild(rowArr[i]);
}
}

The final two columns in the row are numbers, so that is why the method to sort is slightly variable.

4 Answers4

1

Several problems in your code.

First, you didn't declare the x variable.

for(var x...

Second, don't use for-in to iterate an array like collection. Use for.

for (var x = 0, len = tRows.length; x < len; x++){
    rowArr[x] = tRows[x];
}

Third, there is no textContent property of a cells collection.

This is easy to test by logging its value. This should have been the first thing you tried.

console.log(a.cells.textContent); // undefined

You need to decide which cell you want, and ask for it by index.

console.log(a.cells[0].textContent);

Finally, you should be aware that this technique will not show the result of the sorting in the DOM. You're only sorting the Array. You'll need to append the new ordering to the DOM.

Maybe you knew this, but you didn't show it in your code.

I don't know the relationship of the rows to the tBodies, so I can't give an example. But if all the rows are in one tbody, just loop the Array, and tBody[0].appendChild(rowArr[i])

  • tRows is not an array, it's an HTML collection. That is why I used "for in" –  Sep 15 '12 at 17:59
  • Your suggestions were helpful, but didn't answer the question. Thanks for your help! –  Sep 15 '12 at 21:00
  • Declaring the `x` variable isn't necessary, but it does make a global variable named `x` if you don't use `var`. If you look at: http://jsfiddle.net/ex4gV/1/ , you'll see that even though the for loop is scoped in the function, `x` becomes global after its use, but is undefined beforehand. – Ian Sep 16 '12 at 15:48
0
rowArr.sort(function(a,b) {
    a = parseFloat(a.cells.textContent);
    b = parseFloat(b.cells.textContent);
    return (a-b);
};
BenMorel
  • 34,448
  • 50
  • 182
  • 322
C..
  • 802
  • 4
  • 16
  • There's an idea. However, shouldn't it sort alphabetically as well as numerically? –  Sep 15 '12 at 17:11
0

I'm not sure if I'm missing something, but I'm pretty sure you can't use textContent on the cells array. You need to index cells so you know which column to actually sort on. If your rows have 4 columns each (or even if there's only 1), you still need to tell the sort function which column to sort on.

So in your sort function, if you wanted to sort by the second column, you'd want something like:

rowArr.sort(function (a, b) {
    if (a.cells[1].textContent < b.cells[1].textContent) {
        return -1;
    } else if (a.cells[1].textContent > b.cells[1].textContent) {
        return 1;
    }
    return 0;
});

And I'm not sure what's in your cells, but you may want to use .innerHTML, not .textContent.

Ian
  • 50,146
  • 13
  • 101
  • 111
-1

"don't use for-in to iterate an array like collection." - user1673729

tRows is not an array, it's an HTML collection. That is why I used "for in" – nodirtyrockstar

An HTML Collection is an array like collection. Do not use for-in.

  • This answer does not help me to understand your point. for-in is used for iterating a collection. tRows is a collection I want to iterate. –  Sep 15 '12 at 18:23
  • @nodirtyrockstar You're right, but look at this post: http://stackoverflow.com/questions/500504/javascript-for-in-with-arrays – Ian Sep 16 '12 at 15:45