Jamstash/js/plugins/jquery.stupidtable.js
2012-10-18 20:29:55 -04:00

141 lines
5.6 KiB
JavaScript

// Stupid jQuery table plugin.
// Call on a table
// sortFns: Sort functions for your datatypes.
(function ($) {
$.fn.stupidtable = function (sortFns) {
var table = this; sortFns = sortFns || {};
// ==================================================== //
// Utility functions //
// ==================================================== //
// Merge sort functions with some default sort functions.
sortFns = $.extend({}, {
"int": function (a, b) { return parseInt(a, 10) - parseInt(b, 10); },
"float": function (a, b) { return parseFloat(a) - parseFloat(b); },
"string": function (a, b) { if (a < b) return -1; if (a > b) return +1; return 0; }
}, sortFns);
// Array comparison. See http://stackoverflow.com/a/8618383
var arrays_equal = function (a, b) { return !!a && !!b && !(a < b || b < a); }
// Return the resulting indexes of a sort so we can apply
// this result elsewhere. This returns an array of index numbers.
// return[0] = x means "arr's 0th element is now at x"
var sort_map = function (arr, sort_function) {
var sorted = arr.slice(0).sort(sort_function);
var map = [];
var index = 0;
for (var i = 0; i < arr.length; i++) {
index = $.inArray(arr[i], sorted);
// If this index is already in the map, look for the next index.
// This handles the case of duplicate entries.
while ($.inArray(index, map) != -1) {
index++;
}
map.push(index);
}
return map;
}
// Apply a sort map to the array.
var apply_sort_map = function (arr, map) {
var clone = arr.slice(0);
for (var i = 0; i < map.length; i++) {
newIndex = map[i];
clone[newIndex] = arr[i];
}
return clone;
}
// Returns true if array is sorted, false otherwise.
// Checks for both ascending and descending
var is_sorted_array = function (arr, sort_function) {
var clone = arr.slice(0);
var reversed = arr.slice(0).reverse();
var sorted = arr.slice(0).sort(sort_function);
// Check if the array is sorted in either direction.
return arrays_equal(clone, sorted) || arrays_equal(reversed, sorted);
}
// ==================================================== //
// Begin execution! //
// ==================================================== //
// Do sorting when THs are clicked
table.delegate("th", "click", function () {
var trs = table.find("tbody tr");
var i = $(this).index();
var classes = $(this).attr("class");
var type = null;
var sort = {
asc: 'ascending',
desc: 'descending'
};
var direction = sort.asc;
var total = trs.length;
if (total > 0) {
if (classes) {
classes = classes.split(/\s+/);
for (var j = 0; j < classes.length; j++) {
if (classes[j].search("type-") != -1) {
type = classes[j];
break;
}
}
if (type) {
type = type.split('-')[1];
}
}
if (type) {
table.find('th').removeClass('sorted');
var sortMethod = sortFns[type];
// Gather the elements for this column
column = [];
// Push either the value of the 'data-order-by' attribute if specified
// or just the text() value in this column to column[] for comparison.
trs.each(function (index, tr) {
var e = $(tr).children().eq(i);
var order_by = e.attr('data-order-by') || e.text();
column.push(order_by);
});
// If the column is already sorted, just reverse the order. The sort
// map is just reversing the indexes.
if (is_sorted_array(column, sortMethod)) {
if ($(this).hasClass(sort.desc)) {
direction = sort.asc;
} else {
direction = sort.desc
}
table.find('th').removeClass(sort.asc + ' ' + sort.desc);
column.reverse();
var theMap = [];
for (var i = column.length - 1; i >= 0; i--) {
theMap.push(i);
}
}
else {
direction = sort.asc;
// Get a sort map and apply to all rows
theMap = sort_map(column, sortMethod);
}
var sortedTRs = $(apply_sort_map(trs, theMap));
// Replace the content of tbody with the sortedTRs. Strangely (and
// conveniently!) enough, .append accomplishes this for us.
table.find("tbody").append(sortedTRs);
$(this).addClass('sorted');
$(this).addClass(direction);
}
}
});
}
})(jQuery);