Add javascript table sorting

This commit is contained in:
Timothy Warren 2017-11-10 09:03:20 -05:00
parent a6a0872195
commit 2b7594f52d
4 changed files with 276 additions and 1 deletions

View File

@ -42,6 +42,8 @@
<script src="/js/vendor/jquery.js"></script> <script src="/js/vendor/jquery.js"></script>
<script src="/js/vendor/what-input.js"></script> <script src="/js/vendor/what-input.js"></script>
<script src="/js/vendor/foundation.min.js"></script> <script src="/js/vendor/foundation.min.js"></script>
<script src="/js/table-sort.js"></script>
<script src="/js/app.js"></script>
{% block javascripts %}{% endblock %} {% block javascripts %}{% endblock %}
</body> </body>
</html> </html>

View File

@ -1,3 +1,21 @@
/* -----------------------------------------------------------------------------
Table sorting
------------------------------------------------------------------------------*/
table th,
.ascend,
.descend {
vertical-align:text-bottom;
}
table thead th::before {
content: " ↕\00a0";
}
table thead .ascend::before {
content: " ↑\00a0";
}
table thead .descend::before {
content: " ↓\00a0";
}
.page-pad { .page-pad {
margin: 1rem 2rem; margin: 1rem 2rem;
} }

View File

@ -1 +1,9 @@
$(document).foundation() $(document).foundation();
(function() {
var tables = document.getElementsByTagName('table');
if (tables.length > 0) {
tsorter.create(tables[0], 1);
}
}());

247
web/js/table-sort.js Normal file
View File

@ -0,0 +1,247 @@
/*!
* tsorter 2.0.0 - Copyright 2015 Terrill Dent, http://terrill.ca
* JavaScript HTML Table Sorter
* Released under MIT license, http://terrill.ca/sorting/tsorter/LICENSE
*/
var tsorter = (function()
{
'use strict';
var sorterPrototype,
addEvent,
removeEvent,
hasEventListener = !!document.addEventListener;
if( !Object.create ){
// Define Missing Function
Object.create = function( prototype ) {
var Obj = function(){return undefined;};
Obj.prototype = prototype;
return new Obj();
};
}
sorterPrototype = {
getCell: function(row)
{
var that = this;
return that.trs[row].cells[that.column];
},
/* SORT
* Sorts a particular column. If it has been sorted then call reverse
* if not, then use quicksort to get it sorted.
* Sets the arrow direction in the headers.
* @param oTH - the table header cell (<th>) object that is clicked
*/
sort: function( e )
{
var that = this,
th = e.target;
// TODO: make sure target 'th' is not a child element of a <th>
// We can't use currentTarget because of backwards browser support
// IE6,7,8 don't have it.
// set the data retrieval function for this column
that.column = th.cellIndex;
that.get = that.getAccessor( th.getAttribute('data-tsorter') );
if( that.prevCol === that.column )
{
// if already sorted, reverse
th.className = th.className !== 'descend' ? 'descend' : 'ascend';
that.reverseTable();
}
else
{
// not sorted - call quicksort
th.className = 'descend';
if( that.prevCol !== -1 && that.ths[that.prevCol].className !== 'exc_cell'){
that.ths[that.prevCol].className = '';
}
that.quicksort(0, that.trs.length);
}
that.prevCol = that.column;
},
/*
* Choose Data Accessor Function
* @param: the html structure type (from the data-type attribute)
*/
getAccessor: function(sortType)
{
var that = this,
accessors = that.accessors;
if( accessors && accessors[ sortType ] ){
return accessors[ sortType ];
}
switch( sortType )
{
case "link":
return function(row){
return that.getCell(row).firstChild.firstChild.nodeValue;
};
case "input":
return function(row){
return that.getCell(row).firstChild.value;
};
case "numeric":
return function(row){
return parseFloat( that.getCell(row).firstChild.nodeValue.replace(/\D/g,''), 10 );
};
case "number-range":
return function(row){
return parseFloat(
String(this.getCell(row).childNodes[0].nodeValue)
.split('')[0]
.trim()
.replace('ƒ', '')
);
};
case "in-a-link":
return function(row){
return String(
this.getCell(row).getElementsByTagName('a')[0].childNodes[0].nodeValue
).toLowerCase();
};
default: /* Plain Text */
return function(row){
return that.getCell(row).firstChild.nodeValue.toLowerCase();
};
}
},
/*
* Exchange
* A complicated way of exchanging two rows in a table.
* Exchanges rows at index i and j
*/
exchange: function(i, j)
{
var that = this,
tbody = that.tbody,
trs = that.trs,
tmpNode;
if( i === j+1 ) {
tbody.insertBefore(trs[i], trs[j]);
} else if( j === i+1 ) {
tbody.insertBefore(trs[j], trs[i]);
} else {
tmpNode = tbody.replaceChild(trs[i], trs[j]);
if( !trs[i] ) {
tbody.appendChild(tmpNode);
} else {
tbody.insertBefore(tmpNode, trs[i]);
}
}
},
/*
* REVERSE TABLE
* Reverses a table ordering
*/
reverseTable: function()
{
var that = this,
i;
for( i = 1; i < that.trs.length; i++ ) {
that.tbody.insertBefore( that.trs[i], that.trs[0] );
}
},
/*
* QUICKSORT
* @param: lo - the low index of the array to sort
* @param: hi - the high index of the array to sort
*/
quicksort: function(lo, hi)
{
var i, j, pivot,
that = this;
if( hi <= lo+1 ){ return; }
if( (hi - lo) === 2 ) {
if(that.get(hi-1) > that.get(lo)) {
that.exchange(hi-1, lo);
}
return;
}
i = lo + 1;
j = hi - 1;
if( that.get(lo) > that.get( i) ){ that.exchange( i, lo); }
if( that.get( j) > that.get(lo) ){ that.exchange(lo, j); }
if( that.get(lo) > that.get( i) ){ that.exchange( i, lo); }
pivot = that.get(lo);
while(true) {
j--;
while(pivot > that.get(j)){ j--; }
i++;
while(that.get(i) > pivot){ i++; }
if(j <= i){ break; }
that.exchange(i, j);
}
that.exchange(lo, j);
if((j-lo) < (hi-j)) {
that.quicksort(lo, j);
that.quicksort(j+1, hi);
} else {
that.quicksort(j+1, hi);
that.quicksort(lo, j);
}
},
init: function( table, initialSortedColumn, customDataAccessors ){
var that = this,
i;
if( typeof table === 'string' ){
table = document.getElementById(table);
}
that.table = table;
that.ths = table.getElementsByTagName("th");
that.tbody = table.tBodies[0];
that.trs = that.tbody.getElementsByTagName("tr");
that.prevCol = ( initialSortedColumn && initialSortedColumn > 0 ) ? initialSortedColumn : -1;
that.accessors = customDataAccessors;
that.boundSort = that.sort.bind( that );
for( i = 0; i < that.ths.length; i++ ) {
that.ths[i].addEventListener('click', that.boundSort, false);
}
},
destroy: function(){
var that = this,
i;
if( that.ths ){
for( i = 0; i < that.ths.length; i++ ) {
that.ths[i].removeEventListener('click', that.boundSort, false);
}
}
}
};
// Create a new sorter given a table element
return {
create: function( table, initialSortedColumn, customDataAccessors )
{
var sorter = Object.create( sorterPrototype );
sorter.init( table, initialSortedColumn, customDataAccessors );
return sorter;
}
};
}());