@itrocks/autocomplete 0.0.9 → 0.0.10
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 +231 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,3 +7,234 @@
|
|
|
7
7
|
# autocomplete
|
|
8
8
|
|
|
9
9
|
Editable combobox component featuring smart autocomplete from a list of id-caption pairs for it.rocks.
|
|
10
|
+
|
|
11
|
+
*This documentation was written by an artificial intelligence and may contain errors or approximations.
|
|
12
|
+
It has not yet been fully reviewed by a human. If anything seems unclear or incomplete,
|
|
13
|
+
please feel free to contact the author of this package.*
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm i @itrocks/autocomplete
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
This package ships as a small, framework-agnostic ES module plus a CSS file.
|
|
22
|
+
You can use it directly in a browser bundle or through any bundler that
|
|
23
|
+
supports standard `import` statements.
|
|
24
|
+
|
|
25
|
+
At runtime you must also load the stylesheet `autocomplete.css` so that the
|
|
26
|
+
suggestions dropdown is correctly positioned and styled.
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
`@itrocks/autocomplete` provides a smart autocomplete behavior for a plain
|
|
31
|
+
`<input>` element. It turns the input into an editable combobox that:
|
|
32
|
+
|
|
33
|
+
- fetches suggestions from a remote HTTP endpoint,
|
|
34
|
+
- displays them in a dropdown list,
|
|
35
|
+
- lets the user navigate with the keyboard,
|
|
36
|
+
- completes the text directly in the input,
|
|
37
|
+
- optionally keeps a hidden field in sync with the selected item id.
|
|
38
|
+
|
|
39
|
+
The core API is the `AutoComplete` class, which you instantiate on a
|
|
40
|
+
`HTMLInputElement` that will hold the caption shown to the user.
|
|
41
|
+
|
|
42
|
+
### Minimal example
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<!-- HTML -->
|
|
46
|
+
<input
|
|
47
|
+
id="country"
|
|
48
|
+
type="text"
|
|
49
|
+
data-fetch="/api/countries"
|
|
50
|
+
class="empty"
|
|
51
|
+
>
|
|
52
|
+
<input id="country-id" type="hidden">
|
|
53
|
+
|
|
54
|
+
<script type="module">
|
|
55
|
+
import { AutoComplete } from '/node_modules/@itrocks/autocomplete/autocomplete.js'
|
|
56
|
+
|
|
57
|
+
const captionInput = document.getElementById('country')
|
|
58
|
+
|
|
59
|
+
// Attach autocomplete behavior to the visible input
|
|
60
|
+
new AutoComplete(captionInput)
|
|
61
|
+
</script>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
On each change of the visible input, the component will:
|
|
65
|
+
|
|
66
|
+
1. Call `GET /api/countries?startsWith=<current value>` with
|
|
67
|
+
`Accept: application/json`.
|
|
68
|
+
2. Expect a JSON body shaped as an array of `[id, caption]` pairs, for
|
|
69
|
+
example:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
[["33", "France"], ["49", "Germany"], ["39", "Italy"]]
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
3. Display the matching captions in a dropdown list.
|
|
76
|
+
4. Let the user navigate the list with arrow keys and validate with `Enter`.
|
|
77
|
+
5. Keep the hidden `#country-id` input in sync with the selected item id.
|
|
78
|
+
|
|
79
|
+
### Complete example with common behaviors
|
|
80
|
+
|
|
81
|
+
```html
|
|
82
|
+
<label for="customer">Customer</label>
|
|
83
|
+
<input
|
|
84
|
+
id="customer"
|
|
85
|
+
name="customer-caption"
|
|
86
|
+
type="text"
|
|
87
|
+
data-fetch="/customers/summary"
|
|
88
|
+
class="empty"
|
|
89
|
+
autocomplete="off"
|
|
90
|
+
>
|
|
91
|
+
<!-- Hidden field containing the selected customer id -->
|
|
92
|
+
<input id="customer-id" name="customer-id" type="hidden">
|
|
93
|
+
|
|
94
|
+
<script type="module">
|
|
95
|
+
import { AutoComplete } from '/node_modules/@itrocks/autocomplete/autocomplete.js'
|
|
96
|
+
|
|
97
|
+
const customerCaption = document.getElementById('customer')
|
|
98
|
+
|
|
99
|
+
// Initialize the component once the DOM is ready
|
|
100
|
+
new AutoComplete(customerCaption)
|
|
101
|
+
|
|
102
|
+
// Optionally, react to value changes using the standard 'input' event
|
|
103
|
+
customerCaption.addEventListener('input', () => {
|
|
104
|
+
const idInput = document.getElementById('customer-id')
|
|
105
|
+
console.log('Customer caption:', customerCaption.value)
|
|
106
|
+
console.log('Customer id:', idInput.value)
|
|
107
|
+
})
|
|
108
|
+
</script>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
In this example:
|
|
112
|
+
|
|
113
|
+
- The backend route `/customers/summary` must return JSON like
|
|
114
|
+
`[["1", "Acme"], ["2", "Beta Corp"], ...]`.
|
|
115
|
+
- Typing in the `Customer` input shows suggestions and performs
|
|
116
|
+
in-place completion.
|
|
117
|
+
- The hidden `customer-id` input is automatically set to the id of the
|
|
118
|
+
currently selected suggestion when the caption matches exactly.
|
|
119
|
+
- When the user clears the caption or types a caption that does not match
|
|
120
|
+
any suggestion, the hidden id is cleared.
|
|
121
|
+
|
|
122
|
+
## API
|
|
123
|
+
|
|
124
|
+
`@itrocks/autocomplete` exposes a single public class:
|
|
125
|
+
|
|
126
|
+
### `class AutoComplete`
|
|
127
|
+
|
|
128
|
+
Editable combobox behavior attached to a text input element. It keeps a
|
|
129
|
+
dropdown list of suggestions in sync with the input value and, when
|
|
130
|
+
available, with a nearby hidden input used to store the selected item id.
|
|
131
|
+
|
|
132
|
+
#### Constructor
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
new AutoComplete(input: HTMLInputElement)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Parameters:
|
|
139
|
+
|
|
140
|
+
- `input: HTMLInputElement` – The **visible** input used to type and display
|
|
141
|
+
the caption. It becomes the component's main entry field.
|
|
142
|
+
|
|
143
|
+
Behavior and expectations:
|
|
144
|
+
|
|
145
|
+
- The input is considered the caption field. The user always interacts with
|
|
146
|
+
this field; it remains editable at all times.
|
|
147
|
+
- The constructor:
|
|
148
|
+
- stores the input as `autoComplete.input`,
|
|
149
|
+
- looks for a **hidden** sibling input, which may be used as the
|
|
150
|
+
"id" field (see below),
|
|
151
|
+
- registers listeners for `blur`, `keydown` and `input` events.
|
|
152
|
+
|
|
153
|
+
#### Hidden id input detection
|
|
154
|
+
|
|
155
|
+
If you provide a hidden input to store the selected id, you *do not* have to
|
|
156
|
+
wire it manually. The component will automatically discover it with the
|
|
157
|
+
following rules:
|
|
158
|
+
|
|
159
|
+
- If the next sibling of the visible input is an `HTMLInputElement` of
|
|
160
|
+
type `hidden`, it is used as the id input.
|
|
161
|
+
- Otherwise, if the previous sibling meets these conditions, it is used.
|
|
162
|
+
- If neither sibling qualifies, no id input is used and ids are simply
|
|
163
|
+
ignored.
|
|
164
|
+
|
|
165
|
+
The hidden input value is automatically updated whenever the caption changes
|
|
166
|
+
and there is a selected suggestion whose `caption` exactly equals the visible
|
|
167
|
+
input value.
|
|
168
|
+
|
|
169
|
+
#### Fetching suggestions
|
|
170
|
+
|
|
171
|
+
Suggestions are loaded asynchronously from an HTTP endpoint.
|
|
172
|
+
|
|
173
|
+
The component determines the URL from the DOM:
|
|
174
|
+
|
|
175
|
+
- First it checks `input.dataset.fetch` (`data-fetch` attribute on the input
|
|
176
|
+
itself).
|
|
177
|
+
- If not found, it walks up the DOM tree to the closest ancestor element that
|
|
178
|
+
has a `data-fetch` attribute and uses its value.
|
|
179
|
+
|
|
180
|
+
Once the base URL is known, requests are performed with:
|
|
181
|
+
|
|
182
|
+
```text
|
|
183
|
+
GET <data-fetch>?startsWith=<current value>
|
|
184
|
+
Accept: application/json
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
- When the input is empty, the `?startsWith=...` suffix is omitted.
|
|
188
|
+
- The response must be a JSON array of `[id, caption]` items. `id` is
|
|
189
|
+
converted to a number, `caption` is kept as a string.
|
|
190
|
+
|
|
191
|
+
Client-side filtering is applied so that only captions whose lowercase form
|
|
192
|
+
starts with the lowercase input value are proposed as suggestions.
|
|
193
|
+
|
|
194
|
+
#### Keyboard interaction
|
|
195
|
+
|
|
196
|
+
The following keys are handled while the input has focus:
|
|
197
|
+
|
|
198
|
+
- `ArrowDown` / legacy `Down` – Opens the suggestions list (if there is more
|
|
199
|
+
than one suggestion) or moves the selection one item down.
|
|
200
|
+
- `ArrowUp` / legacy `Up` – Moves the selection one item up; if already at the
|
|
201
|
+
first item, the list is closed.
|
|
202
|
+
- `Enter` – Confirms the currently selected suggestion, copies its caption
|
|
203
|
+
into the input, updates the hidden id input (if any) and hides the list.
|
|
204
|
+
- `Escape` – If the list is visible, simply closes it. If the list is hidden,
|
|
205
|
+
clears the input value and resets the hidden id input.
|
|
206
|
+
|
|
207
|
+
Mouse interactions (clicking on a suggestion) are also supported through the
|
|
208
|
+
internal implementation, thanks to the `<ul class="suggestions">` element
|
|
209
|
+
rendered next to the input.
|
|
210
|
+
|
|
211
|
+
#### Input value changes and events
|
|
212
|
+
|
|
213
|
+
Every time the input value is programmatically changed by the component
|
|
214
|
+
(`autoComplete`, suggestion selection...), the component:
|
|
215
|
+
|
|
216
|
+
1. Stores the new value in `input.dataset.lastValue`.
|
|
217
|
+
2. Dispatches a standard `input` event (with `bubbles: true`).
|
|
218
|
+
3. If the input is not the active element anymore, dispatches a `change`
|
|
219
|
+
event as well.
|
|
220
|
+
4. Maintains the `empty` CSS class:
|
|
221
|
+
- If the value is empty, the `empty` class is added.
|
|
222
|
+
- If the value is not empty, the `empty` class is removed.
|
|
223
|
+
|
|
224
|
+
You can therefore rely on standard `input` / `change` events and on the
|
|
225
|
+
presence of the `empty` class to react to user changes, without having to
|
|
226
|
+
listen to internal events.
|
|
227
|
+
|
|
228
|
+
## Typical use cases
|
|
229
|
+
|
|
230
|
+
Here are some common scenarios where `@itrocks/autocomplete` is useful:
|
|
231
|
+
|
|
232
|
+
- **Selecting a customer, supplier or product** by name while submitting the
|
|
233
|
+
underlying numeric id in a form.
|
|
234
|
+
- **Country, city or postal code selection** in address forms.
|
|
235
|
+
- **Filtering long lists** (e.g. employees, projects, tags) where the user
|
|
236
|
+
only remembers the beginning of the name.
|
|
237
|
+
- **Replacing `<select>` elements with thousands of options** by a lightweight
|
|
238
|
+
autocomplete text field backed by a server-side search route.
|
|
239
|
+
- **Back-office search fields** such as "assigned to", "linked ticket" or
|
|
240
|
+
"parent entity" selectors.
|
package/package.json
CHANGED