Skip to content

Commit

Permalink
NPM version 1.15.0; Optimized sort type class inference
Browse files Browse the repository at this point in the history
  • Loading branch information
LeeWannacott committed May 14, 2023
1 parent efba045 commit aac07fc
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 126 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

## TABLE-SORT-JS.

- Description: HTML table sorting library with sort type inference builtin and browser extension available. [#VanillaJS](http://vanilla-js.com/)
- 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)
Expand Down Expand Up @@ -60,7 +60,7 @@ Refer to the documenation for examples on how to use table-sort-js with [HTML](h
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| "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 KiB). Input data ideally in Bytes e.g (10b or 10B) |
| "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 |
Expand Down
4 changes: 2 additions & 2 deletions browser-extension/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"manifest_version": 2,
"author": "Lee Wannacott",
"name": "table-sort-js",
"version": "1.14.0",
"version": "1.15.0",
"description": "Makes tables sortable using table-sort-js: https://github.com/LeeWannacott/table-sort-js",
"icons": { "48": "icons/t.png" },
"browser_action": {
Expand All @@ -11,7 +11,7 @@
},
"content_scripts": [
{
"matches": ["<all_urls>", "https://github.com/*/*/actions/runs/*/usage"],
"matches": ["<all_urls>"],
"js": ["addTableSortClass.js", "table-sort.js"]
}
]
Expand Down
Binary file modified browser-extension/table-sort-js.zip
Binary file not shown.
102 changes: 43 additions & 59 deletions browser-extension/table-sort.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,64 +59,48 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) {
}
}

function addInferredClass(th, columnLength, currentCount, classToAdd) {
const threshold = columnLength / 2;
if (currentCount >= threshold) {
th.classList.add(classToAdd);
}
}

function inferSortClasses(tableRows, tableHeadHeaders) {
for (let [columnIndex, th] of tableHeadHeaders.entries()) {
const regexMinutesAndSeconds = /^(\d+h)?\s?(\d+m)?\s?(\d+s)?$/i;
const regexFileSizeSort = /^([.0-9]+)\s?(B|KB|KiB|MB|MiB|GB|GiB|TB|TiB)/i;
// Doesn't infer dates with delimiter "."; as could capture semantic version numbers.
const datesRegex = /^(\d\d?)[/-](\d\d?)[/-]((\d\d)?\d\d)/;
const regexISODates = /^(\d\d\d\d)[/-](\d\d?)[/-](\d\d?)/;
let runtimeCounter = 0,
fileSizeCounter = 0,
datesCounter = 0,
isoDatesCounter = 0;
let tableColumnLength = th.parentElement.childElementCount;
for (let tr of tableRows) {
let runtimeSortMatch, fileSizeSortMatch, datesMatch, isoDatesMatch;
const tableColumn = tr.querySelectorAll("td").item(columnIndex);
function inferSortClasses(tableRows, columnIndex, th) {
const runtimeRegex = /^(\d+h)?\s?(\d+m)?\s?(\d+s)?$/i;
const fileSizeRegex = /^([.0-9]+)\s?(B|KB|KiB|MB|MiB|GB|GiB|TB|TiB)/i;
// 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 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 },
};
let classNameAdded = false;
let regexNotFoundCount = 0;
const threshold = Math.ceil(tableRows.length / 2);
for (let tr of tableRows) {
if (regexNotFoundCount >= threshold) {
break;
}
const tableColumn = tr.querySelectorAll("td").item(columnIndex);
let foundMatch = false;
for (let key of Object.keys(inferableClasses)) {
let classRegexp = inferableClasses[key].regexp;
if (tableColumn.innerText) {
runtimeSortMatch = tableColumn.innerText.match(
regexMinutesAndSeconds
);
fileSizeSortMatch = tableColumn.innerText.match(regexFileSizeSort);
datesMatch = tableColumn.innerText.match(datesRegex);
isoDatesMatch = tableColumn.innerText.match(regexISODates);
}
if (runtimeSortMatch) {
runtimeCounter++;
}
if (fileSizeSortMatch) {
fileSizeCounter++;
}
if (datesMatch) {
datesCounter++;
if (tableColumn.innerText.match(classRegexp) !== null) {
foundMatch = true;
inferableClasses[key].count++;
}
}
if (isoDatesMatch) {
isoDatesCounter++;
if (inferableClasses[key].count >= threshold) {
th.classList.add(inferableClasses[key].class);
classNameAdded = true;
break;
}
}
// TODO: refactor this into one function called addInferredClasses that loops over sort classes and counters
addInferredClass(th, tableColumnLength, runtimeCounter, "runtime-sort");
addInferredClass(
th,
tableColumnLength,
fileSizeCounter,
"file-size-sort"
);
addInferredClass(th, tableColumnLength, datesCounter, "dates-dmy-sort");
addInferredClass(
th,
tableColumnLength,
isoDatesCounter,
"dates-ymd-sort"
);
if (classNameAdded) {
break;
}
if (!foundMatch) {
regexNotFoundCount++;
continue;
}
}
}

Expand All @@ -128,13 +112,13 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) {

const isNoSortClassInference =
sortableTable.classList.contains("no-class-infer");
if (!isNoSortClassInference) {
inferSortClasses(tableRows, tableHeadHeaders);
}

for (let [columnIndex, th] of tableHeadHeaders.entries()) {
if (!th.classList.contains("disable-sort")) {
th.style.cursor = "pointer";
if (!isNoSortClassInference) {
inferSortClasses(tableRows, columnIndex, th);
}
makeEachColumnSortable(th, columnIndex, tableBody, sortableTable);
}
}
Expand Down Expand Up @@ -504,8 +488,8 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) {
getTableData(tableProperties);
updateTable(tableProperties);
});
let isOnloadSort = th.classList.contains("onload-sort");
if (isOnloadSort) {

if (th.classList.contains("onload-sort")) {
th.click();
}
}
Expand Down
6 changes: 3 additions & 3 deletions npm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@

## TABLE-SORT-JS.

- Description: A JavaScript client-side HTML table sorting library with no dependencies required.
- 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)
- [firefox browser extension](https://addons.mozilla.org/en-US/firefox/addon/table-sort-js/)
- [firefox browser extension](https://addons.mozilla.org/en-US/firefox/addon/table-sort-js/): Tables of any website you visit become sortable!

## Install instructions.

Expand Down Expand Up @@ -60,7 +60,7 @@ Refer to the documenation for examples on how to use table-sort-js with [HTML](h
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| "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 KiB). Input data ideally in Bytes e.g (10b or 10B) |
| "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... |

| &lt;th&gt; Classes that change defaults. | Description |
Expand Down
2 changes: 1 addition & 1 deletion npm/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "table-sort-js",
"version": "1.14.0",
"version": "1.15.0",
"description": "A JavaScript client-side HTML table sorting library with no dependencies required.",
"license": "MIT",
"repository": "LeeWannacott/table-sort-js",
Expand Down
102 changes: 43 additions & 59 deletions npm/table-sort.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,64 +59,48 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) {
}
}

function addInferredClass(th, columnLength, currentCount, classToAdd) {
const threshold = columnLength / 2;
if (currentCount >= threshold) {
th.classList.add(classToAdd);
}
}

function inferSortClasses(tableRows, tableHeadHeaders) {
for (let [columnIndex, th] of tableHeadHeaders.entries()) {
const regexMinutesAndSeconds = /^(\d+h)?\s?(\d+m)?\s?(\d+s)?$/i;
const regexFileSizeSort = /^([.0-9]+)\s?(B|KB|KiB|MB|MiB|GB|GiB|TB|TiB)/i;
// Doesn't infer dates with delimiter "."; as could capture semantic version numbers.
const datesRegex = /^(\d\d?)[/-](\d\d?)[/-]((\d\d)?\d\d)/;
const regexISODates = /^(\d\d\d\d)[/-](\d\d?)[/-](\d\d?)/;
let runtimeCounter = 0,
fileSizeCounter = 0,
datesCounter = 0,
isoDatesCounter = 0;
let tableColumnLength = th.parentElement.childElementCount;
for (let tr of tableRows) {
let runtimeSortMatch, fileSizeSortMatch, datesMatch, isoDatesMatch;
const tableColumn = tr.querySelectorAll("td").item(columnIndex);
function inferSortClasses(tableRows, columnIndex, th) {
const runtimeRegex = /^(\d+h)?\s?(\d+m)?\s?(\d+s)?$/i;
const fileSizeRegex = /^([.0-9]+)\s?(B|KB|KiB|MB|MiB|GB|GiB|TB|TiB)/i;
// 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 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 },
};
let classNameAdded = false;
let regexNotFoundCount = 0;
const threshold = Math.ceil(tableRows.length / 2);
for (let tr of tableRows) {
if (regexNotFoundCount >= threshold) {
break;
}
const tableColumn = tr.querySelectorAll("td").item(columnIndex);
let foundMatch = false;
for (let key of Object.keys(inferableClasses)) {
let classRegexp = inferableClasses[key].regexp;
if (tableColumn.innerText) {
runtimeSortMatch = tableColumn.innerText.match(
regexMinutesAndSeconds
);
fileSizeSortMatch = tableColumn.innerText.match(regexFileSizeSort);
datesMatch = tableColumn.innerText.match(datesRegex);
isoDatesMatch = tableColumn.innerText.match(regexISODates);
}
if (runtimeSortMatch) {
runtimeCounter++;
}
if (fileSizeSortMatch) {
fileSizeCounter++;
}
if (datesMatch) {
datesCounter++;
if (tableColumn.innerText.match(classRegexp) !== null) {
foundMatch = true;
inferableClasses[key].count++;
}
}
if (isoDatesMatch) {
isoDatesCounter++;
if (inferableClasses[key].count >= threshold) {
th.classList.add(inferableClasses[key].class);
classNameAdded = true;
break;
}
}
// TODO: refactor this into one function called addInferredClasses that loops over sort classes and counters
addInferredClass(th, tableColumnLength, runtimeCounter, "runtime-sort");
addInferredClass(
th,
tableColumnLength,
fileSizeCounter,
"file-size-sort"
);
addInferredClass(th, tableColumnLength, datesCounter, "dates-dmy-sort");
addInferredClass(
th,
tableColumnLength,
isoDatesCounter,
"dates-ymd-sort"
);
if (classNameAdded) {
break;
}
if (!foundMatch) {
regexNotFoundCount++;
continue;
}
}
}

Expand All @@ -128,13 +112,13 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) {

const isNoSortClassInference =
sortableTable.classList.contains("no-class-infer");
if (!isNoSortClassInference) {
inferSortClasses(tableRows, tableHeadHeaders);
}

for (let [columnIndex, th] of tableHeadHeaders.entries()) {
if (!th.classList.contains("disable-sort")) {
th.style.cursor = "pointer";
if (!isNoSortClassInference) {
inferSortClasses(tableRows, columnIndex, th);
}
makeEachColumnSortable(th, columnIndex, tableBody, sortableTable);
}
}
Expand Down Expand Up @@ -504,8 +488,8 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) {
getTableData(tableProperties);
updateTable(tableProperties);
});
let isOnloadSort = th.classList.contains("onload-sort");
if (isOnloadSort) {

if (th.classList.contains("onload-sort")) {
th.click();
}
}
Expand Down

0 comments on commit aac07fc

Please sign in to comment.