fix: tweak debouncing & canceling

This commit is contained in:
Gregor Kleen 2020-01-08 22:56:30 +01:00
parent 49bafe1276
commit 6b51cc5e53
4 changed files with 83 additions and 257 deletions

View File

@ -3,12 +3,14 @@ import { StorageManager, LOCATION } from '../../lib/storage-manager/storage-mana
import { Datepicker } from '../form/datepicker';
import { HttpClient } from '../../services/http-client/http-client';
import * as debounce from 'lodash.debounce';
import * as throttle from 'lodash.throttle';
import './async-table-filter.sass';
import './async-table.sass';
const ATTR_SUBMIT_LOCKED = 'submit-locked';
const INPUT_DEBOUNCE = 600;
const FILTER_DEBOUNCE = 100;
const HEADER_HEIGHT = 80;
const ASYNC_TABLE_LOCAL_STORAGE_KEY = 'ASYNC_TABLE';
@ -35,6 +37,8 @@ export class AsyncTable {
_scrollTable;
_cssIdPrefix = '';
_cancelPendingUpdates = [];
_tableFilterInputs = {
search: [],
input: [],
@ -60,7 +64,7 @@ export class AsyncTable {
if (this._element.classList.contains(ASYNC_TABLE_INITIALIZED_CLASS)) {
return false;
}
// param asyncTableDbHeader
if (this._element.dataset.asyncTableDbHeader !== undefined) {
this._asyncTableHeader = this._element.dataset.asyncTableDbHeader;
@ -180,56 +184,62 @@ export class AsyncTable {
}
_addTableFilterEventListeners(tableFilterForm) {
const debouncedUpdateFromTableFilter = throttle((() => this._updateFromTableFilter(tableFilterForm)).bind(this), FILTER_DEBOUNCE, { leading: true, trailing: false });
[...this._tableFilterInputs.search, ...this._tableFilterInputs.input].forEach((input) => {
input.submitLockObserver = new MutationObserver((mutations, observer) => {
const submitLockObserver = new MutationObserver((mutations, observer) => {
for (const mutation of mutations) {
// if the submit lock has been released, trigger an update and disconnect this observer
if (mutation.oldValue === 'true' && input.getAttribute(ATTR_SUBMIT_LOCKED) === 'false') {
this._updateFromTableFilter(tableFilterForm);
if (mutation.target === input && mutation.attributeName === ATTR_SUBMIT_LOCKED && mutation.oldValue === 'true' && mutation.target.getAttribute(mutation.attributeName) === 'false') {
debouncedUpdateFromTableFilter();
observer.disconnect();
break;
}
}
});
this._cancelPendingUpdates.push(() => { submitLockObserver.disconnect(); });
const debouncedInput = debounce(() => {
const submitLockedAttr = input.getAttribute(ATTR_SUBMIT_LOCKED);
const submitLocked = submitLockedAttr === 'true' || submitLockedAttr === null;
const submitLocked = submitLockedAttr === 'true';
if (!submitLocked && (input.value.length === 0 || input.value.length > 2)) {
this._updateFromTableFilter(tableFilterForm);
} else if (submitLocked) {
debouncedUpdateFromTableFilter();
} else if (submitLockedAttr === 'true') {
// observe the submit lock of the input element
input.submitLockObserver.observe(input, {
submitLockObserver.observe(input, {
attributes: true,
attributeFilter: [ATTR_SUBMIT_LOCKED],
attributeOldValue: true,
});
}
}, INPUT_DEBOUNCE);
this._cancelPendingUpdates.push(debouncedInput.cancel);
input.addEventListener('input', debouncedInput);
input.addEventListener('input', () => {
// set flag to ignore any currently pending requests (not debounced)
this._ignoreRequest = true;
debouncedInput();
});
});
this._tableFilterInputs.change.forEach((input) => {
input.addEventListener('change', () => {
//if (this._element.classList.contains(ASYNC_TABLE_LOADING_CLASS))
this._updateFromTableFilter(tableFilterForm);
this._ignoreRequest = true;
debouncedUpdateFromTableFilter();
});
});
this._tableFilterInputs.select.forEach((input) => {
input.addEventListener('change', () => {
this._updateFromTableFilter(tableFilterForm);
this._ignoreRequest = true;
debouncedUpdateFromTableFilter();
});
});
tableFilterForm.addEventListener('submit', (event) =>{
event.preventDefault();
this._updateFromTableFilter(tableFilterForm);
this._ignoreRequest = true;
debouncedUpdateFromTableFilter();
});
}
@ -254,7 +264,6 @@ export class AsyncTable {
}
};
}
this._ignoreRequest = false;
this._updateTableFrom(url, callback && callback.bind(this));
}
@ -339,6 +348,12 @@ export class AsyncTable {
// fetches new sorted element from url with params and replaces contents of current element
_updateTableFrom(url, callback) {
const cancelPendingUpdates = (() => {
this._cancelPendingUpdates.forEach(f => f());
}).bind(this);
[0, INPUT_DEBOUNCE * 1.5, FILTER_DEBOUNCE * 1.5].forEach(delay => window.setTimeout(cancelPendingUpdates, delay));
this._ignoreRequest = false;
this._element.classList.add(ASYNC_TABLE_LOADING_CLASS);
const headers = {

200
package-lock.json generated
View File

@ -5367,17 +5367,6 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
"color-parse": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/color-parse/-/color-parse-1.3.8.tgz",
"integrity": "sha512-1Y79qFv0n1xair3lNMTNeoFvmc3nirMVBij24zbs1f13+7fPpQClMg5b4AuKXLt3szj7BRlHMCXHplkce6XlmA==",
"dev": true,
"requires": {
"color-name": "^1.0.0",
"defined": "^1.0.0",
"is-plain-obj": "^1.1.0"
}
},
"color-string": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
@ -7228,12 +7217,6 @@
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
"dev": true
},
"deepmerge": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz",
"integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==",
"dev": true
},
"define-properties": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
@ -7284,12 +7267,6 @@
}
}
},
"defined": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
"integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
"dev": true
},
"del": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz",
@ -11431,12 +11408,6 @@
"integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==",
"dev": true
},
"lodash.isempty": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz",
"integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=",
"dev": true
},
"lodash.ismatch": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz",
@ -11468,6 +11439,11 @@
"lodash._reinterpolate": "~3.0.0"
}
},
"lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
},
"lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@ -11716,15 +11692,6 @@
}
}
},
"merge-options": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-options/-/merge-options-1.0.1.tgz",
"integrity": "sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==",
"dev": true,
"requires": {
"is-plain-obj": "^1.1"
}
},
"merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@ -16405,15 +16372,6 @@
"postcss": "^7.0.2"
}
},
"postcss-helpers": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/postcss-helpers/-/postcss-helpers-0.3.2.tgz",
"integrity": "sha512-hppnMXY6Ehe8CgLHQCDWbyUsXvBFggdzftWzznL65MhgZsE8o8pUTYbmUbLst0rps+wyUSLIUJ0bGpV2Tzv7lw==",
"dev": true,
"requires": {
"urijs": "^1.18.12"
}
},
"postcss-image-set-function": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz",
@ -17016,88 +16974,6 @@
"uniq": "^1.0.1"
}
},
"posthtml": {
"version": "0.11.6",
"resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.11.6.tgz",
"integrity": "sha512-C2hrAPzmRdpuL3iH0TDdQ6XCc9M7Dcc3zEW5BLerY65G4tWWszwv6nG/ksi6ul5i2mx22ubdljgktXCtNkydkw==",
"dev": true,
"requires": {
"posthtml-parser": "^0.4.1",
"posthtml-render": "^1.1.5"
}
},
"posthtml-match-helper": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/posthtml-match-helper/-/posthtml-match-helper-1.0.1.tgz",
"integrity": "sha1-RRJT3o5YRKNI6WOtXt13aesSlRM=",
"dev": true
},
"posthtml-parser": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.4.2.tgz",
"integrity": "sha512-BUIorsYJTvS9UhXxPTzupIztOMVNPa/HtAm9KHni9z6qEfiJ1bpOBL5DfUOL9XAc3XkLIEzBzpph+Zbm4AdRAg==",
"dev": true,
"requires": {
"htmlparser2": "^3.9.2"
}
},
"posthtml-render": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-1.1.5.tgz",
"integrity": "sha512-yvt54j0zCBHQVEFAuR+yHld8CZrCa/E1Z/OcFNCV1IEWTLVxT8O7nYnM4IIw1CD4r8kaRd3lc42+0lgCKgm87w==",
"dev": true
},
"posthtml-transform": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/posthtml-transform/-/posthtml-transform-1.0.7.tgz",
"integrity": "sha512-ihbO3C1pqjgq94PjgxWyN/S0B+rW3lW3C2o+U0MHYilxDy7zft+u9r+Gk9YT+Nh5DyZyLgWj6Q9H1CR0Z/TPTg==",
"dev": true,
"requires": {
"color-parse": "^1.3.7",
"loader-utils": "^1.1.0",
"lodash": "^4.17.14",
"postcss-values-parser": "^1.5.0",
"posthtml": "^0.11.3",
"posthtml-match-helper": "^1.0.1",
"slashes": "^1.0.5",
"unquote": "^1.1.1"
},
"dependencies": {
"postcss-values-parser": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-1.5.0.tgz",
"integrity": "sha512-3M3p+2gMp0AH3da530TlX8kiO1nxdTnc3C6vr8dMxRLIlh8UYkz0/wcwptSXjhtx2Fr0TySI7a+BHDQ8NL7LaQ==",
"dev": true,
"requires": {
"flatten": "^1.0.2",
"indexes-of": "^1.0.1",
"uniq": "^1.0.1"
}
}
}
},
"postsvg": {
"version": "2.2.7",
"resolved": "https://registry.npmjs.org/postsvg/-/postsvg-2.2.7.tgz",
"integrity": "sha512-TyRnoyEvszrEGOzxaTycnUgJZ0W2Xnd9fOmgfuy61Qjo6JhDPhAIBQ1dspQCvdVpK9KkIlZkSETSjmbO0gVIag==",
"dev": true,
"requires": {
"clone": "^1.0.4",
"deepmerge": "^2.1.0",
"posthtml": "^0.11.3",
"posthtml-match-helper": "^1.0.1",
"posthtml-parser": "^0.4.1",
"posthtml-render": "^1.1.2"
},
"dependencies": {
"clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
"dev": true
}
}
},
"prebuild-install": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.3.tgz",
@ -18295,12 +18171,6 @@
"integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
"dev": true
},
"slashes": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/slashes/-/slashes-1.0.5.tgz",
"integrity": "sha1-IEeY9sYyAU1gm12JtqV6eq9wgo0=",
"dev": true
},
"slice-ansi": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
@ -18613,12 +18483,6 @@
"through": "2"
}
},
"split-on-first": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
"integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==",
"dev": true
},
"split-string": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
@ -19224,54 +19088,6 @@
"has-flag": "^3.0.0"
}
},
"svg-mixer-utils": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/svg-mixer-utils/-/svg-mixer-utils-0.3.4.tgz",
"integrity": "sha512-szkeG+Jn6DRo7QlnUOYKslm4J6dg37I8E+tLG1PB13U6UhSlkC8teCisyT7ZRGRwTcTxmNizvu+/oe8uJUf5EA==",
"dev": true,
"requires": {
"ajv": "^6.5.1",
"anymatch": "^2.0.0",
"memory-fs": "^0.4.1",
"merge-options": "^1.0.0",
"postcss-helpers": "^0.3.2"
}
},
"svg-transform-loader": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/svg-transform-loader/-/svg-transform-loader-2.0.8.tgz",
"integrity": "sha512-cK9PXVGV+hZoiR7lkIir+LOZ2qmJIuq0tm/emv5x7MF4PvyqY/lCNlYuctx37rSNgGE6Lhpdn8lUCZm8d/oNAQ==",
"dev": true,
"requires": {
"loader-utils": "^1.1.0",
"lodash.isempty": "^4.4.0",
"merge-options": "^1.0.0",
"postcss": "^7.0.14",
"posthtml-transform": "^1.0.7",
"postsvg": "^2.2.7",
"query-string": "^6.1.0",
"svg-mixer-utils": "^0.3.4"
},
"dependencies": {
"query-string": {
"version": "6.9.0",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-6.9.0.tgz",
"integrity": "sha512-KG4bhCFYapExLsUHrFt+kQVEegF2agm4cpF/VNc6pZVthIfCc/GK8t8VyNIE3nyXG9DK3Tf2EGkxjR6/uRdYsA==",
"dev": true,
"requires": {
"decode-uri-component": "^0.2.0",
"split-on-first": "^1.0.0",
"strict-uri-encode": "^2.0.0"
}
},
"strict-uri-encode": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
"integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=",
"dev": true
}
}
},
"svgo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz",
@ -20025,12 +19841,6 @@
"punycode": "^2.1.0"
}
},
"urijs": {
"version": "1.19.2",
"resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.2.tgz",
"integrity": "sha512-s/UIq9ap4JPZ7H1EB5ULo/aOUbWqfDi7FKzMC2Nz+0Si8GiT1rIEaprt8hy3Vy2Ex2aJPpOQv4P4DuOZ+K1c6w==",
"dev": true
},
"urix": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",

View File

@ -111,6 +111,7 @@
"@babel/runtime": "^7.7.6",
"@juggle/resize-observer": "^2.5.0",
"core-js": "^3.4.8",
"lodash.throttle": "^4.1.1",
"moment": "^2.24.0",
"npm": "^6.13.4",
"tail.datetime": "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/tail.DateTime.git#master",

View File

@ -19,51 +19,51 @@ module.exports = {
module: {
rules: [
{
loader: 'babel-loader',
loader: 'babel-loader',
options: {
plugins: ['syntax-dynamic-import'],
options: {
plugins: ['syntax-dynamic-import'],
presets: [
[
'@babel/preset-env',
{
modules: false,
targets: {
edge: "17",
firefox: "50",
chrome: "60",
safari: "11.1",
ie: "11",
},
useBuiltIns: "usage",
corejs: 3
}
]
]
},
test: /\.js$/i,
exclude: /node_modules/,
presets: [
[
'@babel/preset-env',
{
modules: false,
targets: {
edge: "17",
firefox: "50",
chrome: "60",
safari: "11.1",
ie: "11",
},
useBuiltIns: "usage",
corejs: 3
}
]
]
},
test: /\.js$/i,
exclude: /node_modules/,
},
{
test: /\.css$/i,
use: [ MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { sourceMap: true }},
{ loader: 'postcss-loader', options: {
sourceMap: true,
plugins: () => [ postcssPresetEnv ]
}},
sourceMap: true,
plugins: () => [ postcssPresetEnv ]
}},
{ loader: 'resolve-url-loader', options: { sourceMap: true }}
]
},
{
test: /\.s(c|a)ss$/i,
test: /\.s(c|a)ss$/i,
use: [ MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { sourceMap: true }},
{ loader: 'postcss-loader', options: {
sourceMap: true,
plugins: () => [ postcssPresetEnv ]
}},
sourceMap: true,
plugins: () => [ postcssPresetEnv ]
}},
{ loader: 'resolve-url-loader', options: { sourceMap: true }},
{ loader: 'sass-loader', options: { implementation: require('sass'), sourceMap: true }}
]
@ -134,27 +134,27 @@ module.exports = {
statsFilename: path.resolve(__dirname, 'config/favicon.json'),
persistentCache: false,
config: {
background: '#fff',
icons: {
android: false,
appleIcon: false,
appleStartup: false,
coast: false,
favicons: true,
firefox: false,
windows: false,
yandex: false
}
background: '#fff',
icons: {
android: false,
appleIcon: false,
appleStartup: false,
coast: false,
favicons: true,
firefox: false,
windows: false,
yandex: false
}
}
}),
new RemovePlugin({
after: {
test: [
{ folder: path.resolve(__dirname, `static/wp-${webpackVersion}`),
method: (filePath) => { return new RegExp(/\/.*-icons\/.*\.(xml|json|webapp)$/, 'm').test(filePath); },
recursive: true
}
]
test: [
{ folder: path.resolve(__dirname, `static/wp-${webpackVersion}`),
method: (filePath) => { return new RegExp(/\/.*-icons\/.*\.(xml|json|webapp)$/, 'm').test(filePath); },
recursive: true
}
]
}
})
],
@ -177,7 +177,7 @@ module.exports = {
sourceMap: true
}),
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
cssProcessorOptions: {
map: {
inline: false
}