collection-crud/public/js/table-sort.js

248 lines
7.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*!
* 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;
}
};
}());