Styling the default input with themes
The default autocomplete implementation doesn't change anything visual about the input element. Functionally speaking, we don't want the input element changed. All we need is the drop-down component once the user starts typing. But let's see if we can go ahead and change the virtual appearance of the autocomplete input element using components from the widget framework and the theme framework.
Getting ready
We'll use the following markup for our example, a simple label
element and a simple input
element:
<div> <label for="autocomplete">Items: </label> <input id="autocomplete"/> </div>
How to do it...
We'll use the following code to extend the autocomplete widget with the CSS classes from the theme framework we'd like applied. We're introducing a minor behavioral tweak with regards to focus events.
( function( $, undefined ) { $.widget( "ab.autocomplete", $.ui.autocomplete, { inputClasses: "ui-widget ui-widget-content ui-corner-all", _create: function() { this._super( "_create" ); this._focusable( this.element ); this.element.addClass( this.inputClasses ); }, _destroy: function() { this._super( "_destroy" ); this.element.removeClass( this.inputClasses ); } }); })( jQuery ); $( function() { var source = [ 'First Item', 'Second Item', 'Third Item', 'Fourth Item' ]; $( "#autocomplete" ).autocomplete( { source: source } ); });
The last thing we need to complete the stylization of our autocomplete's input
element is a new CSS stylesheet with a couple of rules. The stylesheet should be included in the main HTML where the input markup is defined.
input.ui-autocomplete-input { padding: 2px; } input.ui-autocomplete-input:focus { outline: none; }
Here is what our newly-styled autocomplete widget looks like without focus.
Here is what the autocomplete looks like when it has the focus, and with the drop-down menu expanded.
How it works...
When the document loads, we're creating a simple autocomplete using the #autocomplete
input element.
The first thing you'll notice is the inputClasses
attribute. This string represents the three classes from the theme framework we want to apply to the widget: ui-widget
, ui-widget-content
, and ui-corner-all
. The ui-widget
class doesn't do much aside from handling fonts, it's good practice to apply this class to themed elements. The ui-widget-content
class fixes the input's border for us while the ui-corner-all
class applies nice rounded corners for us. The reason we've defined this string as an attribute of the widget is because there are two places these classes are used, and this makes for easy maintenance.
The _create()
method we're overriding here just calls the original implementation of the autocomplete's _create()
method. Once this completes, we're making the input
element focusable by calling _focusable()
. This is a handy utility method defined by the widget factory and inherited by all widgets. It takes care of making the element focusable by applying the ui-state-focus
CSS class from the theme framework when the element is focused. It also removes the class when the element loses focus. Perhaps, the best part about _focusable()
is that the widget factory machinery will clean up any focus event handlers for us when the widget is destroyed. The last job of our customized implementation of _create()
is to add the CSS classes from inputClasses
to the input element.
As always, we need to make sure we clean up after ourselves when we're finished borrowing from the autocomplete widget. This means extending _delete()
to ensure that the inputClasses
attributes are removed from the input element.
Our miniscule CSS rules that we've used to extend the theme framework do two things. The first change is to add a little padding to the input
element—this is purely aesthetic since the other changes we've made make the text look a little tight inside the input. The second change removes the outline that surrounds the input
element when focused. This only applies to certain browsers, like Chrome, where an automatic outline is applied.
Note
Normally, removing the outline isn't advised since accessibility is at stake. But, our changes have taken the focused input into account, so this is fine.