I'm working on project which don't use jQuery but only JavaScript and we have a need to sort alphabetically ascending a table values (without any external library).
The objective is to sort rows elements each time a column (th element) is clicked.
Example
If I have this table
When I click on "Names", the table should be refreshed like that:
When I click on "Tel", the table should be refreshed like that:
I'm sharing my own solution here. If you have any remark or suggestions, please share.
I'm updating my solution by adding an inverse order feature:
- When you first click on Names for example, the table will be refreshed with an ascending order of names.
- When you click a 2nd time on Names, the table will be refreshed with a descending order of names.
- When you click a 3rd time on Names, the table will be refreshed with an ascending order of names.
- etc...
var sortableTable = {
/**
* The table to sort
*/
table: null,
getTable: function(){
return this.table;
},
setTable: function(table){
this.table = table;
},
/**
* The column used for sorting
*/
element: null,
getElement: function(){
return this.element;
},
setElement: function(element){
this.element = element;
},
/**
* When ooderDirection is 1 => Ascending order
* When ooderDirection is -1 => Descending order
*/
orderDirection: 1,
getOrderDirection: function(){
return this.orderDirection;
},
setOrderDirection: function(orderDirection){
this.orderDirection = orderDirection;
},
/**
* Get table rows elements
*/
getRows: function(){
var rows = [];
if(null !== this.getTable()){
var allRows = this.getTable().rows;
/*
When I returned allRows directly,
in the sort function when I do: rows.sort();
it display an error: Uncaught TypeError: rows.sort is not a function
So I'm converting this object to an array
*/
var arrayRows = [];
//allRows contains all rows with <th> elements,
//so I'm removing th elements (index 0)
for(let i=1 ; i<allRows.length ; i++){
arrayRows.push(allRows[i]);
}
return (arrayRows);
}
return null;
},
/**
* Display rows using the sort result
*/
refresh: function(rows){
for(let i=0 ; i<rows.length ; i++){
this.getTable().appendChild(rows[i]);
}
},
/**
* Sort alphabetically (ASC)
*/
sort: function(indexOfClickedTh){
var rows = this.getRows();
var that = this;
rows.sort(function(item1, item2){
var contentItem1 = item1.getElementsByTagName('td')[indexOfClickedTh].innerText;
var contentItem2 = item2.getElementsByTagName('td')[indexOfClickedTh].innerText;
let resultCompare = contentItem1.localeCompare(contentItem2);
resultCompare = resultCompare * that.getOrderDirection();
//console.info('comparing(' + contentItem1 + ', ' + contentItem2 + ')=' + resultCompare);
return resultCompare;
});
this.refresh(rows);
}
}
//The first click will generate an ascending sort
var initialOderDirection = -1;
var myTableToSort = document.getElementById('users');
sortableTable.setTable(myTableToSort);
sortableTable.setOrderDirection(initialOderDirection);
var ListOfTh = document.getElementById('users').getElementsByTagName('th');
for(var i=0 ; i<ListOfTh.length ; i++){
var oneTh = ListOfTh[i];
oneTh.addEventListener("click", function(){
//console.info("------> New sort based on '" + this.innerText + "' <------");
// Set the current clicked <th> element
sortableTable.setElement(this);
//Inverse the order
sortableTable.setOrderDirection( sortableTable.getOrderDirection() * -1 );
//Do the sort and refresh table result
sortableTable.sort(this.cellIndex);
});
};
table{
font-size: 16px;
border-collapse: collapse;
border-spacing: 0;
width: 100%;
}
table th{
padding-top: 11px;
padding-bottom: 11px;
background-color: #6295a5;
color: white;
}
table td{
border: 1px solid #ddd;
text-align: left;
padding: 8px;
}
table tr:nth-child(even) {
background-color: #f2f2f2;
}
table th{
cursor: pointer;
}
table th:hover{
color: #dea82e;
background-color: #37545d;
}
<table id="users">
<thead>
<tr>
<th>Names</th>
<th>Functions</th>
<th>Emails</th>
<th>Tel</th>
</tr>
</thead>
<tbody>
<tr>
<td>xMxxx</td>
<td>Physicists</td>
<td>xmxxx@domain.com</td>
<td>00 55 99 99 99</td>
</tr>
<tr>
<td>xJxxx</td>
<td>Air Traffic Controllers</td>
<td>xjxxx@domain.com</td>
<td>00 22 99 99 99</td>
</tr>
<tr>
<td>xExxx</td>
<td>Engineer</td>
<td>xexxx@domain.com</td>
<td>00 33 99 99 99</td>
</tr>
<tr>
<td>xAxxx</td>
<td>Mechanical engineer</td>
<td>xaxxx@domain.com</td>
<td>00 11 99 99 99</td>
</tr>
<tr>
<td>xZxxx</td>
<td>Doctor</td>
<td>xzxxx@domain.com</td>
<td>00 44 99 99 99</td>
</tr>
<tr>
<td>xPxxx</td>
<td>Professor</td>
<td>xpxxx@domain.com</td>
<td>00 66 99 99 99</td>
</tr>
</tbody>
</table>