Simple autocomplete pure vanilla Javascript library. 🚀 Live Demo v8.3
autoComplete.js is a simple pure vanilla Javascript library that's progressively designed for speed, high versatility and seamless integration with a wide range of projects & systems, made for users and developers in mind.
- Pure Vanilla Javascript
- Zero Dependencies
- Simple & Easy to use
- Extremely Lightweight
- Blazing Fast
- Versatile
- Hackable & highly customizable
- Clone autoComplete.js to your local machine
git clone https://github.com/TarekRaafat/autoComplete.js.git
- Install Dependencies
npm i
- For Development
npm run dev
- Build Production Package
npm run build
CSS
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@8.3.2/dist/css/autoComplete.min.css">
JS
<script src="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@8.3.2/dist/js/autoComplete.min.js"></script>
CSS
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tarekraafat-autocomplete.js/8.3.2/css/autoComplete.min.css">
JS
<script src="https://cdnjs.cloudflare.com/ajax/libs/tarekraafat-autocomplete.js/8.3.2/js/autoComplete.min.js"></script>
CSS
<link rel="stylesheet" href="https://unpkg.com/@tarekraafat/autocomplete.js@8.3.2/dist/css/autoComplete.css">
JS
<script src="https://unpkg.com/@tarekraafat/autocomplete.js@8.3.2/dist/js/autoComplete.min.js"></script>
<script src="./autoComplete.js"></script>
<script src="./index.js" type="module"></script>
import autoComplete from "./autoComplete";
npm i @tarekraafat/autocomplete.js
yarn add @tarekraafat/autocomplete.js
const autoComplete = require("@tarekraafat/autocomplete.js/dist/js/autoComplete");
HTML file
- Place the
CSS
stylesheet inside theHEAD
tag
<link rel="stylesheet" href="./css/autoComplete.css">
OR
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@8.3.2/dist/css/autoComplete.min.css">
- Assign the default
id
value"autoComplete"
to the desired input field or use any customid/class
and configure the API selector accordingly inStep 4
<input id="autoComplete" tabindex="1"> <!-- Default "id" value = "autoComplete"> -->
- Place autoComplete
JS
file & the customJS
file at the bottomBODY
tag
<script src="./js/autoComplete.min.js"></script>
<script src="./js/index.js"></script>
OR
<script src="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@8.3.2/dist/js/autoComplete.min.js"></script>
<script src="./js/index.js"></script>
Custom JS file
- Create new instance of autoComplete engine and configure it
NOT all API configurations are required
new autoComplete({
data: { // Data src [Array, Function, Async] | (REQUIRED)
src: async () => {
// API key token
const token = "this_is_the_API_token_number";
// User search query
const query = document.querySelector("#autoComplete").value;
// Fetch External Data Source
const source = await fetch(`https://www.food2fork.com/api/search?key=${token}&q=${query}`);
// Format data into JSON
const data = await source.json();
// Return Fetched data
return data.recipes;
},
key: ["title"],
cache: false
},
query: { // Query Interceptor | (Optional)
manipulate: (query) => {
return query.replace("pizza", "burger");
}
},
sort: (a, b) => { // Sort rendered results ascendingly | (Optional)
if (a.match < b.match) return -1;
if (a.match > b.match) return 1;
return 0;
},
placeHolder: "Food & Drinks...", // Place Holder text | (Optional)
selector: "#autoComplete", // Input field selector | (Optional)
observer: true, // Input field observer | (Optional)
threshold: 3, // Min. Chars length to start Engine | (Optional)
debounce: 300, // Post duration for engine to start | (Optional)
searchEngine: "strict", // Search Engine type/mode | (Optional)
resultsList: { // Rendered results list object | (Optional)
container: source => {
source.setAttribute("id", "food_list");
},
destination: "#autoComplete",
position: "afterend",
element: "ul"
},
maxResults: 5, // Max. number of rendered results | (Optional)
highlight: {
render: true, // Highlight matching results | (Optional)
}
resultItem: { // Rendered result item | (Optional)
content: (data, source) => {
source.innerHTML = data.match;
},
element: "li"
},
noResults: (dataFeedback, generateList) => {
// Generate autoComplete List
generateList(autoCompleteJS, dataFeedback, dataFeedback.results);
// No Results List Item
const result = document.createElement("li");
result.setAttribute("class", "no_result");
result.setAttribute("tabindex", "1");
result.innerHTML = `<span style="display: flex; align-items: center; font-weight: 100; color: rgba(0,0,0,.2);">Found No Results for "${dataFeedback.query}"</span>`;
document.querySelector(`#${autoCompleteJS.resultsList.idName}`).appendChild(result);
},
onSelection: feedback => { // Action script onSelection event | (Optional)
console.log(feedback.selection.value.image_url);
}
});
Keys | Description | Values | Default |
---|---|---|---|
data |
Data Source, Data Key, Data Caching & Data Results | 1- src: - Array of Strings / Objects OR - Function ( ) => Array of Strings / Objects 2- key: - Array of Strings Required if src is Object , for search to point to desired keys 3- Cache: - true for static data src - false for dynamic data src "API" with queries 4- Results: - (list) => Array of Strings / Objects |
Data src |
trigger |
Engine event & condition trigger | 1- event: - Array of Strings 2- condition: - Function (query) => Condition String |
1- event: ["input"] 2- condition: (query.length > this.threshold && query !== " ") |
query |
Query Interceptor | - Object with 1 method1- manipulate: Function with (query) parameter |
Raw Input |
sort |
Sort rendered results | - Function (firstResult, secondResult) => { ... } |
false (Random Results) |
placeHolder |
Place Holder text | - String |
Blank / Empty |
selector |
Input field selector | - String id /class OR - Function ( ) => document.querySelector("") |
"#autoComplete" |
observer |
Input field observer | - Boolean |
false |
threshold |
Minimum characters length before engine starts rendering results | - Number |
1 |
debounce |
Minimum duration after typing idle state for engine to kick in | - Number Milliseconds value debounce: 300 |
0 |
searchEngine |
Search Engine Type/Mode | - "strict" lowerCase string OR - "loose" lowerCase string OR - customEngine Function (query, record) => each match individually |
"strict" |
diacritics |
Search Engine Diacritics handler | - Boolean |
false |
resultsList |
Rendered results list destination, position, element & navigation | - Object with 8 methods1- render: Boolean 2- container: Function (source) => { ... }3- destination: - String String id /class OR - Function ( ) => document.querySelector("") 4- position: "beforebegin" , "afterbegin" , "beforeend" , "afterend" lowerCase string 5- element: "ul", "span", "div" or Custom 6- idName: "id" 7- className: "class" 8- navigation: Function (event, input, resListElement, onSelection, resListData) => { ... } |
1- render: true 2- container: (source) => { ... } 3- destination: "#autoComplete" 4- position: "afterend" 5- element: "ul" 6- idName: "autoComplete_list" 7- className: "autoComplete_list" 8- navigation: default |
resultItem |
Rendered result Item content & element | - Object with 4 methods1- content: - Function (data, source) => { ... } - data.match has to be used for Highlighted result 2- element: "li", "span", "div" or Custom 3- idName: "id 4- className: "class |
1- content: (data, source) => { ... } 2- element: "li" 3- idName: "autoComplete_result" 4- className: "autoComplete_result" |
noResults |
Action script on noResults found | - Function (dataFeedback, generateList) => { ... } |
No Action |
selection |
Format selected result item | - Object with 1 method1- className: "class" |
1- className: autoComplete_selected |
highlight |
Highlight matching results | - Object with 2 methods1- render: Boolean 2- className: "class" |
1- render: false 2- className: autoComplete_highlighted |
maxResults |
Maximum number of displayed results | - Number |
5 |
feedback |
Action script on dataFeedback event | - Function (data) => { ... } |
No Action |
onSelection |
Action script onSelection event | - Function (feedback) => { ... } |
No Action |
- That's it, you're ready to go!
init
: Fires after "autoComplete.js" engine is initializedfetch
: Fires after fetching data is completeinput
: Fires on every user inputresults
: Fires after search is done and matching results are readyrendered
: Fires after rendering the results listnavigation
: Fires on every "resultsList" navigation interactionunInit
: Fires after "autoComplete.js" engine is un-initialized
-
Live working Demo
For general questions about autoComplete.js, tweet at @TarekRaafat.
For technical questions, you should post a question on Stack Overflow and tag it with autoComplete.js.
IE / Edge |
Firefox |
Chrome |
Safari |
iOS Safari |
Samsung |
Opera |
Opera Mini |
Electron |
---|---|---|---|---|---|---|---|---|
Edge | last version | last version | last version | last version | last version | last version | last version | last version |
Check out Releases Information ✨
- Add support for different types of data source
- Function
- JSON
- Array of Object
- External data source via Promises & Async/Await function
- Multi-keyword Search
- Different types/modes of Search Logic
- Choose different results render destination & position
- Sort rendered results
- Results list Keyboard
ARROW
orTAB
Navigation - Enhance error Handling (Ongoing)
- Number of matching results
- Fetching dynamically External API data source
- Multiple searchable
keys
for datasrc
- Event emitter on input field events
- Handling large data sets
- Event emitter fires on cleared empty input field state
-
Query
Interception & Manipulation - Improve
Promise
usage for external data source handling - Add support for
Diacritics
- Input field Observer
- Automatic deep search over all keys in multiple nested object data source
- Avail Gzip files options
- Comprehensive data feedback on user selection
- Dynamic input field selector
- Minimum characters length before results start getting rendered for more focused results
- No matches found response & text
- API for Rendered result item customization
- API for Rendered results list customization
- Capability for multiple instances
- Render
results
in default case - Render
resultsList
&resultItem
in different/custom elements - HTML elements
ContentEditable
Input Support - Serve results without rendering list through
resultsList.render
API - Custom Search Engine Capability
-
ShadowDom
Support - API support for
customNavigation
- API support for
customEventTriggers
&customTriggerConditions
- Better
resultsList
navigation [Without loosing cursor] - Add event emitters for navigation
- Life Cycle Events
- Add more use examples & cases of the library to the documentation
- Better code compression / optimization for the library to squeeze it back under
[5kb]
- Recent / Most Searches
- Inline Suggestions
- Input Tags
- Virtual Scrolling
- Results List Category Separator
-
IndexedDB
for large data sets handling & offline usage - Themes / Styles & Interactions
- autoComplete.js default style
- Neutral style [01]
- Light style [02]
- Duplicated results when using multiple data source
keys
Contributions are always more than welcome!
If you have any ideas, just open an issue and tell me what you think.
- Please fork the repository and make changes as you'd like. Pull requests are warmly welcome.
If you'd like to contribute:
- Fork it (https://github.com/TarekRaafat/autoComplete.js.git)
- Create your feature branch (
git checkout -b feature/fooBar
) - Commit your changes (
git commit -am 'Add some fooBar'
) - Push to the branch (
git push origin feature/fooBar
) - Create a new Pull Request
Tarek Raafat
- Email: tarek.m.raafat@gmail.com
- Website: http://www.tarekraafat.com/
- Github: https://github.com/TarekRaafat/
Distributed under the Apache 2.0 license. See Apache 2.0
for more information.
Apache 2.0 © Tarek Raafat