diff --git a/README.md b/README.md index 0b47cae..dc7f5a2 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,36 @@ # Choices.js [![Actions Status](https://github.com/jshjohnson/Choices/workflows/Unit%20Tests/badge.svg)](https://github.com/jshjohnson/Choices/actions) [![npm](https://img.shields.io/npm/v/choices.js.svg)](https://www.npmjs.com/package/choices.js) [![codebeat badge](https://codebeat.co/badges/55120150-5866-42d8-8010-6aaaff5d3fa1)](https://codebeat.co/projects/github-com-jshjohnson-choices-master) + A vanilla, lightweight (~19kb gzipped 🎉), configurable select box/text input plugin. Similar to Select2 and Selectize but without the jQuery dependency. [Demo](https://joshuajohnson.co.uk/Choices/) ## TL;DR -* Lightweight -* No jQuery dependency -* Configurable sorting -* Flexible styling -* Fast search/filtering -* Clean API -* Right-to-left support -* Custom templates ----- +- Lightweight +- No jQuery dependency +- Configurable sorting +- Flexible styling +- Fast search/filtering +- Clean API +- Right-to-left support +- Custom templates + +--- + ### Interested in writing your own ES6 JavaScript plugins? Check out [ES6.io](https://ES6.io/friend/JOHNSON) for great tutorials! 💪🏼 ----- + +--- ## Installation + With [NPM](https://www.npmjs.com/package/choices.js): + ```zsh npm install choices.js ``` With [Yarn](https://yarnpkg.com/): + ```zsh yarn add choices.js ``` @@ -34,9 +41,15 @@ From a [CDN](https://www.jsdelivr.com/package/npm/choices.js): ```html - + - + ``` @@ -45,12 +58,13 @@ Or include Choices directly: ```html - + - + ``` + ## Setup If you pass a selector which targets multiple elements, an array of Choices instances @@ -152,24 +166,26 @@ will be returned. If you target one element, that instance will be returned. ``` ## Terminology + | Word | Definition | | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Choice | A choice is a value a user can select. A choice would be equivalent to the `` element within a select input. | | Group | A group is a collection of choices. A group should be seen as equivalent to a `` element within a select input. | | Item | An item is an inputted value (text input) or a selected choice (select element). In the context of a select element, an item is equivalent to a selected option element: `` whereas in the context of a text input an item is equivalent to `` | - ## Configuration options + ### silent -**Type:** `Boolean` **Default:** `false` + +**Type:** `Boolean` **Default:** `false` **Input types affected:** `text`, `select-single`, `select-multiple` **Usage:** Optionally suppress console errors and warnings. - ### items -**Type:** `Array` **Default:** `[]` + +**Type:** `Array` **Default:** `[]` **Input types affected:** `text` @@ -198,7 +214,8 @@ Pass an array of objects: ``` ### choices -**Type:** `Array` **Default:** `[]` + +**Type:** `Array` **Default:** `[]` **Input types affected:** `select-one`, `select-multiple` @@ -226,6 +243,7 @@ Pass an array of objects: ``` ### renderChoiceLimit + **Type:** `Number` **Default:** `-1` **Input types affected:** `select-one`, `select-multiple` @@ -233,6 +251,7 @@ Pass an array of objects: **Usage:** The amount of choices to be rendered within the dropdown list ("-1" indicates no limit). This is useful if you have a lot of choices where it is easier for a user to use the search area to find a choice. ### maxItemCount + **Type:** `Number` **Default:** `-1` **Input types affected:** `text`, `select-multiple` @@ -240,6 +259,7 @@ Pass an array of objects: **Usage:** The amount of items a user can input/select ("-1" indicates no limit). ### addItems + **Type:** `Boolean` **Default:** `true` **Input types affected:** `text` @@ -247,6 +267,7 @@ Pass an array of objects: **Usage:** Whether a user can add items. ### removeItems + **Type:** `Boolean` **Default:** `true` **Input types affected:** `text`, `select-multiple` @@ -254,6 +275,7 @@ Pass an array of objects: **Usage:** Whether a user can remove items. ### removeItemButton + **Type:** `Boolean` **Default:** `false` **Input types affected:** `text`, `select-one`, `select-multiple` @@ -261,6 +283,7 @@ Pass an array of objects: **Usage:** Whether each item should have a remove button. ### editItems + **Type:** `Boolean` **Default:** `false` **Input types affected:** `text` @@ -268,6 +291,7 @@ Pass an array of objects: **Usage:** Whether a user can edit items. An item's value can be edited by pressing the backspace. ### duplicateItemsAllowed + **Type:** `Boolean` **Default:** `true` **Input types affected:** `text`, `select-multiple` @@ -275,6 +299,7 @@ Pass an array of objects: **Usage:** Whether duplicate inputted/chosen items are allowed ### delimiter + **Type:** `String` **Default:** `,` **Input types affected:** `text` @@ -282,6 +307,7 @@ Pass an array of objects: **Usage:** What divides each value. The default delimiter seperates each value with a comma: `"Value 1, Value 2, Value 3"`. ### paste + **Type:** `Boolean` **Default:** `true` **Input types affected:** `text`, `select-multiple` @@ -289,21 +315,23 @@ Pass an array of objects: **Usage:** Whether a user can paste into the input. ### searchEnabled + **Type:** `Boolean` **Default:** `true` **Input types affected:** `select-one` -**Usage:** Whether a search area should be shown. **Note:** Multiple select boxes will *always* show search areas. +**Usage:** Whether a search area should be shown. **Note:** Multiple select boxes will _always_ show search areas. ### searchChoices + **Type:** `Boolean` **Default:** `true` **Input types affected:** `select-one` **Usage:** Whether choices should be filtered by input or not. If `false`, the search event will still emit, but choices will not be filtered. - ### searchFields + **Type:** `Array/String` **Default:** `['label', 'value']` **Input types affected:**`select-one`, `select-multiple` @@ -311,6 +339,7 @@ Pass an array of objects: **Usage:** Specify which fields should be used when a user is searching. If you have added custom properties to your choices, you can add these values thus: `['label', 'value', 'customProperties.example']`. ### searchFloor + **Type:** `Number` **Default:** `1` **Input types affected:** `select-one`, `select-multiple` @@ -318,6 +347,7 @@ Pass an array of objects: **Usage:** The minimum length a search value should be before choices are searched. ### searchResultLimit: 4, + **Type:** `Number` **Default:** `4` **Input types affected:** `select-one`, `select-multiple` @@ -325,6 +355,7 @@ Pass an array of objects: **Usage:** The maximum amount of search results to show. ### position + **Type:** `String` **Default:** `auto` **Input types affected:** `select-one`, `select-multiple` @@ -332,6 +363,7 @@ Pass an array of objects: **Usage:** Whether the dropdown should appear above (`top`) or below (`bottom`) the input. By default, if there is not enough space within the window the dropdown will appear above the input, otherwise below it. ### resetScrollPosition + **Type:** `Boolean` **Default:** `true` **Input types affected:** `select-multiple` @@ -339,6 +371,7 @@ Pass an array of objects: **Usage:** Whether the scroll position should reset after adding an item. ### addItemFilterFn + **Type:** `Function` **Default:** `null` **Input types affected:** `text` @@ -357,6 +390,7 @@ new Choices(element, { ``` ### shouldSort + **Type:** `Boolean` **Default:** `true` **Input types affected:** `select-one`, `select-multiple` @@ -364,6 +398,7 @@ new Choices(element, { **Usage:** Whether choices and groups should be sorted. If false, choices/groups will appear in the order they were given. ### shouldSortItems + **Type:** `Boolean` **Default:** `false` **Input types affected:** `text`, `select-multiple` @@ -371,6 +406,7 @@ new Choices(element, { **Usage:** Whether items should be sorted. If false, items will appear in the order they were selected. ### sortFn + **Type:** `Function` **Default:** sortByAlpha **Input types affected:** `select-one`, `select-multiple` @@ -389,11 +425,12 @@ const example = new Choices(element, { ``` ### placeholder + **Type:** `Boolean` **Default:** `true` **Input types affected:** `text`, `select-multiple` -**Usage:** Whether the input should show a placeholder. Used in conjunction with `placeholderValue`. If `placeholder` is set to true and no value is passed to `placeholderValue`, the passed input's placeholder attribute will be used as the placeholder value. +**Usage:** Whether the input should show a placeholder. Used in conjunction with `placeholderValue`. If `placeholder` is set to true and no value is passed to `placeholderValue`, the passed input's placeholder attribute will be used as the placeholder value. **Note:** For single select boxes, the recommended way of adding a placeholder is as follows: @@ -409,6 +446,7 @@ const example = new Choices(element, { For backward compatibility, `` is also supported. ### placeholderValue + **Type:** `String` **Default:** `null` **Input types affected:** `text`, `select-multiple` @@ -416,6 +454,7 @@ For backward compatibility, `` **Usage:** The value of the inputs placeholder. ### searchPlaceholderValue + **Type:** `String` **Default:** `null` **Input types affected:** `select-one` @@ -423,6 +462,7 @@ For backward compatibility, `` **Usage:** The value of the search inputs placeholder. ### prependValue + **Type:** `String` **Default:** `null` **Input types affected:** `text`, `select-one`, `select-multiple` @@ -430,6 +470,7 @@ For backward compatibility, `` **Usage:** Prepend a value to each item added/selected. ### appendValue + **Type:** `String` **Default:** `null` **Input types affected:** `text`, `select-one`, `select-multiple` @@ -437,6 +478,7 @@ For backward compatibility, `` **Usage:** Append a value to each item added/selected. ### renderSelectedChoices + **Type:** `String` **Default:** `auto` **Input types affected:** `select-multiple` @@ -444,6 +486,7 @@ For backward compatibility, `` **Usage:** Whether selected choices should be removed from the list. By default choices are removed when they are selected in multiple select box. To always render choices pass `always`. ### loadingText + **Type:** `String` **Default:** `Loading...` **Input types affected:** `select-one`, `select-multiple` @@ -451,6 +494,7 @@ For backward compatibility, `` **Usage:** The text that is shown whilst choices are being populated via AJAX. ### noResultsText + **Type:** `String/Function` **Default:** `No results found` **Input types affected:** `select-one`, `select-multiple` @@ -458,6 +502,7 @@ For backward compatibility, `` **Usage:** The text that is shown when a user's search has returned no results. Optionally pass a function returning a string. ### noChoicesText + **Type:** `String/Function` **Default:** `No choices to choose from` **Input types affected:** `select-multiple` @@ -465,6 +510,7 @@ For backward compatibility, `` **Usage:** The text that is shown when a user has selected all possible choices. Optionally pass a function returning a string. ### itemSelectText + **Type:** `String` **Default:** `Press to select` **Input types affected:** `select-multiple`, `select-one` @@ -472,6 +518,7 @@ For backward compatibility, `` **Usage:** The text that is shown when a user hovers over a selectable choice. ### addItemText + **Type:** `String/Function` **Default:** `Press Enter to add "${value}"` **Input types affected:** `text` @@ -479,6 +526,7 @@ For backward compatibility, `` **Usage:** The text that is shown when a user has inputted a new item but has not pressed the enter key. To access the current input value, pass a function with a `value` argument (see the [default config](https://github.com/jshjohnson/Choices#setup) for an example), otherwise pass a string. ### maxItemText + **Type:** `String/Function` **Default:** `Only ${maxItemCount} values can be added` **Input types affected:** `text` @@ -486,6 +534,7 @@ For backward compatibility, `` **Usage:** The text that is shown when a user has focus on the input but has already reached the [max item count](https://github.com/jshjohnson/Choices#maxitemcount). To access the max item count, pass a function with a `maxItemCount` argument (see the [default config](https://github.com/jshjohnson/Choices#setup) for an example), otherwise pass a string. ### itemComparer + **Type:** `Function` **Default:** `strict equality` **Input types affected:** `select-one`, `select-multiple` @@ -493,6 +542,7 @@ For backward compatibility, `` **Usage:** Compare choice and value in appropriate way (e.g. deep equality for objects). To compare choice and value, pass a function with a `itemComparer` argument (see the [default config](https://github.com/jshjohnson/Choices#setup) for an example). ### classNames + **Type:** `Object` **Default:** ``` @@ -527,9 +577,11 @@ classNames: { **Usage:** Classes added to HTML generated by Choices. By default classnames follow the [BEM](http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/) notation. ## Callbacks + **Note:** For each callback, `this` refers to the current instance of Choices. This can be useful if you need access to methods (`this.disable()`) or the config object (`this.config`). ### callbackOnInit + **Type:** `Function` **Default:** `null` **Input types affected:** `text`, `select-one`, `select-multiple` @@ -537,6 +589,7 @@ classNames: { **Usage:** Function to run once Choices initialises. ### callbackOnCreateTemplates + **Type:** `Function` **Default:** `null` **Arguments:** `template` **Input types affected:** `text`, `select-one`, `select-multiple` @@ -547,28 +600,45 @@ classNames: { ```js const example = new Choices(element, { - callbackOnCreateTemplates: function (template) { + callbackOnCreateTemplates: function(template) { return { item: (classNames, data) => { return template(` -
+
${data.label}
`); }, choice: (classNames, data) => { return template(` -
0 ? 'role="treeitem"' : 'role="option"'}> +
0 ? 'role="treeitem"' : 'role="option"' + }> ${data.label}
`); }, }; - } + }, }); ``` ## Events + **Note:** Events fired by Choices behave the same as standard events. Each event is triggered on the element passed to Choices (accessible via `this.passedElement`. Arguments are accessible within the `event.detail` object. **Example:** @@ -577,29 +647,38 @@ const example = new Choices(element, { const element = document.getElementById('example'); const example = new Choices(element); -element.addEventListener('addItem', function(event) { - // do something creative here... - console.log(event.detail.id); - console.log(event.detail.value); - console.log(event.detail.label); - console.log(event.detail.customProperties); - console.log(event.detail.groupValue); -}, false); +element.addEventListener( + 'addItem', + function(event) { + // do something creative here... + console.log(event.detail.id); + console.log(event.detail.value); + console.log(event.detail.label); + console.log(event.detail.customProperties); + console.log(event.detail.groupValue); + }, + false, +); // or const example = new Choices(document.getElementById('example')); -example.passedElement.element.addEventListener('addItem', function(event) { - // do something creative here... - console.log(event.detail.id); - console.log(event.detail.value); - console.log(event.detail.label); - console.log(event.detail.customProperties); - console.log(event.detail.groupValue); -}, false); +example.passedElement.element.addEventListener( + 'addItem', + function(event) { + // do something creative here... + console.log(event.detail.id); + console.log(event.detail.value); + console.log(event.detail.label); + console.log(event.detail.customProperties); + console.log(event.detail.groupValue); + }, + false, +); ``` ### addItem + **Arguments:** `id, value, label, groupValue, keyCode` **Input types affected:** `text`, `select-one`, `select-multiple` @@ -607,6 +686,7 @@ example.passedElement.element.addEventListener('addItem', function(event) { **Usage:** Triggered each time an item is added (programmatically or by the user). ### removeItem + **Arguments:** `id, value, label, groupValue` **Input types affected:** `text`, `select-one`, `select-multiple` @@ -614,6 +694,7 @@ example.passedElement.element.addEventListener('addItem', function(event) { **Usage:** Triggered each time an item is removed (programmatically or by the user). ### highlightItem + **Arguments:** `id, value, label, groupValue` **Input types affected:** `text`, `select-multiple` @@ -621,6 +702,7 @@ example.passedElement.element.addEventListener('addItem', function(event) { **Usage:** Triggered each time an item is highlighted. ### unhighlightItem + **Arguments:** `id, value, label, groupValue` **Input types affected:** `text`, `select-multiple` @@ -628,13 +710,16 @@ example.passedElement.element.addEventListener('addItem', function(event) { **Usage:** Triggered each time an item is unhighlighted. ### choice -**Arguments:** `value, keyCode` + +**Arguments:** `choice` **Input types affected:** `select-one`, `select-multiple` **Usage:** Triggered each time a choice is selected **by a user**, regardless if it changes the value of the input. +`choice` is a Choice object here (see terminology or typings file) ### change + **Arguments:** `value` **Input types affected:** `text`, `select-one`, `select-multiple` @@ -642,6 +727,7 @@ example.passedElement.element.addEventListener('addItem', function(event) { **Usage:** Triggered each time an item is added/removed **by a user**. ### search + **Arguments:** `value`, `resultCount` **Input types affected:** `select-one`, `select-multiple` @@ -649,6 +735,7 @@ example.passedElement.element.addEventListener('addItem', function(event) { **Usage:** Triggered when a user types into an input to search choices. ### showDropdown + **Arguments:** - **Input types affected:** `select-one`, `select-multiple` @@ -656,6 +743,7 @@ example.passedElement.element.addEventListener('addItem', function(event) { **Usage:** Triggered when the dropdown is shown. ### hideDropdown + **Arguments:** - **Input types affected:** `select-one`, `select-multiple` @@ -663,21 +751,24 @@ example.passedElement.element.addEventListener('addItem', function(event) { **Usage:** Triggered when the dropdown is hidden. ### highlightChoice + **Arguments:** `el` **Input types affected:** `select-one`, `select-multiple` -**Usage:** Triggered when a choice from the dropdown is highlighted. The `el` argument is the HTML element node object that was affected. +**Usage:** Triggered when a choice from the dropdown is highlighted. +The `el` argument is choices.passedElement object that was affected. ## Methods + Methods can be called either directly or by chaining: ```js // Calling a method by chaining const choices = new Choices(element, { - addItems: false, - removeItems: false, - }) + addItems: false, + removeItems: false, +}) .setValue(['Set value 1', 'Set value 2']) .disable(); @@ -687,16 +778,18 @@ const choices = new Choices(element, { removeItems: false, }); -choices.setValue(['Set value 1', 'Set value 2']) +choices.setValue(['Set value 1', 'Set value 2']); choices.disable(); ``` ### destroy(); + **Input types affected:** `text`, `select-multiple`, `select-one` **Usage:** Kills the instance of Choices, removes all event listeners and returns passed input to its initial state. ### init(); + **Input types affected:** `text`, `select-multiple`, `select-one` **Usage:** Creates a new instance of Choices, adds event listeners, creates templates and renders a Choices element to the DOM. @@ -704,47 +797,49 @@ choices.disable(); **Note:** This is called implicitly when a new instance of Choices is created. This would be used after a Choices instance had already been destroyed (using `destroy()`). ### highlightAll(); + **Input types affected:** `text`, `select-multiple` **Usage:** Highlight each chosen item (selected items can be removed). - ### unhighlightAll(); + **Input types affected:** `text`, `select-multiple` **Usage:** Un-highlight each chosen item. - ### removeActiveItemsByValue(value); + **Input types affected:** `text`, `select-multiple` **Usage:** Remove each item by a given value. - ### removeActiveItems(excludedId); + **Input types affected:** `text`, `select-multiple` **Usage:** Remove each selectable item. - ### removeHighlightedItems(); + **Input types affected:** `text`, `select-multiple` **Usage:** Remove each item the user has selected. - ### showDropdown(); + **Input types affected:** `select-one`, `select-multiple` **Usage:** Show option list dropdown (only affects select inputs). - ### hideDropdown(); + **Input types affected:** `text`, `select-multiple` **Usage:** Hide option list dropdown (only affects select inputs). ### setChoices(choices, value, label, replaceChoices); + **Input types affected:** `select-one`, `select-multiple` **Usage:** Set choices of select input via an array of objects, a value name and a label name. This behaves the same as passing items via the `choices` option but can be called after initialising Choices. This can also be used to add groups of choices (see example 2); Optionally pass a true `replaceChoices` value to remove any existing choices. Optionally pass a `customProperties` object to add additional data to your choices (useful when searching/filtering etc). Passing an empty array as the first parameter, and a true `replaceChoices` is the same as calling `clearChoices` (see below). @@ -754,11 +849,16 @@ choices.disable(); ```js const example = new Choices(element); -example.setChoices([ - {value: 'One', label: 'Label One', disabled: true}, - {value: 'Two', label: 'Label Two', selected: true}, - {value: 'Three', label: 'Label Three'}, -], 'value', 'label', false); +example.setChoices( + [ + { value: 'One', label: 'Label One', disabled: true }, + { value: 'Two', label: 'Label Two', selected: true }, + { value: 'Three', label: 'Label Three' }, + ], + 'value', + 'label', + false, +); ``` **Example 2:** @@ -766,37 +866,50 @@ example.setChoices([ ```js const example = new Choices(element); -example.setChoices([{ - label: 'Group one', - id: 1, - disabled: false, - choices: [ - {value: 'Child One', label: 'Child One', selected: true}, - {value: 'Child Two', label: 'Child Two', disabled: true}, - {value: 'Child Three', label: 'Child Three'}, - ] -}, -{ - label: 'Group two', - id: 2, - disabled: false, - choices: [ - {value: 'Child Four', label: 'Child Four', disabled: true}, - {value: 'Child Five', label: 'Child Five'}, - {value: 'Child Six', label: 'Child Six', customProperties: { - description: 'Custom description about child six', - random: 'Another random custom property' - }}, - ] -}], 'value', 'label', false); +example.setChoices( + [ + { + label: 'Group one', + id: 1, + disabled: false, + choices: [ + { value: 'Child One', label: 'Child One', selected: true }, + { value: 'Child Two', label: 'Child Two', disabled: true }, + { value: 'Child Three', label: 'Child Three' }, + ], + }, + { + label: 'Group two', + id: 2, + disabled: false, + choices: [ + { value: 'Child Four', label: 'Child Four', disabled: true }, + { value: 'Child Five', label: 'Child Five' }, + { + value: 'Child Six', + label: 'Child Six', + customProperties: { + description: 'Custom description about child six', + random: 'Another random custom property', + }, + }, + ], + }, + ], + 'value', + 'label', + false, +); ``` ### clearChoices(); + **Input types affected:** `select-one`, `select-multiple` **Usage:** Clear all choices from select ### getValue(valueOnly) + **Input types affected:** `text`, `select-one`, `select-multiple` **Usage:** Get value(s) of input (i.e. inputted items (text) or selected choices (select)). Optionally pass an argument of `true` to only return values rather than value objects. @@ -810,6 +923,7 @@ const valueArray = example.getValue(); // returns [{ active: true, choiceId: 1, ``` ### setValue(items); + **Input types affected:** `text` **Usage:** Set value of input based on an array of objects or strings. This behaves exactly the same as passing items via the `items` option but can be called after initialising Choices. @@ -821,16 +935,17 @@ const example = new Choices(element); // via an array of objects example.setValue([ - {value: 'One', label: 'Label One'}, - {value: 'Two', label: 'Label Two'}, - {value: 'Three', label: 'Label Three'}, + { value: 'One', label: 'Label One' }, + { value: 'Two', label: 'Label Two' }, + { value: 'Three', label: 'Label Three' }, ]); // or via an array of strings -example.setValue(['Four','Five','Six']); +example.setValue(['Four', 'Five', 'Six']); ``` ### setChoiceByValue(value); + **Input types affected:** `select-one`, `select-multiple` **Usage:** Set value of input based on existing Choice. `value` can be either a single string or an array of strings @@ -840,9 +955,9 @@ example.setValue(['Four','Five','Six']); ```js const example = new Choices(element, { choices: [ - {value: 'One', label: 'Label One'}, - {value: 'Two', label: 'Label Two', disabled: true}, - {value: 'Three', label: 'Label Three'}, + { value: 'One', label: 'Label One' }, + { value: 'Two', label: 'Label Two', disabled: true }, + { value: 'Three', label: 'Label Three' }, ], }); @@ -850,29 +965,31 @@ example.setChoiceByValue('Two'); // Choice with value of 'Two' has now been sele ``` ### clearStore(); + **Input types affected:** `text`, `select-one`, `select-multiple` **Usage:** Removes all items, choices and groups. Use with caution. - ### clearInput(); + **Input types affected:** `text` **Usage:** Clear input of any user inputted text. - ### disable(); + **Input types affected:** `text`, `select-one`, `select-multiple` **Usage:** Disables input from accepting new value/selecting further choices. ### enable(); + **Input types affected:** `text`, `select-one`, `select-multiple` **Usage:** Enables input to accept new values/select further choices. - ### ajax(fn); + **Input types affected:** `select-one`, `select-multiple` **Usage:** Populate choices/groups via a callback. @@ -899,7 +1016,7 @@ example.ajax(function(callback) { If your structure differs from `data.value` and `data.key` structure you can write your own `key` and `value` into the `callback` function. This could be useful when you don't want to transform the given response. ```js -const example = new Choices(element) +const example = new Choices(element); example.ajax(function(callback) { fetch(url) @@ -915,6 +1032,7 @@ example.ajax(function(callback) { ``` ## Browser compatibility + Choices is compiled using [Babel](https://babeljs.io/) to enable support for [ES5 browsers](http://caniuse.com/#feat=es5). If you need to support a browser that does not support one of the features listed below, I suggest including a polyfill from the very good [polyfill.io](https://cdn.polyfill.io/v2/docs/): **Polyfill example used for the demo:** @@ -925,25 +1043,27 @@ Choices is compiled using [Babel](https://babeljs.io/) to enable support for [ES **Features used in Choices:** -* Array.prototype.forEach -* Array.prototype.map -* Array.prototype.find -* Array.prototype.some -* Array.prototype.includes -* Array.from -* Array.prototype.reduce -* Array.prototype.indexOf -* Object.assign -* Element.prototype.classList -* window.requestAnimationFrame -* CustomEvent +- Array.prototype.forEach +- Array.prototype.map +- Array.prototype.find +- Array.prototype.some +- Array.prototype.includes +- Array.from +- Array.prototype.reduce +- Array.prototype.indexOf +- Object.assign +- Element.prototype.classList +- window.requestAnimationFrame +- CustomEvent ## Development + To setup a local environment: clone this repo, navigate into it's directory in a terminal window and run the following command: -```npm install``` +`npm install` ### NPM tasks + | Task | Usage | | ------------------------- | ------------------------------------------------------------ | | `npm run start` | Fire up local server for development | @@ -958,10 +1078,13 @@ To setup a local environment: clone this repo, navigate into it's directory in a | `npm run css:build` | Compile, minify and prefix SCSS files to CSS | ## License + MIT License ## Web component + Want to use Choices as a web component? You're in luck. Adidas have built one for their design system which can be found [here](https://github.com/adidas/choicesjs-stencil). ## Misc + Thanks to [@mikefrancis](https://github.com/mikefrancis/) for [sending me on a hunt](https://twitter.com/_mikefrancis/status/701797835826667520) for a non-jQuery solution for select boxes that eventually led to this being built! diff --git a/types/index.d.ts b/types/index.d.ts index 73923df..6afa1eb 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -13,7 +13,7 @@ import { FuseOptions } from 'fuse.js'; declare namespace Choices { namespace Types { type strToEl = ( - str: string + str: string, ) => HTMLElement | HTMLInputElement | HTMLOptionElement; type stringFunction = () => string; type noticeStringFunction = (value: string) => string; @@ -99,9 +99,9 @@ declare namespace Choices { * * **Input types affected:** select-one, select-multiple * - * Arguments: value, keyCode + * Arguments: choice: Choice */ - choice: CustomEvent<{ value: string; keyCode: string }>; + choice: CustomEvent<{ choice: Choices.Choice }>; /** * Triggered each time an item is added/removed **by a user**. @@ -143,9 +143,9 @@ declare namespace Choices { * Triggered when a choice from the dropdown is highlighted. * * Input types affected: select-one, select-multiple - * Arguments: el is the HTML element node object that was affected. + * Arguments: el is the choice.passedElement that was affected. */ - highlightChoice: CustomEvent<{ el: HTMLOptionElement }>; + highlightChoice: CustomEvent<{ el: Choices.passedElement }>; } interface Group { @@ -168,52 +168,52 @@ declare namespace Choices { isSelectElement: boolean, isSelectOneElement: boolean, searchEnabled: boolean, - passedElementType: passedElement['type'] + passedElementType: passedElement['type'], ) => HTMLElement; containerInner: (this: Choices, classNames: ClassNames) => HTMLElement; itemList: ( this: Choices, classNames: ClassNames, - isSelectOneElement: boolean + isSelectOneElement: boolean, ) => HTMLElement; placeholder: ( this: Choices, classNames: ClassNames, - value: string + value: string, ) => HTMLElement; item: ( this: Choices, classNames: ClassNames, data: Choice, - removeItemButton: boolean + removeItemButton: boolean, ) => HTMLElement; choiceList: ( this: Choices, classNames: ClassNames, - isSelectOneElement: boolean + isSelectOneElement: boolean, ) => HTMLElement; choiceGroup: ( this: Choices, classNames: ClassNames, - data: Choice + data: Choice, ) => HTMLElement; choice: ( this: Choices, classNames: ClassNames, data: Choice, - selectText: string + selectText: string, ) => HTMLElement; input: ( this: Choices, classNames: ClassNames, - placeholderValue: string + placeholderValue: string, ) => HTMLInputElement; dropdown: (this: Choices, classNames: ClassNames) => HTMLElement; notice: ( this: Choices, classNames: ClassNames, label: string, - type: '' | 'no-results' | 'no-choices' + type: '' | 'no-results' | 'no-choices', ) => HTMLElement; option: (data: Choice) => HTMLOptionElement; } @@ -280,9 +280,9 @@ declare namespace Choices { type: K, listener: ( this: HTMLInputElement | HTMLSelectElement, - ev: Choices.EventMap[K] + ev: Choices.EventMap[K], ) => void, - options?: boolean | AddEventListenerOptions + options?: boolean | AddEventListenerOptions, ): void; }; type: 'text' | 'select-one' | 'select-multiple'; @@ -750,7 +750,7 @@ declare namespace Choices { * @default null */ callbackOnCreateTemplates: ( - template: Choices.Types.strToEl + template: Choices.Types.strToEl, ) => Partial; } } @@ -769,7 +769,7 @@ export default class Choices { constructor( selectorOrElement: string | HTMLInputElement | HTMLSelectElement, - userConfig?: Partial + userConfig?: Partial, ); /** @@ -942,7 +942,7 @@ export default class Choices { choices: Choices.Choice[], value: string, label: string, - replaceChoices?: boolean + replaceChoices?: boolean, ): this; /**