Skip to content

Commit

Permalink
Feature: numeric-sort class: handles negative and decimal numeric cases
Browse files Browse the repository at this point in the history
#63 and #64 (#87)

* fix: handling negative and decimal numeric cases #63 and #64

* fix: handling negative parenthesis case, and NaN cases

* fix: basic refactor and README update

* nit: basic refactor and README update
  • Loading branch information
scodes73 committed May 19, 2023
1 parent 5be4237 commit c7a5030
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 5 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Refer to the documenation for examples on how to use table-sort-js with [HTML](h
| "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... |
| "numeric-sort" | Sorts numbers - Positive, Negative (Both minus and parenthesis representations), and Decimals |

| <th> Classes that change defaults. | Description |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
Expand Down
43 changes: 38 additions & 5 deletions public/table-sort.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -335,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);
}
}

Expand Down
39 changes: 39 additions & 0 deletions test/table.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -489,3 +489,42 @@ test("dates-ymd-sort: ISO 8601 style yyyy/mm/dd; delim . or / or -", () => {
col0: ["2023-03-9", "2023/4/6", "2023/4/32", "2023/09/6", "2023.12.16"],
});
});

test("Sort decimal numbers", () => {
expect(
createTestTable(
{
col0: ["0.1", "0.2", "0.3", "0.11", "0.13", "0.13", "0.14"],
},
{ classTags: "numeric-sort" }
)
).toStrictEqual({
col0: ["0.1", "0.11", "0.13", "0.13", "0.14", "0.2", "0.3"],
});
});

test("Sort all combination positive, negative numbers with parenthesis as well", () => {
expect(
createTestTable(
{
col0: ["1.05", "-2.3", "-3", "1", "-6", "(1.4)", "14"],
},
{ classTags: "numeric-sort" }
)
).toStrictEqual({
col0: ["-6","-3","-2.3","(1.4)","1","1.05","14"],
});
});

test("Sort all combination of negative and positive integers and decimal numbers and even alphabetical random", () => {
expect(
createTestTable(
{
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)",""],
});
});

0 comments on commit c7a5030

Please sign in to comment.