HTML table sort
Check if you could go with any of the below mentioned JQuery plugins. Simply awesome and provide wide range of options to work through, and less pains to integrate. :)
https://github.com/paulopmx/Flexigrid - Flexgrid
http://datatables.net/index - Data tables.
https://github.com/tonytomov/jqGrid
If not, you need to have a link to those table headers that calls a server-side script to invoke the sort.
Sorting HTML table with JavaScript
Just revisiting an old solution, I thought I'd give it a facelift for it's ~5 year anniversary!
- Plain Javascript (ES6)
- Does alpha and numeric sorting - ascending and descending
- Works in Chrome, Firefox, Safari (and IE11, see below)
Quick explanation
- add a
click
event to all header (th
) cells... - for the current
table
, find all rows (except the first)... - sort the rows, based on the value of the clicked column...
- insert the rows back into the table, in the new order.
const getCellValue = (tr, idx) => tr.children[idx].innerText || tr.children[idx].textContent;
const comparer = (idx, asc) => (a, b) => ((v1, v2) =>
v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2)
)(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));
// do the work...
document.querySelectorAll('th').forEach(th => th.addEventListener('click', (() => {
const table = th.closest('table');
Array.from(table.querySelectorAll('tr:nth-child(n+2)'))
.sort(comparer(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
.forEach(tr => table.appendChild(tr) );
})));
table, th, td {
border: 1px solid black;
}
th {
cursor: pointer;
}
<table>
<tr><th>Country</th><th>Date</th><th>Size</th></tr>
<tr><td>France</td><td>2001-01-01</td><td><i>25</i></td></tr>
<tr><td><a href=#>spain</a></td><td><i>2005-05-05</i></td><td></td></tr>
<tr><td><b>Lebanon</b></td><td><a href=#>2002-02-02</a></td><td><b>-17</b></td></tr>
<tr><td><i>Argentina</i></td><td>2005-04-04</td><td><a href=#>100</a></td></tr>
<tr><td>USA</td><td></td><td>-6</td></tr>
</table>
Sorting a HTML table, which has inputs in it's td
For completeness, the solution given via comment was to use a plugin. Loosely cited from DataTables.net:
Example: Live DOM ordering
... Use information available in the DOM to order columns.
Typically DataTables will read information to be ordered during its initialisation phase.
This will not be updated based on user interaction.
So ordering on columns with inputs may not reflect the current value of the inputs.
Getting current values
You must update the data that DataTables will order on, just prior to the order.
This method is much more efficient than actually ordering using the DOM, since only one DOM query is needed for each cell to be ordered.
Docs: Sorting plug-ins – Custom data source sorting
Allows complete control of the data that is to be sorted. Typically this is used to retrieve data live from the DOM just prior to the table being sorted, to perform sorting on data that can be updated by the end-user or by some other script.
Predefined data extractors
<input type=text>
as string<input type=text>
as numeric<input type=select>
as string<input type=checkbox>
as boolean
Sorting a HTML table with Array#sort
You can use Array.from
to get the td
elements in an array that can be sorted. Then add each of them again to the table in that order. This will be understood as a move in the DOM, so you'll end up with sorted table rows:
let table = document.getElementById("table1");
let trs = table.rows;
Array.from(trs)
.sort((a, b) => a.cells[0].textContent - b.cells[0].textContent)
.forEach(tr => table.appendChild(tr));
<table id="table1">
<tr><td>2</td></tr>
<tr><td>4</td></tr>
<tr><td>3</td></tr>
<tr><td>1</td></tr>
</table>
How to sort table in HTML by number
Something like this would do the job (without using any libraries):
const tb=document.getElementById("homes"),
trs=[...tb.children];
document.body.onclick=ev=>{
let col= ev.target.dataset?.col;
if(col){
trs.sort((a,b)=>a.children[col].textContent-b.children[col].textContent);
trs.forEach(tr=>tb.append(tr));
}
}
<button data-col="1">sort by number</button>
<button data-col="2">sort by batting order</button>
<table class='table table-hover table-dark table-bordered sortable'>
<thead>
<tr>
<!-- <th>Picture</th> -->
<th>Name</th>
<th>Number</th>
<th>Batting Order</th>
<th>Action</th>
</tr>
</thead>
<tbody id="homes">
<tr>
<td>Harry</td>
<td>23</td>
<td>10</td>
<td>go</td>
</tr>
<tr>
<td>Sally</td>
<td>56</td>
<td>1</td>
<td>stop</td>
</tr>
<tr>
<td>Tony</td>
<td>11</td>
<td>2</td>
<td>wait</td>
</tr>
</tbody>
</table>
Sorting a table in JavaScript - hiding table rows with no subsequent rows
This is my Vanilla JavaScript take on it.
Before writing the script I changed all name
attributes to data-name
as tr
s cannot have name
attributes "legally".
In a first filter()
loop I make all tr
s invisible and filter out only those tr
s that don't match the given pattern pat
and are not of class "header". In a forEach()
loop applied on this filtered set I then make only those tr
s visible again that either themselves have a dataset.name
attribute or whose direct successor has this attribute.
const trs=[...document.querySelector("#myTable>tbody").children];
function fltTbl(pat){
trs
.filter(tr=>(tr.style.display="none",tr.classList.contains("header")||
tr.dataset?.name.indexOf(pat)>-1))
.forEach((tr,i,a)=>{
if (tr.dataset.name
|| a[i+1]?.dataset.name)
tr.style.display="";
});
}
<button class="btn" onclick="fltTbl('policy-outcomes')">Policy Outcomes</button>
<button class="btn" onclick="fltTbl('latin_america')">Latin America</button>
<button class="btn" onclick="fltTbl('deforestation')">Deforestation</button>
<table class="mytable" id="myTable">
<tr class="header">
<th style="width:60%;">2020</th>
</tr>
<tr data-name="latin_america_zero-deforestation">
<td>"Cattle Ranchers and Deforestation.”
</td>
</tr>
<tr data-name="latin_america_policy-outcomes">
<td>“Impacts on Land Use Conversion.”
</td>
</tr>
<tr data-name="latin_america_supply-chain_policy-outcomes">
<td>“Costs of the Amazon Soy Moratorium.”
</td>
</tr>
<tr class="header">
<th style="width:60%;">2019</th>
</tr>
<tr data-name="africa_policy-outcomes">
<td>“Environmental Change”
</td>
</tr>
<tr data-name="latin_america_policy-outcomes">
<td>“Land Use Change”
</td>
</tr>
<tr class="header">
<th style="width:60%;">2018</th>
</tr>
<tr data-name="north_america_zero-deforestation">
<td>“Deforestation Remedies”
</td>
</tr>
<tr data-name="latin_america_zero-deforestation">
<td>“Land Use Change in Latin American Cerrados”
</td>
</tr>
</table>
Related Topics
Make Grid Items Fill Columns Not Rows
Arrange 2 Items Per Row Using Flexbox
To "User-Scalable=No" or Not to "User-Scalable=No"
Why Are Horizontal Scroll Bars Shown on My Website
How to Center The Twitter Bootstrap Tabs on The Page
How to Make a Transparent Border Using CSS
Multi-Coloured Circular Div Using Background Colours
The Ajax Response: Data (JSON, Xml) or HTML Snippet
How to Style a Horizontal List with Bullets Between Items Using CSS
How to Serve HTML File from Another Directory as Actionresult
Balanced Text Wrapping in HTML
Why Are 3-Digit Hex Color Code Values Interpreted Differently in Internet Explorer
Overlaying a Div on Top of HTML 5 Video
How to Vertically Align Both Image and Text in a Div Using CSS
Break Long Word in Table Cell with Percentage Widths
Emoji Rendered in Chrome Have Different Widths Than in Other Browsers