Skip to content

Commit

Permalink
NPM release 1.12.0; automatically infer sort classes (file-size-sort …
Browse files Browse the repository at this point in the history
…and runtime)
  • Loading branch information
LeeWannacott committed May 9, 2023
1 parent 4c2ed4e commit 10e9b8e
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 34 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ Refer to the documenation for examples on how to use table-sort-js with [HTML](h

#### Classes:

| <table> classes | Description |
| --------------------- | --------------------------------------------------------------------------------------------|
| "table-sort" | Make the table sortable! (Words, numbers)... |
| "table-arrows" | Display ascending or descending triangles. |
| "no-class-infer" | Turns off inference for adding sort classes automatically (file-size-sort and runtime-sort).|
| "remember-sort" | If clicking on different columns remembers sort of the original column. |
| <table> classes | Description |
| --------------------- | -------------------------------------------------------------------------------------------- |
| "table-sort" | Make the table sortable! (Words, numbers)... |
| "table-arrows" | Display ascending or descending triangles. |
| "no-class-infer" | Turns off inference for adding sort classes automatically (file-size-sort and runtime-sort). |
| "remember-sort" | If clicking on different columns remembers sort of the original column. |

| <th> classes | Description |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
Expand Down
125 changes: 112 additions & 13 deletions browser-extension/table-sort.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,28 +35,88 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) {
}
}

function makeTableSortable(sortableTable) {
function createMissingTableHead(sortableTable) {
let createTableHead;
let tableBody;
if (testingTableSortJS === true) {
createTableHead = domDocumentWindow.createElement("thead");
} else {
createTableHead = document.createElement("thead");
}
createTableHead.appendChild(sortableTable.rows[0]);
sortableTable.insertBefore(createTableHead, sortableTable.firstChild);
}

function getTableBody(sortableTable) {
if (sortableTable.getElementsByTagName("thead").length === 0) {
if (testingTableSortJS === true) {
createTableHead = domDocumentWindow.createElement("thead");
} else {
createTableHead = document.createElement("thead");
}
createTableHead.appendChild(sortableTable.rows[0]);
sortableTable.insertBefore(createTableHead, sortableTable.firstChild);
createMissingTableHead(sortableTable);
if (sortableTable.querySelectorAll("tbody").length > 1) {
tableBody = sortableTable.querySelectorAll("tbody")[1];
return sortableTable.querySelectorAll("tbody")[1];
} else {
tableBody = sortableTable.querySelector("tbody");
return sortableTable.querySelector("tbody");
}
} else {
tableBody = sortableTable.querySelector("tbody");
return sortableTable.querySelector("tbody");
}
}

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;
let runtimeSortCounter = 0,
fileSizeSortCounter = 0;

let tableColumnLength = th.parentElement.childElementCount;
for (let tr of tableRows) {
let runtimeSortMatch, fileSizeSortMatch;
const tableColumn = tr.querySelectorAll("td").item(columnIndex);
if (tableColumn.innerText) {
runtimeSortMatch = tableColumn.innerText.match(
regexMinutesAndSeconds
);
fileSizeSortMatch = tableColumn.innerText.match(regexFileSizeSort);
}
if (runtimeSortMatch) {
runtimeSortCounter++;
}
if (fileSizeSortMatch) {
fileSizeSortCounter++;
}
}
// TODO: refactor this into one function called addInferredClasses that loops over sort classes and counters
addInferredClass(
th,
tableColumnLength,
runtimeSortCounter,
"runtime-sort"
);
addInferredClass(
th,
tableColumnLength,
fileSizeSortCounter,
"file-size-sort"
);
}
}

function makeTableSortable(sortableTable) {
const tableBody = getTableBody(sortableTable);
const tableHead = sortableTable.querySelector("thead");
const tableHeadHeaders = tableHead.querySelectorAll("th");
const tableRows = tableBody.querySelectorAll("tr");

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")) {
Expand Down Expand Up @@ -116,6 +176,34 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) {
}
}

function sortByRuntime(tableRows, columnData) {
for (let [i, tr] of tableRows.entries()) {
const regexMinutesAndSeconds = /^(\d+h)?\s?(\d+m)?\s?(\d+s)?$/i;
let columnOfTd = tr
.querySelectorAll("td")
.item(columnIndex).textContent;
let match = columnOfTd.match(regexMinutesAndSeconds);
let [minutesInSeconds, hours, seconds, timeinSeconds] = [0, 0, 0, 0];
if (match) {
const regexHours = match[1];
if (regexHours) {
hours = Number(regexHours.replace("h", "")) * 60 * 60;
}
const regexMinutes = match[2];
if (regexMinutes) {
minutesInSeconds = Number(regexMinutes.replace("m", "")) * 60;
}
const regexSeconds = match[3];
if (regexSeconds) {
seconds = Number(regexSeconds.replace("s", ""));
}
timeinSeconds = hours + minutesInSeconds + seconds;
}
columnData.push(`${timeinSeconds}#${i}`);
columnIndexAndTableRow[columnData[i]] = tr.innerHTML;
}
}

let [timesClickedColumn, columnIndexesClicked] = [0, []];

function rememberSort(timesClickedColumn, columnIndexesClicked) {
Expand Down Expand Up @@ -146,6 +234,7 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) {
tableRows,
columnData,
isFileSize,
isTimeSort,
isDataAttribute,
colSpanData,
colSpanSum,
Expand All @@ -165,7 +254,7 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) {
if (isFileSize) {
fileSizeColumnTextAndRow[columnData[i]] = tr.innerHTML;
}
if (!isFileSize && !isDataAttribute) {
if (!isFileSize && !isDataAttribute && !isTimeSort) {
columnData.push(`${tdTextContent}#${i}`);
columnIndexAndTableRow[`${tdTextContent}#${i}`] = tr.innerHTML;
}
Expand Down Expand Up @@ -301,6 +390,11 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) {
sortFileSize(visibleTableRows, columnData);
}

const isTimeSort = th.classList.contains("runtime-sort");
if (isTimeSort) {
sortByRuntime(visibleTableRows, columnData);
}

const isRememberSort = sortableTable.classList.contains("remember-sort");
if (!isRememberSort) {
rememberSort(timesClickedColumn, columnIndexesClicked);
Expand All @@ -314,12 +408,17 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) {
columnData,
isFileSize,
isDataAttribute,
isTimeSort,
colSpanData,
colSpanSum,
};
getTableData(tableProperties);
updateTable(tableProperties);
});
let isOnloadSort = th.classList.contains("onload-sort");
if (isOnloadSort) {
th.click();
}
}
}

Expand Down
11 changes: 6 additions & 5 deletions npm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ Refer to the documenation for examples on how to use table-sort-js with [HTML](h

#### Classes:

| <table> classes | Description |
| --------------------- | ----------------------------------------------------------------------- |
| "table-sort" | Make the table sortable! (Words, numbers, dates) |
| "table-arrows" | Display ascending or descending triangles. |
| "remember-sort" | If clicking on different columns remembers sort of the original column. |
| <table> classes | Description |
| --------------------- | -------------------------------------------------------------------------------------------- |
| "table-sort" | Make the table sortable! (Words, numbers)... |
| "table-arrows" | Display ascending or descending triangles. |
| "no-class-infer" | Turns off inference for adding sort classes automatically (file-size-sort and runtime-sort). |
| "remember-sort" | If clicking on different columns remembers sort of the original column. |

| <th> classes | 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.11.2",
"version": "1.12.0",
"description": "A JavaScript client-side HTML table sorting library with no dependencies required.",
"license": "MIT",
"repository": "LeeWannacott/table-sort-js",
Expand Down
70 changes: 63 additions & 7 deletions npm/table-sort.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,64 @@ 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;
let runtimeSortCounter = 0,
fileSizeSortCounter = 0;

let tableColumnLength = th.parentElement.childElementCount;
for (let tr of tableRows) {
let runtimeSortMatch, fileSizeSortMatch;
const tableColumn = tr.querySelectorAll("td").item(columnIndex);
if (tableColumn.innerText) {
runtimeSortMatch = tableColumn.innerText.match(
regexMinutesAndSeconds
);
fileSizeSortMatch = tableColumn.innerText.match(regexFileSizeSort);
}
if (runtimeSortMatch) {
runtimeSortCounter++;
}
if (fileSizeSortMatch) {
fileSizeSortCounter++;
}
}
// TODO: refactor this into one function called addInferredClasses that loops over sort classes and counters
addInferredClass(
th,
tableColumnLength,
runtimeSortCounter,
"runtime-sort"
);
addInferredClass(
th,
tableColumnLength,
fileSizeSortCounter,
"file-size-sort"
);
}
}

function makeTableSortable(sortableTable) {
const tableBody = getTableBody(sortableTable);
const tableHead = sortableTable.querySelector("thead");
const tableHeadHeaders = tableHead.querySelectorAll("th");
const tableRows = tableBody.querySelectorAll("tr");

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")) {
Expand Down Expand Up @@ -124,24 +178,26 @@ function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) {

function sortByRuntime(tableRows, columnData) {
for (let [i, tr] of tableRows.entries()) {
const regexMinutesAndSeconds = /^(\d+m)\s?(\d+s)$/i;
const regexMinutesAndSeconds = /^(\d+h)?\s?(\d+m)?\s?(\d+s)?$/i;
let columnOfTd = tr
.querySelectorAll("td")
.item(columnIndex).textContent;
let match = columnOfTd.match(regexMinutesAndSeconds);
let minutesInSeconds,
seconds,
timeinSeconds = [0, 0, 0];
let [minutesInSeconds, hours, seconds, timeinSeconds] = [0, 0, 0, 0];
if (match) {
const regexMinutes = match[1];
const regexHours = match[1];
if (regexHours) {
hours = Number(regexHours.replace("h", "")) * 60 * 60;
}
const regexMinutes = match[2];
if (regexMinutes) {
minutesInSeconds = Number(regexMinutes.replace("m", "")) * 60;
}
const regexSeconds = match[2];
const regexSeconds = match[3];
if (regexSeconds) {
seconds = Number(regexSeconds.replace("s", ""));
}
timeinSeconds = minutesInSeconds + seconds;
timeinSeconds = hours + minutesInSeconds + seconds;
}
columnData.push(`${timeinSeconds}#${i}`);
columnIndexAndTableRow[columnData[i]] = tr.innerHTML;
Expand Down
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ <h1>Testing table sort js</h1>
<table class="table-sort table-arrows">
<thead>
<tr>
<th >Last Name</th>
<th>Last Name</th>
<th>First Name</th>
<th class="order-by-desc">Birth Date</th>
<th>Employee ID</th>
Expand Down
2 changes: 1 addition & 1 deletion test/table.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const tableSortJs = require("../public/table-sort");
function createTestTable(
testTableData,
thAttributes = { classTags: "", colspan: "" },
props = { colsToClick: [], invisibleIndex: [] ,tableTags:""}
props = { colsToClick: [], invisibleIndex: [], tableTags: "" }
) {
const numberOfTableColumns = Object.keys(testTableData).length;
let testTableHeaders = "";
Expand Down

0 comments on commit 10e9b8e

Please sign in to comment.