Robust Dynamic Multiple Select Widget For jQuery UI - UI MultiSearch

File Size: 97.1 KB
Views Total: 5357
Last Update:
Publish Date:
Official Website: Go to website
License: MIT
   
Robust Dynamic Multiple Select Widget For jQuery UI - UI MultiSearch

MultiSearch is a robust, extensible jQuery UI widget that provides a multiple select UI with autocomplete/autosuggestion for input fields such as tags input and token inputs.

Key features:

  • Type ahead partial searching with suggested results against either a remote or local data source.
  • Built-in caching and throttling logic to help alleviate load on a remote data source.
  • Result records can have any number of attributes which are passed through to template functions and triggered event handlers.
  • Multiple keys and search fields can be defined to enable duplicate detection, lookups, and hit highlighting.
  • Keyboard interaction to navigate suggestion list and selected items.
  • Many event hooks and callbacks to customize behavior and control layout and styling
  • API methods to get/set the list of selected items and add/remove individual items.

Basic usage:

1. Make sure you have jQuery, jQuery UI and Underscore JavaScript libraries installed in the document.

<script src="/path/to/jquery.min.js"></script>
<script src="/path/to/jquery-ui.min.js"></script>
<script src="/path/to/lodash.underscore.min.js"></script>

2. Download jQuery UI MultiSearch and include the jqueryui-multisearch.js after jQuery library.

<script src="src/jqueryui-multisearch.js"></script>

3. Create the html for a basic multiple select interface.

<div id="myMultiSearch">
  <div data-role="selected-list">
     <input data-role="input" type="text" placeholder="Search...">
  </div>

  <div data-role="picker" class="picker">
     <ul class="list-group" data-role="picker-list">
     </ul>
  </div>
</div>

4. Add predefined data to the multiple select.

var babyNames = [
   { name: 'Aaliyah' },
   { name: 'Aaron' },
   { name: 'Abigail' },
   { name: 'Adam' },
   { name: 'Addison' },
   { name: 'Adrian' },
   ...
];

5. Initialize the plugin and we're ready to go.

$("#myMultiSearch").multisearch({
  source: babyNames,
});

6. Full plugin options with default values.

/*
*  The data source to search.  Can be a string, function, or array of objects
*
*  - A string should be a valid remote datasource.
*
*  - A function can implement a data search and should call the passed in
*    callback with the results:
*
*       function ( term, callback ) { ... }
*
*  - An array repesents a local dataset and all searches will be done locally
*    on the contents.
*/
source: null,

/*
*  Hash of options that are used in the $.ajax call on a remote resource.
*  Only used when source is a string representing the path of the resource.
*  Currently accepts overrides for dataType and method options.  Also adds
*  a custom options:
*
*     - searchTerm: the parameter name that will contain the search term
*                   ( ie path/to/resource?term=abc )
*
*  Defaults:
*     searchTerm: 'term',
*     dataType: 'json',
*     method: 'GET'
*/
ajaxOptions: null,

/*
*  An array of fields in the result object which represent the unique key for the object.
*  Used to detect duplicate items.  If not set, will default to ['id']
*/
keyAttrs: null,

/*
*  An array of fields in the result object to search for the entered criteria.
*  If not set, will default to ['name']
*/
searchAttrs: null,

/*
*  A function that returns an HTML string repesenting the item to add to the suggestion picker
*  as a search is entered into the input..  The hash returned by the remote server or local cache
*  is passed to the function.  This can be a Underscore template() function.
*/
formatPickerItem: function( data ) {
  return '<li><a href="#">'+data.name+'</a></li>';
},

/*
*  A function that returns an HTML string repesenting the item to add to the selected
*  items list.  Called each time a search term is selected from the suggestion picker or,
*  when not found items are allowed, a new entry is completed.  The hash from the result
*  set is passed to the function.  This can be a Underscore template() function.
*/
formatSelectedItem: function( data ) {
  return '<a href="#">'+data.name+'</a>';
},

/*
*  When adding items that are not found in the suggestion picker, this function is called
*  to define the object that is expected in the formatSelectedItem() template.  Generally,
*  you'll leave the keyAttrs attributes null and set the primary display field with the
*  text from the input box which is passed to the function.
*/
buildNewItem: function( text ) {
  return { id: null, name: text };
},

/*
*  How many characters need to be typed to trigger a search
*/
minSearchChars: 2,

/*
*  How quickly can successive searches be triggered.  The value is in milliseconds
*  and uses Underscore's throttle() function to control triggering calls to the
*  remote resource.  This does not affect local cache searching.
*/
searchThrottle: 200,

/*
*  How many results to show in the picker.  Even if 200 are returned by the server, you
*  can control how many are actually displayed in the suggestion picker.  Set it to zero
*  to show everything.  Ensure you enable some kind of scrolling on the element you define
*  as the picker/picker-list role if you allow longer lists of items.
*/
maxShowOptions: 5,

/*
*  When to start refining a search against the local cache.  Each remote search is saved by term
*  if the remote result set has less than minLocalCache items in it, each subsequent character typed
*  will use that result as a basis for searching.  This can reduce the number of hits on the remote
*  resource and can be fine-tuned to match your needs.  Set it to zero to disable local refinements
*  against the cache.  If you do use it, make sure any limits on the server side are set high enough
*  to ensure that a search term that refines the remote search below this threshold will contain all
*  possible items that could be found if the subsequent searches were run against the server.
*/
minLocalCache: 50,

/*
*  Can items not found in the suggestion picker be added to the seleced item list.  If allowed,
*  buildNewItem() will be called to allow setting defaults on the object that represents the
*  search data to be prefilled before calling formatSelectedItem().  The adding and added events
*  will have the notfound flag set to true when an item will be added that in not in the picker.
*/
preventNotFound: false,

/*
*  Using the keyAttrs, should duplicates be prevented.  A duplicate event is triggered if one is found
*  allowing custom UI logic to be defined externally.  Otherwise, nothing will happen.  The suggestion
*  picker will remain open and it will appear that the widget is not responding.  Items that are not
*  found in the picker but are added to the selected item list will not be considered a duplicate
*  unless you provide custom logic during adding that would assign a key.
*/
preventDuplicates: true,

/*
*  Automatically resize the input box to match the text.  Helpful for inline/floating elements so
*  the input only wraps as needed.  Disable if using block elements that you want to fill the
*  parent space.
*/
useAutoWidth: true,

/*
*  Use jQueryUI.position plugin to position the picker box relative to the input control.  The default is the
*  basic drop-down menu box under the input entry box.  Depending on the structure, you may want to adjust this
*  setting.
*/
pickerPosition: {
  my: 'left top',
  at: 'left bottom',
},

/*
*  Where is the input relative to the item list.  Determines how the keyboard navigation
*  moves through the items and where new items are added.  Valid values are "start" and "end"
*  defaults to "end".  Depending on where you position the input box, adjust this setting
*  so the UI interactions make sense.
*/
inputPosition: 'end',

/*
*  For each field defined in searchAttrs, search for the input text using the function below.  This is used
*  for both local cache searches and hit highlighting.  It should match with the search method from the remote.
*  The default is to look for the search string anywhere in the target field.  If you want to match only from
*  the leading edge of the field, you'll need to override this function.
*/
localMatcher: function( needle, haystack ) { return haystack.toLowerCase().indexOf( needle.toLowerCase() ) > -1; }

7. API methods. These methods all suppress any events that would normally be triggered by user interaction.

  • Value: Getter/Setter for list of selected items.  Use it to retreive the list of items entered by the user or seed the list with existing items (from a database, etc). Getting the value returns a shallow clone of the objects in the item list.  If you're using nested objects from a shared dataset, be aware you may be referencing them in the returned set. Setting the value will destory the current selections.  If you want more control, use add/remove to selectively update the list.
  • Add: Add an item to the selection list.  Optional second arguement can be used to specify the position to insert the item.  If the item already exists, it will be merged and trigger rendering the content of the item again such that updated data can be applied to the list.
  • Remove: Remove one or all items form the selected list: No arguements will remove everything; Pass an Integer representing the ordinal index of the item to remove; Pass an Object containing the keys of the item to remove.

Changelog:

2022-10-13

  • Only autocomplete if dropdown is visible

2016-07-13

  • Unset any auto-selected item when Esc key is pressed

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