stimulus-library 0.9.5 → 0.9.7
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/README.md +43 -43
- package/dist/controllers/index.js +1 -2
- package/dist/controllers/tables/table_sort_controller.js +2 -2
- package/dist/controllers/turbo/index.js +3 -0
- package/dist/controllers/turbo/turbo_frame_history_controller.js +27 -0
- package/dist/controllers/turbo/turbo_frame_rc_controller.js +65 -0
- package/dist/controllers/turbo/turbo_frame_refresh_controller.js +33 -0
- package/dist/controllers/visual/countdown_controller.js +13 -7
- package/dist/controllers/visual/tween_number_controller.js +16 -2
- package/dist/mixins/use_resize_observer.js +9 -0
- package/package.json +6 -6
- package/dist/controllers/forms/disable_inputs_controller.js +0 -21
- package/dist/controllers/media/fallback_iframe_controller.js +0 -44
- package/dist/controllers/signal/signal_attribute_sync_controller.js +0 -10
- package/dist/controllers/signal/signal_content_sync_controller.js +0 -9
- package/dist/controllers/tables/table_filter_controller.js +0 -53
package/README.md
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
# Stimulus-Library
|
|
2
|
-
|
|
3
|
-
[Documentation](https://sub-xaero.github.io/stimulus-library/) | [Full List of Controllers](https://sub-xaero.github.io/stimulus-library/)
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-

|
|
7
|
-

|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## Installation
|
|
11
|
-
|
|
12
|
-
To get started, you'll need to add the `stimulus-library` package to your project.
|
|
13
|
-
|
|
14
|
-
To do so, either add `stimulus-library` to your package.json manually
|
|
15
|
-
|
|
16
|
-
```json
|
|
17
|
-
{
|
|
18
|
-
"dependencies": {
|
|
19
|
-
"stimulus-library": "latest"
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
or run
|
|
25
|
-
`npm install --save stimulus-library` or `yarn add stimulus-library`
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Then, to get started, import and register the controllers you want to use.
|
|
29
|
-
|
|
30
|
-
*Please Note* as below, that when registering the name for the controller, you should use `kebab-case` and omit the `-controller` suffix.
|
|
31
|
-
|
|
32
|
-
```js
|
|
33
|
-
import { Application } from "@hotwired/stimulus";
|
|
34
|
-
import { AutoSubmitFormController } from "stimulus-library";
|
|
35
|
-
|
|
36
|
-
const application = Application.start();
|
|
37
|
-
application.register("auto-submit-form", AutoSubmitFormController);
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Tree-shaking
|
|
41
|
-
If you use the ESM builds of the library, this library fully supports tree-shaking,
|
|
42
|
-
only the controllers you directly import will be bundled with your application.
|
|
43
|
-
|
|
1
|
+
# Stimulus-Library
|
|
2
|
+
|
|
3
|
+
[Documentation](https://sub-xaero.github.io/stimulus-library/) | [Full List of Controllers](https://sub-xaero.github.io/stimulus-library/)
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
To get started, you'll need to add the `stimulus-library` package to your project.
|
|
13
|
+
|
|
14
|
+
To do so, either add `stimulus-library` to your package.json manually
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"stimulus-library": "latest"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
or run
|
|
25
|
+
`npm install --save stimulus-library` or `yarn add stimulus-library`
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
Then, to get started, import and register the controllers you want to use.
|
|
29
|
+
|
|
30
|
+
*Please Note* as below, that when registering the name for the controller, you should use `kebab-case` and omit the `-controller` suffix.
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
import { Application } from "@hotwired/stimulus";
|
|
34
|
+
import { AutoSubmitFormController } from "stimulus-library";
|
|
35
|
+
|
|
36
|
+
const application = Application.start();
|
|
37
|
+
application.register("auto-submit-form", AutoSubmitFormController);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Tree-shaking
|
|
41
|
+
If you use the ESM builds of the library, this library fully supports tree-shaking,
|
|
42
|
+
only the controllers you directly import will be bundled with your application.
|
|
43
|
+
|
|
@@ -5,6 +5,7 @@ export * from './media';
|
|
|
5
5
|
export * from './scroll';
|
|
6
6
|
export * from './signal';
|
|
7
7
|
export * from './tables';
|
|
8
|
+
export * from './turbo';
|
|
8
9
|
export * from './utility';
|
|
9
10
|
export * from './visual';
|
|
10
11
|
// Controllers
|
|
@@ -30,5 +31,3 @@ export * from './teleport_controller';
|
|
|
30
31
|
export * from './temporary_state_controller';
|
|
31
32
|
export * from './toggle_class_controller';
|
|
32
33
|
export * from './trix_modifier_controller';
|
|
33
|
-
export * from './turbo_frame_rc_controller';
|
|
34
|
-
export * from './turbo_frame_refresh_controller';
|
|
@@ -78,8 +78,8 @@ export class TableSortController extends BaseController {
|
|
|
78
78
|
let cells = Array.from(row.cells);
|
|
79
79
|
let otherCells = Array.from(otherRow.cells);
|
|
80
80
|
// TODO: Handle colspans?
|
|
81
|
-
let x = cells[index]?.innerText || "";
|
|
82
|
-
let y = otherCells[index]?.innerText || "";
|
|
81
|
+
let x = cells[index]?.dataset?.sortValue || cells[index]?.innerText || "";
|
|
82
|
+
let y = otherCells[index]?.dataset?.sortValue || otherCells[index]?.innerText || "";
|
|
83
83
|
let sortVal = x.localeCompare(y, "en", { sensitivity: "base", numeric: true, caseFirst: "upper" });
|
|
84
84
|
if (row.dataset.sortTop || otherRow.dataset.sortBottom) {
|
|
85
85
|
if (row.dataset.sortTop && otherRow.dataset.sortTop) {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { BaseController } from "../../utilities";
|
|
2
|
+
import { useMutationObserver } from "../../mixins";
|
|
3
|
+
export default class TurboFrameHistoryController extends BaseController {
|
|
4
|
+
initialize() {
|
|
5
|
+
this.mutate = this.mutate.bind(this);
|
|
6
|
+
}
|
|
7
|
+
connect() {
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
if (!window.Turbo) {
|
|
10
|
+
throw new Error('Expected Turbo to be defined on the window.');
|
|
11
|
+
}
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
const { navigator } = window.Turbo;
|
|
14
|
+
this.navigator = navigator;
|
|
15
|
+
useMutationObserver(this, this.el, this.mutate, { attributes: true });
|
|
16
|
+
}
|
|
17
|
+
mutate(entries) {
|
|
18
|
+
entries.forEach((mutation) => {
|
|
19
|
+
if (mutation.type === 'attributes' && mutation.attributeName === 'src') {
|
|
20
|
+
const src = this.element.getAttribute('src');
|
|
21
|
+
if (src != null) {
|
|
22
|
+
this.navigator.history.push(new URL(src));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { BaseController } from "../../utilities/base_controller";
|
|
2
|
+
import { isHTMLAnchorElement } from "../../utilities/elements";
|
|
3
|
+
import { isTurboFrame } from "../../utilities/turbo";
|
|
4
|
+
export class TurboFrameRCController extends BaseController {
|
|
5
|
+
static values = {
|
|
6
|
+
frameId: String,
|
|
7
|
+
src: String,
|
|
8
|
+
loadingMessage: String,
|
|
9
|
+
};
|
|
10
|
+
toggle(event) {
|
|
11
|
+
event?.preventDefault();
|
|
12
|
+
let frame = this._getFrame();
|
|
13
|
+
let frameSrc = frame.src;
|
|
14
|
+
if (frameSrc == null || frameSrc !== this._getSrc()) {
|
|
15
|
+
this._setSrc();
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
this._clear();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
setSrc(event) {
|
|
22
|
+
event?.preventDefault();
|
|
23
|
+
this._setSrc();
|
|
24
|
+
}
|
|
25
|
+
clear(event) {
|
|
26
|
+
event?.preventDefault();
|
|
27
|
+
this._clear();
|
|
28
|
+
}
|
|
29
|
+
_setSrc() {
|
|
30
|
+
let frame = this._getFrame();
|
|
31
|
+
if (this.hasLoadingMessageValue) {
|
|
32
|
+
frame.innerHTML = this.loadingMessageValue;
|
|
33
|
+
}
|
|
34
|
+
frame.src = this._getSrc();
|
|
35
|
+
}
|
|
36
|
+
_clear() {
|
|
37
|
+
let frame = this._getFrame();
|
|
38
|
+
frame.src = "";
|
|
39
|
+
frame.innerHTML = "";
|
|
40
|
+
}
|
|
41
|
+
_getFrame() {
|
|
42
|
+
let frame = document.getElementById(`${this.frameIdValue}`);
|
|
43
|
+
if (frame == null) {
|
|
44
|
+
throw new Error(`Could not find frame with ID '${this.frameIdValue}'`);
|
|
45
|
+
}
|
|
46
|
+
if (!isTurboFrame(frame)) {
|
|
47
|
+
throw new Error(`Element targeted by ID '${this.frameIdValue}'`);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
return frame;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
_getSrc() {
|
|
54
|
+
let element = this.el;
|
|
55
|
+
if (this.hasSrcValue) {
|
|
56
|
+
return this.srcValue;
|
|
57
|
+
}
|
|
58
|
+
else if (isHTMLAnchorElement(element)) {
|
|
59
|
+
return element.href;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
throw new Error("No link given to drive frame to");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { BaseController } from "../../utilities/base_controller";
|
|
2
|
+
import { isTurboFrame } from "../../utilities/turbo";
|
|
3
|
+
import { useTimeout } from "../../mixins/use_timeout";
|
|
4
|
+
// noinspection SillyAssignmentJS
|
|
5
|
+
export class TurboFrameRefreshController extends BaseController {
|
|
6
|
+
static values = {
|
|
7
|
+
interval: Number,
|
|
8
|
+
poll: Boolean,
|
|
9
|
+
};
|
|
10
|
+
get _poll() {
|
|
11
|
+
return this.hasPollValue ? this.pollValue : false;
|
|
12
|
+
}
|
|
13
|
+
connect() {
|
|
14
|
+
let element = this.el;
|
|
15
|
+
if (isTurboFrame(element)) {
|
|
16
|
+
if (!!element.src) {
|
|
17
|
+
throw new Error('The provided <turbo-frame> element has no `src` attribute.');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
throw new Error('Expected controller to be mounted on a <turbo-frame> element.');
|
|
22
|
+
}
|
|
23
|
+
if (this._poll) {
|
|
24
|
+
requestAnimationFrame(() => useTimeout(this, this.refresh, this.intervalValue));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
refresh(event) {
|
|
28
|
+
event?.preventDefault();
|
|
29
|
+
let element = this.el;
|
|
30
|
+
// @ts-ignore
|
|
31
|
+
element.reload();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -7,15 +7,19 @@ export class CountdownController extends BaseController {
|
|
|
7
7
|
static targets = ["years", "months", "days", "hours", "minutes", "seconds"];
|
|
8
8
|
static classes = ["countingDown", "ended"];
|
|
9
9
|
// Instance Data
|
|
10
|
-
|
|
10
|
+
_timeout = null;
|
|
11
11
|
get _removeUnused() {
|
|
12
12
|
return this.hasRemoveUnusedValue ? this.removeUnusedValue : false;
|
|
13
13
|
}
|
|
14
14
|
get _deadlineDate() {
|
|
15
15
|
return new Date(this.deadlineValue);
|
|
16
16
|
}
|
|
17
|
+
initialize() {
|
|
18
|
+
this._tick = this._tick.bind(this);
|
|
19
|
+
}
|
|
17
20
|
connect() {
|
|
18
|
-
this.
|
|
21
|
+
this._timeout = setTimeout(this._tick, 1000);
|
|
22
|
+
console.log(this._timeout);
|
|
19
23
|
installClassMethods(this);
|
|
20
24
|
this.addCountingDownClasses();
|
|
21
25
|
}
|
|
@@ -26,8 +30,8 @@ export class CountdownController extends BaseController {
|
|
|
26
30
|
}
|
|
27
31
|
deadlineValueChanged() {
|
|
28
32
|
// Countdown had previously ended, restart ticking. Updating mid-tick will just work.
|
|
29
|
-
if (this.
|
|
30
|
-
this.
|
|
33
|
+
if (this._timeout == null) {
|
|
34
|
+
this._timeout = setTimeout(this._tick, 1000);
|
|
31
35
|
}
|
|
32
36
|
}
|
|
33
37
|
_tick() {
|
|
@@ -41,9 +45,11 @@ export class CountdownController extends BaseController {
|
|
|
41
45
|
this.removeCountingDownClasses();
|
|
42
46
|
this.addEndedClasses();
|
|
43
47
|
this.dispatchEvent(this.el, "countdown:ended");
|
|
48
|
+
return;
|
|
44
49
|
}
|
|
45
50
|
else {
|
|
46
51
|
distance = intervalToDuration({ start: this._deadlineDate, end: now });
|
|
52
|
+
this._timeout = setTimeout(this._tick, 1000);
|
|
47
53
|
}
|
|
48
54
|
if (this.hasYearsTarget) {
|
|
49
55
|
this._updateTarget(this.yearsTarget, this._years(distance));
|
|
@@ -70,9 +76,9 @@ export class CountdownController extends BaseController {
|
|
|
70
76
|
}
|
|
71
77
|
}
|
|
72
78
|
_clearTick() {
|
|
73
|
-
if (this.
|
|
74
|
-
|
|
75
|
-
this.
|
|
79
|
+
if (this._timeout) {
|
|
80
|
+
clearTimeout(this._timeout);
|
|
81
|
+
this._timeout = null;
|
|
76
82
|
}
|
|
77
83
|
}
|
|
78
84
|
_updateTarget(target, value) {
|
|
@@ -8,6 +8,10 @@ export class TweenNumberController extends BaseController {
|
|
|
8
8
|
duration: Number,
|
|
9
9
|
easing: String,
|
|
10
10
|
};
|
|
11
|
+
observer;
|
|
12
|
+
observe;
|
|
13
|
+
unobserve;
|
|
14
|
+
teardownObserver;
|
|
11
15
|
get start() {
|
|
12
16
|
if (this.hasStartValue) {
|
|
13
17
|
return this.startValue;
|
|
@@ -42,7 +46,11 @@ export class TweenNumberController extends BaseController {
|
|
|
42
46
|
return EasingFunctions[str] || fallback;
|
|
43
47
|
}
|
|
44
48
|
connect() {
|
|
45
|
-
useIntersection(this, this.el, this.appear);
|
|
49
|
+
let { observer, observe, unobserve, teardown, } = useIntersection(this, this.el, this.appear);
|
|
50
|
+
this.observer = observer;
|
|
51
|
+
this.observe = observe;
|
|
52
|
+
this.unobserve = unobserve;
|
|
53
|
+
this.teardownObserver = teardown;
|
|
46
54
|
}
|
|
47
55
|
appear(_entry) {
|
|
48
56
|
this.tween();
|
|
@@ -50,16 +58,22 @@ export class TweenNumberController extends BaseController {
|
|
|
50
58
|
;
|
|
51
59
|
tween() {
|
|
52
60
|
let startTimestamp = null;
|
|
61
|
+
let self = this;
|
|
53
62
|
const step = (timestamp) => {
|
|
54
63
|
if (!startTimestamp) {
|
|
55
64
|
startTimestamp = timestamp;
|
|
56
65
|
}
|
|
57
66
|
const elapsed = timestamp - startTimestamp;
|
|
58
67
|
const progress = Math.min(elapsed / this.durationMs, 1);
|
|
59
|
-
this.element.innerHTML =
|
|
68
|
+
this.element.innerHTML =
|
|
69
|
+
Math.floor(this.easingFunction(progress) * (this.end - this.start) + this.start).toString();
|
|
60
70
|
if (progress < 1) {
|
|
61
71
|
requestAnimationFrame(step);
|
|
62
72
|
}
|
|
73
|
+
else {
|
|
74
|
+
self.unobserve?.();
|
|
75
|
+
self.teardownObserver?.();
|
|
76
|
+
}
|
|
63
77
|
};
|
|
64
78
|
requestAnimationFrame(step);
|
|
65
79
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useMixin } from "./create_mixin";
|
|
2
|
+
export function useResizeObserver(controller, element, handler, options) {
|
|
3
|
+
handler = handler.bind(controller);
|
|
4
|
+
let observer = new ResizeObserver(handler);
|
|
5
|
+
let setup = () => observer.observe(element, options);
|
|
6
|
+
let teardown = () => observer.disconnect();
|
|
7
|
+
useMixin(controller, setup, teardown);
|
|
8
|
+
return teardown;
|
|
9
|
+
}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"ruby on rails",
|
|
10
10
|
"ruby-on-rails"
|
|
11
11
|
],
|
|
12
|
-
"version": "0.9.
|
|
12
|
+
"version": "0.9.7",
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"author": {
|
|
15
15
|
"name": "Sub-Xaero",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"test:treeshake": "agadoo dist"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@babel/runtime": "^7.20.
|
|
37
|
+
"@babel/runtime": "^7.20.13",
|
|
38
38
|
"@hotwired/stimulus": "^3.2.1",
|
|
39
39
|
"date-fns": "^2.29.3",
|
|
40
40
|
"dialog-polyfill": "^0.5.6",
|
|
@@ -46,11 +46,11 @@
|
|
|
46
46
|
"@types/lodash-es": "^4.17.6",
|
|
47
47
|
"@types/smoothscroll-polyfill": "^0.3.1",
|
|
48
48
|
"agadoo": "^3.0.0",
|
|
49
|
-
"cypress": "^12.1
|
|
49
|
+
"cypress": "^12.5.1",
|
|
50
50
|
"fast-glob": "^3.2.12",
|
|
51
|
-
"rimraf": "^
|
|
51
|
+
"rimraf": "^4.1.2",
|
|
52
52
|
"standard-version": "^9.5.0",
|
|
53
|
-
"typescript": "^4.
|
|
54
|
-
"vite": "^4.
|
|
53
|
+
"typescript": "^4.9.5",
|
|
54
|
+
"vite": "^4.1.1"
|
|
55
55
|
}
|
|
56
56
|
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { BaseController } from "../../utilities/base_controller";
|
|
2
|
-
export class DisableInputsController extends BaseController {
|
|
3
|
-
connect() {
|
|
4
|
-
}
|
|
5
|
-
disable() {
|
|
6
|
-
let shouldClear = this.hasClearValue && this.clearValue;
|
|
7
|
-
this.inputTargets.forEach((el, _) => {
|
|
8
|
-
if (shouldClear) {
|
|
9
|
-
el.value = "";
|
|
10
|
-
}
|
|
11
|
-
el.disabled = true;
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
enable() {
|
|
15
|
-
this.inputTargets.forEach((el, _) => el.disabled = false);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
DisableInputsController.targets = ["input"];
|
|
19
|
-
DisableInputsController.values = {
|
|
20
|
-
clear: Boolean,
|
|
21
|
-
};
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { BaseController } from "../../utilities/base_controller";
|
|
2
|
-
export class FallbackImageController extends BaseController {
|
|
3
|
-
initialize() {
|
|
4
|
-
this._hasLoadedSuccessfully = this._hasLoadedSuccessfully.bind(this);
|
|
5
|
-
this._success = this._success.bind(this);
|
|
6
|
-
this._fail = this._fail.bind(this);
|
|
7
|
-
}
|
|
8
|
-
connect() {
|
|
9
|
-
let element = this.el;
|
|
10
|
-
element.onerror = this._fail;
|
|
11
|
-
if (element.complete && !this._hasLoadedSuccessfully()) {
|
|
12
|
-
this._fail();
|
|
13
|
-
}
|
|
14
|
-
else {
|
|
15
|
-
this._success();
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
disconnect() {
|
|
19
|
-
this.removeSuccessClasses();
|
|
20
|
-
this.removeFailClasses();
|
|
21
|
-
}
|
|
22
|
-
_success() {
|
|
23
|
-
this.addSuccessClasses();
|
|
24
|
-
}
|
|
25
|
-
_fail() {
|
|
26
|
-
let element = this.el;
|
|
27
|
-
this.addFailClasses();
|
|
28
|
-
if (this.hasPlaceholderValue && element.src !== this.placeholderValue) {
|
|
29
|
-
this.dispatchEvent(element, this.eventName("placeholder"));
|
|
30
|
-
element.src = this.placeholderValue;
|
|
31
|
-
element.onerror = this._fail;
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
this.dispatchEvent(element, this.eventName("fail"));
|
|
35
|
-
element.style.display = "none";
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
_hasLoadedSuccessfully() {
|
|
39
|
-
let element = this.el;
|
|
40
|
-
return element.naturalHeight > 0 && element.naturalWidth > 0;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
FallbackImageController.values = { placeholder: String };
|
|
44
|
-
FallbackImageController.classes = ["success", "fail"];
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { SignalBaseController } from "./base_controller";
|
|
2
|
-
export class SignalAttributeSyncController extends SignalBaseController {
|
|
3
|
-
_onSignal(payload) {
|
|
4
|
-
this.el.setAttribute(this.attributeValue, payload.value);
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
SignalAttributeSyncController.values = {
|
|
8
|
-
name: String,
|
|
9
|
-
attribute: String,
|
|
10
|
-
};
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { BaseController } from "../../utilities/base_controller";
|
|
2
|
-
import { useMutationObserver } from "../../mixins/use_mutation_observer";
|
|
3
|
-
export class TableFilterController extends BaseController {
|
|
4
|
-
get _tableBody() {
|
|
5
|
-
return this.el.tBodies[0];
|
|
6
|
-
}
|
|
7
|
-
get _tableRows() {
|
|
8
|
-
return Array.from(this._tableBody.rows);
|
|
9
|
-
}
|
|
10
|
-
connect() {
|
|
11
|
-
useMutationObserver(this, this._tableBody, this.mutate, { childList: true });
|
|
12
|
-
requestAnimationFrame(() => {
|
|
13
|
-
this.filter();
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
filter(event) {
|
|
17
|
-
event === null || event === void 0 ? void 0 : event.preventDefault();
|
|
18
|
-
if (this.searchValue == "") {
|
|
19
|
-
this._tableRows.forEach((row) => this._showElement(row));
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
let filter = this.searchValue.toLocaleUpperCase();
|
|
23
|
-
this._tableRows.forEach((row) => {
|
|
24
|
-
this.columns(row).forEach((col) => {
|
|
25
|
-
let text = col.textContent || col.innerText;
|
|
26
|
-
if (text.includes(filter)) {
|
|
27
|
-
this._showElement(row);
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
this._hideElement(row);
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
clear() {
|
|
36
|
-
this.searchValue = "";
|
|
37
|
-
}
|
|
38
|
-
columns(row) {
|
|
39
|
-
return Array.from(row.cells);
|
|
40
|
-
}
|
|
41
|
-
mutate(entries) {
|
|
42
|
-
this.filter();
|
|
43
|
-
}
|
|
44
|
-
_showElement(el) {
|
|
45
|
-
el.style.display = "";
|
|
46
|
-
}
|
|
47
|
-
_hideElement(el) {
|
|
48
|
-
el.style.display = "none";
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
TableFilterController.values = {
|
|
52
|
-
search: String,
|
|
53
|
-
};
|