jQuery UI Cookbook
上QQ阅读APP看书,第一时间看更新

Building data sources using select options

Sometimes, using an array as the source of data for autocomplete widgets isn't the best option. For example, if we already have a select element in our user interface, it would make sense to reuse the options in that element to make an autocomplete. Otherwise, we would have to not only design some new code to build the array data source, but we would also have to remove the existing select element.

Getting ready

Let's put together some basic markup for this example. Typically, the autocomplete widget expects an input as its element. Instead, we're going to give it a select element with some simple options.

<div>
    <label for="autocomplete">Items: </label>
    <select id="autocomplete">
        <option>First Item</option>
        <option>Second Item</option>
        <option>Third Item</option>
        <option>Fourth Item</option>
    </select>
</div>

How to do it...

We'll go ahead and extend the capabilities of the autocomplete widget so that it knows how to handle the select elements. After which, we're able to target our select element with the autocomplete widget.

( function( $, undefined ) {

$.widget( "ab.autocomplete", $.ui.autocomplete, {

    inputClasses: "ui-widget ui-widget-content ui-corner-all",

    _create: function() {

        if ( this.element.is( "select" ) ) {

            var self = this;
            this.original = this.element.hide();
            this.element = $( "<input/>" ).insertAfter( this.original );

            this.options.source = function( request, response ) {

                var filter = $.ui.autocomplete.filter,
                    options = self.original.find( "option" ),
                    result = options.map( function() {
                        return $( this ).val();
                    });

                response( filter( result, request.term ) );

            };

        }

        this._super( "_create" );

    },

    _destroy: function() {

        this._super( "_destroy" );
        this.element.remove();
        this.original.show();

    }

});

})( jQuery );

$( function() {
    $( "#autocomplete" ).autocomplete();
});

Now you should see something that looks like a plain old autocomplete—no select element in sight. Further, if you try using the autocomplete, you'll see that the options presented are the same as those in the select element's options.

How it works...

Here, we need to add support to the autocomplete widget for select elements; we do this at the beginning of our custom _create() implementation. If we're dealing with a select element, the first thing we do is hide it and store a reference to it in the original attribute. Remember, we're only interested in the data source the select element has to offer by means of its options—we don't want to actually display the select. Instead, we're replacing the select with an input element since this is how the user types and the widget completes.

The source option of the autocomplete widget is how we're able to specify a custom function that returns the source data to be used. In our case, we're providing a function that grabs the values from each select option. Recall that the select element was stored in the original attribute earlier. We're using the jQuery map() utility function here to turn the select options into an array that autocomplete can use. The filter() function gets applied, and the response() function is sent to the drop-down menu.

When the widget is destroyed, we'd like to restore the original select element, since this is what we replaced. The original element gets displayed once again in our customized implementation of _delete()—this happens after calling the original _delete() method to perform routine cleanup tasks. The input element we created is also destroyed here.