Simple Flexible Autocomplete Plugin - Flexdatalist

File Size: 51.4 KB
Views Total: 28706
Last Update:
Publish Date:
Official Website: Go to website
License: MIT
   
Simple Flexible Autocomplete Plugin - Flexdatalist

Flexdatalist (v3) is a ES6 autocomplete and tag input library that transforms a standard text input into a fully featured suggestion dropdown backed by remote endpoints or static data arrays. Version 3 is a complete rewrite of the library. jQuery version (v2) is available here.

The library supports remote and static data sources, tag-style multi-value input, result grouping, keyboard navigation, accent-insensitive search, localStorage caching, and thin framework adapters for Vue 3, React 18+, and Svelte 4+.

Features:

  • Zero dependencies.
  • Auto-discovers and initializes any marked input on page load.
  • Retrieves suggestions from remote endpoints using GET or POST requests.
  • Accepts static data arrays or a JSON file URL as a data source.
  • Reads option values from linked native HTML option lists.
  • Supports multi-value tag input with add, remove, and toggle per-tag operations.
  • Groups result items by any data property with section headers and item counts.
  • Keyboard navigation: arrow keys, Enter, Escape, Backspace, and Tab.
  • Four search modes: starts-with, contains, exact match, and word-by-word.
  • Strips accent characters before comparison for accent-insensitive matching.
  • Highlights matched text within each result item.
  • Caches remote responses in browser storage with a configurable expiry and automatic garbage collection.
  • Links chained inputs and forwards their current values with every data request.
  • Fully themeable through CSS custom properties on any ancestor element.
  • Positions the suggestion dropdown correctly inside modal dialog elements.
  • ARIA attribute support for screen reader accessibility.
  • Returns a chainable API instance from the async initializer.

Migrating from v2 (jQuery)

The event names and CSS class names are identical between v2 and v3. Only the initialization syntax and method call style changed. Here is a direct comparison:

// --- v2 (jQuery) ---

// Initialize
$('#product-search').flexdatalist({ url: '/api/products', minLength: 2 });

// Listen for selection
$('#product-search').on('select:flexdatalist', fn);

// Get value
$('#product-search').flexdatalist('value');

// Set value
$('#product-search').flexdatalist('value', 'electronics');

// Destroy
$('#product-search').flexdatalist('destroy');


// --- v3 (Standalone) ---

// Initialize (async)
const [fd] = await Flexdatalist.init('#product-search', { url: '/api/products', minLength: 2 });

// Listen for selection
fd.on('select:flexdatalist', fn);
// or: document.querySelector('#product-search').addEventListener('select:flexdatalist', fn);

// Get value
fd.getValue();

// Set value
fd.setValue('electronics');

// Destroy
fd.destroy();

Swap the stylesheet from jquery.flexdatalist.css to flexdatalist.css. The class names are backwards-compatible.

How to use it (v3):

1. Install and import Flexdatalist into your project.

# NPM
$ npm install flexdatalist

# Vue 3
npm install flexdatalist flexdatalist-vue

# React 18+
npm install flexdatalist flexdatalist-react

# Svelte 4+
npm install flexdatalist flexdatalist-svelte
// Import the core constructor
import Flexdatalist from 'flexdatalist';

// Import the default stylesheet
import 'flexdatalist/css';

2. Or directly load the Flexdatalist's files in the document.

<link rel="stylesheet" href="/dist/flexdatalist.css">
<script src="dist/flexdatalist.js"></script>

<!-- Or from a CDN -->
<script src="
https://cdn.jsdelivr.net/npm/flexdatalist/dist/flexdatalist.umd.min.js
"></script>
<link href="
https://cdn.jsdelivr.net/npm/flexdatalist/dist/flexdatalist.min.css
" rel="stylesheet">

3. Auto-initialize a basic autocomplete input. This setup works well for a server-backed search field. The widget auto-initializes on page load when the input carries the `flexdatalist` class.

<input
  id="country-search"
  type="text"
  class="flexdatalist"
  data-url="/api/countries"
  data-search-in="name,code"
  data-value-property="code"
  data-min-length="2"
  name="country">

4. Initialize it in JavaScript:

<input id="city-picker" type="text" name="city">
const [cityPicker] = await Flexdatalist.init('#city-picker', {
  // Query your endpoint after 2 characters
  url: '/api/locations/cities',
  minLength: 2,

  // Search these properties in each result
  searchIn: ['name', 'region'],

  // Store the city id in the hidden value
  valueProperty: 'id',

  // Show a friendly label in the visible input
  textProperty: '{name} ({region})',

  // Render these fields in each dropdown row
  visibleProperties: ['name', 'region']
});

// Listen for item selection
cityPicker.on('select:flexdatalist', (e) => {
  console.log('Selected city:', e.detail);
});

// Read the stored value later
console.log(cityPicker.getValue());

5. Use local static data:

<input id="language-picker" type="text" name="language">
const [languagePicker] = await Flexdatalist.init('#language-picker', {
  data: [
    { id: 1, label: 'JavaScript', type: 'Language' },
    { id: 2, label: 'TypeScript', type: 'Language' },
    { id: 3, label: 'Rust', type: 'Language' }
  ],
  searchIn: ['label'],
  valueProperty: 'id',
  textProperty: '{label}',
  visibleProperties: ['label', 'type'],
  minLength: 0
});

// Open with an empty input on focus
languagePicker.search('');

6. Read options from a native datalist:

<!-- Keep your existing datalist markup -->
<input id="stack-picker" type="text" class="flexdatalist" list="stack-options" name="stack">

<datalist id="stack-options">
  <option value="Next.js">Next.js</option>
  <option value="Astro">Astro</option>
  <option value="SvelteKit">SvelteKit</option>
</datalist>

7. Create a multi-select tag input:

<input id="topic-picker" type="text" multiple name="topics">
const [topicPicker] = await Flexdatalist.init('#topic-picker', {
  data: [
    { slug: 'frontend', label: 'Frontend' },
    { slug: 'accessibility', label: 'Accessibility' },
    { slug: 'testing', label: 'Testing' },
    { slug: 'performance', label: 'Performance' }
  ],
  searchIn: ['label'],
  valueProperty: 'slug',
  textProperty: '{label}',
  multiple: true,
  limitOfValues: 5,
  removeOnBackspace: true,
  collapseAfterN: 3
});

// Add values in code
topicPicker.addValue('frontend').addValue('testing');

// Get the display text as a comma-separated string
console.log(topicPicker.getText('string'));

8. Group result rows:

<input id="asset-search" type="text" name="asset">
const [assetSearch] = await Flexdatalist.init('#asset-search', {
  data: [
    { id: 11, name: 'Button Kit', category: 'UI' },
    { id: 12, name: 'Chart Pack', category: 'UI' },
    { id: 21, name: 'Hero Photo', category: 'Media' }
  ],
  searchIn: ['name'],
  valueProperty: 'id',
  textProperty: '{name}',
  visibleProperties: ['name'],
  groupBy: 'category'
});

9. Send extra request parameters:

const [repoSearch] = await Flexdatalist.init('#repo-search', {
  url: '/api/repositories',
  searchIn: ['name'],
  valueProperty: 'id',
  textProperty: '{name}',
  params(keyword) {
    return {
      q: keyword,
      limit: 8,
      team: 'docs'
    };
  }
});

10. Chain related inputs:

<input id="region" type="text" name="region">
<input id="city" type="text" name="city">
const [cityField] = await Flexdatalist.init('#city', {
  url: '/api/city-search',
  searchIn: ['name'],
  valueProperty: 'id',
  textProperty: '{name}',
  relatives: '#region',
  chainedRelatives: true
});

// Update the region field in any way you want
document.querySelector('#region').addEventListener('change', () => {
  cityField.clear();
});

11. Framework Usage:

Vue 3

<script setup>
import { ref } from 'vue';
import { Flexdatalist } from 'flexdatalist-vue';
import 'flexdatalist/css';

const selectedProduct = ref('');
</script>

<template>
  <Flexdatalist
    v-model="selectedProduct"
    url="/api/products"
-min-length="2"
    placeholder="Search products..."
    @select="item => console.log('Selected:', item)"
  />
</template>

React

import { useRef } from 'react';
import { Flexdatalist } from 'flexdatalist-react';
import 'flexdatalist/css';

function ProductPicker() {
    const ref = useRef(null);

    return (
        <Flexdatalist
            ref={ref}
            url="/api/products"
            minLength={2}
            placeholder="Search products..."
            onSelect={item => console.log('Selected:', item)}
        />
    );
}

Svelte

<script>
    import { Flexdatalist } from 'flexdatalist-svelte';
    import 'flexdatalist/css';

    let selectedProduct = '';
</script>

<Flexdatalist
    bind:value={selectedProduct}
    url="/api/products"
    minLength={2}
    placeholder="Search products..."
    on:select={e => console.log('Selected:', e.detail)}
/>

12. Default plugin options. Options can be overwritten when initializing the plugin by passing an object literal, or set via data-attributes on the input element.

  • url (string|null): Remote URL to fetch results from.
  • data (array|string): Static data array or URL to a JSON file.
  • params (object|function): Extra params sent with every request, or a callback that returns params from the current keyword.
  • relatives (string|NodeList|null): CSS selector or nodes for related inputs whose values are sent with requests.
  • chainedRelatives (boolean): Disables the current input when all relatives are empty.
  • resultsProperty (string): JSON key that contains the results array.
  • minLength (number): Minimum character count before a search starts.
  • searchIn (string[]): Item properties used for matching.
  • searchContain (boolean): Matches the keyword anywhere in the string.
  • searchEqual (boolean): Requires a full exact match.
  • searchByWord (boolean): Splits the keyword into separate words and matches each word.
  • searchDisabled (boolean): Skips local filtering and leaves filtering to the server.
  • searchDelay (number): Debounce delay in milliseconds.
  • normalizeString (function|null): Custom normalizer function for string matching.
  • textProperty (string|null): Property name or placeholder template used for visible text.
  • valueProperty (string|string[]|null): Property stored as the value. '*' stores the full object as JSON.
  • visibleProperties (string[]): Properties rendered in each result row.
  • iconProperty (string): Property name that holds the image URL for an icon.
  • groupBy (string|false): Property used to group results.
  • maxShownResults (number): Maximum number of results rendered. 0 removes the cap.
  • focusFirstResult (boolean): Activates the first result row automatically.
  • noResultsText (string): Message shown when no item matches the keyword.
  • resultsLoader (string|null): URL of a loader image for pending results.
  • multiple (boolean|null): Enables tag input mode. The widget can infer this from the multiple attribute.
  • limitOfValues (number): Maximum number of selected tags. 0 means unlimited.
  • valuesSeparator (string): Separator used to serialize multiple values.
  • allowDuplicateValues (boolean): Allows the same value to appear more than once.
  • removeOnBackspace (boolean): Removes the last tag when the input is empty and the user presses Backspace.
  • toggleSelected (boolean): Lets users toggle a selected tag between enabled and disabled.
  • collapseAfterN (number|false): Collapses tags after a set count into one control.
  • collapsedValuesText (string): Label for the collapsed-tag control.
  • selectionRequired (boolean): Forces users to pick from results and blocks free text.
  • disabled (boolean|null): Starts the widget in a disabled state.
  • redoSearchOnFocus (boolean): Runs search again when focus returns to the field.
  • showAddNewItem (boolean): Shows an add-new row when no result matches.
  • addNewItemText (string): Label shown for the add-new row.
  • requestType (string): HTTP method for remote requests. Valid values are get and post.
  • requestContentType (string): POST content type. Valid values include x-www-form-urlencoded and json.
  • requestHeaders (object|null): Extra request headers.
  • keywordParamName (string): Parameter name used for the typed keyword.
  • searchContainParamName (string): Parameter name used for the contains-search flag.
  • cache (boolean): Enables localStorage caching.
  • cacheLifetime (number): Cache lifetime in seconds.
/** @type {string|null} Remote URL to fetch results from. */
url: null,
/** @type {Array|string} Static data array or URL string to pre-load. */
data: [],
/**
* Extra query-string / body params sent with every remote request.
* May also be a function `(keyword) => Object`.
* @type {Object|Function}
*/
params: {},
/**
* CSS selector or NodeList of inputs whose values are sent as
* `relatives[name]` with every request.
* @type {string|NodeList|null}
*/
relatives: null,
/** @type {boolean} Disable this input when all relatives are empty. */
chainedRelatives: false,
/** @type {boolean} Cache remote results in localStorage. */
cache: true,
/** @type {number} Cache lifetime in seconds. */
cacheLifetime: 60,
/** @type {number} Minimum characters before triggering search (0 = show all on focus). */
minLength: 3,
/** @type {string|false} Item property name to group results by. */
groupBy: false,
/**
* Property (or `{placeholder}` pattern) used as the display text in
* the alias input. Defaults to the first entry of `searchIn`.
* @type {string|null}
*/
textProperty: null,
/**
* Property name(s) stored as the actual value.
* Use `'*'` to store the entire matched object as JSON.
* @type {string|string[]|null}
*/
valueProperty: null,
/**
* Properties rendered inside each result `<li>`.
* Supports `{placeholder}` patterns. Defaults to `searchIn`.
* @type {string[]}
*/
visibleProperties: [],
/** @type {string} Property containing an image URL rendered as <img>. */
iconProperty: 'thumb',
/** @type {string[]} Properties searched when filtering results. */
searchIn: ['label'],
/** @type {boolean} Match keyword anywhere in the string (not just at start). */
searchContain: false,
/** @type {boolean} Require exact full-string match. */
searchEqual: false,
/** @type {boolean} Split keyword on spaces and match all words independently. */
searchByWord: false,
/** @type {boolean} Skip local filtering entirely (rely on server-side search). */
searchDisabled: false,
/** @type {number} Debounce delay in ms before running a search. */
searchDelay: 300,
/**
* Custom string normalizer called before comparison.
* Signature: `(string) => string`
* @type {Function|null}
*/
normalizeString: null,
/** @type {boolean|null} Allow multiple values. Inferred from [multiple] attribute when null. */
multiple: null,
/** @type {boolean|null} Start disabled. Inferred from [disabled] attribute when null. */
disabled: null,
/** @type {boolean} Require the user to select a result (disables free-text). */
selectionRequired: false,
/** @type {boolean} Automatically activate the first result item. */
focusFirstResult: false,
/** @type {string} Key in the remote JSON response that holds the results array. */
resultsProperty: 'results',
/** @type {number} Maximum number of results rendered (0 = unlimited). */
maxShownResults: 100,
/**
* Collapse multiple-value tags after this many items.
* Set `false` to disable collapsing.
* @type {number|false}
*/
collapseAfterN: 50,
/** @type {string} Label for the collapse toggle. `{count}` is replaced. */
collapsedValuesText: '{count} More',
/** @type {string} Message shown when no results match. `{keyword}` is replaced. */
noResultsText: 'No results found for "{keyword}"',
/**
* URL of a loading spinner image shown while fetching results.
* Set null to disable.
* @type {string|null}
*/
resultsLoader: null,
/** @type {boolean} Clicking a selected tag toggles its disabled state. */
toggleSelected: false,
/** @type {boolean} Allow the same value to be added more than once. */
allowDuplicateValues: false,
/** @type {boolean} Pressing Backspace on an empty alias marks then removes the last tag. */
removeOnBackspace: true,
/** @type {string} HTTP method for remote requests ('get' or 'post'). */
requestType: 'get',
/** @type {string} Content-type for POST bodies ('x-www-form-urlencoded' or 'json'). */
requestContentType: 'x-www-form-urlencoded',
/** @type {Object|null} Extra HTTP headers merged into every request. */
requestHeaders: null,
/** @type {string} Query-string parameter name that carries the typed keyword. */
keywordParamName: 'keyword',
/** @type {string} Query-string parameter name that carries the searchContain flag. */
searchContainParamName: 'contain',
/** @type {number} Maximum number of tags in multiple mode (0 = unlimited). */
limitOfValues: 0,
/** @type {string} Separator used when serialising multiple values into a string. */
valuesSeparator: ',',
/** @type {boolean} Show an "Add new item" option when no results exist. */
showAddNewItem: false,
/** @type {string} Text of the "Add new item" option. `{keyword}` is replaced. */
addNewItemText: 'No results found for "{keyword}". Click to add it.',
/** @type {boolean} Log warnings to the console. */
debug: true,

13. API methods.

// Get the current stored value
fd.getValue();

// Get the visible text in default array mode, string mode, or a custom separator
fd.getText();
fd.getText('string');
fd.getText(' | ');

// Replace the current value
fd.setValue('london');

// Append one or more values in multiple mode
fd.addValue('frontend');
fd.addValue(['frontend', 'testing']);

// Remove a selected value in multiple mode
fd.removeValue('frontend');

// Toggle a tag state when toggleSelected is active
fd.toggleValue('frontend');

// Clear the current selection
fd.clear();

// Disable the widget
fd.disable();

// Enable the widget
fd.enable();

// Set readonly state or read it back
fd.readonly(true);
fd.readonly();

// Check disabled state
fd.isDisabled();

// Check readonly state
fd.isReadonly();

// Trigger a search from code
fd.search('san');

// Close the dropdown
fd.closeResults();

// Read one option at runtime
fd.getOption('minLength');

// Update one option at runtime
fd.setOption('minLength', 1);

// Subscribe to a custom event
fd.on('select:flexdatalist', (e) => {
  console.log('Item selected:', e.detail);
});

// Remove an event listener
const onChange = (e) => {
  console.log('Changed:', e.detail);
};
fd.on('change:flexdatalist', onChange);
fd.off('change:flexdatalist', onChange);

// Destroy the instance and restore the original input
fd.destroy();
fd.destroy(true);

// Initialize one or more inputs
const instances = await Flexdatalist.init('.js-auto', {
  minLength: 2
});

// Get the instance attached to one element
const existing = Flexdatalist.getInstance('#city-picker');

14. Events.

// Fires when the widget finishes initialization
input.addEventListener('init:flexdatalist', function (e) {
  console.log(e.detail);
});

// Fires when a result is selected
input.addEventListener('select:flexdatalist', function (e) {
  console.log(e.detail);
});

// Fires when the stored value changes
input.addEventListener('change:flexdatalist', function (e) {
  console.log(e.detail);
});

// Fires when values are cleared
input.addEventListener('clear:flexdatalist', function (e) {
  console.log(e.detail);
});

// Fires when the add-new row is clicked
input.addEventListener('addnew:flexdatalist', function (e) {
  console.log(e.detail);
});

// Fires before selection is applied
input.addEventListener('before:flexdatalist.select', function (e) {
  console.log(e.detail);
});

// Fires after selection is applied
input.addEventListener('after:flexdatalist.select', function (e) {
  console.log(e.detail);
});

// Fires before value extraction
input.addEventListener('before:flexdatalist.value', function (e) {
  console.log(e.detail);
});

// Fires after value extraction
input.addEventListener('after:flexdatalist.value', function (e) {
  console.log(e.detail);
});

// Fires before one tag is removed
input.addEventListener('before:flexdatalist.remove', function (e) {
  console.log(e.detail);
});

// Fires after one tag is removed
input.addEventListener('after:flexdatalist.remove', function (e) {
  console.log(e.detail);
});

// Fires before local filtering starts
input.addEventListener('before:flexdatalist.search', function (e) {
  console.log(e.detail);
});

// Fires after local filtering finishes
input.addEventListener('after:flexdatalist.search', function (e) {
  console.log(e.detail);
});

// Fires before result rows render
input.addEventListener('show:flexdatalist.results', function (e) {
  console.log(e.detail);
});

// Fires after result rows render
input.addEventListener('shown:flexdatalist.results', function (e) {
  console.log(e.detail);
});

// Fires when one result row element is created
input.addEventListener('item:flexdatalist.results', function (e) {
  console.log(e.detail);
});

// Fires when no results match
input.addEventListener('empty:flexdatalist.results', function (e) {
  console.log(e.detail);
});

// Fires when the dropdown starts removal
input.addEventListener('remove:flexdatalist.results', function (e) {
  console.log(e.detail);
});

// Fires before data loading starts
input.addEventListener('before:flexdatalist.data', function (e) {
  console.log(e.detail);
});

// Fires after data loading finishes
input.addEventListener('after:flexdatalist.data', function (e) {
  console.log(e.detail);
});

15. Theme the library with CSS custom properties:

:root {
   --fdl-accent:       #3b82f6;   /* Active highlight, focus ring, and selected background */
   --fdl-accent-fg:    #ffffff;   /* Text color rendered on the accent background */
   --fdl-accent-light: #eff6ff;   /* Soft tint applied to keyword-match highlights */
   --fdl-tag-bg:       #eff6ff;   /* Background color for each tag in multiple mode */
   --fdl-tag-border:   #bfdbfe;   /* Border color for each tag */
   --fdl-tag-fg:       #1d4ed8;   /* Text color inside each tag */
   --fdl-radius:       0.375rem;  /* Border radius on the dropdown and tags */
   --fdl-font-size:    0.875rem;  /* Base font size for the widget */
   --fdl-shadow:       0 4px 8px -2px rgba(0,0,0,.1),
                     0 12px 24px -4px rgba(0,0,0,.08);
}

/* Scope overrides to a specific container */
.dark-form {
   --fdl-accent:    #818cf8;
   --fdl-tag-bg:    #1e1b4b;
   --fdl-tag-border:#4338ca;
   --fdl-tag-fg:    #c7d2fe;
}

Alternatives:

Changelog:

v3.1.1 (2026-04-09)

  • Improved code structure and readability across the core Flexdatalist module
  • Enhanced request handling logic for better clarity

v3.1.0 (2026-04-04)

  • New API getText() — retrieve the user-facing display text from the input.
  • Added official adapters for React, Vue, and Svelte

v3.0.1 (2026-04-01)

  • Rewritten in Vanilla JavaScript.
  • Updated doc.

2021-02-16

  • prevent form submission when pressing enter to add value on multiple config

v2.3.0 (2021-02-14)

  • Added support for taking a string/value from nested objects for valueProperty, textProperty and visibleProperties
  • Allow to customize the parameter name 'contain' that goes to the server
  • Added 'params' option to also be a callback function that allows the customization of the parameters
  • Added event 'empty:flexdatalist.results'
  • Added event 'item:flexdatalist.results' to allow for personalization of the item result
  • Prevent form submit when adding value from enter key
  • Added isArray() polyfill
  • Removed deprecated jQuery methods to trigger/listen to events
  • Added 'requestHeaders' option
  • Fixed value duplication bug for multiple mode
  • Fix unescaped string in regex processing, on the highlight function (thks @antunesl)
  • Fix when handling the value limit
  • Fix for when array values are mixed with JSON object and simple strings
  • Fix when toggling values
  • Improved accessibility

2021-02-13

  • Find results for accented words event when the keyword doesn't have them
  • Fix for when array values are mixed with JSON object and simple strings

2020-06-11

  • JS Update

2018-03-25

  • added tabindex -1 on input to prevent usability issues

2018-01-09

  • prevent plugin to autodiscover/load the input

2017-09-26

  • added tabindex -1 on input to prevent usability issues

2017-09-10

  • placeholder fix

2017-09-09

  • dynamic multiple input size

2017-09-06

  • minor backspace value removal fix

2017-08-05

  • minor fix on toggle

2017-08-03

  • valueProperty now accepts array of properties to pick from object item as value

2017-07-29

  • added garbage collector for cache to prevent filling all localStorage available storage space

2017-07-28

  • don't hide input container when there's no values

2017-07-17

  • v2.1.3: minor fixes and improvements

2017-07-16

  • now behaviour more like a select control
  • minor changes

2017-07-15

  • v2.1.2: bugfix

2017-07-10

  • v2.1.1
  • better alias identification

2017-07-09

  • minor fix

2017-07-08

  • disabled state handling
  • improvements and fixes

2017-07-07

  • added options 'url ' to cache key

2017-07-05

  • Multiple values fix

2017-07-04

  • remove event fix

2017-07-03

  • added more option
  • added autocomplete off

2017-06-24

  • prevent multiple instances of flexdatalist

2017-06-19

  • added searchDelay option

2017-05-17

  • results position fixed

2017-04-05

  • Minor fixes in valueSeparator option

2017-03-21

  • default value fix

2017-02-28

  • minor fixes and improvements

2017-02-17

  • minor fixes

2017-02-14

  • on result item click, refocus field (multiple only)

2017-02-13

  • added search by word option

2017-01-21

  • added 'limitOfValues' option

2017-01-16

  • added 'allowDuplicateValues' and 'requestType' to change type of AJAX/HTTP request

2017-01-11

  • add value to multiple input with "enter" key press

2017-01-08

  • send options with the AJAX request

2017-01-07

  • minor fix

2017-01-04

  • minor tweak in CSS and disabled multiple selection
  • minor fix in the relative field name

2016-12-29

  • clear value on multiple values input
  • minor fix

2016-12-25

  • added possibility of having the current input keyword in noResultsText string with {keyword}

2016-11-05

  • minor fix
  • not clearing the value correctly

2016-10-28

  • console.log removed

2016-09-25

  • minor fix

2016-09-24

  • fixes and improvements

2016-09-14

  • Multiple Values: added option to disable selected value on click/tap

2016-09-10

  • minor fix

2016-08-11

  • respect input autofocus attribute

2016-08-07

  • allowing to add/change option(s) after input instance initialization

2016-07-15

  • on reset/destroy remove values

2016-07-12

  • v1.4.6

2016-07-09

  • fixed result highlight not matching correctly the keyword in field

2016-07-08

  • Prevent remove button class conflict

2016-07-02

  • Minor fix

2016-07-01

  • not processing default input value

2016-06-30

  • added 'relatives', 'maxShownResults' and 'chainedRelatives' options

2016-06-29

  • minor fix in loading the default value

2016-06-15

  • Ignore empty data parameter

2016-05-14

  • fixed data option being replaced by default option

2016-04-26

  • minor fix

This awesome jQuery plugin is developed by sergiodlopes. For more Advanced Usages, please check the demo page or visit the official website.