# autoComplete

## An extremely lightweight completion suggester plugin for jQuery.

Download View on GitHub

### Overview and Features

Released under the MIT License. Source on Github (changelog). Compatible with jQuery 1.7.0+ in Firefox, Safari, Chrome, Opera, Internet Explorer 7+. No dependencies except the jQuery library.

- Lightweight: 3.4 kB of JavaScript - less than 1.4 kB gzipped
- Fully flexible data source
- Smart caching, delay and minimum character settings
- Callbacks

This plugin was developed by and for Pixabay.com - an international repository for free Public Domain images. We have implemented this piece of software in production and we share it - in the spirit of Pixabay - freely with others.

### Why another jQuery autocomplete plugin?

This plugin is largely based on DevBridge's wonderful Ajax AutoComplete. We used this autocompleter for several weeks on Pixabay and it worked nicely. However, we ended up hacking more and more into the original code - changing keyboard navigation and AJAX requests. Finally, we decided to go for an own, ultra lightweight plugin code that is perfectly optimized for our needs. And here we are ...

### Usage

Include the stylesheet jquery.auto-complete.css in the <head> section of your page - and the JavaScript file jquery.auto-complete.min.js after loading the jQuery library. autoComplete accepts settings from an object of key/value pairs, and can be assigned to any text input field.

    $(selector).autoComplete({key1: value1, key2: value2});

### Settings

Property | Default | Description
--- | --- | ---
source(term, response) | null | Required callback function to connect any data source to autoComplete. The callback gets two arguments: term, which refers to the value currently in the text input. A response callback, which expects a single argument: the data to suggest to the user. This data must be an array of filtered suggestions based on the provided term: ['suggestion 1', 'suggestion 2', 'suggestion 3', ...]
minChars | 3 | Minimum number of characters (>=1) a user must type before a search is performed.
delay | 150 | The delay in milliseconds between when a keystroke occurs and when a search is performed. A zero-delay is more responsive, but can produce a lot of load.
cache | true | Determines if performed searches should be cached.
menuClass | '' | Custom class/es that get/s added to the dropdown menu container. Example: { menuClass: 'class1 class2' }
renderItem | function | A function that gives you control over how suggestions are displayed. Default:
    function (item, search){
        search = search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
        var re = new RegExp("(" + search.split(' ').join('|') + ")", "gi");
        return '<div class="autocomplete-suggestion" data-val="' + item + '">'\
            + item.replace(re, "<b>$1</b>") + '</div>';
    }
Callbacks |
onSelect(event, term, item) | A callback function that fires when a suggestion is selected by mouse click, enter, or tab. event is the event that triggered the callback, term is the selected value. and item is the item rendered by the renderItem function.
Public Methods |
destroy | Removes the autoComplete instance and its bindings.

### Demos

#### Searching in local data

This plugin was designed mainly with AJAX requests in mind, but it may be used with local data, as well. Connecting the autocompletion suggester to an array of strings can be done in the source function like so:

    $('input[name="q"]').autoComplete({
        minChars: 2,
        source: function(term, suggest){
            term = term.toLowerCase();
            var choices = ['ActionScript', 'AppleScript', 'Asp', ...];
            var matches = [];
            for (i=0; i<choices.length; i++)
                if (~choices[i].toLowerCase().indexOf(term)) matches.push(choices[i]);
            suggest(matches);
        }
    });

The source function iterates through an array of (local) choices and we return a new array containing all (lowercased) matches. Simple as that.

#### AJAX requests

AJAX requests may come with very different requirements: JSON, JSONP, GET, POST, additionaly params, authentications, etc. In order to keep the source code small while retaining full flexibility, we decided to only use a simple callback function as the source for suggestions. Make your AJAX call inside this function and return matching suggestions with the response callback:

    $('input[name="q"]').autoComplete({
        source: function(term, response){
            $.getJSON('/some/ajax/url/', { q: term }, function(data){ response(data); });
        }
    });

The AJAX call in this example needs to return an array of strings. The callback response must always be called, even if no suggestions are returned or if an error occured. This ensures the correct state of the autoComplete instance.

#### Optimizing AJAX requests

All search results are cached by default and unnecessary requests are prevented in order to keep server load as low as possible. To further reduce server impact, it's possible to abort unfinished AJAX requests before starting new ones:

    var xhr;
    $('input[name="q"]').autoComplete({
        source: function(term, response){
            try { xhr.abort(); } catch(e){}
            xhr = $.getJSON('/some/ajax/url/', { q: term }, function(data){ response(data); });
        }
    });

By typing along, the user may trigger one AJAX request after the other. With this little trick, we make sure that only the most current one actually gets executed - if not done so already.

#### Advanced suggestions handling and custom layout

By making use of the renderItem() function, it's possible to turn the autocompleter into an item suggester:

While typing country names or language codes, a list of matching suggestions is displayed. E.g. typing "de" will show "Germany" as a suggestion, because "de" is the language code for German. Source code for this example:

    $('input[name="q"]').autoComplete({
        minChars: 1,
        source: function(term, suggest){
            term = term.toLowerCase();
            var choices = [['Australia', 'au'], ['Austria', 'at'], ['Brasil', 'br'], ...];
            var suggestions = [];
            for (i=0;i<choices.length;i++)
                if (~(choices[i][0]+' '+choices[i][1]).toLowerCase().indexOf(term)) suggestions.push(choices[i]);
            suggest(suggestions);
        },
        renderItem: function (item, search){
            search = search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
            var re = new RegExp("(" + search.split(' ').join('|') + ")", "gi");
            return '<div class="autocomplete-suggestion" data-langname="'+item[0]+'" data-lang="'+item[1]+'" data-val="'+search+'"><img src="img/'+item[1]+'.png"> '+item[0].replace(re, "<b>$1</b>")+'</div>';
        },
        onSelect: function(e, term, item){
            alert('Item "'+item.data('langname')+' ('+item.data('lang')+')" selected by '+(e.type == 'keydown' ? 'pressing enter' : 'mouse click')+'.');
        }
    });

In this case, autocompleting the text field is not desired, so we turn it off by setting data-val="'+search+'" in the renderItem() function. However, when choosing an item, the onSelect() callback returns all required information.

Please report any bugs and issues at the GitHub repositiory.

This software is released as Open Source under the MIT License by Simon Steinberger / Pixabay.com.

About Us Blog More Goodies © Pixabay.com / Simon Steinberger / Hans Braxmeier