A vanilla JavaScript library to perform multiple autocomplete on input, textarea, and contenteditable elements or editors that are based on textarea or contenteditable elements.
It design in mind to work with large arrays of suggestion, e.g. language dictionaries.
When user is typing in an editable element, the library checks for the specified trigger character(s) and following (query) character(s) (control by RegExp).
If condition is met (involve threshold opt.), it performs searching (affected by maxResults opt.) in provided suggestion array. If searching succeeds, it displays a suggestion list.
When desired item is clicked, the query part is replaced by the suggestion (can be change on select callback).
It has the two searching mode:
- starts with typed sequence
- contains typed sequence
A startsWith option allow to boost searching by indexing a suggestions array (see the optimize option).
Thus, instead of looping through whole array, it's search for suggestions within start and end indexes of the array.
- Pure Vanilla JavaScript
- Zero Dependencies
- Lightweight
- Optimize Search Feature
- Debounce Support
<link href="../auto-complete.css" rel="stylesheet">
<script src="../auto-complete.js"></script>const instance = new autoComplete(ctx, options);Example of using the select callback
new autoComplete(selector, {
suggestions: dictionary,
startsWith: true,
select: (data) => {
// way to keep original typed sequence with 'startsWith' option
return data.query + data.text.substr(data.query.length);
// translates the first letter of suggestion to uppercase at the start of an editor
// or after '.?!' characters regardless of the 'startsWith' option
if (/^$|[.?!]\s*$/.test(data.trigger)) {
return data.text.charAt(0).toUpperCase() + data.text.substr(1);
}
return data.text;
}
});The library allows to change context element without creating a new instance. Can be useful for dynamically creating elements.
const instance = new autoComplete(ctx, options);
. . .
instance.newElement(selector or HTMLElement);There can be some problems adding autocomplete to existing editors, e.g.:
-
codejar- theauto-complete.jsshould be instantiated before the editor. Otherwise, there will be a problem withEnterandTabkeys in Firefox.
See demo. -
codeflask- as it dynamically creates atextareaelement, so there is no possibility to instantiateauto-complete.jsfirst. In addition it requires to fire someKeyboardEventto update text changes in overlaypreelement (seeeventoption).EnterandTabkeys won't work on suggestion list.
Firefox have a bug in contenteditable element that has plaintext-only state. It appeared when autocomplete is performed at the beginning of a line - a suggestion is inserted at the end of previous line (<br> element is disappeared on replacing query).
-
ctx- an HTMLElement or CSS selector string -
options- the object:-
suggestions- accepted:- an array of strings
- an array of arrays of strings - can be used when order of appearance in suggestion list is important,
e.g. the suggestions of first array will be placed at the beginning of suggestion list and so on. - an object that created by
createIndexes(array)API in another instance (instances must have the samethresholdandcaseSensitiveoptions).
Note that instance(s) intended to work with this object must also havestartsWith: trueoption.
Seeoptimizeoption.
-
triggerChars- a string of characters that triggers suggestion list (optional).
Unicode class\p{..}, \u{..}or a special RegExp characters\s\W\D\n\talso can be used.
If the first character is '^', the internal RegExp character set logic is switch to negation.
If a custom RegExp is provided, this option ignored. -
queryChars- a string of query characters (optional);
Unicode class\p{..}, \u{..}or a special RegExp characters\w\d\D\Salso can be used.
If the first character is '^', the internal RegExp character set logic is switch to negation.
If a custom RegExp is provided, this option ignored. -
regex- a custom RegExp; must contain two capturing groups: the first must specify trigger characters, the second - query characters, and ended by$character.
It also allow to use two named capturing groups:/(?<trigger>...)(?<query>...)$/.
A simple regex forinputelement which trigger autocomplete only at the beginning element:/(^\s*)(\S+)$/.
A trigger can be any combination of characters, e.g./(name: *)([\p{L}]+)$/iutriggers autocomplete only aftername:. -
optimize{boolean} - whether to optimize thesuggestionsarray to speed up searching (default isfalse).
It only make sense when array is really large.
Note that it only available withstartsWith: trueoption.
It cloned and sorted array, then creates start and end indexes for the first characters (depend onthresholdoption), e.g.
threshold: 1- [1,1-2,1-3],threshold: 2- [1-2,1-3],threshold: 3- [1-3],threshold: 4- [1-4] ... -
startsWith{boolean} - whether to search starts with (default isfalse). The default searching mode iscontains typed sequence. -
caseSensitive{boolean} - whether to search case sensitive (default isfalse). -
threshold- a number of typed characters that trigger suggestion process (default is1). -
highlight{boolean} - whether to highlight matching in suggestion list (default isfalse). -
maxResults- a number of items in suggestion list (default is100).
Note that searching is stopped, when it reachesmaxResults. -
listTag{string} - an element tag name of suggestion list (default isul). -
listClass{string} - an element class name of suggestion list (default isautocomplete-list). -
listItemTag{string} - an element tag name of suggestion list item (default isli). -
listItemClass{string} - an element class name of suggestion list item (default isautocomplete-item). -
listOffsetY{number} - a vertical offset of suggestion list (default is5). -
listOffsetX{number} - a horizontal offset of suggestion list (default is5).
The suggestion list is flipped vertically or horizontally if it does not fit the window. These options are kept offsets on flipping. -
filter: (results) => {}{function} - A callback on getting suggestion results;
Note that it must return results, if a new array is created on filtering.results{array} - the array of objects containing suggestion information; an item is an object with these properties:text{string} - the original suggestion string to be added to suggestion list as list item text contentquery{string} - the original query stringstartIndex{number} - the start index of a query substring in suggestion string
-
sort{boolean} - whether to sort a suggestion list by ascending order of thestartIndexand place exact match as first item (default isfalse).
It only make sense withstartsWith: falseoption.
The sorting performs after customfilter()callback, if any, before building the suggestion list. -
listItem: (element, data) => {}{function} - A callback on creation of suggestion list item:
The highlighting is performed just before this callback, ifhighlight: true.element{HTMLelement} - a list item elementdata{object} - an object containing suggestion information:
Thedataobject is converted after this callback to JSON string and added to thiselementas the value of the attribute 'data-json'.text{string} - the original suggestion string to be added to suggestion list as list item text contentquery{string} - the original query string; do not change the query length!trigger{string} - the trigger stringstartIndex{number} - the start index of a query substring in suggestion string
-
open: (list) => {}{function} - A callback on showing a suggestion list:list{HTMLelement} - a list element
-
select: (data) => {}{function} - A callback on selecting list item; must return a string:data{object} - an object containing suggestion information:text{string} - the original suggestion stringquery{string} - the original query string; do not change the query length!trigger{string} - the trigger stringstartIndex{number} - the start index of a query substring in suggestion string
-
event{KeyboardEvent|InputEvent} - a event, that should be fired, when a suggestion is added to context element, in order to force an editor to update (default isundefined), e.g.event: new InputEvent("input"),event: new KeyboardEvent("keyup")... Note that it's only may require for some editors (see Troubleshooting). -
debug{boolean} - logs to the console internal messages (default isfalse).
The default options:
const options = { suggestions : [], queryChars : '\\d\\p{L}_', // all Unicode letter, 0-9 digits and `_` triggerChars : '\\s!"#$%&\'()*+,-./:;<=>?@[]\\^`{|}~`, // white spaces and punctuation regex : `/(^|[\s!"#$%&'()*+,\-./:;<=>?@[\]\\\^`{|}~]+)([\d\p{L}_]+)$/u`, caseSensitive : false, listTag : 'ul', listItemTag : 'li', listClass : 'auto-complete-list', listItemClass : 'auto-complete-item', listOffsetX : 5, listOffsetY : 5, debounce : 1, threshold : 1, maxResults : 100, // filter : (array) = {}, // listItem : (elem, data) => {}, // select : (data) => {}, debug : false, };
-