From a12603e9745af2c5886055e46782798c3fbb68f0 Mon Sep 17 00:00:00 2001 From: n-a-m-e Date: Tue, 28 Feb 2017 11:25:44 +1100 Subject: [PATCH] Create tablesorter.user.js added require for moment.js and added button to sort by date. also changed the ABC, 123 to read Alpha and Num, just my personal preference. --- tablesorter.user.js | 473 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 473 insertions(+) create mode 100644 tablesorter.user.js diff --git a/tablesorter.user.js b/tablesorter.user.js new file mode 100644 index 0000000..b06ae4b --- /dev/null +++ b/tablesorter.user.js @@ -0,0 +1,473 @@ +// +// ==UserScript== +// @name TableSorter +// @namespace http://codebox.org.uk/TableSorter +// @description A script for making tables on web pages sortable +// @include * +// @require https://momentjs.com/downloads/moment.min.js +// @grant metaData + +// ==/UserScript== + +(function() { + function forEach(arr, fnDoThis) { + var len = arr.length; + for (var i = 0; i < len; i++) { + fnDoThis(arr[i], i); + } + } + + function forEachObject(obj, fnDoThis) { + for (var item in obj) { + if (obj.hasOwnProperty(item)) { + fnDoThis(obj[item]); + } + } + } + + function processAllTables() { + forEach(document.getElementsByTagName("TABLE"), function (table) { + processTable(table); + }); + } + + function processTable(tableElement) { + if (!checkTableStructureOk(tableElement)) { + return null; + } + + // State is initialised here + var rowObjects = []; + var currentSortColIndex = null; + var currentSortAscending = null; + var linkTds = []; + var rowWithArrows, rowWithOptions; + var colCount = 0; + var sortTypes = { + 'NONE': { + 'text': 'none', + 'fn': sortRestore + }, + 'ALPHA': { + 'text': 'alpha', + 'fn': sortColByAlpha + }, + 'NUM': { + 'text': 'num', + 'fn': sortColByNum + }, + 'DATE': { + 'text': 'date', + 'fn': sortColByDate + } + }; + var currentSortType = sortTypes.NONE; + + + function sortRestore() { + rowObjects.sort(function (a, b) { + return a.getOriginalIndex() - b.getOriginalIndex(); + }); + redraw(); + } + + function sortColByAlpha(col, ascending) { + if (col < colCount) { + var multiplier = ascending ? 1 : -1; + rowObjects.sort(function (a, b) { + var aItem = a.getCellValue(col); + aItem = aItem ? aItem.toLowerCase() : aItem; + + var bItem = b.getCellValue(col); + bItem = bItem ? bItem.toLowerCase() : bItem; + + if (aItem) { + if (bItem) { + if (aItem > bItem) { + return 1 * multiplier; + } else if (aItem < bItem) { + return -1 * multiplier; + } else { + return 0; + } + } else { + return 1 * multiplier; + } + } else { + if (bItem) { + return -1 * multiplier; + } else { + return 0; + } + } + }); + } + redraw(); + } + + function sortColByNum(col, ascending) { + function makeNumFromText(txt) { + return parseFloat(txt.replace(/,/g, '').replace(/[^0-9\.+\-]+/, ' ')); + } + + if (col < colCount) { + var multiplier = ascending ? 1 : -1; + rowObjects.sort(function (a, b) { + var aNum = makeNumFromText(a.getCellValue(col)); + if (isNaN(aNum)) { + // Make non-numeric values go to the bottom of the list + return Infinity; + } + var bNum = makeNumFromText(b.getCellValue(col)); + if (isNaN(bNum)) { + // Make non-numeric values go to the bottom of the list + return -Infinity; + } + return (aNum - bNum) * multiplier; + }); + } + redraw(); + } + + function sortColByDate(col, ascending) { + function makeNumFromText(txt) { + return parseFloat(txt.replace(/,/g, '').replace(/[^0-9\.+\-]+/, ' ')); + } + function makeDateFromText(txt){ + //return moment(txt, "DD MMM YYYY hh:mm A"); + return parseFloat(moment(txt).valueOf()); + } + + if (col 0) { + return false; + } + + // tables that have less than 2 rows are not processed... + var rows = tableElement.getElementsByTagName("TR"); + if (rows.length < 2) { + return false; + } + + // tables that don't have any text nodes are not processed... + function checkForTextNodeChildren(item) { + var childNodes = item.childNodes; + + if (!childNodes) { + return false; + } + + var childNode; + var TEXT_NODE_TYPE = 3; + var TRIM_REGEX = /^\s+|\s+$/; + for (var i = 0, l = childNodes.length; i < l; i++) { + childNode = childNodes[i]; + if (childNode.nodeType === TEXT_NODE_TYPE) { + var text = childNode.nodeValue; + text = text.replace(TRIM_REGEX, ''); + if (text.length > 0) { + return true; + } + } else { + if (checkForTextNodeChildren(childNode)) { + return true; + } + } + } + return false; + } + + if (!checkForTextNodeChildren(tableElement)) { + return false; + } + + return true; + } + + function buildRowObject(trElement, index) { + if (trElement.parentNode.tagName === 'THEAD') { + // Any rows inside a header are ignored + return null; + } + + var tdElements = trElement.getElementsByTagName("TD"); + if (tdElements.length === 0) { + // Rows without any TDs are ignored, these are usually headers with THs instead + return null; + } + + var obj = {}; + + obj.getTr = function () { + return trElement; + }; + + var parent = trElement.parentNode; + var cellToElementMappingArray = []; + var cellIndex = 0; + + /* Produces a mapping from 'virtual' cells to TD elements + so if the third cell has colspan='3' then virtual cells 2,3 and 4 all map to TD 2 + |A|B| C | + [0,1,2,2,2] */ + forEach(tdElements, function (item, i) { + var colSpan = +(item.colSpan); + if (isNaN(colSpan) || colSpan === 0) { + colSpan = 1; + } + for (var j = 0; j < colSpan; j++) { + cellToElementMappingArray[cellIndex++] = i; + } + }); + + obj.getCellCount = function () { + return cellToElementMappingArray.length; + }; + + obj.getCellValue = function (index) { + if (index >= cellToElementMappingArray.length) { + return null; + } else { + var tdIndex = cellToElementMappingArray[index]; + + var cellContent = tdElements[tdIndex].innerHTML; + // This might contain markup, eg