Last active
October 13, 2023 21:44
-
-
Save jasonbyrne/c0ef4c08f5140b396159bc6651b972e5 to your computer and use it in GitHub Desktop.
DataTable in TypeScript that can be sorted and filtered and what not
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace JCB { | |
export enum SortStyle { | |
String, | |
Numeric, | |
CaseSensitiveString | |
} | |
export enum SortOrder { | |
ASC, | |
DESC | |
} | |
export class SortArgument { | |
public key: string = null; | |
public order: SortOrder = SortOrder.ASC; | |
public style: SortStyle = SortStyle.String; | |
constructor(key: string = null, order: SortOrder = SortOrder.ASC, style: SortStyle = SortStyle.String) { | |
this.key = key; | |
this.order = order; | |
this.style = style; | |
} | |
private numericCompare(valueA: number, valueB: number): number { | |
if (valueA == valueB) { | |
return 0; | |
} | |
return (this.order == SortOrder.ASC) ? | |
valueA - valueB : | |
valueB - valueA; | |
} | |
private stringCompare(valueA: string, valueB: string): number { | |
if (valueA == valueB) { | |
return 0; | |
} | |
return (this.order == SortOrder.ASC) ? | |
((valueA < valueB) ? -1 : 1) : | |
((valueA < valueB) ? 1 : -1); | |
} | |
public compare(a, b): number { | |
// Get values to compare | |
a = DataTable.isObject(a) && this.key ? a[this.key] : a; | |
b = DataTable.isObject(b) && this.key ? b[this.key] : b; | |
// Numeric sort | |
if (this.style == SortStyle.Numeric) { | |
return this.numericCompare( | |
Number(a), | |
Number(b) | |
); | |
} | |
// Case-insensitive string sort | |
else if (this.style == SortStyle.String) { | |
return this.stringCompare( | |
a.toLocaleString().toLocaleLowerCase(), | |
b.toLocaleString().toLocaleLowerCase() | |
); | |
} | |
// Case-sensitive string sort | |
else if (this.style = SortStyle.CaseSensitiveString) { | |
return this.stringCompare( | |
a.toLocaleString(), | |
b.toLocaleString() | |
); | |
} | |
return 0; | |
} | |
} | |
export class DataTable { | |
private items: Array<any> = []; | |
private sortBy: Array<SortArgument> = []; | |
constructor(items: Array<any>) { | |
this.items = items || []; | |
} | |
public static isObject(item): boolean { | |
return (item instanceof Object); | |
} | |
private sorter(table: DataTable) { | |
return function(a: any, b: any) { | |
let val: number = 0; | |
if (table.sortBy.length > 0) { | |
table.sortBy.some( | |
function(sortField: SortArgument) { | |
val = sortField.compare(a, b); | |
// If we got a value then break out | |
return (val != 0); | |
} | |
); | |
} | |
return val || 0; | |
} | |
}; | |
private static matches(row: any, key: string, pattern: any) { | |
let value = DataTable.isObject(row) ? row[key] : row; | |
// Regular expression compare | |
if (pattern instanceof RegExp) { | |
if (pattern.test(value.toString())) { | |
return true; | |
} | |
} | |
// Equality | |
else if (value == pattern) { | |
return true; | |
} | |
return false; | |
} | |
private sort(): DataTable { | |
if (this.sortBy.length > 0) { | |
this.items.sort(this.sorter(this)); | |
} | |
return this; | |
} | |
public add(row: any): DataTable { | |
this.items.push(row); | |
return this; | |
} | |
public remove(index: number): DataTable { | |
this.items = this.items.splice(index, 1); | |
return this; | |
} | |
public getSort(): Array<SortArgument> { | |
return this.sortBy; | |
} | |
public clear(): DataTable { | |
this.items = []; | |
return this; | |
} | |
public clearSort(): DataTable { | |
this.sortBy = []; | |
return this; | |
} | |
public asc(fieldName: string, style: SortStyle = SortStyle.String): DataTable { | |
this.sortBy.push( | |
new SortArgument(fieldName, SortOrder.ASC, style) | |
); | |
return this; | |
} | |
public desc(fieldName: string, style: SortStyle = SortStyle.String): DataTable { | |
this.sortBy.push( | |
new SortArgument(fieldName, SortOrder.DESC, style) | |
); | |
return this; | |
} | |
public getFirst(n: number): Array<any> { | |
return this.getAll().slice(0, n); | |
} | |
public getLast(n: number): Array<any> { | |
return this.getAll().slice(n * -1); | |
} | |
public getFrom(offset: number, limit: number): Array<any> { | |
return this.getAll().slice(offset, (offset + limit)); | |
} | |
public getAll(): Array<any> { | |
return this.sort().items; | |
} | |
public filter(key: string, pattern: any): DataTable { | |
this.items = this.search(key, pattern); | |
return this; | |
} | |
public search(key: string, pattern: any): Array<any> { | |
let matching: Array<any> = []; | |
this.sort().items.forEach(function(row) { | |
if (DataTable.matches(row, key, pattern)) { | |
matching.push(row); | |
} | |
}); | |
return matching; | |
} | |
public indexOf(key: string, pattern: any): number { | |
let index = 0, | |
firstMatch: number = -1; | |
this.sort().items.some(function(row) { | |
if (DataTable.matches(row, key, pattern)) { | |
firstMatch = index; | |
return true; | |
} | |
index++; | |
return false; | |
}); | |
return firstMatch; | |
} | |
public lastIndexOf(key: string, pattern: any): number { | |
let index: number = 0, | |
lastMatch: number = -1; | |
this.sort().items.forEach(function(row) { | |
if (DataTable.matches(row, key, pattern)) { | |
lastMatch = index; | |
} | |
index++; | |
}); | |
return lastMatch; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<script src="datatable.js"></script> | |
</head> | |
<body> | |
<script> | |
var data = [ | |
{ name: "Jason", value: 200 }, | |
{ name: "Jason", value: 20 }, | |
{ name: "Andrew", value: 0 }, | |
{ name: "Michael", value: 100 } | |
]; | |
var table = new JCB.DataTable(data); | |
table.asc('name').asc('value', JCB.SortStyle.Numeric); | |
console.log(table.getAll()); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment