@peckadesign/pd-naja 1.5.2 → 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/README.md +34 -0
- package/dist/PdNaja.esm.js +296 -53
- package/dist/PdNaja.esm.js.map +1 -1
- package/dist/{utils → classes}/ControlManager.d.ts +5 -3
- package/dist/classes/Suggest.d.ts +34 -0
- package/dist/extensions/BtnSpinnerExtension.d.ts +5 -9
- package/dist/extensions/ScrollToExtension.d.ts +16 -0
- package/dist/extensions/SpinnerExtension.d.ts +5 -7
- package/dist/extensions/SuggestExtension.d.ts +18 -0
- package/dist/extensions/ToggleClassExtension.d.ts +19 -0
- package/dist/index.esm.d.ts +6 -3
- package/dist/index.esm.js +296 -53
- package/dist/index.esm.js.map +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/utils.d.ts +3 -0
- package/package.json +2 -4
- package/src/{utils → classes}/ControlManager.ts +10 -8
- package/src/classes/Suggest.ts +215 -0
- package/src/extensions/BtnSpinnerExtension.ts +10 -32
- package/src/extensions/ScrollToExtension.ts +48 -0
- package/src/extensions/SpinnerExtension.ts +9 -24
- package/src/extensions/SuggestExtension.ts +66 -0
- package/src/extensions/ToggleClassExtension.ts +61 -0
- package/src/extensions/ViewTransitionExtension.txt +32 -0
- package/src/index.esm.ts +6 -4
- package/src/{utils/Control.ts → types.ts} +9 -2
- package/src/utils.ts +22 -0
- package/dist/utils/Control.d.ts +0 -4
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { SpinnerPropsFn, SpinnerType } from '../types';
|
|
2
|
+
type SuggestOptions = {
|
|
3
|
+
minLength: number;
|
|
4
|
+
timeout: number;
|
|
5
|
+
};
|
|
6
|
+
export declare class Suggest {
|
|
7
|
+
readonly spinner?: SpinnerType;
|
|
8
|
+
readonly getSpinnerProps?: SpinnerPropsFn;
|
|
9
|
+
static readonly className = "js-suggest";
|
|
10
|
+
readonly inputClassName: string;
|
|
11
|
+
readonly buttonClassName: string;
|
|
12
|
+
readonly suggestClassName: string;
|
|
13
|
+
readonly linkClassName: string;
|
|
14
|
+
private readonly form;
|
|
15
|
+
private readonly input;
|
|
16
|
+
private readonly button;
|
|
17
|
+
private readonly suggest;
|
|
18
|
+
private suggestSpinner;
|
|
19
|
+
private isOpen;
|
|
20
|
+
private timer;
|
|
21
|
+
private lastSearched;
|
|
22
|
+
private readonly options;
|
|
23
|
+
constructor(form: HTMLFormElement, options?: Partial<SuggestOptions>, spinner?: SpinnerType | undefined, getSpinnerProps?: SpinnerPropsFn);
|
|
24
|
+
private isEmpty;
|
|
25
|
+
private showSuggest;
|
|
26
|
+
private hideSuggest;
|
|
27
|
+
private emptySuggest;
|
|
28
|
+
startSuggest(): void;
|
|
29
|
+
finishSuggest(): void;
|
|
30
|
+
private handleInputKeydown;
|
|
31
|
+
private handleInputKeyup;
|
|
32
|
+
private handleSuggestMousedown;
|
|
33
|
+
}
|
|
34
|
+
export {};
|
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
import { Extension, Naja } from 'naja/dist/Naja';
|
|
2
|
+
import { SpinnerPropsFn, SpinnerType, WithSpinner } from '../types';
|
|
2
3
|
declare module 'naja/dist/Naja' {
|
|
3
4
|
interface Options {
|
|
4
5
|
btnSpinnerInitiator?: Element;
|
|
5
6
|
btnSpinner?: Element;
|
|
6
7
|
}
|
|
7
8
|
}
|
|
8
|
-
|
|
9
|
-
type spinnerPropsFn = ((initiator: Element) => any) | undefined;
|
|
10
|
-
export declare class BtnSpinnerExtension implements Extension {
|
|
9
|
+
export declare class BtnSpinnerExtension implements Extension, WithSpinner {
|
|
11
10
|
readonly timeout: number;
|
|
12
|
-
readonly spinner:
|
|
13
|
-
readonly getSpinnerProps
|
|
14
|
-
constructor(spinner:
|
|
11
|
+
readonly spinner: SpinnerType;
|
|
12
|
+
readonly getSpinnerProps: SpinnerPropsFn;
|
|
13
|
+
constructor(spinner: SpinnerType, getSpinnerProps?: SpinnerPropsFn, timeout?: number);
|
|
15
14
|
initialize(naja: Naja): void;
|
|
16
15
|
private checkExtensionEnabled;
|
|
17
16
|
private handleStartEvent;
|
|
18
17
|
private handleCompleteEvent;
|
|
19
|
-
private showSpinner;
|
|
20
|
-
private hideSpinner;
|
|
21
18
|
}
|
|
22
|
-
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Extension, Naja } from 'naja/dist/Naja';
|
|
2
|
+
type NajaScrollToEvent = 'before' | 'success';
|
|
3
|
+
declare module 'naja/dist/Naja' {
|
|
4
|
+
interface Options {
|
|
5
|
+
scrollToEvent?: NajaScrollToEvent;
|
|
6
|
+
scrollToSelector?: string;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export declare class ScrollToExtension implements Extension {
|
|
10
|
+
defaultScrollToEvent: NajaScrollToEvent;
|
|
11
|
+
constructor(defaultScrollToEvent?: NajaScrollToEvent);
|
|
12
|
+
initialize(naja: Naja): void;
|
|
13
|
+
private checkExtensionEnabled;
|
|
14
|
+
private checkScroll;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Extension, Naja } from 'naja/dist/Naja';
|
|
2
|
+
import { SpinnerPropsFn, SpinnerType, WithSpinner } from '../types';
|
|
2
3
|
/**
|
|
3
4
|
* @author Radek Šerý
|
|
4
5
|
*
|
|
@@ -17,14 +18,12 @@ declare module 'naja/dist/Naja' {
|
|
|
17
18
|
spinnerInitiator?: Element;
|
|
18
19
|
}
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
readonly spinner: spinnerType;
|
|
24
|
-
readonly getSpinnerProps?: spinnerPropsFn;
|
|
21
|
+
export declare class SpinnerExtension implements Extension, WithSpinner {
|
|
22
|
+
readonly spinner: SpinnerType;
|
|
23
|
+
readonly getSpinnerProps: SpinnerPropsFn;
|
|
25
24
|
readonly ajaxSpinnerWrapSelector: string;
|
|
26
25
|
readonly ajaxSpinnerPlaceholderSelector: string;
|
|
27
|
-
constructor(spinner:
|
|
26
|
+
constructor(spinner: SpinnerType, getSpinnerProps?: SpinnerPropsFn, ajaxSpinnerWrapSelector?: string, ajaxSpinnerPlaceholderSelector?: string);
|
|
28
27
|
initialize(naja: Naja): void;
|
|
29
28
|
private getSpinnerInitiator;
|
|
30
29
|
private showSpinners;
|
|
@@ -33,4 +32,3 @@ export declare class SpinnerExtension implements Extension {
|
|
|
33
32
|
private getPlaceholdersByQuerySelector;
|
|
34
33
|
private getPlaceholdersByDOM;
|
|
35
34
|
}
|
|
36
|
-
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Extension, Naja } from 'naja/dist/Naja';
|
|
2
|
+
import { Suggest } from '../classes/Suggest';
|
|
3
|
+
import { SpinnerPropsFn, SpinnerType } from '../types';
|
|
4
|
+
declare module 'naja/dist/Naja' {
|
|
5
|
+
interface Options {
|
|
6
|
+
suggest?: Suggest;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export declare class SuggestExtension implements Extension {
|
|
10
|
+
private requestQueue;
|
|
11
|
+
readonly spinner: SpinnerType | undefined;
|
|
12
|
+
readonly getSpinnerProps?: SpinnerPropsFn;
|
|
13
|
+
constructor(spinner?: SpinnerType | undefined, getSpinnerProps?: SpinnerPropsFn);
|
|
14
|
+
initialize(naja: Naja): void;
|
|
15
|
+
private checkExtensionEnabled;
|
|
16
|
+
private start;
|
|
17
|
+
private complete;
|
|
18
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Extension, Naja } from 'naja/dist/Naja';
|
|
2
|
+
type ToggleClassRecord = Record<string, string>;
|
|
3
|
+
type ToggleClassOptions = {
|
|
4
|
+
element: Element;
|
|
5
|
+
toggleClass: ToggleClassRecord;
|
|
6
|
+
};
|
|
7
|
+
declare module 'naja/dist/Naja' {
|
|
8
|
+
interface Options {
|
|
9
|
+
toggleClassOptions?: ToggleClassOptions;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export declare class ToggleClassExtension implements Extension {
|
|
13
|
+
initialize(naja: Naja): void;
|
|
14
|
+
private checkExtensionEnabled;
|
|
15
|
+
private start;
|
|
16
|
+
private complete;
|
|
17
|
+
private applyToggleClass;
|
|
18
|
+
}
|
|
19
|
+
export {};
|
package/dist/index.esm.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
export { ControlManager } from './classes/ControlManager';
|
|
2
|
+
export { Suggest } from './classes/Suggest';
|
|
2
3
|
export { AjaxModalExtension } from './extensions/AjaxModalExtension';
|
|
3
4
|
export { AjaxModalPreventRedrawExtension } from './extensions/AjaxModalPreventRedrawExtension';
|
|
4
5
|
export { AjaxOnceExtension } from './extensions/AjaxOnceExtension';
|
|
@@ -7,8 +8,10 @@ export { ConfirmExtension } from './extensions/ConfirmExtension';
|
|
|
7
8
|
export { FollowUpRequestExtension } from './extensions/FollowUpRequestExtension';
|
|
8
9
|
export { ForceRedirectExtension } from './extensions/ForceRedirectExtension';
|
|
9
10
|
export { ForceReplaceExtension } from './extensions/ForceReplaceExtension';
|
|
11
|
+
export { ScrollToExtension } from './extensions/ScrollToExtension';
|
|
10
12
|
export { SingleSubmitExtension } from './extensions/SingleSubmitExtension';
|
|
11
13
|
export { SnippetFormPartExtension } from './extensions/SnippetFormPartExtension';
|
|
12
14
|
export { SpinnerExtension } from './extensions/SpinnerExtension';
|
|
13
|
-
export {
|
|
14
|
-
export
|
|
15
|
+
export { SuggestExtension } from './extensions/SuggestExtension';
|
|
16
|
+
export { ToggleClassExtension } from './extensions/ToggleClassExtension';
|
|
17
|
+
export { isDatasetFalsy, isDatasetTruthy, showSpinner, hideSpinner } from './utils';
|
package/dist/index.esm.js
CHANGED
|
@@ -5,21 +5,20 @@
|
|
|
5
5
|
* @author PeckaDesign, s.r.o <support@peckadesign.cz>
|
|
6
6
|
* @license MIT
|
|
7
7
|
*
|
|
8
|
-
* @version
|
|
8
|
+
* @version 2.0.0
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import naja from 'naja';
|
|
12
|
-
|
|
13
11
|
let instance = null;
|
|
14
12
|
class ControlManager {
|
|
15
|
-
constructor() {
|
|
13
|
+
constructor(naja) {
|
|
16
14
|
this.onLoadControl = [];
|
|
17
15
|
this.onLiveControl = [];
|
|
18
16
|
if (instance === null) {
|
|
19
17
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
20
18
|
instance = this;
|
|
21
|
-
naja
|
|
22
|
-
naja.snippetHandler.addEventListener('
|
|
19
|
+
this.naja = naja;
|
|
20
|
+
this.naja.snippetHandler.addEventListener('beforeUpdate', this.onBeforeSnippetUpdate.bind(this));
|
|
21
|
+
this.naja.snippetHandler.addEventListener('afterUpdate', this.onSnippetUpdate.bind(this));
|
|
23
22
|
}
|
|
24
23
|
return instance;
|
|
25
24
|
}
|
|
@@ -28,8 +27,8 @@ class ControlManager {
|
|
|
28
27
|
this.initialize(this.onLiveControl);
|
|
29
28
|
}
|
|
30
29
|
onBeforeSnippetUpdate(event) {
|
|
31
|
-
if (event.detail.operation === naja.snippetHandler.op.append ||
|
|
32
|
-
event.detail.operation === naja.snippetHandler.op.prepend) {
|
|
30
|
+
if (event.detail.operation === this.naja.snippetHandler.op.append ||
|
|
31
|
+
event.detail.operation === this.naja.snippetHandler.op.prepend) {
|
|
33
32
|
return;
|
|
34
33
|
}
|
|
35
34
|
this.destroy(this.onLiveControl, event.detail.snippet);
|
|
@@ -57,6 +56,180 @@ class ControlManager {
|
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
58
|
|
|
59
|
+
function showSpinner(target, initiator = target) {
|
|
60
|
+
let spinner;
|
|
61
|
+
if (typeof this.spinner === 'function') {
|
|
62
|
+
spinner = this.getSpinnerProps ? this.spinner(this.getSpinnerProps(initiator)) : this.spinner();
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
spinner = this.spinner;
|
|
66
|
+
}
|
|
67
|
+
target.appendChild(spinner);
|
|
68
|
+
spinner.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 100 });
|
|
69
|
+
return spinner;
|
|
70
|
+
}
|
|
71
|
+
function hideSpinner(spinner) {
|
|
72
|
+
const animation = spinner.animate({ opacity: 0 }, { duration: 100 });
|
|
73
|
+
animation.finished.then(() => spinner?.remove());
|
|
74
|
+
}
|
|
75
|
+
const isDatasetTruthy = (element, datasetName) => {
|
|
76
|
+
const datasetValue = element.dataset[datasetName];
|
|
77
|
+
return datasetValue !== undefined && datasetValue !== 'false' && datasetValue !== 'off';
|
|
78
|
+
};
|
|
79
|
+
const isDatasetFalsy = (element, datasetName) => {
|
|
80
|
+
const datasetValue = element.dataset[datasetName];
|
|
81
|
+
return datasetValue === 'off' || datasetValue === 'false';
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
class Suggest {
|
|
85
|
+
constructor(form, options = {}, spinner = undefined, getSpinnerProps = undefined) {
|
|
86
|
+
this.inputClassName = `${Suggest.className}__input`;
|
|
87
|
+
this.buttonClassName = `${Suggest.className}__btn`;
|
|
88
|
+
this.suggestClassName = `${Suggest.className}__suggest`;
|
|
89
|
+
this.linkClassName = `${Suggest.className}__link`;
|
|
90
|
+
this.isOpen = false;
|
|
91
|
+
this.timer = undefined;
|
|
92
|
+
this.lastSearched = '';
|
|
93
|
+
this.options = {
|
|
94
|
+
minLength: 2,
|
|
95
|
+
timeout: 200
|
|
96
|
+
};
|
|
97
|
+
this.form = form;
|
|
98
|
+
this.spinner = spinner;
|
|
99
|
+
this.getSpinnerProps = getSpinnerProps;
|
|
100
|
+
const input = form.querySelector(`.${this.inputClassName}`);
|
|
101
|
+
const button = form.querySelector(`.${this.buttonClassName}`);
|
|
102
|
+
const suggest = form.querySelector(`.${this.suggestClassName}`);
|
|
103
|
+
if (!input || !button || !suggest) {
|
|
104
|
+
throw new Error('Suggest: Missing input, button or suggest element.');
|
|
105
|
+
}
|
|
106
|
+
this.input = input;
|
|
107
|
+
this.button = button;
|
|
108
|
+
this.suggest = suggest;
|
|
109
|
+
this.options = { ...this.options, ...options };
|
|
110
|
+
this.input.addEventListener('focus', this.showSuggest.bind(this));
|
|
111
|
+
this.input.addEventListener('blur', this.hideSuggest.bind(this));
|
|
112
|
+
this.input.addEventListener('keydown', this.handleInputKeydown.bind(this));
|
|
113
|
+
this.input.addEventListener('keyup', this.handleInputKeyup.bind(this));
|
|
114
|
+
this.suggest.addEventListener('mousedown', this.handleSuggestMousedown.bind(this));
|
|
115
|
+
this.form._suggest = this;
|
|
116
|
+
}
|
|
117
|
+
isEmpty() {
|
|
118
|
+
return this.suggest.childElementCount === 0;
|
|
119
|
+
}
|
|
120
|
+
showSuggest() {
|
|
121
|
+
if (this.isEmpty() || this.input.value.length < this.options.minLength) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const event = new CustomEvent('show.suggest', { bubbles: true, cancelable: true });
|
|
125
|
+
this.suggest.dispatchEvent(event);
|
|
126
|
+
if (event.defaultPrevented) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
this.isOpen = true;
|
|
130
|
+
this.suggest.classList.add(`${this.suggestClassName}--shown`);
|
|
131
|
+
}
|
|
132
|
+
hideSuggest() {
|
|
133
|
+
const event = new CustomEvent('hide.suggest', { bubbles: true, cancelable: true });
|
|
134
|
+
this.suggest.dispatchEvent(event);
|
|
135
|
+
if (event.defaultPrevented) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
this.isOpen = false;
|
|
139
|
+
this.suggest.classList.remove(`${this.suggestClassName}--shown`);
|
|
140
|
+
}
|
|
141
|
+
emptySuggest() {
|
|
142
|
+
this.suggest.classList.add(`${this.suggestClassName}--empty`);
|
|
143
|
+
this.suggest.replaceChildren();
|
|
144
|
+
}
|
|
145
|
+
startSuggest() {
|
|
146
|
+
this.suggest.dispatchEvent(new CustomEvent('loading.suggest', { bubbles: true }));
|
|
147
|
+
this.input.classList.add(`${this.inputClassName}--loading`);
|
|
148
|
+
if (this.spinner && !this.suggestSpinner) {
|
|
149
|
+
this.suggestSpinner = showSpinner.call(this, this.form);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
finishSuggest() {
|
|
153
|
+
this.suggest.dispatchEvent(new CustomEvent('loaded.suggest', { bubbles: true }));
|
|
154
|
+
this.input.classList.remove(`${this.inputClassName}--loading`);
|
|
155
|
+
this.suggest.classList.toggle(`${this.suggestClassName}--empty`, this.isEmpty());
|
|
156
|
+
if (this.isEmpty() || document.activeElement !== this.input) {
|
|
157
|
+
this.hideSuggest();
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
this.showSuggest();
|
|
161
|
+
}
|
|
162
|
+
if (this.suggestSpinner) {
|
|
163
|
+
hideSpinner(this.suggestSpinner);
|
|
164
|
+
this.suggestSpinner = undefined;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
handleInputKeydown(event) {
|
|
168
|
+
let anchors;
|
|
169
|
+
let activeAnchor;
|
|
170
|
+
let activeAnchorIndex;
|
|
171
|
+
const activeClassName = `${this.linkClassName}--active`;
|
|
172
|
+
switch (event.key) {
|
|
173
|
+
case 'Escape':
|
|
174
|
+
event.preventDefault();
|
|
175
|
+
this.hideSuggest();
|
|
176
|
+
this.input.blur();
|
|
177
|
+
break;
|
|
178
|
+
case 'ArrowDown':
|
|
179
|
+
case 'ArrowUp':
|
|
180
|
+
event.preventDefault();
|
|
181
|
+
anchors = Array.from(this.suggest.querySelectorAll(`.${this.linkClassName}`));
|
|
182
|
+
activeAnchor = anchors.find((element) => element.classList.contains(activeClassName));
|
|
183
|
+
activeAnchorIndex = activeAnchor ? anchors.indexOf(activeAnchor) : undefined;
|
|
184
|
+
activeAnchor?.classList.remove(activeClassName);
|
|
185
|
+
if (event.key === 'ArrowDown') {
|
|
186
|
+
activeAnchorIndex = activeAnchorIndex !== undefined ? activeAnchorIndex + 1 : 0;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
activeAnchorIndex = activeAnchorIndex !== undefined ? activeAnchorIndex - 1 : anchors.length - 1;
|
|
190
|
+
}
|
|
191
|
+
anchors[activeAnchorIndex]?.classList.add(activeClassName);
|
|
192
|
+
break;
|
|
193
|
+
case 'Enter':
|
|
194
|
+
activeAnchor = this.suggest.querySelector(`.${activeClassName}`);
|
|
195
|
+
if (activeAnchor) {
|
|
196
|
+
event.preventDefault();
|
|
197
|
+
event.stopPropagation();
|
|
198
|
+
location.href = activeAnchor.href;
|
|
199
|
+
}
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
handleInputKeyup() {
|
|
204
|
+
clearTimeout(this.timer);
|
|
205
|
+
const query = this.input.value;
|
|
206
|
+
if (query.length < this.options.minLength) {
|
|
207
|
+
this.hideSuggest();
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (!this.isOpen) {
|
|
211
|
+
// If the suggestion wasn't open and this query is different from the last query, we need to clear the
|
|
212
|
+
// results because they are not relevant. This only needs to be done if the suggestion has been closed.
|
|
213
|
+
if (query !== this.lastSearched) {
|
|
214
|
+
this.emptySuggest();
|
|
215
|
+
}
|
|
216
|
+
this.showSuggest();
|
|
217
|
+
}
|
|
218
|
+
// If the query is the same, there's nothing more to do.
|
|
219
|
+
if (query === this.lastSearched) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
this.timer = setTimeout(() => {
|
|
223
|
+
this.lastSearched = query;
|
|
224
|
+
this.button.click();
|
|
225
|
+
}, this.options.timeout);
|
|
226
|
+
}
|
|
227
|
+
handleSuggestMousedown(event) {
|
|
228
|
+
event.preventDefault();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
Suggest.className = 'js-suggest';
|
|
232
|
+
|
|
60
233
|
class AjaxModalExtension {
|
|
61
234
|
constructor(modal) {
|
|
62
235
|
this.uniqueExtKey = 'modal';
|
|
@@ -373,15 +546,6 @@ class AjaxModalPreventRedrawExtension {
|
|
|
373
546
|
}
|
|
374
547
|
}
|
|
375
548
|
|
|
376
|
-
const isDatasetTruthy = (element, datasetName) => {
|
|
377
|
-
const datasetValue = element.dataset[datasetName];
|
|
378
|
-
return datasetValue !== undefined && datasetValue !== 'false' && datasetValue !== 'off';
|
|
379
|
-
};
|
|
380
|
-
const isDatasetFalsy = (element, datasetName) => {
|
|
381
|
-
const datasetValue = element.dataset[datasetName];
|
|
382
|
-
return datasetValue === 'off' || datasetValue === 'false';
|
|
383
|
-
};
|
|
384
|
-
|
|
385
549
|
class AjaxOnceExtension {
|
|
386
550
|
initialize(naja) {
|
|
387
551
|
naja.uiHandler.addEventListener('interaction', this.checkAjaxOnce.bind(this));
|
|
@@ -422,9 +586,9 @@ class BtnSpinnerExtension {
|
|
|
422
586
|
isDatasetTruthy(button, 'noBtnSpinner')) {
|
|
423
587
|
return true;
|
|
424
588
|
}
|
|
425
|
-
const spinner =
|
|
589
|
+
const spinner = showSpinner.call(this, button);
|
|
426
590
|
form.dataset.btnSpinnerTimeout = String(setTimeout(() => {
|
|
427
|
-
|
|
591
|
+
hideSpinner(spinner);
|
|
428
592
|
delete form.dataset.btnSpinnerTimeout;
|
|
429
593
|
}, this.timeout));
|
|
430
594
|
});
|
|
@@ -446,30 +610,14 @@ class BtnSpinnerExtension {
|
|
|
446
610
|
if (!options.btnSpinnerInitiator) {
|
|
447
611
|
return;
|
|
448
612
|
}
|
|
449
|
-
options.btnSpinner =
|
|
613
|
+
options.btnSpinner = showSpinner.call(this, options.btnSpinnerInitiator);
|
|
450
614
|
}
|
|
451
615
|
handleCompleteEvent(event) {
|
|
452
616
|
const { options } = event.detail;
|
|
453
617
|
if (options.forceRedirect || !options.btnSpinner) {
|
|
454
618
|
return;
|
|
455
619
|
}
|
|
456
|
-
|
|
457
|
-
}
|
|
458
|
-
showSpinner(button) {
|
|
459
|
-
let spinner;
|
|
460
|
-
if (typeof this.spinner === 'function') {
|
|
461
|
-
spinner = this.getSpinnerProps ? this.spinner(this.getSpinnerProps(button)) : this.spinner();
|
|
462
|
-
}
|
|
463
|
-
else {
|
|
464
|
-
spinner = this.spinner;
|
|
465
|
-
}
|
|
466
|
-
button.appendChild(spinner);
|
|
467
|
-
spinner.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 100 });
|
|
468
|
-
return spinner;
|
|
469
|
-
}
|
|
470
|
-
hideSpinner(spinner) {
|
|
471
|
-
const animation = spinner.animate({ opacity: 0 }, { duration: 100 });
|
|
472
|
-
animation.finished.then(() => spinner?.remove());
|
|
620
|
+
hideSpinner(options.btnSpinner);
|
|
473
621
|
}
|
|
474
622
|
}
|
|
475
623
|
|
|
@@ -535,6 +683,36 @@ class ForceReplaceExtension {
|
|
|
535
683
|
}
|
|
536
684
|
}
|
|
537
685
|
|
|
686
|
+
class ScrollToExtension {
|
|
687
|
+
constructor(defaultScrollToEvent) {
|
|
688
|
+
this.defaultScrollToEvent = 'before';
|
|
689
|
+
if (defaultScrollToEvent) {
|
|
690
|
+
this.defaultScrollToEvent = defaultScrollToEvent;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
initialize(naja) {
|
|
694
|
+
naja.uiHandler.addEventListener('interaction', this.checkExtensionEnabled.bind(this));
|
|
695
|
+
naja.addEventListener('before', this.checkScroll.bind(this));
|
|
696
|
+
naja.addEventListener('success', this.checkScroll.bind(this));
|
|
697
|
+
}
|
|
698
|
+
checkExtensionEnabled(event) {
|
|
699
|
+
const { element, options } = event.detail;
|
|
700
|
+
const selector = element.getAttribute('data-naja-scroll-to');
|
|
701
|
+
if (selector) {
|
|
702
|
+
const event = element.getAttribute('data-naja-scroll-to-event');
|
|
703
|
+
options.scrollToSelector = selector;
|
|
704
|
+
options.scrollToEvent = event ?? this.defaultScrollToEvent;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
checkScroll(event) {
|
|
708
|
+
const { options } = event.detail;
|
|
709
|
+
if (options.scrollToSelector && event.type === options.scrollToEvent) {
|
|
710
|
+
const scrollToElement = document.querySelector(options.scrollToSelector);
|
|
711
|
+
scrollToElement?.scrollIntoView();
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
538
716
|
class SingleSubmitExtension {
|
|
539
717
|
constructor(buttonDisabledClass, timeout = 60000) {
|
|
540
718
|
this.timeout = 60000;
|
|
@@ -677,16 +855,7 @@ class SpinnerExtension {
|
|
|
677
855
|
else {
|
|
678
856
|
options.spinnerQueue = options.spinnerQueue || [];
|
|
679
857
|
placeholders.forEach((placeholder) => {
|
|
680
|
-
|
|
681
|
-
if (typeof this.spinner === 'function') {
|
|
682
|
-
spinner = this.getSpinnerProps ? this.spinner(this.getSpinnerProps(spinnerInitiator)) : this.spinner();
|
|
683
|
-
}
|
|
684
|
-
else {
|
|
685
|
-
spinner = this.spinner;
|
|
686
|
-
}
|
|
687
|
-
placeholder.appendChild(spinner);
|
|
688
|
-
options.spinnerQueue.push(spinner);
|
|
689
|
-
spinner.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 100 });
|
|
858
|
+
options.spinnerQueue.push(showSpinner.call(this, placeholder, spinnerInitiator));
|
|
690
859
|
});
|
|
691
860
|
}
|
|
692
861
|
}
|
|
@@ -695,10 +864,7 @@ class SpinnerExtension {
|
|
|
695
864
|
if (options.forceRedirect) {
|
|
696
865
|
return;
|
|
697
866
|
}
|
|
698
|
-
options.spinnerQueue?.forEach((spinner) =>
|
|
699
|
-
const animation = spinner.animate({ opacity: 0 }, { duration: 100 });
|
|
700
|
-
animation.finished.then(() => spinner.remove());
|
|
701
|
-
});
|
|
867
|
+
options.spinnerQueue?.forEach((spinner) => hideSpinner(spinner));
|
|
702
868
|
}
|
|
703
869
|
getPlaceholders(element) {
|
|
704
870
|
if (!element) {
|
|
@@ -725,7 +891,84 @@ class SpinnerExtension {
|
|
|
725
891
|
}
|
|
726
892
|
}
|
|
727
893
|
|
|
728
|
-
|
|
894
|
+
class SuggestExtension {
|
|
895
|
+
constructor(spinner = undefined, getSpinnerProps = undefined) {
|
|
896
|
+
this.requestQueue = new Set();
|
|
897
|
+
this.spinner = spinner;
|
|
898
|
+
this.getSpinnerProps = getSpinnerProps;
|
|
899
|
+
const forms = document.querySelectorAll(`.${Suggest.className}`);
|
|
900
|
+
forms.forEach((form) => {
|
|
901
|
+
new Suggest(form, {}, spinner, getSpinnerProps);
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
initialize(naja) {
|
|
905
|
+
naja.uiHandler.addEventListener('interaction', this.checkExtensionEnabled.bind(this));
|
|
906
|
+
naja.addEventListener('start', this.start.bind(this));
|
|
907
|
+
naja.addEventListener('complete', this.complete.bind(this));
|
|
908
|
+
}
|
|
909
|
+
checkExtensionEnabled(event) {
|
|
910
|
+
const { element, options } = event.detail;
|
|
911
|
+
const inputElement = element;
|
|
912
|
+
if (inputElement.form && inputElement.form._suggest) {
|
|
913
|
+
options.suggest = inputElement.form._suggest;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
start(event) {
|
|
917
|
+
const { options, request } = event.detail;
|
|
918
|
+
if (options.suggest) {
|
|
919
|
+
this.requestQueue.add(request);
|
|
920
|
+
options.suggest.startSuggest();
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
complete(event) {
|
|
924
|
+
const { options, request } = event.detail;
|
|
925
|
+
if (!options.suggest) {
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
this.requestQueue.delete(request);
|
|
929
|
+
if (this.requestQueue.size === 0) {
|
|
930
|
+
options.suggest.finishSuggest();
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
class ToggleClassExtension {
|
|
936
|
+
initialize(naja) {
|
|
937
|
+
naja.uiHandler.addEventListener('interaction', this.checkExtensionEnabled.bind(this));
|
|
938
|
+
naja.addEventListener('start', this.start.bind(this));
|
|
939
|
+
naja.addEventListener('complete', this.complete.bind(this));
|
|
940
|
+
}
|
|
941
|
+
checkExtensionEnabled(event) {
|
|
942
|
+
const { element, options } = event.detail;
|
|
943
|
+
const toggleClass = JSON.parse(element.getAttribute('data-naja-toggle-class') || String(null));
|
|
944
|
+
if (toggleClass) {
|
|
945
|
+
options.toggleClassOptions = {
|
|
946
|
+
element,
|
|
947
|
+
toggleClass
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
start(event) {
|
|
952
|
+
const { options } = event.detail;
|
|
953
|
+
if (options.toggleClassOptions) {
|
|
954
|
+
this.applyToggleClass(options.toggleClassOptions);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
complete(event) {
|
|
958
|
+
const { error, options } = event.detail;
|
|
959
|
+
if (error && options.toggleClassOptions) {
|
|
960
|
+
this.applyToggleClass(options.toggleClassOptions);
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
applyToggleClass(toggleClassOptions) {
|
|
964
|
+
for (const [selector, classNames] of Object.entries(toggleClassOptions.toggleClass)) {
|
|
965
|
+
const targets = toggleClassOptions.element.querySelectorAll(selector);
|
|
966
|
+
targets.forEach((target) => {
|
|
967
|
+
classNames.split(' ').forEach((className) => target.classList.toggle(className));
|
|
968
|
+
});
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
}
|
|
729
972
|
|
|
730
|
-
export { AjaxModalExtension, AjaxModalPreventRedrawExtension, AjaxOnceExtension, BtnSpinnerExtension, ConfirmExtension, FollowUpRequestExtension, ForceRedirectExtension, ForceReplaceExtension, SingleSubmitExtension, SnippetFormPartExtension, SpinnerExtension,
|
|
973
|
+
export { AjaxModalExtension, AjaxModalPreventRedrawExtension, AjaxOnceExtension, BtnSpinnerExtension, ConfirmExtension, ControlManager, FollowUpRequestExtension, ForceRedirectExtension, ForceReplaceExtension, ScrollToExtension, SingleSubmitExtension, SnippetFormPartExtension, SpinnerExtension, Suggest, SuggestExtension, ToggleClassExtension, hideSpinner, isDatasetFalsy, isDatasetTruthy, showSpinner };
|
|
731
974
|
//# sourceMappingURL=index.esm.js.map
|