===== Usage ===== Initialisation ============== Explicit initialisation ----------------------- Call ``dropulous()`` on any ```` element: .. code-block:: html Pass an options object as a second argument: .. code-block:: js 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``: .. code-block:: html 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: .. code-block:: js 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 `` This will only work with a ```` 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: .. code-block:: html .. _from-api: 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: .. code-block:: html The API is called with a ``?q=`` parameter as the user types. It must return an object with an ``options`` array: .. code-block:: json { "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: .. code-block:: json { "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 :ref:`custom formatters `), add a ``data`` object to that option: .. code-block:: json { "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): .. code-block:: json { "options": [ {"value": "clubs", "label": "Clubs", "html": " Clubs"} ] } Single vs multiple selection ============================ Single selection is the default. Multiple selection is enabled by the ``multiple`` attribute on a ````: .. code-block:: html In multiple mode, selected values are displayed as removable tags. Custom parsing -------------- For ```` 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: .. code-block:: js 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: .. code-block:: html 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 ```` 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. Keyboard navigation =================== - **Down arrow / Up arrow** - move through options - **Enter** - select the highlighted option (or add a new one if ``canAdd`` is set) - **Escape** - close the dropdown - **Backspace** (multiple mode, empty input) - remove the last selected tag .. _instance-api: Instance API ------------ ``dropulous()`` returns a Dropulous instance with the following methods: .. js:method:: selectOption(value) Select an option by value, and either replace the current selection in single mode. or add it to the selection in multiple mode, .. js:method:: deselectOption(value) Remove a specific value from the selection. .. js:method:: addNewOption(value) Create a new option and immediately select it. .. js:method:: open() Open the dropdown. .. js:method:: close() Close the dropdown. .. js:method:: getValue() Return the selected value or ``null`` (single mode), or the selected values as an array (multiple mode), .. js:method:: setValue(value) Replace the current selection. Accepts a single value, an array of values (multiple mode only), or ``null`` to clear. .. js:method:: setOptions(options) Replace the available options with an array of ``{value, label}`` objects. .. js:method:: clearCache() Discard cached remote results, so the next open or keystroke fetches fresh data from ``source``. Use this if the data behind a remote source has changed. .. js:method:: destroy() Remove the Dropulous control and restore the original field. .. code-block:: js const field = dropulous(document.querySelector('#my-field')); field.selectOption('two');