Dependencies

NameFile
Coredist/js/core.js
Selectmenudist/js/selectmenu.js

Assets

TypeFile
jsdist/js/autocomplete.js
cssdist/css/autocomplete.css
lessdist/less/autocomplete.less
scssdist/scss/autocomplete.scss

Examples

One Selection, Predefined Data.

Bare bones Autocomplete example. You can select one result from a prefefined list of data or enter your own text.

Four Selections

Same setup as the last, except this time you can select up to four entries. You can change the number of selections with the limit (or data-limit) config option.

Categories & Headers

To use categories, your data must be an array of objects with a 'label' and 'items' property. The 'items' is an array of results the user can select from and each result must contain at least a 'label' and 'value' property.

Remote URLs

Same setup as the last (up to four total entires) but this time we're hitting a remote endpoint for data. You can achieve remote/xhr ability by hooking into the request events (see Events Section).

Comma Seperate

Add the ability to split user entires by comma and enter those values into the selections stack with the comma (or data-comma) config option.

Only Allow Result Selections

Retstrict users to only select results from the result list and NOT enter anything they choose with the anything (or data-anything) config attribute.

Removed Tag UI

Remote the tag interface easily. Just set the notags (or data-notags) config option to true.

Setup

<div class="mk-ac-root">
	<input class="mk-ac" type="text" name="search" aria-label="Search for Stuff" placeholder="Search..." />
</div>

Configuration Options via Data-Attributes

There are two ways to configure Autocomplete, the first of which is by providing data attributes on the root input. Below is a list of all possible data attributes you may add to configure an instance. All data attributes are optional.

<div class="mk-ac-root">
	<input type="text"
		name="search"
		aria-label="Search for Stuff"
		<!-- Number of characters before filtering/requesting data. Default is 1. -->
		data-chars="3"
		<!-- Keeps the list of results open (after selecting) when set to true. Default is false. -->
		data-persistopen="true"
		<!-- time in milliseconds for a data request to kick off after user entry. Default is 300. -->
		data-time="500"
		<!-- total number of possible results a user can select. Default is 1. -->
		data-limit="4"
		<!-- Allow the user to enter, or 'select,' anything they like, including their own input. Default is true. -->
		data-anything="true"
		<!-- Allows commas to seperate user entered values and add them to the selection list. Default is false. -->
		data-comma="true"
		<!-- Allows searching any data fields, or omission of a default. Default is "value,label". -->
		data-searchkeys="label,myOtherField"
		<!-- Remove the tag UI. Default is false. -->
		data-notags="false"
		<!-- Allows delete (when text entry is '') to pop the last selected items from selections. -->
		<!-- Default is false for single select and true for more than one (limit > 1). -->
		data-doubledelete="true"
		placeholder="Search..." />
</div>

Instantiation

Below is an example of instantiating an Autocomplete. Like all other Mk components, the first argument is the root and the second is configuration options. In the example below, we've provided all possible config options, however, all config properties are completely optional.

//get autocomplete object
var Autocomplete = Mk.get('Autocomplete');
//
//create instance
var autocomplete = new Autocomplete('#selector', {
	//number of selections user is allowed. Default is 1
	limit: 1,
	//number of characters typed by user before kicking off a request/search. Default is 1
	chars: 3,
	//keeps the list of results open (after selecting) when set to true. Default is false.
	persistopen: true,
	//delay before trigering request events for data. Default is 300.
	time: 500,
	//allow the user to input/select anything (including anything they enter manually) Default is true.
	anything: true,
	//allows the doubledelete functionality to pop old selections. Default is true.
	doubledelete: false,
	//hide the tag UI. Default is false.
	notags: false,
	//allow comma seperated user input to be split and added to selections. Default is false.
	comma: true,
	//allows searching any data fields, or omission of a default. Default is "value,label".
	searchkeys: "label,myOtherField",
	//data you would like to provide on instantiation (vs. remote requests).
	//you can also do both static and remote data.
	data: [
		..predefined data set..
		{
			label: 'Example Result 1',
			value: 'my-result-key'
		}
	],
	//template overrides/additions
	templates: {
		..template overrides..
	},
	//format overrides/additions
	formats: {
		..format overrides..
	},
	//events you want bound
	events: {
		..you can bind events here or by using on() one() and off()..
	}
});

Dynamic Data and Remote Urls

Autocomplete does not take care of XMLHttpRequests, JSONP, or any other method of retrieving dynamic data to populate a users search. We do, however, provide the proper hooks for you to tie your own custom requests into the Autocomplete. This is actually great news. Now you can use whatever existing tools for remote requests your project is already using. Below is an example of a JSONP call using jQuery, which hooks into the Autocomplete system.

//get the autocomplete object
var Autocomplete = Mk.get('Autocomplete');
//
//create an instance
var autocomplete = new Autocomplete('.mk-ac-root' /*, options */);
//will keep refernece to our ajax request
var xhr;
//
// set the request.send and request.abort events
autocomplete.on('request.send', function (query, requestnum) {
	//notify screen readers and add optional loading indicator
	ac.notify(ac.NOTIFY_STATES.LOADING, query);
	//
	//you can use the 'requestnum'
	//to catch situations where an abort() procedure isn't possible.
	//see the success method for more info
	xhr = $.ajax({
		url: 'http://dev.markitondemand.com/Api/v2/Lookup/jsonp',
		data: {input: query},
		type: 'get',
		dataType: 'jsonp',
		success: function (data) {
			//
			//requests is a number keeping track of the current request count.
			//you can use that to check if a request is 'stale' and leave or abort an old request.
			if (autocomplete.requests > requestnum) {
				//exit, we have a more current request coming
				return;
			}
			//
			//autocomplete expects two properties to function correctly: value and label.
			//our API endpoint does not hand back objects with those properties, but we can set them...
			autocomplete.each(data, function (obj, index) {
				obj.label = obj.Name;
				obj.value = obj.Symbol;
			});
			//
			//We're also going to store the retrieved data in the autocomplete cache.
			//This way if the user searches the same term again, we'll pull it from cache vs. sending another request.
			autocomplete.setCache(query, data);
			//
			//finally, it's time to render out data.
			autocomplete.render(data, query);
		},
		error: function () {
			//autocomplete has events already set up if/when an error occurs.
			//The events notify screen readers and users of what's going on, so it's important to wire them in.
			//you can also add your own handlers to the request.error event.
			autocomplete.emit('request.error');
		}
	});
	//
	// lets also set up an abort events
	autocomplete.on('request.abort', function () {
		//abort our xhr request if possible.
		//we can also use the requests/requestnum logic to do our own aborting.
		if (xhr) xhr.abort();
	})
});

Events

All events are part of the Mk EventEmitter and *not* added to the DOM. Events are also called in context of the component instance so it isn't a great idea to use a proxy function to change context, as you'll loose a lot of beneficial object access.

render

Fired when data has been retrieved and the list is ready to be built. Binding this event replaces the original rending with your own, custom, rendering.


instance.on('render', function (data) {
	console.info(data);
});
		

change

Fires when autocomplete value changes.


instance.on('change', function () {
	console.info('base 64:', this.value);
	console.info('raw objects:', this.selections);
});
		

submit

Fires when autocomplete submit button is clicked/pressed.


instance.on('submit', function () {
	console.info('base 64:', this.value);
	console.info('raw objects:', this.selections);
});
		

show

Fired when menu is shown.


instance.on('show', function () {
	console.info('Menu has opened!');
});
		

hide

Fired when menu is hidden.


instance.on('hide', function () {
	console.info('Menu has closed!');
});
		

activate

Fired when an option becomes active.


instance.on('activate', function (option, keyboard) {
	console.info('active option:', option);
	console.info('came from keyboard (vs mouse):', keyboard);
});
		

disabled

Fired when selectmenu is disabled, if previously enabled.


instance.on('disabled', function () {
	console.info('Selectmenu has been diabled.');
});
		

enabled

Fired when selectmenu is enabled, if previously disabled.


instance.on('enabled', function () {
	console.info('Selectmenu has become enabled.');
});
		

update

Fired when updates are made to the rendered UI through the use of update().


instance.on('update', function () {
	console.info('Changes to the native autocomplete have been applied to the UI.');
});
		

capacity

Fired when you've reached the selection limit. Does not fire for single selects.


instance.on('capacity', function () {
	console.info('We reached capacity!');
});
		

create.tag

Fired when a tab is being created. You can customize the tag properties through here.


instance.on('create.tag', function (o) {
	o.label = 'New Label!';
});
		

request.send

Used when hooking into request logic to send requests to the server for data.


instance.on('request.send', function (query, requestnumber) {
	console.info('about to search for ', query);
});
		

request.error

Since remote requests are left the end developers, this event must be emit by the end developer as well, typically in an error handler. Since the end developer emits this event, you may pass in any arguments you like.


instance.on('request.error', function () {
	console.info('request failed');
});
		

request.abort

Fired when a request is being aborted.


instance.on('request.abort', function () {
	console.info('my request is being aborted due to new user actions.');
});
		

API

Below are the different public properties and methods accessible to you, the end developer. All of these are accessible on your Autocomplete [ac] instance as well as inside event handlers bound to your instance. Some methods have intentionally been left out due to their difficulty tof use for end developers vs. internal use.

Methods

  • instance.unmount()

    Remove all mounted nodes, data, events, and cache associated with the Autocomplete instance to free up memory and resources.

    • No params required.
  • instance.move([up])

    Move the active list item up or down from the currently activated.

    Parameters
    • Name
      up
      Type
      Boolean
      Description
      Set to true to move up the list. Default is false.
  • instance.search(key[, add])

    Runs a search for the query.

    Parameters
    • Name
      key
      Type
      String
      Description
      a string representing query text.
    • Name
      add
      Type
      Boolean
      Description
      Add the the current query, or replace the current query. Default is false (replace).
  • instance.request()

    Invokes the request event handlers associated with the autocomplete instance. If your autocomplete uses dynaimc data (API endpoints), setup a requset event to hook your requset into.

    • No params required.
  • instance.flatten(value)

    Invokes JSON.stringify and btoa on an object.

    Parameters
    • Name
      value
      Type
      Object
      Description
      Object to convert to a flattened string.
  • instance.unflatten(value)

    Invokes atob and JSON.parse on a string.

    Parameters
    • Name
      value
      Type
      String
      Description
      String to convert back into an object.
  • instance.hasCache(key)

    Returns true when cache exists for a query, false when it does not.

    Parameters
    • Name
      key
      Type
      string
      Description
      a previously searched query.
  • instance.getCache(key)

    Returns data for a previously cached query.

    Parameters
    • Name
      key
      Type
      string
      Description
      a previously searched query.
  • instance.setCache(key, data)

    Caches object for a given query.

    Parameters
    • Name
      key
      Type
      string
      Description
      a string represending query text.
    • Name
      data
      Type
      Object/Array
      Description
      Object to be cached.
  • instance.data([value])

    Generate a JSON representation of the current autocomplete state.

    Parameters
    • Name
      value
      Type
      String
      Description
      Cache key for query data. Empty will give you static data (if provided).
  • instance.filterData(key, data)

    Filters a dataset by query text.

    Parameters
    • Name
      key
      Type
      String
      Description
      a string represending query text.
    • Name
      data
      Type
      Array
      Description
      A dataset as Array (typically of objects).
  • instance.prepData(data[, query])

    Prep a date set for use with templating and user interactions.

    Parameters
    • Name
      data
      Type
      Array
      Description
      An array of (typically) objects. Objects must contain a 'value' and 'label' property for templating and mapping.
    • Name
      query
      Type
      String
      Description
      A text term used for term highlighting results for the user.
  • instance.select(value[, silent])

    Selects a value from results, or a custom value provided by you.

    Parameters
    • Name
      value
      Type
      String
      Description
      a flattened string representing a selection object.
    • Name
      silent
      Type
      Boolean
      Description
      Pass true to prevent change events from triggering.
  • instance.deselect(value[, silent])

    Deselects a value from results, or a custom value provided by you.

    Parameters
    • Name
      value
      Type
      String
      Description
      a flattened string representing a selection object.
    • Name
      silent
      Type
      Boolean
      Description
      Pass true to prevent change events from triggering.
  • instance.deselectAll([silent])

    Removes all current selections.

    Parameters
    • Name
      silent
      Type
      Boolean
      Description
      Pass true to prevent change events from triggering.
  • instance.exists(value)

    Check raw object against autocomplete selections for a match.

    Parameters
    • Name
      value
      Type
      Object
      Description
      Object with a property named 'value' to check for selection matches.
  • instance.abort()

    Invokes the abort event to let end developer know they should cancel their current request, if any.

    • No params required.
  • instance.error()

    Method invoked when request error event is emit. When making requests for search term data, if an error occurs, emit the error event to invoke this functionality.

    • No params required.
  • instance.blur()

    Invokes XHR abort event and stops internal loading processes.

    • No params required.
  • instance.clear()

    Clears screen reader text, list results, and close the menu.

    • No params required.
  • instance.pop()

    Pop a selection from the current collection.

    • No params required.
  • instance.notify(type[, query])

    Sends text notifications to the screen reader about the state of the Autocomplete. Also applies state classes (request loading for example) to the Autocomplete.

    Parameters
    • Name
      type
      Type
      CONSTANT
      Description
      CONSTANT value from instance.NOTIFY_STATES which determines what format text to use for screen readers and user message updating.
    • Name
      query
      Type
      String
      Description
      Used in the format text for screen readers and user message updates.
    • Name
      count
      Type
      Number
      Description
      Result count. Only used for the NOTIFY_STATES.LOADED type representing the number of results returned from the request.
  • instance.updateRoot()

    Updates the root input to reflect the current Autocomplete selections.

    • No params required.
  • instance.render(data[, query])

    Renders a result list based off the data parameter provided

    Parameters
    • Name
      data
      Type
      Array
      Description
      Array of data objects to create a list from. Data objects must contain a 'label' and 'value' property.
    • Name
      query
      Type
      String
      Description
      The query term representing the data set. Used for screen readers. If not provided, default is instance.query property.
  • instance.update()

    Make changes to your original input then call this for the UI to consume new changes.

    Parameters
    • Name
      config
      Type
      Object
      Description
      Configuration object used to rewrite current properties..

Properties

  • instance.input

    The wrapped, rendered triggering input element.

  • instance.tagroot

    The wrapped root element holding tags.

  • instance.tags

    The wrapped collection of UI tags.

  • instance.live

    The wrapped live element responsible for updating screen reader users with atomic information.

  • instance.notifications

    Similar to the live element, but hold notifications such as when a request fails.

  • instance.isLoading

    Boolean representing if the autocomplete is requesting data.

  • instance.limit

    Number of selections an autocompelete instance can have

  • instance.doubledelete

    Boolean representing whether doubledelete is enabled.

  • instance.multiple

    Boolean representing if the use can select more than one result.

  • instance.capacity

    Boolean representing if the autocomplete is at max selections.

  • instance.anything

    Boolean representing if the autocomplete will accept any value or only a value from the result list.

  • instance.value

    String value set on your root's input element. The value is flattened, which means it's an object that's been base64 encoded.

  • instance.empty

    Boolean representing if we have no results.

  • instance.remote

    Boolean representing if our instance is equipt to make XHR requests for data.

  • instance.searchkeys

    Array of object fields to be searched.

  • instance.deletecount

    How many times delete has been pressed in a row. Used with doubledelete.

  • instance.selections

    Array of objects holding the value/label pairs currently selected.

  • instance.requests

    How many requests have been kicked off in total.

  • instance.cache

    Object containing all cached requests.

  • instance.query

    The current query string.