From fb30170bc138ee2ec609927150ca8c33c378400d Mon Sep 17 00:00:00 2001 From: sp00n Date: Thu, 20 May 2021 22:41:03 +0200 Subject: Added the ability to set the label and value key names You can now set the names of the `label` and `value` keys in the options. They default to `label` and `value` to not break the current behavior, but you can also set them to `null`, so that you can use a simple object instead of an array of objects, just like in bootstrap-4-autocomplete. Examples: ``` const ac = new Autocomplete(field, { data: [{name: "entry1", text: "The first entry"}, {name: "entry2", text: "The second entry"}], label: "name", value: "text", onSelectItem: ({label, value}) => { console.log("user selected:", label, value); } }); const ac = new Autocomplete(field, { data: {entry1: "The first entry", entry2: "The second entry"}, label: null, value: null, onSelectItem: ({label, value}) => { console.log("user selected:", label, value); } }); ``` --- autocomplete.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/autocomplete.js b/autocomplete.js index 7a9f151..016f8c3 100644 --- a/autocomplete.js +++ b/autocomplete.js @@ -3,6 +3,8 @@ const DEFAULTS = { maximumItems: 5, highlightTyped: true, highlightClass: 'text-primary', + label: 'label', + value: 'value' }; class Autocomplete { @@ -15,7 +17,7 @@ class Autocomplete { field.setAttribute('data-bs-toggle', 'dropdown'); field.classList.add('dropdown-toggle'); - const dropdown = ce(``); + const dropdown = ce(``); if (this.options.dropdownClass) dropdown.classList.add(this.options.dropdownClass); @@ -84,10 +86,17 @@ class Autocomplete { const items = this.field.nextSibling; items.innerHTML = ''; + const keys = Object.keys(this.options.data); + let count = 0; - for (let i = 0; i < this.options.data.length; i++) { - const {label, value} = this.options.data[i]; - const item = {label, value}; + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + const entry = this.options.data[key]; + const item = { + label: this.options.label ? entry[this.options.label] : key, + value: this.options.value ? entry[this.options.value] : entry + }; + if (item.label.toLowerCase().indexOf(lookup.toLowerCase()) >= 0) { items.appendChild(this.createItem(lookup, item)); if (this.options.maximumItems > 0 && ++count >= this.options.maximumItems) -- cgit v1.2.3 From 32bcb0326a097d37196ad689e8222c1c5e41c7b5 Mon Sep 17 00:00:00 2001 From: sp00n Date: Thu, 20 May 2021 22:55:02 +0200 Subject: Update README.md --- README.md | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fa67f9b..d5f704d 100644 --- a/README.md +++ b/README.md @@ -21,12 +21,37 @@ ac.setData([ ]); ``` + +Or use custom label/value keys: +```js +const ac = new Autocomplete(field, { + data: [{name: "entry1", text: "The first entry"}, {name: "entry2", text: "The second entry"}], + label: "name", + value: "text", + onSelectItem: ({label, value}) => { + console.log("user selected:", label, value); + } +}); +``` + +Or use a simple object instead of an array of objects: +```js +const ac = new Autocomplete(field, { + data: {entry1: "The first entry", entry2: "The second entry"}, + label: null, + value: null, + onSelectItem: ({label, value}) => { + console.log("user selected:", label, value); + } +}); +``` + ### Options Options is a JSON object with the following attributes (in alphabetical order): **data**: -The data from where autocomplete will lookup items to show. This data has to be an array of JSON objects. The format for every item in the array is: +The data from where autocomplete will lookup items to show. This data can be a simple object or an array of JSON objects. By default the format for every object in the array is as following, but you can also change the name of the label and value keys (see below): {"label": "This is a text", "value": 42} @@ -42,10 +67,14 @@ The class to use when highlighting typed text on items. Only used when highlight **highlightTyped**: Wether to highlight (style) typed text on items. Default is true. +**label**: +The name of the `label` key in your data. The label is what will be shown on each item in the autocomplete list. + **maximumItems**: How many items you want to show when the autocomplete is displayed. Default is 5. Set to 0 to display all available items. -**onInput** +**onInput**: +A callback function to execute on user input. **onSelectItem**: A callback that is fired every time an item is selected. It receives an object in following format: @@ -55,6 +84,9 @@ A callback that is fired every time an item is selected. It receives an object i **treshold**: The number of characters that need to be typed on the input in order to trigger the autocomplete. Default is 4. +**value**: +The name of the `value` key in your data. + ### License -MIT \ No newline at end of file +MIT -- cgit v1.2.3 From 024880c5248f748881731f0507e90370997e8aad Mon Sep 17 00:00:00 2001 From: sp00n Date: Thu, 20 May 2021 23:53:28 +0200 Subject: Added a displayLabelWithValue option Setting displayLabelWithValue to true will display the value after the label in the dropdown. Also added a couple of missing semicolons. --- autocomplete.js | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/autocomplete.js b/autocomplete.js index 016f8c3..f6daa71 100644 --- a/autocomplete.js +++ b/autocomplete.js @@ -4,7 +4,8 @@ const DEFAULTS = { highlightTyped: true, highlightClass: 'text-primary', label: 'label', - value: 'value' + value: 'value', + displayLabelWithValue: false, }; class Autocomplete { @@ -23,7 +24,7 @@ class Autocomplete { insertAfter(dropdown, field); - this.dropdown = new bootstrap.Dropdown(field, this.options.dropdownOptions) + this.dropdown = new bootstrap.Dropdown(field, this.options.dropdownOptions); field.addEventListener('click', (e) => { if (this.createItems() === 0) { @@ -67,13 +68,19 @@ class Autocomplete { if (this.options.highlightTyped) { const idx = item.label.toLowerCase().indexOf(lookup.toLowerCase()); const className = Array.isArray(this.options.highlightClass) ? this.options.highlightClass.join(' ') - : (typeof this.options.highlightClass == 'string' ? this.options.highlightClass : '') + : (typeof this.options.highlightClass == 'string' ? this.options.highlightClass : ''); label = item.label.substring(0, idx) + `${item.label.substring(idx, idx + lookup.length)}` + item.label.substring(idx + lookup.length, item.label.length); - } else + } else { label = item.label; - return ce(``); + } + + if (this.options.displayLabelWithValue) { + label += ` ${item.value}`; + } + + return ce(``); } createItems() { @@ -106,13 +113,18 @@ class Autocomplete { this.field.nextSibling.querySelectorAll('.dropdown-item').forEach((item) => { item.addEventListener('click', (e) => { + let dataLabel = e.target.getAttribute('data-label'); let dataValue = e.target.getAttribute('data-value'); - this.field.value = e.target.innerText; - if (this.options.onSelectItem) + + this.field.value = dataLabel; + + if (this.options.onSelectItem) { this.options.onSelectItem({ - value: e.target.dataset.value, - label: e.target.innerText, + value: dataValue, + label: dataLabel }); + } + this.dropdown.hide(); }) }); @@ -137,5 +149,5 @@ function ce(html) { * @returns {*} */ function insertAfter(elem, refElem) { - return refElem.parentNode.insertBefore(elem, refElem.nextSibling) + return refElem.parentNode.insertBefore(elem, refElem.nextSibling); } -- cgit v1.2.3 From 5b499555fac1be9343bc7ca4d580bcafe2ca141a Mon Sep 17 00:00:00 2001 From: sp00n Date: Thu, 20 May 2021 23:59:12 +0200 Subject: Renamed to displayLabelWithValue to showValue --- autocomplete.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autocomplete.js b/autocomplete.js index f6daa71..fd79b36 100644 --- a/autocomplete.js +++ b/autocomplete.js @@ -5,7 +5,7 @@ const DEFAULTS = { highlightClass: 'text-primary', label: 'label', value: 'value', - displayLabelWithValue: false, + showValue: false, }; class Autocomplete { -- cgit v1.2.3 From ce7994b85dc3208c5138de3196bdba21fafdd521 Mon Sep 17 00:00:00 2001 From: sp00n Date: Thu, 20 May 2021 23:59:55 +0200 Subject: Forgot one showValue --- autocomplete.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autocomplete.js b/autocomplete.js index fd79b36..169d3ed 100644 --- a/autocomplete.js +++ b/autocomplete.js @@ -76,7 +76,7 @@ class Autocomplete { label = item.label; } - if (this.options.displayLabelWithValue) { + if (this.options.showValue) { label += ` ${item.value}`; } -- cgit v1.2.3 From 4c10d574c4360d9d6e52acfdaa8bb87d2319633d Mon Sep 17 00:00:00 2001 From: sp00n Date: Fri, 21 May 2021 00:01:09 +0200 Subject: Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index d5f704d..b394308 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,9 @@ A callback that is fired every time an item is selected. It receives an object i {label: