4

I have several columns in a table such as column A,B,C,D and E which I need to show in my HTML page. In some pages I need to show sorted results based on only one column of page, such as for Column "C" which is 3rd column of table. I am able to do this using the below code:

function Ascending(a, b) {
  if (a < b) return -1;
  if (a > b) return 1;
  return 0;
}
var rows = $('#table tr').not(':first').get();
$('#table tr').slice(1).remove();
rows.sort(function(rowA, rowB) {
  var keyA = $(rowA).children('td').eq(2).text().toUpperCase();
  var keyB = $(rowB).children('td').eq(2).text().toUpperCase();
  return Ascending(keyA, keyB);
});

But I have another requirement wherein I need to show the sorted results based on two columns i.e. based on the sorting of Column C in above case, results of column E should also get sorted. For example:

Before sorting:

Column C  Column E
2         Fish
1         Box
7         Cat
2         Dog
1         Apple
2         Box
2         Axe
7         Box
2         Answer
7         Apple
6         Year
2         Goat

After sorting Column C only:

Column C  Column E
1         Box
1         Apple
2         Dog
2         Fish
2         Box
2         Axe
2         Goat
2         Answer
6         Year
7         Box
7         Apple
7         Cat

After sorting Column C then Column E:

Column C  Column E
1         Apple
1         Box
2         Answer
2         Axe
2         Box
2         Dog
2         Fish
2         Goat
6         Year
7         Apple
7         Box
7         Cat

Example of table wherein M should come below L in second column

Which I am unable to implement. How can I do it?

Salman A
  • 262,204
  • 82
  • 430
  • 521
Nishant Kumar
  • 235
  • 2
  • 4
  • 13
  • 1
    Would you mind using code tags to format the HTML so we can see what you want the output to look like? It's a bit hard to tell what you're trying to achieve by looking at your example because it's all scrunched up onto one line. – Eamonn Gormley Apr 15 '15 at 05:38
  • Its not entirely clear from your post how you want the data sorted. Edit your post to include before and after examples. Make sure they are arranged clearly so they are easier to understand. Try using a bulleted list. – Bob Apr 15 '15 at 05:43
  • Are you trying to achieve a secondary sort (for column E in the example)? – Udi Cohen Apr 15 '15 at 05:45
  • You might check out https://www.datatables.net/ which are capable of this type of sorting with very little coding – Wesley Smith Apr 15 '15 at 06:31
  • In general, sorting by n columns works as follows: check the results of compare(a.col1, b.col1), compare(a.col2, b.col2), ... until you get a non-zero result or you have checked all the columns, return that result. – Salman A Apr 15 '15 at 08:31
  • thanks @Salman A for your comment.I am clear about the logic but implementing it is an issue for me.It will be great if you can help me with the code, in the same way which I have given for two elements above. – Nishant Kumar Apr 15 '15 at 08:39

2 Answers2

11

To sort by more than one column you write the comparison function like this:

(Comparison function is passed two "rows")

  1. Compare row 1 column 1 with row 2 column 1
    • If they are different then return the result (a +ve or -ve number)
  2. Compare row 1 column 2 with row 2 column 2
    • If they are different then return the result (a +ve or -ve number)
  3. Repeat for remaining columns
  4. Return 0

The following example shows how to write the compare function that sorts by two columns. It is possible to use a loop or recursion to sort by n columns.

$(function() {
  function sortByColumn3(row1, row2) {
    var v1, v2;
    v1 = $(row1).find("td:eq(2)").text();
    v2 = $(row2).find("td:eq(2)").text();
    // for numbers you can simply return a-b instead of checking greater/smaller/equal
    return v1 - v2;
  }

  function sortByColumn3And5(row1, row2) {
    var v1, v2, r;
    v1 = $(row1).find("td:eq(2)").text();
    v2 = $(row2).find("td:eq(2)").text();
    r = v1 - v2;
    if (r === 0) {
      // we have a tie in column 1 values, compare column 2 instead
      v1 = $(row1).find("td:eq(4)").text();
      v2 = $(row2).find("td:eq(4)").text();
      if (v1 < v2) {
        r = -1;
      } else if (v1 > v2) {
        r = 1;
      } else {
        r = 0;
      }
    }
    return r;
  }
  $("#button1, #button2").on("click", function() {
    var rows = $("#table1 tbody tr").detach().get();
    switch (this.id) {
      case "button1":
        rows.sort(sortByColumn3);
        break;
      case "button2":
        rows.sort(sortByColumn3And5);
        break;
    }
    $("#table1 tbody").append(rows);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<input type="button" id="button1" value="sortByColumn3">
<input type="button" id="button2" value="sortByColumn3And5">

<table id="table1" border="1" width="100%">
  <thead>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
      <td>4</td>
      <td>5</td>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>x</td>
      <td>y</td>
      <td>2</td>
      <td>z</td>
      <td>Fish</td>
    </tr>
    <tr>
      <td>y</td>
      <td>z</td>
      <td>1</td>
      <td>x</td>
      <td>Box</td>
    </tr>
    <tr>
      <td>z</td>
      <td>x</td>
      <td>7</td>
      <td>y</td>
      <td>Cat</td>
    </tr>
    <tr>
      <td>x</td>
      <td>y</td>
      <td>2</td>
      <td>z</td>
      <td>Dog</td>
    </tr>
    <tr>
      <td>y</td>
      <td>z</td>
      <td>1</td>
      <td>x</td>
      <td>Apple</td>
    </tr>
    <tr>
      <td>z</td>
      <td>x</td>
      <td>2</td>
      <td>y</td>
      <td>Box</td>
    </tr>
    <tr>
      <td>x</td>
      <td>y</td>
      <td>2</td>
      <td>z</td>
      <td>Axe</td>
    </tr>
    <tr>
      <td>y</td>
      <td>z</td>
      <td>7</td>
      <td>x</td>
      <td>Box</td>
    </tr>
    <tr>
      <td>z</td>
      <td>x</td>
      <td>2</td>
      <td>y</td>
      <td>Answer</td>
    </tr>
    <tr>
      <td>x</td>
      <td>y</td>
      <td>7</td>
      <td>z</td>
      <td>Apple</td>
    </tr>
    <tr>
      <td>y</td>
      <td>z</td>
      <td>6</td>
      <td>x</td>
      <td>Year</td>
    </tr>
    <tr>
      <td>z</td>
      <td>x</td>
      <td>2</td>
      <td>y</td>
      <td>Goat</td>
    </tr>
  </tbody>
</table>
Salman A
  • 262,204
  • 82
  • 430
  • 521
  • thanks a lot @Salman A for your help and detailed code. It worked well. Any idea how the same thing will be implemented if the column 5 contains date in DDMMYYYY format. – Nishant Kumar Apr 15 '15 at 09:49
  • You need to create a JavaScript date object. Then use the subtraction logic to compare them. `DDMMYY` cannot be used directly with dates, you need extract DD, MM and YYYY using substring function and use long date constructor (`new Date(year, month, date)`). – Salman A Apr 15 '15 at 09:56
  • ok, thanks a lot for your reply.Will try implementing the same in my code. – Nishant Kumar Apr 15 '15 at 10:02
0

function sortTable() {
    var table, rows, switching, i, x, y, a, b, shouldSwitch;
    table = document.getElementById("mytable");
    switching = true;
    while (switching) {
        switching = false;
        rows = table.getElementsByTagName("TR");
        for (i = 0; i < (rows.length - 1); i++) {
            shouldSwitch = false;
            /*Get the two elements you want to compare,
            one from current row and one from the next:*/
            x = rows[i].getElementsByTagName("TD")[3];
            y = rows[i + 1].getElementsByTagName("TD")[3];
            //check if the two rows should switch place:
            if (Number(x.innerHTML) < Number(y.innerHTML)) {
                //if so, mark as a switch and break the loop:
                shouldSwitch = true;
                break;
            }


        }
        if (shouldSwitch) {
            /*If a switch has been marked, make the switchcand mark that a switch has been done:*/
            rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
            switching = true;
        }
    }
  
    for (i = 0; i < (rows.length - 1); i++) {
        /*Get the two elements you want to compare,one from current row and one from the next:*/
        for (j = i + 1; j < (rows.length); j++) {
            x = rows[i].getElementsByTagName("TD")[3];
            y = rows[j].getElementsByTagName("TD")[3];
            a = rows[i].getElementsByTagName("TD")[0];
            b = rows[j].getElementsByTagName("TD")[0];
            //check if the two rows should switch place:
            if (Number(x.innerHTML) == Number(y.innerHTML)) {
                //if so, swap
                if (Number(a.innerHTML) > Number(b.innerHTML)) {
                    rows[i].parentNode.insertBefore(rows[j], rows[i]);

                }
            }
        }
    }
}
<body>
<div class="container">
  <form class="form-horizontal" role="form">
    <div class="form-group">
      <button id="sort" onclick="sortTable()" type="button" class="btn btn-default">sort</button>
    </div>
  </form>

  <div class="contents">
    <table class="table">
      <thead>
        <tr>
          <th>Id</th>
          <th>Image</th>
          <th>Name</th>
          <th>Price</th>
        </tr>
      </thead>
     <tbody id="mytable"><tr><td>5</td><td><img src="image/5.gif"></td><td>cony #5</td><td>170</td></tr><tr><td>1</td><td><img src="image/1.gif"></td><td>cony #1</td><td>170</td></tr><tr><td>2</td><td><img src="image/2.gif"></td><td>cony #2</td><td>270</td></tr><tr><td>8</td><td><img src="image/8.gif"></td><td>cony #8</td><td>70</td></tr><tr><td>10</td><td><img src="image/10.gif"></td><td>cony #10</td><td>170</td></tr><tr><td>4</td><td><img src="image/4.gif"></td><td>cony #4</td><td>150</td></tr><tr><td>3</td><td><img src="image/3.gif"></td><td>cony #3</td><td>130</td></tr><tr><td>6</td><td><img src="image/6.gif"></td><td>cony #6</td><td>160</td></tr><tr><td>9</td><td><img src="image/9.gif"></td><td>cony #9</td><td>170</td></tr><tr><td>7</td><td><img src="image/7.gif"></td><td>cony #7</td><td>170</td></tr></tbody>
   
    </table>
  </div>
</div>
</body>

Simple solution in Javascript The above example is in descending order of price if same price column id will be in ascending order

Ramesh arr
  • 19
  • 6
  • Code only answers arent encouraged as they dont provide much information for future readers please provide some explanation to what you have written – WhatsThePoint Jun 20 '18 at 10:51
  • @WhatsThePoint The above code sort table by descending order of price column and if same price it will sort by ascending order of id column – Ramesh arr Sep 26 '18 at 05:30