From db2c2d499878be92273e770b77b3dd29e8c82ebc Mon Sep 17 00:00:00 2001 From: LeeWannacott Date: Sat, 20 May 2023 18:32:30 +1200 Subject: [PATCH] NPM version 1.16.0; numeric-sort class; plus bug fixes. --- README.md | 10 +- browser-extensions/chrome/table-sort-js.zip | Bin 7364 -> 7626 bytes browser-extensions/chrome/table-sort.js | 190 +++++++++++-------- browser-extensions/firefox/table-sort-js.zip | Bin 7364 -> 7626 bytes browser-extensions/firefox/table-sort.js | 190 +++++++++++-------- npm/README.md | 55 ++++-- npm/table-sort.js | 190 +++++++++++-------- public/table-sort.js | 2 +- test/table.test.js | 32 +++- 9 files changed, 418 insertions(+), 251 deletions(-) diff --git a/README.md b/README.md index 30f772b..6e0d26f 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,8 @@ ## Install instructions. -- Option 1: Install from npm: +- Option 1: Install from npm: + ```javascript npm install table-sort-js ``` @@ -25,16 +26,21 @@ npm install table-sort-js ```javascript import tableSort from "table-sort-js/table-sort.js"; ``` + Examples on using table-sort-js with frontend frameworks such as [React.js](https://leewannacott.github.io/table-sort-js/docs/react.html) and [Vue.js](https://leewannacott.github.io/table-sort-js/docs/vue.html) - Option 2: Load as script from a Content Delivery Network (CDN): + ```javascript ``` + Or Minified (smaller size, but harder to debug!): + ```javascript ``` + Refer to the documenation for examples on how to use table-sort-js with [HTML](https://leewannacott.github.io/table-sort-js/docs/html5.html) - Option 3: Download [table-sort.js](https://cdn.jsdelivr.net/npm/table-sort-js@latest/table-sort.js) (Select save as.), or download a [minified version](https://cdn.jsdelivr.net/npm/table-sort-js@latest/table-sort.min.js) (~5kB) @@ -72,7 +78,7 @@ Then rename and add the following script before your HTML table: | <th> Inferred Classes. | Description | | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | -| "numeric-sort" | Sorts numbers including decimals - Positive, Negative (in both minus and parenthesis representations) | +| "numeric-sort" | Sorts numbers including decimals - Positive, Negative (in both minus and parenthesis representations) | | "dates-dmy-sort" | Sorts dates in dd/mm/yyyy format. e.g (18/10/1995). Can use "/" or "-" as separator. | | "dates-ymd-sort" | Sorts dates in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) yyyy/mm/dd format. e.g (2021/10/28). Use "/" or "-" as separator. | | "file-size-sort" | Sorts file sizes(B->TiB) uses the binary prefix. (e.g 10 B, 100 KiB, 1 MiB); optional space between number and prefix. | diff --git a/browser-extensions/chrome/table-sort-js.zip b/browser-extensions/chrome/table-sort-js.zip index adf59672bcd780de450e78547ed0382d2d5c101d..ed4be8a96b9f67af750e445b881dbc790871aa93 100644 GIT binary patch delta 5144 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 ikq7usqf-BsB>ziX0vI`f|HLJ=l#v;SoZ+8 1) { @@ -260,14 +276,15 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { const secondLastColumnClicked = columnIndexesClicked[columnIndexesClicked.length - 2]; if (lastColumnClicked !== secondLastColumnClicked) { - timesClickedColumn = 0; columnIndexesClicked.shift(); + timesClickedColumn = 0; } } + return timesClickedColumn; } - function getColSpanData(sortableTable, column) { - sortableTable.querySelectorAll("th").forEach((th, index) => { + function getColSpanData(headers, column) { + headers.forEach((th, index) => { column.span[index] = th.colSpan; if (index === 0) column.spanSum[index] = th.colSpan; else column.spanSum[index] = column.spanSum[index - 1] + th.colSpan; @@ -285,16 +302,7 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { } function getTableData(tableProperties) { - const { - tableRows, - column, - isFileSize, - isTimeSort, - isSortDateDayMonthYear, - isSortDateMonthDayYear, - isSortDateYearMonthDay, - isDataAttribute, - } = tableProperties; + const { tableRows, column, hasThClass, isSortDates } = tableProperties; for (let [i, tr] of tableRows.entries()) { let tdTextContent = getColumn( tr, @@ -305,17 +313,17 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { tdTextContent = ""; } if (tdTextContent.trim() !== "") { - if (isFileSize) { + if (hasThClass.fileSize) { fileSizeColumnTextAndRow[column.toBeSorted[i]] = tr.outerHTML; } // These classes already handle pushing to column and setting the tr html. if ( - !isFileSize && - !isDataAttribute && - !isTimeSort && - !isSortDateDayMonthYear && - !isSortDateYearMonthDay && - !isSortDateMonthDayYear + !hasThClass.fileSize && + !hasThClass.dataSort && + !hasThClass.runtime && + !isSortDates.dayMonthYear && + !isSortDates.yearMonthDay && + !isSortDates.monthDayYear ) { column.toBeSorted.push(`${tdTextContent}#${i}`); columnIndexAndTableRow[`${tdTextContent}#${i}`] = tr.outerHTML; @@ -329,17 +337,48 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { const isPunctSort = th.classList.contains("punct-sort"); const isAlphaSort = th.classList.contains("alpha-sort"); + const isNumericSort = th.classList.contains("numeric-sort"); + + function parseNumberFromString(str) { + let num; + str = str.slice(0, str.indexOf("#")); + if (str.match(/^\((\d+(?:\.\d+)?)\)$/)) { + num = -1 * Number(str.slice(1, -1)); + } else { + num = Number(str); + } + return num; + } + + function strLocaleCompare(str1, str2) { + return str1.localeCompare( + str2, + navigator.languages[0] || navigator.language, + { numeric: !isAlphaSort, ignorePunctuation: !isPunctSort } + ); + } + + function handleNumbers(str1, str2) { + let num1, num2; + num1 = parseNumberFromString(str1); + num2 = parseNumberFromString(str2); + + if (!isNaN(num1) && !isNaN(num2)) { + return num1 - num2; + } else { + return strLocaleCompare(str1, str2); + } + } + function sortAscending(a, b) { if (a.includes(`${fillValue}#`)) { return 1; } else if (b.includes(`${fillValue}#`)) { return -1; + } else if (isNumericSort) { + return handleNumbers(a, b); } else { - return a.localeCompare( - b, - navigator.languages[0] || navigator.language, - { numeric: !isAlphaSort, ignorePunctuation: !isPunctSort } - ); + return strLocaleCompare(a, b); } } @@ -391,9 +430,9 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { } function updateTable(tableProperties) { - const { tableRows, column, isFileSize } = tableProperties; + const { tableRows, column, hasThClass } = tableProperties; for (let [i, tr] of tableRows.entries()) { - if (isFileSize) { + if (hasThClass.fileSize) { tr.innerHTML = fileSizeColumnTextAndRow[column.toBeSorted[i]]; let fileSizeInBytesHTML = tr .querySelectorAll("td") @@ -426,71 +465,70 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { } tr.querySelectorAll("td").item(columnIndex).innerHTML = fileSizeInBytesHTML; - } else if (!isFileSize) { + } else if (!hasThClass.fileSize) { tr.outerHTML = columnIndexAndTableRow[column.toBeSorted[i]]; } } } + let timesClickedColumn = 0; th.addEventListener("click", function () { - timesClickedColumn += 1; const column = { - // column used for sorting; better name? toBeSorted: [], span: {}, spanSum: {}, }; - const visibleTableRows = Array.prototype.filter.call( - tableBody.querySelectorAll("tr"), + table.visibleRows = Array.prototype.filter.call( + table.body.querySelectorAll("tr"), (tr) => { return tr.style.display !== "none"; } ); - getColSpanData(sortableTable, column); + getColSpanData(table.headers, column); - const isDataAttribute = th.classList.contains("data-sort"); - if (isDataAttribute) { - sortDataAttributes(visibleTableRows, column); + const isRememberSort = sortableTable.classList.contains("remember-sort"); + if (!isRememberSort) { + timesClickedColumn = rememberSort(); } + timesClickedColumn += 1; - const isFileSize = th.classList.contains("file-size-sort"); - if (isFileSize) { - sortFileSize(visibleTableRows, column); - } + const hasThClass = { + dataSort: th.classList.contains("data-sort"), + fileSize: th.classList.contains("file-size-sort"), + runtime: th.classList.contains("runtime-sort"), + }; - const isTimeSort = th.classList.contains("runtime-sort"); - if (isTimeSort) { - sortByRuntime(visibleTableRows, column); + if (hasThClass.dataSort) { + sortDataAttributes(table.visibleRows, column); } - - const isSortDateDayMonthYear = th.classList.contains("dates-dmy-sort"); - const isSortDateMonthDayYear = th.classList.contains("dates-mdy-sort"); - const isSortDateYearMonthDay = th.classList.contains("dates-ymd-sort"); - // pick mdy first to override the inferred default class which is dmy. - if (isSortDateMonthDayYear) { - sortDates("mdy", visibleTableRows, column); - } else if (isSortDateYearMonthDay) { - sortDates("ymd", visibleTableRows, column); - } else if (isSortDateDayMonthYear) { - sortDates("dmy", visibleTableRows, column); + if (hasThClass.fileSize) { + sortFileSize(table.visibleRows, column); + } + if (hasThClass.runtime) { + sortByRuntime(table.visibleRows, column); } - const isRememberSort = sortableTable.classList.contains("remember-sort"); - if (!isRememberSort) { - rememberSort(timesClickedColumn, columnIndexesClicked); + const isSortDates = { + dayMonthYear: th.classList.contains("dates-dmy-sort"), + monthDayYear: th.classList.contains("dates-mdy-sort"), + yearMonthDay: th.classList.contains("dates-ymd-sort"), + }; + // pick mdy first to override the inferred default class which is dmy. + if (isSortDates.monthDayYear) { + sortDates("mdy", table.visibleRows, column); + } else if (isSortDates.yearMonthDay) { + sortDates("ymd", table.visibleRows, column); + } else if (isSortDates.dayMonthYear) { + sortDates("dmy", table.visibleRows, column); } const tableProperties = { - tableRows: visibleTableRows, + tableRows: table.visibleRows, column, - isFileSize, - isSortDateDayMonthYear, - isSortDateMonthDayYear, - isSortDateYearMonthDay, - isDataAttribute, - isTimeSort, + hasThClass, + isSortDates, }; getTableData(tableProperties); updateTable(tableProperties); diff --git a/browser-extensions/firefox/table-sort-js.zip b/browser-extensions/firefox/table-sort-js.zip index 971b05135b1c0b7cc2d5b0560e501f3c3f4b7168..fc637c64e2a765fecffa7395cb7dda730fab1c9a 100644 GIT binary patch delta 5144 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 diff --git a/browser-extensions/firefox/table-sort.js b/browser-extensions/firefox/table-sort.js index 385b443..4b19ea0 100644 --- a/browser-extensions/firefox/table-sort.js +++ b/browser-extensions/firefox/table-sort.js @@ -65,11 +65,13 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { // Doesn't infer dates with delimiter "."; as could capture semantic version numbers. const dmyRegex = /^(\d\d?)[/-](\d\d?)[/-]((\d\d)?\d\d)/; const ymdRegex = /^(\d\d\d\d)[/-](\d\d?)[/-](\d\d?)/; + const numericRegex = /^(?:\(\d+(?:\.\d+)?\)|-?\d+(?:\.\d+)?)$/; const inferableClasses = { runtime: { regexp: runtimeRegex, class: "runtime-sort", count: 0 }, filesize: { regexp: fileSizeRegex, class: "file-size-sort", count: 0 }, dmyDates: { regexp: dmyRegex, class: "dates-dmy-sort", count: 0 }, ymdDates: { regexp: ymdRegex, class: "dates-ymd-sort", count: 0 }, + numericRegex: { regexp: numericRegex, class: "numeric-sort", count: 0 }, }; let classNameAdded = false; let regexNotFoundCount = 0; @@ -105,28 +107,44 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { } function makeTableSortable(sortableTable) { - const tableBody = getTableBody(sortableTable); - const tableHead = sortableTable.querySelector("thead"); - const tableHeadHeaders = tableHead.querySelectorAll("th"); - const tableRows = tableBody.querySelectorAll("tr"); + const table = { + body: getTableBody(sortableTable), + head: sortableTable.querySelector("thead"), + }; + table.headers = table.head.querySelectorAll("th"); + table.rows = table.body.querySelectorAll("tr"); + + let columnIndexesClicked = []; const isNoSortClassInference = sortableTable.classList.contains("no-class-infer"); - for (let [columnIndex, th] of tableHeadHeaders.entries()) { + for (let [columnIndex, th] of table.headers.entries()) { if (!th.classList.contains("disable-sort")) { th.style.cursor = "pointer"; if (!isNoSortClassInference) { - inferSortClasses(tableRows, columnIndex, th); + inferSortClasses(table.rows, columnIndex, th); } - makeEachColumnSortable(th, columnIndex, tableBody, sortableTable); + makeEachColumnSortable( + th, + columnIndex, + table, + sortableTable, + columnIndexesClicked + ); } } } - function makeEachColumnSortable(th, columnIndex, tableBody, sortableTable) { + function makeEachColumnSortable( + th, + columnIndex, + table, + sortableTable, + columnIndexesClicked + ) { const desc = th.classList.contains("order-by-desc"); - let tableArrows = sortableTable.classList.contains("table-arrows"); + const tableArrows = sortableTable.classList.contains("table-arrows"); const [arrowUp, arrowDown] = [" ▲", " ▼"]; const fillValue = "!X!Y!Z!"; @@ -249,9 +267,7 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { } } - let [timesClickedColumn, columnIndexesClicked] = [0, []]; - - function rememberSort(timesClickedColumn, columnIndexesClicked) { + function rememberSort() { // if user clicked different column from first column reset times clicked. columnIndexesClicked.push(columnIndex); if (timesClickedColumn === 1 && columnIndexesClicked.length > 1) { @@ -260,14 +276,15 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { const secondLastColumnClicked = columnIndexesClicked[columnIndexesClicked.length - 2]; if (lastColumnClicked !== secondLastColumnClicked) { - timesClickedColumn = 0; columnIndexesClicked.shift(); + timesClickedColumn = 0; } } + return timesClickedColumn; } - function getColSpanData(sortableTable, column) { - sortableTable.querySelectorAll("th").forEach((th, index) => { + function getColSpanData(headers, column) { + headers.forEach((th, index) => { column.span[index] = th.colSpan; if (index === 0) column.spanSum[index] = th.colSpan; else column.spanSum[index] = column.spanSum[index - 1] + th.colSpan; @@ -285,16 +302,7 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { } function getTableData(tableProperties) { - const { - tableRows, - column, - isFileSize, - isTimeSort, - isSortDateDayMonthYear, - isSortDateMonthDayYear, - isSortDateYearMonthDay, - isDataAttribute, - } = tableProperties; + const { tableRows, column, hasThClass, isSortDates } = tableProperties; for (let [i, tr] of tableRows.entries()) { let tdTextContent = getColumn( tr, @@ -305,17 +313,17 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { tdTextContent = ""; } if (tdTextContent.trim() !== "") { - if (isFileSize) { + if (hasThClass.fileSize) { fileSizeColumnTextAndRow[column.toBeSorted[i]] = tr.outerHTML; } // These classes already handle pushing to column and setting the tr html. if ( - !isFileSize && - !isDataAttribute && - !isTimeSort && - !isSortDateDayMonthYear && - !isSortDateYearMonthDay && - !isSortDateMonthDayYear + !hasThClass.fileSize && + !hasThClass.dataSort && + !hasThClass.runtime && + !isSortDates.dayMonthYear && + !isSortDates.yearMonthDay && + !isSortDates.monthDayYear ) { column.toBeSorted.push(`${tdTextContent}#${i}`); columnIndexAndTableRow[`${tdTextContent}#${i}`] = tr.outerHTML; @@ -329,17 +337,48 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { const isPunctSort = th.classList.contains("punct-sort"); const isAlphaSort = th.classList.contains("alpha-sort"); + const isNumericSort = th.classList.contains("numeric-sort"); + + function parseNumberFromString(str) { + let num; + str = str.slice(0, str.indexOf("#")); + if (str.match(/^\((\d+(?:\.\d+)?)\)$/)) { + num = -1 * Number(str.slice(1, -1)); + } else { + num = Number(str); + } + return num; + } + + function strLocaleCompare(str1, str2) { + return str1.localeCompare( + str2, + navigator.languages[0] || navigator.language, + { numeric: !isAlphaSort, ignorePunctuation: !isPunctSort } + ); + } + + function handleNumbers(str1, str2) { + let num1, num2; + num1 = parseNumberFromString(str1); + num2 = parseNumberFromString(str2); + + if (!isNaN(num1) && !isNaN(num2)) { + return num1 - num2; + } else { + return strLocaleCompare(str1, str2); + } + } + function sortAscending(a, b) { if (a.includes(`${fillValue}#`)) { return 1; } else if (b.includes(`${fillValue}#`)) { return -1; + } else if (isNumericSort) { + return handleNumbers(a, b); } else { - return a.localeCompare( - b, - navigator.languages[0] || navigator.language, - { numeric: !isAlphaSort, ignorePunctuation: !isPunctSort } - ); + return strLocaleCompare(a, b); } } @@ -391,9 +430,9 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { } function updateTable(tableProperties) { - const { tableRows, column, isFileSize } = tableProperties; + const { tableRows, column, hasThClass } = tableProperties; for (let [i, tr] of tableRows.entries()) { - if (isFileSize) { + if (hasThClass.fileSize) { tr.innerHTML = fileSizeColumnTextAndRow[column.toBeSorted[i]]; let fileSizeInBytesHTML = tr .querySelectorAll("td") @@ -426,71 +465,70 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { } tr.querySelectorAll("td").item(columnIndex).innerHTML = fileSizeInBytesHTML; - } else if (!isFileSize) { + } else if (!hasThClass.fileSize) { tr.outerHTML = columnIndexAndTableRow[column.toBeSorted[i]]; } } } + let timesClickedColumn = 0; th.addEventListener("click", function () { - timesClickedColumn += 1; const column = { - // column used for sorting; better name? toBeSorted: [], span: {}, spanSum: {}, }; - const visibleTableRows = Array.prototype.filter.call( - tableBody.querySelectorAll("tr"), + table.visibleRows = Array.prototype.filter.call( + table.body.querySelectorAll("tr"), (tr) => { return tr.style.display !== "none"; } ); - getColSpanData(sortableTable, column); + getColSpanData(table.headers, column); - const isDataAttribute = th.classList.contains("data-sort"); - if (isDataAttribute) { - sortDataAttributes(visibleTableRows, column); + const isRememberSort = sortableTable.classList.contains("remember-sort"); + if (!isRememberSort) { + timesClickedColumn = rememberSort(); } + timesClickedColumn += 1; - const isFileSize = th.classList.contains("file-size-sort"); - if (isFileSize) { - sortFileSize(visibleTableRows, column); - } + const hasThClass = { + dataSort: th.classList.contains("data-sort"), + fileSize: th.classList.contains("file-size-sort"), + runtime: th.classList.contains("runtime-sort"), + }; - const isTimeSort = th.classList.contains("runtime-sort"); - if (isTimeSort) { - sortByRuntime(visibleTableRows, column); + if (hasThClass.dataSort) { + sortDataAttributes(table.visibleRows, column); } - - const isSortDateDayMonthYear = th.classList.contains("dates-dmy-sort"); - const isSortDateMonthDayYear = th.classList.contains("dates-mdy-sort"); - const isSortDateYearMonthDay = th.classList.contains("dates-ymd-sort"); - // pick mdy first to override the inferred default class which is dmy. - if (isSortDateMonthDayYear) { - sortDates("mdy", visibleTableRows, column); - } else if (isSortDateYearMonthDay) { - sortDates("ymd", visibleTableRows, column); - } else if (isSortDateDayMonthYear) { - sortDates("dmy", visibleTableRows, column); + if (hasThClass.fileSize) { + sortFileSize(table.visibleRows, column); + } + if (hasThClass.runtime) { + sortByRuntime(table.visibleRows, column); } - const isRememberSort = sortableTable.classList.contains("remember-sort"); - if (!isRememberSort) { - rememberSort(timesClickedColumn, columnIndexesClicked); + const isSortDates = { + dayMonthYear: th.classList.contains("dates-dmy-sort"), + monthDayYear: th.classList.contains("dates-mdy-sort"), + yearMonthDay: th.classList.contains("dates-ymd-sort"), + }; + // pick mdy first to override the inferred default class which is dmy. + if (isSortDates.monthDayYear) { + sortDates("mdy", table.visibleRows, column); + } else if (isSortDates.yearMonthDay) { + sortDates("ymd", table.visibleRows, column); + } else if (isSortDates.dayMonthYear) { + sortDates("dmy", table.visibleRows, column); } const tableProperties = { - tableRows: visibleTableRows, + tableRows: table.visibleRows, column, - isFileSize, - isSortDateDayMonthYear, - isSortDateMonthDayYear, - isSortDateYearMonthDay, - isDataAttribute, - isTimeSort, + hasThClass, + isSortDates, }; getTableData(tableProperties); updateTable(tableProperties); diff --git a/npm/README.md b/npm/README.md index 445219c..6e0d26f 100644 --- a/npm/README.md +++ b/npm/README.md @@ -1,41 +1,57 @@ -![table-sort-js](https://img.shields.io/npm/v/table-sort-js) -![table-sort-js](https://img.shields.io/npm/dm/table-sort-js) -![table-sort-js](https://img.shields.io/github/repo-size/leewannacott/table-sort-js) -![table-sort-js](https://img.shields.io/github/license/LeeWannacott/table-sort-js) -![table-sort-js](https://img.shields.io/github/actions/workflow/status/leewannacott/table-sort-js/jest.yml?branch=master) +![npm version](https://img.shields.io/npm/v/table-sort-js) +![npm downloads](https://img.shields.io/npm/dm/table-sort-js) +[![jsDeliver downloads](https://data.jsdelivr.com/v1/package/npm/table-sort-js/badge)](https://www.jsdelivr.com/package/npm/table-sort-js) +![repo size](https://img.shields.io/github/repo-size/leewannacott/table-sort-js) +![MIT licence](https://img.shields.io/github/license/LeeWannacott/table-sort-js) +![build status](https://img.shields.io/github/actions/workflow/status/leewannacott/table-sort-js/jest.yml?branch=master) -## TABLE-SORT-JS. +# TABLE-SORT-JS. - Description: HTML table sorting library with sort type inference builtin and browser extension available. [#VanillaJS](http://vanilla-js.com/) - [Demo](https://leewannacott.github.io/Portfolio/#/GitHub) - [Documentation.](https://leewannacott.github.io/table-sort-js/docs/about.html) (work in progress) -- [npm package.](https://www.npmjs.com/package/table-sort-js) +- [npm package.](https://www.npmjs.com/package/table-sort-js) and [jsDelivr](https://www.jsdelivr.com/package/npm/table-sort-js) - [Firefox](https://addons.mozilla.org/en-US/firefox/addon/table-sort-js/) and [Chrome](https://chrome.google.com/webstore/detail/table-sort-js/dioemkojkjhlhmfiocgniipejgkbfibb) browser extensions: Tables of any website you visit become sortable! ## Install instructions. -Option 1. Install from npm: ` npm install table-sort-js` +- Option 1: Install from npm: + +```javascript +npm install table-sort-js +``` ```javascript import tableSort from "table-sort-js/table-sort.js"; ``` -Refer to the documentation for examples on using table-sort-js with frontend frameworks such as -[React.js](https://leewannacott.github.io/table-sort-js/docs/react.html) and [Vue.js](https://leewannacott.github.io/table-sort-js/docs/vue.html) +Examples on using table-sort-js with frontend frameworks such as [React.js](https://leewannacott.github.io/table-sort-js/docs/react.html) and [Vue.js](https://leewannacott.github.io/table-sort-js/docs/vue.html) -Option 2. Download [table-sort.js](https://leewannacott.github.io/table-sort-js/table-sort.js) (Select save as.), or download a [minified version](https://cdn.jsdelivr.net/npm/table-sort-js) (~5kB) +- Option 2: Load as script from a Content Delivery Network (CDN): -Then add the following script before your HTML table: +```javascript + +``` -```html - +Or Minified (smaller size, but harder to debug!): + +```javascript + ``` Refer to the documenation for examples on how to use table-sort-js with [HTML](https://leewannacott.github.io/table-sort-js/docs/html5.html) -#### To make tables sortable: +- Option 3: Download [table-sort.js](https://cdn.jsdelivr.net/npm/table-sort-js@latest/table-sort.js) (Select save as.), or download a [minified version](https://cdn.jsdelivr.net/npm/table-sort-js@latest/table-sort.min.js) (~5kB) + +Then rename and add the following script before your HTML table: + +```html + +``` + +## To make tables sortable: - Add `class="table-sort"` to HTML <table> tags. - Click on table headers to sort columns. @@ -49,6 +65,8 @@ Refer to the documenation for examples on how to use table-sort-js with [HTML](h | "table-arrows" | Display ascending or descending triangles. | | "remember-sort" | If clicking on different columns remembers sort of the original column. | +
+ | <th> classes | Description | | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | | "data-sort" | Sort by [data attributes](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes), e.g <td data-sort="42"> | @@ -56,19 +74,24 @@ Refer to the documenation for examples on how to use table-sort-js with [HTML](h | "onload-sort" | Sort column on loading of the page. Simulates a click from the user. (can only sort onload for one column) | | "disable-sort" | Disallow sorting the table by this specific column. | +
+ | <th> Inferred Classes. | Description | | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| "numeric-sort" | Sorts numbers including decimals - Positive, Negative (in both minus and parenthesis representations) | | "dates-dmy-sort" | Sorts dates in dd/mm/yyyy format. e.g (18/10/1995). Can use "/" or "-" as separator. | | "dates-ymd-sort" | Sorts dates in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) yyyy/mm/dd format. e.g (2021/10/28). Use "/" or "-" as separator. | | "file-size-sort" | Sorts file sizes(B->TiB) uses the binary prefix. (e.g 10 B, 100 KiB, 1 MiB); optional space between number and prefix. | | "runtime-sort" | Sorts runtime in hours minutes and seconds e.g (10h 1m 20s). Useful for sorting the GitHub actions Run time column... | +
+ | <th> Classes that change defaults. | Description | | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | | "order-by-desc" | Order by descending on first click. (default is aescending) | | "alpha-sort" | Sort alphabetically (z11,z2); default is [natural sort](https://en.wikipedia.org/wiki/Natural_sort_order) (z2,z11). | | "punct-sort" | Sort punctuation; default ignores punctuation. | -#### Development: +## Development: If you wish to contribute, install instructions can be found [here.](https://leewannacott.github.io/table-sort-js/docs/development.html) diff --git a/npm/table-sort.js b/npm/table-sort.js index 385b443..4b19ea0 100644 --- a/npm/table-sort.js +++ b/npm/table-sort.js @@ -65,11 +65,13 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { // Doesn't infer dates with delimiter "."; as could capture semantic version numbers. const dmyRegex = /^(\d\d?)[/-](\d\d?)[/-]((\d\d)?\d\d)/; const ymdRegex = /^(\d\d\d\d)[/-](\d\d?)[/-](\d\d?)/; + const numericRegex = /^(?:\(\d+(?:\.\d+)?\)|-?\d+(?:\.\d+)?)$/; const inferableClasses = { runtime: { regexp: runtimeRegex, class: "runtime-sort", count: 0 }, filesize: { regexp: fileSizeRegex, class: "file-size-sort", count: 0 }, dmyDates: { regexp: dmyRegex, class: "dates-dmy-sort", count: 0 }, ymdDates: { regexp: ymdRegex, class: "dates-ymd-sort", count: 0 }, + numericRegex: { regexp: numericRegex, class: "numeric-sort", count: 0 }, }; let classNameAdded = false; let regexNotFoundCount = 0; @@ -105,28 +107,44 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { } function makeTableSortable(sortableTable) { - const tableBody = getTableBody(sortableTable); - const tableHead = sortableTable.querySelector("thead"); - const tableHeadHeaders = tableHead.querySelectorAll("th"); - const tableRows = tableBody.querySelectorAll("tr"); + const table = { + body: getTableBody(sortableTable), + head: sortableTable.querySelector("thead"), + }; + table.headers = table.head.querySelectorAll("th"); + table.rows = table.body.querySelectorAll("tr"); + + let columnIndexesClicked = []; const isNoSortClassInference = sortableTable.classList.contains("no-class-infer"); - for (let [columnIndex, th] of tableHeadHeaders.entries()) { + for (let [columnIndex, th] of table.headers.entries()) { if (!th.classList.contains("disable-sort")) { th.style.cursor = "pointer"; if (!isNoSortClassInference) { - inferSortClasses(tableRows, columnIndex, th); + inferSortClasses(table.rows, columnIndex, th); } - makeEachColumnSortable(th, columnIndex, tableBody, sortableTable); + makeEachColumnSortable( + th, + columnIndex, + table, + sortableTable, + columnIndexesClicked + ); } } } - function makeEachColumnSortable(th, columnIndex, tableBody, sortableTable) { + function makeEachColumnSortable( + th, + columnIndex, + table, + sortableTable, + columnIndexesClicked + ) { const desc = th.classList.contains("order-by-desc"); - let tableArrows = sortableTable.classList.contains("table-arrows"); + const tableArrows = sortableTable.classList.contains("table-arrows"); const [arrowUp, arrowDown] = [" ▲", " ▼"]; const fillValue = "!X!Y!Z!"; @@ -249,9 +267,7 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { } } - let [timesClickedColumn, columnIndexesClicked] = [0, []]; - - function rememberSort(timesClickedColumn, columnIndexesClicked) { + function rememberSort() { // if user clicked different column from first column reset times clicked. columnIndexesClicked.push(columnIndex); if (timesClickedColumn === 1 && columnIndexesClicked.length > 1) { @@ -260,14 +276,15 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { const secondLastColumnClicked = columnIndexesClicked[columnIndexesClicked.length - 2]; if (lastColumnClicked !== secondLastColumnClicked) { - timesClickedColumn = 0; columnIndexesClicked.shift(); + timesClickedColumn = 0; } } + return timesClickedColumn; } - function getColSpanData(sortableTable, column) { - sortableTable.querySelectorAll("th").forEach((th, index) => { + function getColSpanData(headers, column) { + headers.forEach((th, index) => { column.span[index] = th.colSpan; if (index === 0) column.spanSum[index] = th.colSpan; else column.spanSum[index] = column.spanSum[index - 1] + th.colSpan; @@ -285,16 +302,7 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { } function getTableData(tableProperties) { - const { - tableRows, - column, - isFileSize, - isTimeSort, - isSortDateDayMonthYear, - isSortDateMonthDayYear, - isSortDateYearMonthDay, - isDataAttribute, - } = tableProperties; + const { tableRows, column, hasThClass, isSortDates } = tableProperties; for (let [i, tr] of tableRows.entries()) { let tdTextContent = getColumn( tr, @@ -305,17 +313,17 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { tdTextContent = ""; } if (tdTextContent.trim() !== "") { - if (isFileSize) { + if (hasThClass.fileSize) { fileSizeColumnTextAndRow[column.toBeSorted[i]] = tr.outerHTML; } // These classes already handle pushing to column and setting the tr html. if ( - !isFileSize && - !isDataAttribute && - !isTimeSort && - !isSortDateDayMonthYear && - !isSortDateYearMonthDay && - !isSortDateMonthDayYear + !hasThClass.fileSize && + !hasThClass.dataSort && + !hasThClass.runtime && + !isSortDates.dayMonthYear && + !isSortDates.yearMonthDay && + !isSortDates.monthDayYear ) { column.toBeSorted.push(`${tdTextContent}#${i}`); columnIndexAndTableRow[`${tdTextContent}#${i}`] = tr.outerHTML; @@ -329,17 +337,48 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { const isPunctSort = th.classList.contains("punct-sort"); const isAlphaSort = th.classList.contains("alpha-sort"); + const isNumericSort = th.classList.contains("numeric-sort"); + + function parseNumberFromString(str) { + let num; + str = str.slice(0, str.indexOf("#")); + if (str.match(/^\((\d+(?:\.\d+)?)\)$/)) { + num = -1 * Number(str.slice(1, -1)); + } else { + num = Number(str); + } + return num; + } + + function strLocaleCompare(str1, str2) { + return str1.localeCompare( + str2, + navigator.languages[0] || navigator.language, + { numeric: !isAlphaSort, ignorePunctuation: !isPunctSort } + ); + } + + function handleNumbers(str1, str2) { + let num1, num2; + num1 = parseNumberFromString(str1); + num2 = parseNumberFromString(str2); + + if (!isNaN(num1) && !isNaN(num2)) { + return num1 - num2; + } else { + return strLocaleCompare(str1, str2); + } + } + function sortAscending(a, b) { if (a.includes(`${fillValue}#`)) { return 1; } else if (b.includes(`${fillValue}#`)) { return -1; + } else if (isNumericSort) { + return handleNumbers(a, b); } else { - return a.localeCompare( - b, - navigator.languages[0] || navigator.language, - { numeric: !isAlphaSort, ignorePunctuation: !isPunctSort } - ); + return strLocaleCompare(a, b); } } @@ -391,9 +430,9 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { } function updateTable(tableProperties) { - const { tableRows, column, isFileSize } = tableProperties; + const { tableRows, column, hasThClass } = tableProperties; for (let [i, tr] of tableRows.entries()) { - if (isFileSize) { + if (hasThClass.fileSize) { tr.innerHTML = fileSizeColumnTextAndRow[column.toBeSorted[i]]; let fileSizeInBytesHTML = tr .querySelectorAll("td") @@ -426,71 +465,70 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { } tr.querySelectorAll("td").item(columnIndex).innerHTML = fileSizeInBytesHTML; - } else if (!isFileSize) { + } else if (!hasThClass.fileSize) { tr.outerHTML = columnIndexAndTableRow[column.toBeSorted[i]]; } } } + let timesClickedColumn = 0; th.addEventListener("click", function () { - timesClickedColumn += 1; const column = { - // column used for sorting; better name? toBeSorted: [], span: {}, spanSum: {}, }; - const visibleTableRows = Array.prototype.filter.call( - tableBody.querySelectorAll("tr"), + table.visibleRows = Array.prototype.filter.call( + table.body.querySelectorAll("tr"), (tr) => { return tr.style.display !== "none"; } ); - getColSpanData(sortableTable, column); + getColSpanData(table.headers, column); - const isDataAttribute = th.classList.contains("data-sort"); - if (isDataAttribute) { - sortDataAttributes(visibleTableRows, column); + const isRememberSort = sortableTable.classList.contains("remember-sort"); + if (!isRememberSort) { + timesClickedColumn = rememberSort(); } + timesClickedColumn += 1; - const isFileSize = th.classList.contains("file-size-sort"); - if (isFileSize) { - sortFileSize(visibleTableRows, column); - } + const hasThClass = { + dataSort: th.classList.contains("data-sort"), + fileSize: th.classList.contains("file-size-sort"), + runtime: th.classList.contains("runtime-sort"), + }; - const isTimeSort = th.classList.contains("runtime-sort"); - if (isTimeSort) { - sortByRuntime(visibleTableRows, column); + if (hasThClass.dataSort) { + sortDataAttributes(table.visibleRows, column); } - - const isSortDateDayMonthYear = th.classList.contains("dates-dmy-sort"); - const isSortDateMonthDayYear = th.classList.contains("dates-mdy-sort"); - const isSortDateYearMonthDay = th.classList.contains("dates-ymd-sort"); - // pick mdy first to override the inferred default class which is dmy. - if (isSortDateMonthDayYear) { - sortDates("mdy", visibleTableRows, column); - } else if (isSortDateYearMonthDay) { - sortDates("ymd", visibleTableRows, column); - } else if (isSortDateDayMonthYear) { - sortDates("dmy", visibleTableRows, column); + if (hasThClass.fileSize) { + sortFileSize(table.visibleRows, column); + } + if (hasThClass.runtime) { + sortByRuntime(table.visibleRows, column); } - const isRememberSort = sortableTable.classList.contains("remember-sort"); - if (!isRememberSort) { - rememberSort(timesClickedColumn, columnIndexesClicked); + const isSortDates = { + dayMonthYear: th.classList.contains("dates-dmy-sort"), + monthDayYear: th.classList.contains("dates-mdy-sort"), + yearMonthDay: th.classList.contains("dates-ymd-sort"), + }; + // pick mdy first to override the inferred default class which is dmy. + if (isSortDates.monthDayYear) { + sortDates("mdy", table.visibleRows, column); + } else if (isSortDates.yearMonthDay) { + sortDates("ymd", table.visibleRows, column); + } else if (isSortDates.dayMonthYear) { + sortDates("dmy", table.visibleRows, column); } const tableProperties = { - tableRows: visibleTableRows, + tableRows: table.visibleRows, column, - isFileSize, - isSortDateDayMonthYear, - isSortDateMonthDayYear, - isSortDateYearMonthDay, - isDataAttribute, - isTimeSort, + hasThClass, + isSortDates, }; getTableData(tableProperties); updateTable(tableProperties); diff --git a/public/table-sort.js b/public/table-sort.js index eaf9bcd..4b19ea0 100644 --- a/public/table-sort.js +++ b/public/table-sort.js @@ -71,7 +71,7 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) { filesize: { regexp: fileSizeRegex, class: "file-size-sort", count: 0 }, dmyDates: { regexp: dmyRegex, class: "dates-dmy-sort", count: 0 }, ymdDates: { regexp: ymdRegex, class: "dates-ymd-sort", count: 0 }, - numericRegex: {regexp: numericRegex, class: "numeric-sort",count:0} + numericRegex: { regexp: numericRegex, class: "numeric-sort", count: 0 }, }; let classNameAdded = false; let regexNotFoundCount = 0; diff --git a/test/table.test.js b/test/table.test.js index 32b7c6e..6d1f99e 100644 --- a/test/table.test.js +++ b/test/table.test.js @@ -512,7 +512,7 @@ test("Sort all combination positive, negative numbers with parenthesis as well", { classTags: "numeric-sort" } ) ).toStrictEqual({ - col0: ["-6","-3","-2.3","(1.4)","1","1.05","14"], + col0: ["-6", "-3", "-2.3", "(1.4)", "1", "1.05", "14"], }); }); @@ -520,11 +520,35 @@ test("Sort all combination of negative and positive integers and decimal numbers expect( createTestTable( { - col0: ["1.05", "-2.3", "-3", "1", "-6", "","(0.5)","1a","b","(c)","{1}"], + col0: [ + "1.05", + "-2.3", + "-3", + "1", + "-6", + "", + "(0.5)", + "1a", + "b", + "(c)", + "{1}", + ], }, { classTags: "numeric-sort" } ) ).toStrictEqual({ - col0: ["-6","-3","-2.3","(0.5)","1","1.05","{1}","1a","b","(c)",""], + col0: [ + "-6", + "-3", + "-2.3", + "(0.5)", + "1", + "1.05", + "{1}", + "1a", + "b", + "(c)", + "", + ], }); -}); \ No newline at end of file +});