Skip to content

Latest commit

 

History

History
159 lines (123 loc) · 6.15 KB

README.md

File metadata and controls

159 lines (123 loc) · 6.15 KB

Autocomplete npm version

This is a light-weight JavaScript widget that provides autocomplete for freeform text inputs that get their suggestions from remote sources. One such example is address autocomplete. It has the following nice features:

  • Handles fetching results via HTTP.
  • Supports keyboard navigation.
  • Customizable to support different data format.
  • No dependencies and small in size.

Demo: http://danqing.github.io/autocomplete/

Install

Get it from npm, or simply download the ac.js file and put it into your project.

npm install remote-ac --save

Usage

var AC = require('remote-ac');
var ac = new AC(input, urlFn, requestFn, resultFn, rowFn, triggerFn, anchorEl);

where:

  • input is the text field that holds the user input to autocomplete.
  • urlFn is the function that takes the user input string and returns the URL to retrieve the autocomplete results. It is assumed that it is a GET request.
  • requestFn is the function that allows full customization of a request behavior. It takes the user input string and should update this.results with the desired result and call this.render() to update the autocomplete. If this function is provided, both urlFn and resultFn will be ignored.
  • resultFn is the function that processes the returned results, in case you have some custom format. It takes the raw HTTP response, and returns a list of autocomplete results. If the response is already a list of results, you do not need to specify this function.
  • rowFn is the function that takes the data of a row to render the row in the DOM. If it is not provided, autocomplete will generate the rows automatically.
  • triggerFn is the function called when the user clicks on an autocomplete row. The result associated with the row will be passed in as the first parameter. The second parameter is the triggering event (click or keypress) so you can prevent event bubbling or process it in other ways.
  • anchorEl is the element to position the autocomplete against, in case you don't want it to be positioned below the input element.

If you would like to use the default row rendering function, you can have a primary text label and an optional secondary text label. The default keys to them are title and subtitle, i.e.:

[{
  'title': 'Some Title Label',
  'subtitle': 'Some Subtitle Label',
  'other_key': '...'
}, {
  ...
}]

If your payload has some other keys, you can change the label keys with the following:

var ac = new AC(...);
ac.primaryTextKey = 'your_key';
ac.secondaryTextKey = 'your_secondary_key';

Full example (find it in the gh-pages branch):

var service = new google.maps.places.PlacesService(...);

// Custom request function.
var requestFn = function(query) {
  if (!query) {
    this.results = [];
    this.render();
    return;
  }

  service.textSearch({query: query}, (results, status) => {
    this.results = [];
    if (status === google.maps.places.PlacesServiceStatus.OK) {
      this.results = results.length > 5 ? results.slice(0, 5) : results;
    }
    this.render();
  });
};

var triggerFn = function(obj) {
  var output = document.getElementById('output');
  output.textContent = 'You selected ' + obj.name;
};

var input = document.getElementById('input');
var ac = new AC(input, null, requestFn, null, null, triggerFn);
// This is the key to get the primary text from.
ac.primaryTextKey = 'name';
// This is the key to get the secondary text from. If the key does not exist,
// it will be ignored.
ac.secondaryTextKey = 'formatted_address';

Three other configurations are available:

  • delay is the delay after each keystroke before firing the XHR request, in milliseconds. Default is 300ms.
  • minLength is the minimum input length required before firing the XHR request. Default is 1. This only works with the default requestFn. If you supply a custom requestFn, it will always be triggered and it is up to you to handle minimum length logic.
  • cssPrefix is the prefix added to each CSS class name, in case the default prefix conflicts, or you have multiple widgets with different styling. The default is 'ac-'.

They are not exposed as part of the constructor function, but can be set after the autocomplete object is created:

var ac = new AC(...);
ac.delay = 500;
ac.minLength = 3;
ac.cssPrefix = 'ac-secondary-widget-';

When the autocomplete is created, it's automatically activated, meaning that focusing on the input will trigger the autocomplete logic. You can call ac.deactivate() to deactivate the autocomplete, and reactivate it with ac.activate().

Styles

The library comes with a default style for your reference. Start with it so the autocomplete is working, and then modify it to meet your UI requirements.

The following CSS classes are applied to the autocomplete DOM elements if you are using the default rendering system:

AC.CLASS = {
  WRAPPER: 'ac-wrap',
  ROW_WRAPPER: 'ac-rwrap',
  ROW: 'ac-row',
  SELECTED_ROW: 'ac-row selected',
  PRIMARY_SPAN: 'ac-pr',
  SECONDARY_SPAN: 'ac-sc',
  MOBILE_INPUT: 'ac-minput',
  CANCEL: 'ac-cancel'
};

Utilities

The autocomplete library comes with two utility functions that you may find useful:

/**
 * Turns a query dictionary into a HTML-escaped query string.
 *
 * @param {Object} obj The query dict such as {a: 'b', c: 'd'}.
 * @return {string} The encoded query string such as a=b&c=d.
 */
AC.encodeQuery = function encode(obj);

/**
 * Creates DOM elements for autocomplete result input highlighting. With the
 * whitespaces in the input trimmed, the input will be in bold (b) whereas
 * everything else will be left intact (span).
 *
 * @param {string} input The user input string.
 * @param {string} complete The autocompleted string.
 * @return {Fragment} The document fragment that contains the created DOM
 *     elements.
 */
AC.createMatchTextEls = function match(input, complete);

The first function may be useful when you construct your URL in the urlFn. The second function may be useful if you have custom rendering logic but still want the keyword highlight.

License

MIT.