@itrocks/autocomplete 0.1.3 → 0.1.5
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/autocomplete.css +6 -10
- package/autocomplete.d.ts +3 -0
- package/autocomplete.js +43 -28
- package/package.json +1 -1
package/autocomplete.css
CHANGED
|
@@ -1,30 +1,26 @@
|
|
|
1
|
-
.
|
|
2
|
-
display: block;
|
|
3
|
-
}
|
|
4
|
-
.combobox .suggestions {
|
|
1
|
+
.autocomplete + .suggestions {
|
|
5
2
|
background: white;
|
|
6
3
|
border: 1px solid #ddd;
|
|
7
4
|
margin-top: -1px;
|
|
8
5
|
padding: 0;
|
|
9
6
|
position: absolute;
|
|
10
|
-
top: 100%;
|
|
11
7
|
z-index: 1;
|
|
12
8
|
}
|
|
13
|
-
.
|
|
9
|
+
.autocomplete + .suggestions:empty {
|
|
14
10
|
height: 2em;
|
|
15
11
|
width: 50px;
|
|
16
12
|
}
|
|
17
|
-
.
|
|
13
|
+
.autocomplete + .suggestions > * {
|
|
18
14
|
cursor: pointer;
|
|
19
15
|
list-style: none;
|
|
20
16
|
padding: 0.5em 1em;
|
|
21
17
|
}
|
|
22
|
-
.
|
|
18
|
+
.autocomplete + .suggestions > *:hover {
|
|
23
19
|
background: #efe;
|
|
24
20
|
}
|
|
25
|
-
.
|
|
21
|
+
.autocomplete + .suggestions > *.selected {
|
|
26
22
|
background: #edf;
|
|
27
23
|
}
|
|
28
|
-
.
|
|
24
|
+
.autocomplete + .suggestions > *.selected:hover {
|
|
29
25
|
background: #dce;
|
|
30
26
|
}
|
package/autocomplete.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare class AutoComplete {
|
|
|
15
15
|
fetch(): void;
|
|
16
16
|
initIdInput(): HTMLInputElement | undefined;
|
|
17
17
|
initInput(input: HTMLInputElement): HTMLInputElement;
|
|
18
|
+
initParent(): void;
|
|
18
19
|
keyDown(event: Event): void;
|
|
19
20
|
keyEnter(event: Event): void;
|
|
20
21
|
keyEscape(event: Event): void;
|
|
@@ -23,6 +24,8 @@ export declare class AutoComplete {
|
|
|
23
24
|
onInput(event: Event): void;
|
|
24
25
|
onInputValueChange(): void;
|
|
25
26
|
onKeyDown(event: KeyboardEvent): void;
|
|
27
|
+
onTouchStart(event: Event): void;
|
|
28
|
+
openSuggestions(event: Event): boolean;
|
|
26
29
|
select(): void;
|
|
27
30
|
suggest(value?: string): void;
|
|
28
31
|
}
|
package/autocomplete.js
CHANGED
|
@@ -11,9 +11,11 @@ export class AutoComplete {
|
|
|
11
11
|
this.input = this.initInput(input);
|
|
12
12
|
this.idInput = this.initIdInput();
|
|
13
13
|
this.suggestions = new Suggestions(this);
|
|
14
|
+
this.initParent();
|
|
14
15
|
input.addEventListener('blur', event => this.onBlur(event));
|
|
15
16
|
input.addEventListener('keydown', event => this.onKeyDown(event));
|
|
16
17
|
input.addEventListener('input', event => this.onInput(event));
|
|
18
|
+
input.addEventListener('touchstart', event => this.onTouchStart(event));
|
|
17
19
|
}
|
|
18
20
|
autoComplete() {
|
|
19
21
|
if (DEBUG)
|
|
@@ -112,25 +114,20 @@ export class AutoComplete {
|
|
|
112
114
|
input.dataset.lastValue = input.value;
|
|
113
115
|
return input;
|
|
114
116
|
}
|
|
117
|
+
initParent() {
|
|
118
|
+
const parent = this.input.parentElement;
|
|
119
|
+
if (!parent)
|
|
120
|
+
return;
|
|
121
|
+
parent.style.position = 'relative';
|
|
122
|
+
}
|
|
115
123
|
keyDown(event) {
|
|
116
124
|
if (DEBUG)
|
|
117
125
|
console.log('keyDown()');
|
|
118
|
-
|
|
119
|
-
if (!suggestions.length) {
|
|
120
|
-
this.fetch();
|
|
121
|
-
}
|
|
122
|
-
if (!suggestions.isVisible()) {
|
|
123
|
-
if (suggestions.length > 1) {
|
|
124
|
-
event.preventDefault();
|
|
125
|
-
suggestions.show();
|
|
126
|
-
}
|
|
126
|
+
if (this.openSuggestions(event))
|
|
127
127
|
return;
|
|
128
|
-
|
|
129
|
-
event.preventDefault();
|
|
130
|
-
if (suggestions.isLastSelected()) {
|
|
128
|
+
if (this.suggestions.isLastSelected())
|
|
131
129
|
return;
|
|
132
|
-
|
|
133
|
-
this.suggest(suggestions.selectNext()?.caption);
|
|
130
|
+
this.suggest(this.suggestions.selectNext()?.caption);
|
|
134
131
|
}
|
|
135
132
|
keyEnter(event) {
|
|
136
133
|
if (DEBUG)
|
|
@@ -216,7 +213,26 @@ export class AutoComplete {
|
|
|
216
213
|
return this.keyEnter(event);
|
|
217
214
|
}
|
|
218
215
|
}
|
|
216
|
+
onTouchStart(event) {
|
|
217
|
+
this.openSuggestions(event);
|
|
218
|
+
}
|
|
219
|
+
openSuggestions(event) {
|
|
220
|
+
const suggestions = this.suggestions;
|
|
221
|
+
if (!suggestions.length) {
|
|
222
|
+
this.fetch();
|
|
223
|
+
}
|
|
224
|
+
if (suggestions.isVisible()) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
if ((suggestions.length > 1) || (!this.input.value.length && suggestions.length)) {
|
|
228
|
+
event.preventDefault();
|
|
229
|
+
suggestions.show();
|
|
230
|
+
}
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
219
233
|
select() {
|
|
234
|
+
if (DEBUG)
|
|
235
|
+
console.log('select()');
|
|
220
236
|
const suggestions = this.suggestions;
|
|
221
237
|
const suggestion = suggestions.selected();
|
|
222
238
|
if (!suggestion)
|
|
@@ -254,29 +270,22 @@ class Suggestions {
|
|
|
254
270
|
}
|
|
255
271
|
createList() {
|
|
256
272
|
if (DEBUG)
|
|
257
|
-
console.log('
|
|
273
|
+
console.log('createList()');
|
|
258
274
|
const list = this.list = document.createElement('ul');
|
|
259
275
|
list.classList.add('suggestions');
|
|
260
|
-
|
|
261
|
-
const idInput = input.nextElementSibling;
|
|
262
|
-
if ((idInput instanceof HTMLInputElement) && (idInput.type === 'hidden')) {
|
|
263
|
-
input = idInput;
|
|
264
|
-
}
|
|
265
|
-
input.insertAdjacentElement('afterend', list);
|
|
266
|
-
if (DEBUG)
|
|
267
|
-
console.log('Suggestions.prepareClic');
|
|
276
|
+
this.combo.input.insertAdjacentElement('afterend', list);
|
|
268
277
|
list.addEventListener('pointerdown', event => this.onPointerDown(event));
|
|
269
278
|
return list;
|
|
270
279
|
}
|
|
271
280
|
first() {
|
|
272
281
|
if (DEBUG)
|
|
273
|
-
console.log('
|
|
282
|
+
console.log('first()');
|
|
274
283
|
const item = this.list?.firstElementChild ?? null;
|
|
275
284
|
return item && { caption: item.innerText, id: +(item.dataset.id ?? 0) };
|
|
276
285
|
}
|
|
277
286
|
hide() {
|
|
278
287
|
if (DEBUG)
|
|
279
|
-
console.log('
|
|
288
|
+
console.log('hide()');
|
|
280
289
|
const list = this.list;
|
|
281
290
|
if (!list)
|
|
282
291
|
return;
|
|
@@ -297,7 +306,7 @@ class Suggestions {
|
|
|
297
306
|
}
|
|
298
307
|
onPointerDown(event) {
|
|
299
308
|
if (DEBUG)
|
|
300
|
-
console.log('
|
|
309
|
+
console.log('onPointerDown()', event.button);
|
|
301
310
|
if (event.button !== 0)
|
|
302
311
|
return;
|
|
303
312
|
if (!(event.target instanceof Element))
|
|
@@ -317,16 +326,17 @@ class Suggestions {
|
|
|
317
326
|
}
|
|
318
327
|
removeList() {
|
|
319
328
|
if (DEBUG)
|
|
320
|
-
console.log('
|
|
329
|
+
console.log('removeList()');
|
|
321
330
|
if (!this.list)
|
|
322
331
|
return;
|
|
332
|
+
this.length = 0;
|
|
323
333
|
this.list.remove();
|
|
324
334
|
this.list = undefined;
|
|
325
335
|
}
|
|
326
336
|
selected(item = null) {
|
|
327
337
|
item ??= this.list?.querySelector('li.selected') ?? null;
|
|
328
338
|
if (DEBUG)
|
|
329
|
-
console.log('
|
|
339
|
+
console.log('selected()', item && { caption: item.innerText, id: +(item.dataset.id ?? 0) });
|
|
330
340
|
return item && { caption: item.innerText, id: +(item.dataset.id ?? 0) };
|
|
331
341
|
}
|
|
332
342
|
selectFirst() {
|
|
@@ -369,11 +379,16 @@ class Suggestions {
|
|
|
369
379
|
console.log('show()');
|
|
370
380
|
if (this.list) {
|
|
371
381
|
this.list.style.removeProperty('display');
|
|
382
|
+
if (!this.list.getAttribute('style')?.length) {
|
|
383
|
+
this.list.removeAttribute('style');
|
|
384
|
+
}
|
|
372
385
|
return this.list;
|
|
373
386
|
}
|
|
374
387
|
return this.createList();
|
|
375
388
|
}
|
|
376
389
|
unselect(item = this.list?.querySelector('li.selected')) {
|
|
390
|
+
if (DEBUG)
|
|
391
|
+
console.log('unselect()');
|
|
377
392
|
if (!item)
|
|
378
393
|
return;
|
|
379
394
|
const classList = item.classList;
|
package/package.json
CHANGED