@danielgindi/dgtable.js 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +288 -0
- package/connectors/jquery/index.js +27 -0
- package/connectors/jquery/package.json +46 -0
- package/dist/lib.cjs.js +6290 -0
- package/dist/lib.cjs.js.map +1 -0
- package/dist/lib.cjs.min.js +7 -0
- package/dist/lib.cjs.min.js.map +1 -0
- package/dist/lib.es6.js +6288 -0
- package/dist/lib.es6.js.map +1 -0
- package/dist/lib.es6.min.js +7 -0
- package/dist/lib.es6.min.js.map +1 -0
- package/dist/lib.umd.js +4365 -0
- package/dist/lib.umd.js.map +1 -0
- package/dist/lib.umd.min.js +7 -0
- package/dist/lib.umd.min.js.map +1 -0
- package/eslint.config.mjs +133 -0
- package/package.json +55 -0
- package/src/SelectionHelper.js +65 -0
- package/src/by_column_filter.js +25 -0
- package/src/column_collection.js +153 -0
- package/src/index.js +4003 -0
- package/src/row_collection.js +183 -0
- package/src/util.js +17 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import globals from "globals";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import js from "@eslint/js";
|
|
5
|
+
import { FlatCompat } from "@eslint/eslintrc";
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
const compat = new FlatCompat({
|
|
10
|
+
baseDirectory: __dirname,
|
|
11
|
+
recommendedConfig: js.configs.recommended,
|
|
12
|
+
allConfig: js.configs.all,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export default [
|
|
16
|
+
{
|
|
17
|
+
ignores: [
|
|
18
|
+
"tests/**/*",
|
|
19
|
+
"test/**/*",
|
|
20
|
+
"!tests/**/*tests.js",
|
|
21
|
+
"!test/**/*tests.js",
|
|
22
|
+
"!tests/**/*_test.js",
|
|
23
|
+
"!test/**/*_test.js",
|
|
24
|
+
"!tests/**/*_helpers.js",
|
|
25
|
+
"!test/**/*_helpers.js",
|
|
26
|
+
"dist/**/*",
|
|
27
|
+
"example/**/*",
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
...compat.extends("eslint:recommended"),
|
|
31
|
+
{
|
|
32
|
+
languageOptions: {
|
|
33
|
+
globals: {
|
|
34
|
+
...globals.browser,
|
|
35
|
+
...globals.node,
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
ecmaVersion: 2020,
|
|
39
|
+
sourceType: "module",
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
rules: {
|
|
43
|
+
semi: ["warn", "always"],
|
|
44
|
+
"comma-dangle": ["warn", "always-multiline"],
|
|
45
|
+
"comma-style": ["warn", "last"],
|
|
46
|
+
"no-var": ["warn"],
|
|
47
|
+
|
|
48
|
+
"arrow-spacing": ["warn", {
|
|
49
|
+
before: true,
|
|
50
|
+
after: true,
|
|
51
|
+
}],
|
|
52
|
+
|
|
53
|
+
"space-infix-ops": ["warn", {
|
|
54
|
+
int32Hint: true,
|
|
55
|
+
}],
|
|
56
|
+
|
|
57
|
+
"keyword-spacing": ["warn", {
|
|
58
|
+
before: true,
|
|
59
|
+
after: true,
|
|
60
|
+
}],
|
|
61
|
+
|
|
62
|
+
"space-unary-ops": ["warn", {
|
|
63
|
+
words: true,
|
|
64
|
+
nonwords: false,
|
|
65
|
+
}],
|
|
66
|
+
|
|
67
|
+
"comma-spacing": ["warn", {
|
|
68
|
+
before: false,
|
|
69
|
+
after: true,
|
|
70
|
+
}],
|
|
71
|
+
|
|
72
|
+
"object-curly-spacing": ["warn", "always"],
|
|
73
|
+
|
|
74
|
+
"no-unused-vars": ["warn", {
|
|
75
|
+
vars: "all",
|
|
76
|
+
args: "after-used",
|
|
77
|
+
varsIgnorePattern: "[iIgnored]|^_",
|
|
78
|
+
ignoreRestSiblings: false,
|
|
79
|
+
argsIgnorePattern: "^_",
|
|
80
|
+
caughtErrors: "all",
|
|
81
|
+
caughtErrorsIgnorePattern: "^ignore",
|
|
82
|
+
}],
|
|
83
|
+
|
|
84
|
+
"no-console": "warn",
|
|
85
|
+
"no-extra-semi": "warn",
|
|
86
|
+
"no-unreachable": "warn",
|
|
87
|
+
|
|
88
|
+
"no-fallthrough": ["error", {
|
|
89
|
+
commentPattern: "break[\\s\\w]*omitted|fallthrough",
|
|
90
|
+
}],
|
|
91
|
+
|
|
92
|
+
"no-useless-escape": "warn",
|
|
93
|
+
"no-constant-condition": "warn",
|
|
94
|
+
"no-return-await": "warn",
|
|
95
|
+
"no-async-promise-executor": "warn",
|
|
96
|
+
},
|
|
97
|
+
}, {
|
|
98
|
+
files: [
|
|
99
|
+
"tests/**/*tests.js",
|
|
100
|
+
"test/**/*tests.js",
|
|
101
|
+
"tests/**/*_test.js",
|
|
102
|
+
"test/**/*_test.js",
|
|
103
|
+
],
|
|
104
|
+
|
|
105
|
+
languageOptions: {
|
|
106
|
+
globals: {
|
|
107
|
+
...Object.fromEntries(Object.entries(globals.browser).map(([key]) => [key, "off"])),
|
|
108
|
+
...globals.node,
|
|
109
|
+
...globals.mocha,
|
|
110
|
+
...globals.jest,
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
rules: {
|
|
115
|
+
"no-console": "off",
|
|
116
|
+
},
|
|
117
|
+
}, {
|
|
118
|
+
files: ["*db*/**/migrations/**/*.js"],
|
|
119
|
+
|
|
120
|
+
rules: {
|
|
121
|
+
"no-console": "off",
|
|
122
|
+
},
|
|
123
|
+
}, {
|
|
124
|
+
files: ["scripts/**/*.js", "**/.eslintrc.js"],
|
|
125
|
+
|
|
126
|
+
languageOptions: {
|
|
127
|
+
globals: {
|
|
128
|
+
...Object.fromEntries(Object.entries(globals.browser).map(([key]) => [key, "off"])),
|
|
129
|
+
...globals.node,
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
];
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@danielgindi/dgtable.js",
|
|
3
|
+
"description": "High-performance table View for vanilla JS",
|
|
4
|
+
"version": "2.0.0",
|
|
5
|
+
"main": "dist/lib.cjs.min.js",
|
|
6
|
+
"module": "dist/lib.es6.min.js",
|
|
7
|
+
"broswer": "dist/lib.umd.min.js",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"author": {
|
|
10
|
+
"name": "Daniel Cohen Gindi",
|
|
11
|
+
"email": "danielgindi@gmail.com"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git://github.com/danielgindi/dgtable.js.git"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "npm run lint && node ./scripts/build.js",
|
|
19
|
+
"lint": "node -e \"process.env.NODE_ENV != 'production' && process.exit(1)\" || eslint -f codeframe ./",
|
|
20
|
+
"lint-fix": "node -e \"process.env.NODE_ENV != 'production' && process.exit(1)\" || eslint -f codeframe --fix ./",
|
|
21
|
+
"prepare": "node -e \"process.env.NODE_ENV != 'production' && process.exit(1)\" || husky",
|
|
22
|
+
"prepublishOnly": "node -e \"process.env.NODE_ENV != 'production' && process.exit(1)\" || npm run build"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/danielgindi/dgtable.js/issues"
|
|
26
|
+
},
|
|
27
|
+
"licenses": [
|
|
28
|
+
{
|
|
29
|
+
"type": "MIT",
|
|
30
|
+
"url": "https://github.com/danielgindi/dgtable.js/blob/master/LICENSE"
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@danielgindi/dom-utils": "^1.0.11",
|
|
35
|
+
"@danielgindi/virtual-list-helper": "^1.0.17",
|
|
36
|
+
"mitt": "^3.0.1"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@babel/core": "^7.28.5",
|
|
40
|
+
"@babel/preset-env": "^7.28.5",
|
|
41
|
+
"@babel/runtime": "^7.28.4",
|
|
42
|
+
"@rollup/plugin-babel": "^6.1.0",
|
|
43
|
+
"@rollup/plugin-commonjs": "^28.0.9",
|
|
44
|
+
"@rollup/plugin-node-resolve": "^15.3.1",
|
|
45
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
46
|
+
"core-js": "^3.47.0",
|
|
47
|
+
"eslint": "^9.39.1",
|
|
48
|
+
"eslint-formatter-codeframe": "^7.32.2",
|
|
49
|
+
"fs-extra": "^11.3.2",
|
|
50
|
+
"globals": "^15",
|
|
51
|
+
"husky": "^9.1.7",
|
|
52
|
+
"pinst": "^3.0.0",
|
|
53
|
+
"rollup": "^4.53.3"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/* eslint-env browser */
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
// saveSelection/restoreSelection courtesy of Tim Down, with my improvements
|
|
6
|
+
// https://stackoverflow.com/questions/13949059/persisting-the-changes-of-range-objects-after-selection-in-html/13950376#13950376
|
|
7
|
+
|
|
8
|
+
function isChildOf(child, parent) {
|
|
9
|
+
while ((child = child.parentNode) && child !== parent);
|
|
10
|
+
return !!child;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class SelectionHelper {
|
|
14
|
+
|
|
15
|
+
static saveSelection(el) {
|
|
16
|
+
let range = window.getSelection().getRangeAt(0);
|
|
17
|
+
|
|
18
|
+
if (el !== range.commonAncestorContainer && !isChildOf(range.commonAncestorContainer, el))
|
|
19
|
+
return null;
|
|
20
|
+
|
|
21
|
+
let preSelectionRange = range.cloneRange();
|
|
22
|
+
preSelectionRange.selectNodeContents(el);
|
|
23
|
+
preSelectionRange.setEnd(range.startContainer, range.startOffset);
|
|
24
|
+
let start = preSelectionRange.toString().length;
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
start: start,
|
|
28
|
+
end: start + range.toString().length,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static restoreSelection(el, savedSel) {
|
|
33
|
+
let charIndex = 0;
|
|
34
|
+
let nodeStack = [el], node, foundStart = false, stop = false;
|
|
35
|
+
let range = document.createRange();
|
|
36
|
+
range.setStart(el, 0);
|
|
37
|
+
range.collapse(true);
|
|
38
|
+
|
|
39
|
+
while (!stop && (node = nodeStack.pop())) {
|
|
40
|
+
if (node.nodeType === 3) {
|
|
41
|
+
let nextCharIndex = charIndex + node.length;
|
|
42
|
+
if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
|
|
43
|
+
range.setStart(node, savedSel.start - charIndex);
|
|
44
|
+
foundStart = true;
|
|
45
|
+
}
|
|
46
|
+
if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
|
|
47
|
+
range.setEnd(node, savedSel.end - charIndex);
|
|
48
|
+
stop = true;
|
|
49
|
+
}
|
|
50
|
+
charIndex = nextCharIndex;
|
|
51
|
+
} else {
|
|
52
|
+
let i = node.childNodes.length;
|
|
53
|
+
while (i--) {
|
|
54
|
+
nodeStack.push(node.childNodes[i]);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let sel = window.getSelection();
|
|
60
|
+
sel.removeAllRanges();
|
|
61
|
+
sel.addRange(range);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default SelectionHelper;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function ByColumnFilter (row, args) {
|
|
4
|
+
|
|
5
|
+
let column = args.column;
|
|
6
|
+
let keyword = args.keyword == null ? '' : args.keyword.toString();
|
|
7
|
+
|
|
8
|
+
if (!keyword || !column) return true;
|
|
9
|
+
|
|
10
|
+
let actualVal = row[column];
|
|
11
|
+
if (actualVal == null) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
actualVal = actualVal.toString();
|
|
16
|
+
|
|
17
|
+
if (!args.caseSensitive) {
|
|
18
|
+
actualVal = actualVal.toLowerCase();
|
|
19
|
+
keyword = keyword.toLowerCase();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return actualVal.indexOf(keyword) !== -1;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default ByColumnFilter;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Define class RowCollection
|
|
4
|
+
function ColumnCollection () {
|
|
5
|
+
|
|
6
|
+
// Instantiate an Array. Seems like the `.length = ` of an inherited Array does not work well.
|
|
7
|
+
// I will not use the IFRAME solution either in fear of memory leaks, and we're supporting large datasets...
|
|
8
|
+
let collection = [];
|
|
9
|
+
|
|
10
|
+
// Synthetically set the 'prototype'
|
|
11
|
+
Object.assign(collection, ColumnCollection.prototype);
|
|
12
|
+
|
|
13
|
+
// Call initializer
|
|
14
|
+
collection.initialize.apply(collection, arguments);
|
|
15
|
+
|
|
16
|
+
return collection;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Inherit Array
|
|
20
|
+
ColumnCollection.prototype = [];
|
|
21
|
+
|
|
22
|
+
ColumnCollection.prototype.initialize = function () {
|
|
23
|
+
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Get the column by this name
|
|
28
|
+
* @param {string} column column name
|
|
29
|
+
* @returns {Object} the column object
|
|
30
|
+
*/
|
|
31
|
+
ColumnCollection.prototype.get = function (column) {
|
|
32
|
+
for (let i = 0, len = this.length; i < len; i++) {
|
|
33
|
+
if (this[i].name === column) {
|
|
34
|
+
return this[i];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get the index of the column by this name
|
|
42
|
+
* @param {string} column column name
|
|
43
|
+
* @returns {int} the index of this column
|
|
44
|
+
*/
|
|
45
|
+
ColumnCollection.prototype.indexOf = function (column) {
|
|
46
|
+
for (let i = 0, len = this.length; i < len; i++) {
|
|
47
|
+
if (this[i].name === column) {
|
|
48
|
+
return i;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return -1;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Get the column by the specified order
|
|
56
|
+
* @param {number} order the column's order
|
|
57
|
+
* @returns {Object} the column object
|
|
58
|
+
*/
|
|
59
|
+
ColumnCollection.prototype.getByOrder = function (order) {
|
|
60
|
+
for (let i = 0, len = this.length; i < len; i++) {
|
|
61
|
+
if (this[i].order === order) {
|
|
62
|
+
return this[i];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Normalize order
|
|
70
|
+
* @returns {ColumnCollection} self
|
|
71
|
+
*/
|
|
72
|
+
ColumnCollection.prototype.normalizeOrder = function () {
|
|
73
|
+
let ordered = [], i;
|
|
74
|
+
for (i = 0; i < this.length; i++) {
|
|
75
|
+
ordered.push(this[i]);
|
|
76
|
+
}
|
|
77
|
+
ordered.sort(function(col1, col2){ return col1.order < col2.order ? -1 : (col1.order > col2.order ? 1 : 0); });
|
|
78
|
+
for (i = 0; i < ordered.length; i++) {
|
|
79
|
+
ordered[i].order = i;
|
|
80
|
+
}
|
|
81
|
+
return this;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get the array of columns, order by the order property
|
|
86
|
+
* @returns {Array<Object>} ordered array of columns
|
|
87
|
+
*/
|
|
88
|
+
ColumnCollection.prototype.getColumns = function () {
|
|
89
|
+
let cols = [];
|
|
90
|
+
for (let i = 0, column; i < this.length; i++) {
|
|
91
|
+
column = this[i];
|
|
92
|
+
cols.push(column);
|
|
93
|
+
}
|
|
94
|
+
cols.sort((col1, col2) => col1.order < col2.order ? -1 : (col1.order > col2.order ? 1 : 0));
|
|
95
|
+
return cols;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Get the array of visible columns, order by the order property
|
|
100
|
+
* @returns {Array<Object>} ordered array of visible columns
|
|
101
|
+
*/
|
|
102
|
+
ColumnCollection.prototype.getVisibleColumns = function () {
|
|
103
|
+
let cols = [];
|
|
104
|
+
for (let i = 0, column; i < this.length; i++) {
|
|
105
|
+
column = this[i];
|
|
106
|
+
if (column.visible) {
|
|
107
|
+
cols.push(column);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
cols.sort((col1, col2) => col1.order < col2.order ? -1 : (col1.order > col2.order ? 1 : 0));
|
|
111
|
+
return cols;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @returns {int} maximum order currently in the array
|
|
116
|
+
*/
|
|
117
|
+
ColumnCollection.prototype.getMaxOrder = function () {
|
|
118
|
+
let order = 0;
|
|
119
|
+
for (let i = 0, column; i < this.length; i++) {
|
|
120
|
+
column = this[i];
|
|
121
|
+
if (column.order > order) {
|
|
122
|
+
order = column.order;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return order;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Move a column to a new spot in the collection
|
|
130
|
+
* @param {Object} src the column to move
|
|
131
|
+
* @param {Object} dest the destination column
|
|
132
|
+
* @returns {ColumnCollection} self
|
|
133
|
+
*/
|
|
134
|
+
ColumnCollection.prototype.moveColumn = function (src, dest) {
|
|
135
|
+
if (src && dest) {
|
|
136
|
+
let srcOrder = src.order, destOrder = dest.order, i, col;
|
|
137
|
+
if (srcOrder < destOrder) {
|
|
138
|
+
for (i = srcOrder + 1; i <= destOrder; i++) {
|
|
139
|
+
col = this.getByOrder(i);
|
|
140
|
+
col.order--;
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
for (i = srcOrder - 1; i >= destOrder; i--) {
|
|
144
|
+
col = this.getByOrder(i);
|
|
145
|
+
col.order++;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
src.order = destOrder;
|
|
149
|
+
}
|
|
150
|
+
return this;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export default ColumnCollection;
|