html table sorting with javascript

july 28, 2021

Sorting table rows can't be performed with CSS, only javascript can do that.

demo

To generate new table content, try reloading / refreshing this page with your browser. And if you need to see different number of rows, enter number of rows here first: then click following button: .

alphanumeric numeric

html - structure

<div id="demo">
	<table>
		<thead><tr>
			<th class="sort-able alph">alphanumeric</th>
			<th class="sort-able num">numeric</th>
		</tr></thead>

		<tbody></tbody>
	</table>
</div><!--#demo ends-->

css - layout and style

.sort-able{
	position: relative;
	padding-right: 1em !important;/*give space for sort icon*/
}
.sort-able:after{
	content: '';
	position: absolute;
	bottom: 0;
	right: 0;
	padding: 0.5em;
	background-repeat: no-repeat;
	background-image: url(sort-able.svg);/*sort icon file, an svg sprite containing 2 icons*/
	background-position: 0 0;
}
.sort-able.asc:after{/*ascending sort icon*/
	background-position: 100% 0;
}
.sort-able.desc:after{/*descending sort icon = rotated, ascending icon*/
	background-position: 100% 0;
	transform: rotate(180deg);
}

js - javascript

'use strict';
+function(){
	//column index of th to parent element
	let iColCompare = -1;

	//listen to click on ths
	document.getElementById('demo').addEventListener('click', function(ev){
		const trs = this.getElementsByTagName('tbody')[0].getElementsByTagName('tr'),
			rows = [],
			clicked = ev.target;//clicked element
			
		let isAlph = true,
			isAsc = true;
			
		//define function to populate rows from trs
		function trsToRows(){
			rows.length = 0;//delete rows
			
			for(let i = 0; i < trs.length; i++){
				const tds = trs[i].getElementsByTagName('td'),
					cols = [];
				for(let j = 0; j < tds.length; j++)
					cols.push(tds[j].textContent);
				rows.push(cols);
			}
		}
		
		//define function to populate trs from rows
		function rowsToTrs(){
			for(let i = 0; i < trs.length; i++){
				const tds = trs[i].getElementsByTagName('td');
				for(let j = 0; j < tds.length; j++)
					tds[j].textContent = rows[i][j];
			}
		}
		
		//define sorting function
		function compare(s1, s2){
			if(isAlph){
				const minSLen = Math.min(s1[iColCompare].length, s2[iColCompare].length); //get minimum of 2 string lengths
				let delt = 0;
				for(let i = 0; i < minSLen; i++){
					if(isAsc)
						delt += s1[iColCompare].charCodeAt(i) - s2[iColCompare].charCodeAt(i);
					else
						delt += s2[iColCompare].charCodeAt(i) - s1[iColCompare].charCodeAt(i);
					if(delt !== 0)
						break;
				}
				return delt;
			}
			else{
				if(isAsc)
					return Number(s1[iColCompare]) - Number(s2[iColCompare]);
				else
					return Number(s2[iColCompare]) - Number(s1[iColCompare]);
			}
		}
		
		//if clicked element has sortable class and iColCompare isn't currently used
		if(clicked.className.search(/\bsort-able\b/) !== -1 && iColCompare === -1){			
			//trs -> rows
			trsToRows();

			//define iColCompare 1st
			let el = clicked;
			for(iColCompare = 0; (el = el.previousElementSibling); iColCompare++);
			
			//walk through ths
			const ths = clicked.parentNode.getElementsByClassName('sort-able');
			for(let i = 0; i < ths.length; i++)
				if(ths[i] !== clicked)//if a th isn't the clicked element, remove asc / desc classes
					ths[i].className = ths[i].className.replace(/\bdesc\b|\basc\b/g, '');
				else{//if a th is the clicked element perform sorting on rows
					if(ths[i].className.search(/\basc\b/) !== -1){
						ths[i].className = ths[i].className.replace(/\basc\b/g, 'desc');
						
						isAlph = (ths[i].className.search(/\balph\b/) !== -1);//define alphabetic or numerical sorting
						isAsc = false;//define descending sort
						rows.sort(compare);
					}
					else{
						if(ths[i].className.search(/\bdesc\b/) !== -1)
							ths[i].className = ths[i].className.replace(/\bdesc\b/g, 'asc');
						else
							ths[i].className = ths[i].className.trim() + ' asc';
						
						isAlph = (ths[i].className.search(/\balph\b/) !== -1);//define alphabetic or numerical sorting
						isAsc = true;//define ascending sort
						rows.sort(compare);
					}
					iColCompare = -1;//sorting done: reset iColCompare
					rowsToTrs();//rows -> trs
				}
		}
	});
}();

Comments