Usage
Initialisation
Explicit initialisation
Call dropulous() on any <select> or <input type="text"> element:
<select id="my-field">
<option value="one">One</option>
<option value="two" selected>Two</option>
<option value="three">Three</option>
</select>
<script>
dropulous(document.querySelector('#my-field'));
</script>
Pass an options object as a second argument:
dropulous(document.querySelector('#my-field'), {
source: '/api/options/',
canAdd: true,
});
Auto-initialisation
Add a data-dropulous attribute and Dropulous will initialise the element
automatically on DOMContentLoaded:
<select data-dropulous data-source="/api/options/">
</select>
Calling dropulous() on an already-initialised element returns the existing instance.
Auto-initialisation runs Dropulous.init() on DOMContentLoaded. Call it yourself
to initialise elements added to the page later, or to use a different selector:
Dropulous.init('.my-selector', { canAdd: true });
It accepts a CSS selector (default 'select[data-dropulous], input[data-dropulous]'),
a single element, or a collection of elements, and returns an array of the
Dropulous instances created.
Dropdown choices
You can set dropdown choices in three ways:
From the DOM
If you provide no options, Dropulous will take existing options from the <select>
element:
<select id="my-field">
<option value="one">One</option>
<option value="two" selected>Two</option>
</select>
This will only work with a <select> element; for an <input> use one of the other
options below.
From a JSON attribute
Dropulous will check for a data-options attribute on the field. This should contain
a JSON array of {value, label} objects:
<input
id="my-field"
type="text"
value="two"
data-options='[
{"value": "one", "label": "One"},
{"value": "two", "label": "Two"}
]'
>
From an API
Dropulous can also fetch options from a remote API endpoint. Set the data-source
attribute to the URL of your API, and Dropulous will fetch options as the user types:
<select id="my-field" data-source="/api/options/" data-value="two">
</select>
The API is called with a ?q=<query> parameter as the user types. It must return an
object with an options array:
{
"options": [
{"value": "one", "label": "One"},
{"value": "two", "label": "Two"}
]
}
If your endpoint paginates and there are more matches than you’ve returned, set
more: true so Dropulous knows to keep querying the API as the user refines their
search:
{
"options": [
{"value": "one", "label": "One"},
{"value": "two", "label": "Two"}
],
"more": true
}
When more: true, Dropulous shows an ellipsis at the bottom of the list
to indicate there are unseen matches for the current query.
more defaults to false, so once you’ve returned a response Dropulous normally
assumes it has every match for that query, and then filters it locally as the user keeps
typing a more specific search.
To include extra data on an option (for use with custom formatters),
add a data object to that option:
{
"options": [
{"value": "clubs", "label": "Clubs", "data": {"icon": "/icons/clubs.svg"}}
]
}
To return HTML labels from the API, add an optional html key alongside the
plain-text label (which will then just be used for search matching):
{
"options": [
{"value": "clubs", "label": "Clubs", "html": "<img src='/icons/clubs.svg'> Clubs"}
]
}
Single vs multiple selection
Single selection is the default. Multiple selection is enabled by the multiple
attribute on a <select>, or the data-multiple attribute on an <input>:
<!-- Multiple select -->
<select id="my-field" multiple>
<option value="one">One</option>
<option value="two" selected>Two</option>
<option value="three" selected>Three</option>
</select>
<!-- Multiple input -->
<input
id="my-field"
type="text"
value="two,three"
data-multiple
data-options='[{"value":"one","label":"One"},{"value":"two","label":"Two"},{"value":"three","label":"Three"}]'
>
In multiple mode, selected values are displayed as removable tags.
Custom parsing
For <input> elements, the field value is a comma-separated string, split by
parseValue(str) and rejoined by formatValue(values).
You can override both in a subclass to use a different format:
class MyDropulous extends Dropulous {
parseValue(str) {
return str.split(';');
}
formatValue(values) {
return values.join(';');
}
}
Allowing new options (tagging)
Set data-can-add (or canAdd: true in the options object) to let users create
options that aren’t in the list:
<select id="my-field" data-can-add>
<option value="one">One</option>
</select>
When the user types a value that doesn’t match any option and presses Enter (or blurs the field), the new value is added and selected.
Field synchronisation
The original <select> or <input> element is kept hidden but stays in sync with
the Dropulous control at all times.
Form submission, change event listeners, and any other code that reads from the
original field will work without modification.