jQuery UI & Autocomplete: Combo box

jQuery UI Autocomplete – Combobox

A custom widget built by composition of Autocomplete and Button.

You can either type something into the field to get filtered suggestions based on your input, or use the button to get the full list of selections.

The input is read from an existing select-element for progressive enhancement, passed to Autocomplete with a customized source-option.

This is not a supported or even complete widget. Its purely for demoing what autocomplete can do with a bit of customization.

<!doctype html>
<html lang='en'>
<head>
    <meta charset='utf-8'>
    <title>jQuery UI Autocomplete - Combobox</title>
    <link rel='stylesheet' href='//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css'>
    <script src='//code.jquery.com/jquery-1.10.2.js'></script>
    <script src='//code.jquery.com/ui/1.10.4/jquery-ui.js'></script>
    <link rel='stylesheet' href='https://codecrawl.com/code/jqueryui/jqueryui_style.css'>
    <style>
        .custom-combobox {
            position: relative;
            display: inline-block;
        }

        .custom-combobox-toggle {
            position: absolute;
            top: 0;
            bottom: 0;
            margin-left: -1px;
            padding: 0;
            /* support: IE7 */
            *height: 1.7em;
            *top: 0.1em;
        }

        .custom-combobox-input {
            margin: 0;
            padding: 0.3em;
        }
    </style>
    <script>
        (function ($) {
            $.widget('custom.combobox', {
                _create: function () {
                    this.wrapper = $('<span>')
                            .addClass('custom-combobox')
                            .insertAfter(this.element);

                    this.element.hide();
                    this._createAutocomplete();
                    this._createShowAllButton();
                },

                _createAutocomplete: function () {
                    var selected = this.element.children(':selected'),
                            value = selected.val() ? selected.text() : '';

                    this.input = $('<input>')
                            .appendTo(this.wrapper)
                            .val(value)
                            .attr('title', '')
                            .addClass('custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left')
                            .autocomplete({
                                delay: 0,
                                minLength: 0,
                                source: $.proxy(this, '_source')
                            })
                            .tooltip({
                                tooltipClass: 'ui-state-highlight'
                            });

                    this._on(this.input, {
                        autocompleteselect: function (event, ui) {
                            ui.item.option.selected = true;
                            this._trigger('select', event, {
                                item: ui.item.option
                            });
                        },

                        autocompletechange: '_removeIfInvalid'
                    });
                },

                _createShowAllButton: function () {
                    var input = this.input,
                            wasOpen = false;

                    $('<a>')
                            .attr('tabIndex', -1)
                            .attr('title', 'Show All Items')
                            .tooltip()
                            .appendTo(this.wrapper)
                            .button({
                                icons: {
                                    primary: 'ui-icon-triangle-1-s'
                                },
                                text: false
                            })
                            .removeClass('ui-corner-all')
                            .addClass('custom-combobox-toggle ui-corner-right')
                            .mousedown(function () {
                                wasOpen = input.autocomplete('widget').is(':visible');
                            })
                            .click(function () {
                                input.focus();

                                // Close if already visible
                                if (wasOpen) {
                                    return;
                                }

                                // Pass empty string as value to search for, displaying all results
                                input.autocomplete('search', '');
                            });
                },

                _source: function (request, response) {
                    var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), 'i');
                    response(this.element.children('option').map(function () {
                        var text = $(this).text();
                        if (this.value && ( !request.term || matcher.test(text) ))
                            return {
                                label: text,
                                value: text,
                                option: this
                            };
                    }));
                },

                _removeIfInvalid: function (event, ui) {

                    // Selected an item, nothing to do
                    if (ui.item) {
                        return;
                    }

                    // Search for a match (case-insensitive)
                    var value = this.input.val(),
                            valueLowerCase = value.toLowerCase(),
                            valid = false;
                    this.element.children('option').each(function () {
                        if ($(this).text().toLowerCase() === valueLowerCase) {
                            this.selected = valid = true;
                            return false;
                        }
                    });

                    // Found a match, nothing to do
                    if (valid) {
                        return;
                    }

                    // Remove invalid value
                    this.input
                            .val('')
                            .attr('title', value + ' didnt match any item')
                            .tooltip('open');
                    this.element.val('');
                    this._delay(function () {
                        this.input.tooltip('close').attr('title', '');
                    }, 2500);
                    this.input.data('ui-autocomplete').term = '';
                },

                _destroy: function () {
                    this.wrapper.remove();
                    this.element.show();
                }
            });
        })(jQuery);

        $(function () {
            $('#combobox').combobox();
            $('#toggle').click(function () {
                $('#combobox').toggle();
            });
        });
    </script>
</head>
<body>

<div class='ui-widget'>
    <label>Your preferred programming language: </label>
    <select id='combobox'>
        <option value=''>Select one...</option>
        <option value='ActionScript'>ActionScript</option>
        <option value='AppleScript'>AppleScript</option>
        <option value='Asp'>Asp</option>
        <option value='BASIC'>BASIC</option>
        <option value='C'>C</option>
        <option value='C++'>C++</option>
        <option value='Clojure'>Clojure</option>
        <option value='COBOL'>COBOL</option>
        <option value='ColdFusion'>ColdFusion</option>
        <option value='Erlang'>Erlang</option>
        <option value='Fortran'>Fortran</option>
        <option value='Groovy'>Groovy</option>
        <option value='Haskell'>Haskell</option>
        <option value='Java'>Java</option>
        <option value='JavaScript'>JavaScript</option>
        <option value='Lisp'>Lisp</option>
        <option value='Perl'>Perl</option>
        <option value='PHP'>PHP</option>
        <option value='Python'>Python</option>
        <option value='Ruby'>Ruby</option>
        <option value='Scala'>Scala</option>
        <option value='Scheme'>Scheme</option>
    </select>
</div>
<button id='toggle'>Show underlying select</button>


</body>
</html>
Try The Code
Series Navigation<< jQuery UI & Autocomplete: Accent folding
jQuery UI & Autocomplete: Categories >>