Show:
                            /**
                             * The AutoComplete Utility
                             *
                             * @module aui-autocomplete
                             */
                            
                            var Lang = A.Lang,
                                isArray = Lang.isArray,
                                isString = Lang.isString,
                                isNull = Lang.isNull,
                                isFunction = Lang.isFunction,
                            
                                getClassName = A.getClassName,
                            
                                KeyMap = A.Event.KeyMap,
                            
                                ALERT = 'alert',
                                CONTENT = 'content',
                                HELPER = 'helper',
                                HIDDEN = 'hidden',
                                ICON = 'icon',
                                ITEM = 'item',
                                LIST = 'list',
                                LOADING = 'loading',
                                NAME = 'autocomplete',
                                RESET = 'reset',
                                RESULTS = 'results',
                                SELECTED = 'selected',
                            
                                ICON_DEFAULT = 'icon-circle-arrow-down',
                                ICON_ERROR = ALERT,
                                ICON_LOADING = LOADING,
                            
                                CSS_HIGLIGHT = getClassName(NAME, SELECTED),
                                CSS_HIDDEN = getClassName(HELPER, HIDDEN),
                                CSS_LIST_ITEM = getClassName(NAME, LIST, ITEM),
                                CSS_RESULTS_LIST = getClassName(HELPER, RESET),
                                CSS_RESULTS_OVERLAY = getClassName(NAME, RESULTS),
                                CSS_RESULTS_OVERLAY_CONTENT = getClassName(NAME, RESULTS, CONTENT),
                            
                                BACKSPACE = 'BACKSPACE',
                                TAB = 'TAB',
                                ENTER = 'ENTER',
                                ALT = 'ALT',
                                ESC = 'ESC',
                                UP = 'UP',
                                DOWN = 'DOWN',
                                RIGHT = 'RIGHT',
                                WIN_IME = 'WIN_IME',
                            
                                OVERLAY_ALIGN = {
                                    node: null,
                                    points: ['tl', 'bl']
                                },
                            
                                BOUNDING_BOX = 'boundingBox',
                                CONTENT_BOX = 'contentBox';
                            
                            /**
                             * <p><img src="assets/images/aui-autocomplete/main.png"/></p>
                             *
                             * A base class for AutoComplete, providing:
                             * <ul>
                             *    <li>Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)</li>
                             *    <li>Presenting users choices based on their input</li>
                             *    <li>Separating selected items</li>
                             *    <li>Keyboard interaction for selecting items</li>
                             * </ul>
                             *
                             * Quick Example:<br/>
                             *
                             * <pre><code>var instance = new A.AutoCompleteDeprecated({
                             *	dataSource: [['AL', 'Alabama', 'The Heart of Dixie'],
                             * 	['AK', 'Alaska', 'The Land of the Midnight Sun'],
                             *	['AZ', 'Arizona', 'The Grand Canyon State']],
                             *	schema: {
                             *		resultFields: ['key', 'name', 'description']
                             *	},
                             *	matchKey: 'name',
                             *	delimChar: ',',
                             *	typeAhead: true,
                             *	contentBox: '#myAutoComplete'
                             * }).render();
                             * </code></pre>
                             *
                             * Check the list of <a href="AutoComplete.html#configattributes">Configuration Attributes</a> available for
                             * AutoComplete.
                             *
                             * @param config {Object} Object literal specifying widget configuration properties.
                             *
                             * @class AutoComplete
                             * @constructor
                             * @extends Component
                             */
                            
                            var AutoComplete = A.Component.create({
                            
                                /**
                                 * Static property provides a string to identify the class.
                                 *
                                 * @property AutoComplete.NAME
                                 * @type String
                                 * @static
                                 */
                            
                                NAME: NAME,
                            
                                /**
                                 * Static property used to define the default attribute
                                 * configuration for the AutoComplete.
                                 *
                                 * @property AutoComplete.ATTRS
                                 * @type Object
                                 * @static
                                 */
                            
                                ATTRS: {
                                    /**
                                     * Always show the results container, instead of only showing when the
                                     * user is requesting them.
                                     *
                                     * @attribute alwaysShowContainer
                                     * @default false
                                     * @type Boolean
                                     */
                                    alwaysShowContainer: {
                                        value: false
                                    },
                            
                                    /**
                                     * Automatically highlight the first item in the list when the results are
                                     * made visible.
                                     *
                                     * @attribute autoHighlight
                                     * @default true
                                     * @type Boolean
                                     */
                                    autoHighlight: {
                                        value: true
                                    },
                            
                                    /**
                                     * If set to true, the <a href="AutoComplete.html#method_filterResults">filterResults</a>
                                     * method will be run on the response from the data source.
                                     *
                                     * @attribute applyLocalFilter
                                     * @default true
                                     * @type Boolean
                                     */
                                    applyLocalFilter: {
                                        value: null
                                    },
                            
                                    /**
                                     * To use a button
                                     *
                                     * @attribute button
                                     * @default true
                                     * @type Boolean
                                     * @deprecated
                                     */
                                    button: {
                                        value: true
                                    },
                            
                                    /**
                                     * The data source that results will be read from. This can either be
                                     * an existing <a href="DataSource.html">DataSource</a> object, or it can be a
                                     * value that would be passed to <a href="DataSource.html">DataSource</a>.
                                     *
                                     * @attribute dataSource
                                     * @default null
                                     * @type Object | String | Function | Array
                                     */
                                    dataSource: {
                                        value: null
                                    },
                            
                                    /**
                                     * The type of the data source passed into <a href="AutoComplete.html#config_dataSource">dataSource</a>.
                                     * This can be used to explicitly declare what kind of <a href="DataSource.html">DataSource</a> object will
                                     * be created.
                                     *
                                     * @attribute dataSourceType
                                     * @default null
                                     * @type String
                                     */
                                    dataSourceType: {
                                        value: null
                                    },
                            
                                    /**
                                     * The character used to indicate the beginning or ending of a new value. Most commonly used
                                     * is a ",".
                                     *
                                     * @attribute delimChar
                                     * @default null
                                     * @type String
                                     */
                                    delimChar: {
                                        value: null,
                                        setter: function(value) {
                                            if (isString(value) && (value.length > 0)) {
                                                value = [value];
                                            }
                                            else if (!isArray(value)) {
                                                value = A.Attribute.INVALID_VALUE;
                                            }
                            
                                            return value;
                                        }
                                    },
                            
                                    /**
                                     * If <a href="AutoComplete.html#config_typeAhead">typeAhead</a> is true, this
                                     * will clear a selection when the overlay closes unless a user explicitly selects an item.
                                     *
                                     * @attribute forceSelection
                                     * @default false
                                     * @type Boolean
                                     */
                                    forceSelection: {
                                        value: false
                                    },
                            
                                    /**
                                     * The input field which will recieve the users input.
                                     *
                                     * @attribute input
                                     * @default null
                                     * @type String | Node
                                     */
                                    input: {
                                        value: null
                                    },
                            
                                    /**
                                     * The key or numeric index in the schema to match the result against.
                                     *
                                     * @attribute matchKey
                                     * @default 0
                                     * @type String | Number
                                     */
                                    matchKey: {
                                        value: 0
                                    },
                            
                                    /**
                                     * The maximum number of results to display.
                                     *
                                     *
                                     * @attribute maxResultsDisplayed
                                     * @default 10
                                     * @type Number
                                     */
                                    maxResultsDisplayed: {
                                        value: 10
                                    },
                            
                                    /**
                                     * The minimum number of characters required to query the data source.
                                     *
                                     * @attribute minQueryLength
                                     * @default 1
                                     * @type Number
                                     */
                                    minQueryLength: {
                                        value: 1
                                    },
                            
                                    /**
                                     * The amount of time in seconds to delay before submitting the query.
                                     *
                                     * @attribute queryDelay
                                     * @default 0.2
                                     * @type Number
                                     */
                                    queryDelay: {
                                        value: 0.2,
                                        getter: function(value) {
                                            return value * 1000;
                                        }
                                    },
                            
                                    /**
                                     * When IME usage is detected or interval detection is explicitly enabled,
                                     * AutoComplete will detect the input value at the given interval and send a
                                     * query if the value has changed.
                                     *
                                     * @attribute queryInterval
                                     * @default 0.5
                                     * @type Number
                                     */
                                    queryInterval: {
                                        value: 0.5,
                                        getter: function(value) {
                                            return value * 1000;
                                        }
                                    },
                            
                                    /**
                                     * When <a href="AutoComplete.html#config_applyLocalFilter">applyLocalFilter</a> is true,
                                     * setting this to true will match only results with the same case.
                                     *
                                     * @attribute queryMatchCase
                                     * @default false
                                     * @type Boolean
                                     */
                                    queryMatchCase: {
                                        value: false
                                    },
                            
                                    /**
                                     * When <a href="AutoComplete.html#config_applyLocalFilter">applyLocalFilter</a> is true,
                                     * setting this to true will match results which contain the query anywhere in the text,
                                     * instead of just matching just items that start with the query.
                                     *
                                     * @attribute queryMatchContains
                                     * @default false
                                     * @type Boolean
                                     */
                                    queryMatchContains: {
                                        value: false
                                    },
                            
                                    /**
                                     * For IO DataSources, AutoComplete will automatically insert a "?" between the server URI and
                                     * the encoded query string. To prevent this behavior, you can
                                     * set this value to false. If you need to customize this even further, you
                                     * can override the <a href="AutoComplete.html#method_generateRequest">generateRequest</a> method.
                                     *
                                     * @attribute queryQuestionMark
                                     * @default true
                                     * @type Boolean
                                     */
                                    queryQuestionMark: {
                                        value: true
                                    },
                            
                                    /**
                                     * A valid configuration object for any of <a href="module_datasource.html">DataSource</a> schema plugins.
                                     *
                                     * @attribute schema
                                     * @default null
                                     * @type Object
                                     */
                                    schema: {
                                        value: null
                                    },
                            
                                    /**
                                     * A valid type of <a href="module_datasource.html">DataSource</a> schema plugin, such as array, json, xml, etc.
                                     *
                                     * @attribute schemaType
                                     * @default array
                                     * @type String
                                     */
                                    schemaType: {
                                        value: '',
                                        validator: isString
                                    },
                            
                                    /**
                                     * Whether or not the input field should be updated with selections.
                                     *
                                     * @attribute suppressInputUpdate
                                     * @default false
                                     * @type Boolean
                                     */
                                    suppressInputUpdate: {
                                        value: false
                                    },
                            
                                    /**
                                     * If <a href="AutoComplete.html#config_autoHighlight">autoHighlight</a> is enabled, whether or not the
                                     * input field should be automatically updated with the first result as the user types,
                                     * automatically selecting the portion of the text the user has not typed yet.
                                     *
                                     * @attribute typeAhead
                                     * @default false
                                     * @type Boolean
                                     */
                                    typeAhead: {
                                        value: false
                                    },
                            
                                    /**
                                     * If <a href="AutoComplete.html#config_typeAhead">typeAhead</a> is true, number of seconds
                                     * to delay before updating the input. In order to prevent certain race conditions, this value must
                                     * always be greater than the <a href="AutoComplete.html#config_queryDelay">queryDelay</a>.
                                     *
                                     * @attribute typeAheadDelay
                                     * @default 0.2
                                     * @type Number
                                     */
                                    typeAheadDelay: {
                                        value: 0.2,
                                        getter: function(value) {
                                            return value * 1000;
                                        }
                                    },
                            
                                    /**
                                     * The unique ID of the input element.
                                     *
                                     * @attribute uniqueName
                                     * @default null
                                     * @type String
                                     */
                                    uniqueName: {
                                        value: null
                                    }
                                },
                            
                                prototype: {
                                    /**
                                     * Construction logic executed during AutoComplete instantiation. Lifecycle.
                                     *
                                     * @method initializer
                                     * @protected
                                     */
                                    initializer: function(config) {
                                        var instance = this;
                            
                                        instance._overlayAlign = A.mix({}, OVERLAY_ALIGN);
                            
                                        instance._createDataSource();
                                    },
                            
                                    /**
                                     * Create the DOM structure for the AutoComplete. Lifecycle.
                                     *
                                     * @method renderUI
                                     * @protected
                                     */
                                    renderUI: function() {
                                        var instance = this;
                            
                                        instance._renderInput();
                                        instance._renderOverlay();
                                    },
                            
                                    /**
                                     * Bind the events on the AutoComplete UI. Lifecycle.
                                     *
                                     * @method bindUI
                                     * @protected
                                     */
                                    bindUI: function() {
                                        var instance = this;
                            
                                        var button = instance.button;
                                        var inputNode = instance.inputNode;
                            
                                        instance.dataSource.on('request', A.bind(button.set, button, ICON, ICON_LOADING));
                            
                                        button.on('click', instance._onButtonMouseDown, instance);
                            
                                        inputNode.on('blur', instance._onTextboxBlur, instance);
                                        inputNode.on('focus', instance._onTextboxFocus, instance);
                                        inputNode.on('keydown', instance._onTextboxKeyDown, instance);
                                        inputNode.on('keypress', instance._onTextboxKeyPress, instance);
                                        inputNode.on('keyup', instance._onTextboxKeyUp, instance);
                            
                                        var overlayBoundingBox = instance.overlay.get(BOUNDING_BOX);
                            
                                        overlayBoundingBox.on('click', instance._onContainerClick, instance);
                                        overlayBoundingBox.on('mouseout', instance._onContainerMouseout, instance);
                                        overlayBoundingBox.on('mouseover', instance._onContainerMouseover, instance);
                                        overlayBoundingBox.on('scroll', instance._onContainerScroll, instance);
                            
                                        /**
                                         * Handles the containerCollapse event. Fired when the container is hidden.
                                         *
                                         * @event containerCollapse
                                         * @param {Event.Facade} event The containerCollapse event.
                                         */
                                        instance.publish('containerCollapse');
                            
                                        /**
                                         * Handles the containerExpand event. Fired when the container is shown.
                                         *
                                         * @event containerExpand
                                         * @param {Event.Facade} event The containerExpand event.
                                         */
                                        instance.publish('containerExpand');
                            
                                        /**
                                         * Handles the containerPopulate event. Fired when the container is populated.
                                         *
                                         * @event containerPopulate
                                         * @param {Event.Facade} event The containerPopulate event.
                                         */
                                        instance.publish('containerPopulate');
                            
                                        /**
                                         * Handles the dataError event. Fired when there is an error accessing the data.
                                         *
                                         * @event dataError
                                         * @param {Event.Facade} event The dataError event.
                                         */
                                        instance.publish('dataError');
                            
                                        /**
                                         * Handles the dataRequest event. Fired when ever a query is sent to the data source.
                                         *
                                         * @event dataRequest
                                         * @param {Event.Facade} event The dataRequest event.
                                         */
                                        instance.publish('dataRequest');
                            
                                        /**
                                         * Handles the dataReturn event. Fired when data successfully comes back from the data request.
                                         *
                                         * @event dataReturn
                                         * @param {Event.Facade} event The dataReturn event.
                                         */
                                        instance.publish('dataReturn');
                            
                                        /**
                                         * Handles the itemArrowFrom event. Fired when the user navigates via the keyboard away from
                                         * a selected item.
                                         *
                                         * @event itemArrowFrom
                                         * @param {Event.Facade} event The itemArrowFrom event.
                                         */
                                        instance.publish('itemArrowFrom');
                            
                                        /**
                                         * Handles the itemArrowTo event. Fired when the user navigates via the keyboard to a selected item.
                                         *
                                         * @event itemArrowTo
                                         * @param {Event.Facade} event The itemArrowTo event.
                                         */
                                        instance.publish('itemArrowTo');
                            
                                        /**
                                         * Handles the itemMouseOut event. Fired when the user mouses away from an item.
                                         *
                                         * @event itemMouseOut
                                         * @param {Event.Facade} event The itemMouseOut event.
                                         */
                                        instance.publish('itemMouseOut');
                            
                                        /**
                                         * Handles the itemMouseOver event. Fired when the user mouses over an item.
                                         *
                                         * @event itemMouseOver
                                         * @param {Event.Facade} event The itemMouseOver event.
                                         */
                                        instance.publish('itemMouseOver');
                            
                                        /**
                                         * Handles the itemSelect event. Fired when an item in the list is selected.
                                         *
                                         * @event itemSelect
                                         * @param {Event.Facade} event The itemSelect event.
                                         */
                                        instance.publish('itemSelect');
                            
                                        /**
                                         * Handles the selectionEnforce event. Fired if <a href="Autocomplete.html#config_forceSelection">forceSelection</a>
                                         * is enabled and the users input element has been cleared because it did not match one of the results.
                                         *
                                         * @event selectionEnforce
                                         * @param {Event.Facade} event The selectionEnforce event.
                                         */
                                        instance.publish('selectionEnforce');
                            
                                        /**
                                         * Handles the textboxBlur event. Fired when the user leaves the input element.
                                         *
                                         * @event textboxBlur
                                         * @param {Event.Facade} event The textboxBlur event.
                                         */
                                        instance.publish('textboxBlur');
                            
                                        /**
                                         * Handles the textboxChange event. Fired when the value in the input element is changed.
                                         *
                                         * @event textboxChange
                                         * @param {Event.Facade} event The textboxChange event.
                                         */
                                        instance.publish('textboxChange');
                            
                                        /**
                                         * Handles the textboxFocus event. Fired when user moves focus to the input element.
                                         *
                                         * @event textboxFocus
                                         * @param {Event.Facade} event The textboxFocus event.
                                         */
                                        instance.publish('textboxFocus');
                            
                                        /**
                                         * Handles the textboxKey event. Fired when the input element receives key input.
                                         *
                                         * @event textboxKey
                                         * @param {Event.Facade} event The textboxKey event.
                                         */
                                        instance.publish('textboxKey');
                            
                                        /**
                                         * Handles the typeAhead event. Fired when the input element has been pre-filled by the type-ahead feature.
                                         *
                                         * @event typeAhead
                                         * @param {Event.Facade} event The typeAhead event.
                                         */
                                        instance.publish('typeAhead');
                            
                                        /**
                                         * Handles the unmatchedItemSelect event. Fired when a user selects something that does
                                         * not match any of the displayed results.
                                         *
                                         * @event unmatchedItemSelect
                                         * @param {Event.Facade} event The unmatchedItemSelect event.
                                         */
                                        instance.publish('unmatchedItemSelect');
                            
                                        instance.overlay.after('visibleChange', instance._realignContainer, instance);
                                    },
                            
                                    /**
                                     * Sync the AutoComplete UI. Lifecycle.
                                     *
                                     * @method syncUI
                                     * @protected
                                     */
                                    syncUI: function() {
                                        var instance = this;
                            
                                        instance.inputNode.setAttribute('autocomplete', 'off');
                                    },
                            
                                    /**
                                     * Destructor lifecycle implementation for the Autocomplete class.
                                     * Purges events attached to the node (and all child nodes).
                                     *
                                     * @method destructor
                                     * @protected
                                     */
                                    destructor: function() {
                                        var instance = this;
                            
                                        instance.overlay.destroy();
                                    },
                            
                                    /**
                                     * An overridable method that is executed before the result container is shown.
                                     * The method can return false to prevent the container from being shown.
                                     *
                                     * @method doBeforeExpandContainer
                                     * @param {String} query The query that was submitted to the data source
                                     * @param {Object} allResults The parsed results
                                     * @return {Boolean}
                                     */
                                    doBeforeExpandContainer: function() {
                                        return true;
                                    },
                            
                                    /**
                                     * An overridable method that is executed before the result overlay is loaded with results.
                                     *
                                     * @method doBeforeLoadData
                                     * @param {EventFacade} event
                                     * @return {Boolean}
                                     */
                                    doBeforeLoadData: function(event) {
                                        return true;
                                    },
                            
                                    /**
                                     * Executed by the data source as a mechanism to do simple client-side
                                     * filtering of the results.
                                     *
                                     * @method filterResults
                                     * @param {EventFacade} event
                                     * @return {Object} Filtered response object
                                     */
                                    filterResults: function(event) {
                                        var instance = this;
                            
                                        var callback = event.callback;
                                        var query = event.request;
                                        var response = event.response;
                            
                                        if (callback && callback.argument && callback.argument.query) {
                                            query = callback.argument.query;
                                        }
                            
                                        if (query) {
                                            var dataSource = instance.dataSource;
                                            var allResults = response.results;
                                            var filteredResults = [];
                                            var matchFound = false;
                                            var matchKey = instance.get('matchKey');
                                            var matchCase = instance.get('queryMatchCase');
                                            var matchContains = instance.get('queryMatchContains');
                                            var showAll = (query == '*');
                            
                                            var fields = instance.get('schema.resultFields');
                            
                                            for (var i = allResults.length - 1; i >= 0; i--) {
                                                var result = allResults[i];
                            
                                                var strResult = null;
                            
                                                if (isString(result)) {
                                                    strResult = result;
                                                }
                                                else if (isArray(result)) {
                                                    strResult = result[0];
                                                }
                                                else if (fields) {
                                                    strResult = result[matchKey || fields[0]];
                                                }
                            
                                                if (isString(strResult)) {
                                                    var keyIndex = -1;
                            
                                                    if (matchCase) {
                                                        keyIndex = strResult.indexOf(decodeURIComponent(query));
                                                    }
                                                    else {
                                                        keyIndex = strResult.toLowerCase().indexOf(decodeURIComponent(query).toLowerCase());
                                                    }
                            
                                                    if (
                                                        (showAll) ||
                                                        (!matchContains && (keyIndex === 0)) ||
                                                        (matchContains && (keyIndex > -1))
                                                    ) {
                                                        filteredResults.unshift(result);
                                                    }
                                                }
                                            }
                            
                                            response.results = filteredResults;
                                        }
                            
                                        return response;
                                    },
                            
                                    /**
                                     * An overridable method for formatting the result of the query before it's displayed in the overlay.
                                     *
                                     * @method formatResult
                                     * @param {Object} result The result data object
                                     * @param {String} request The current query string
                                     * @param {String} resultMatch The string from the results that matches the query
                                     * @return {String}
                                     */
                                    formatResult: function(result, request, resultMatch) {
                                        return resultMatch || '';
                                    },
                            
                                    /**
                                     * An overridable method that creates an object to be passed to the sendRequest
                                     * method of the data source object. Useful to overwrite if you wish to create
                                     * a custom request object before it's sent.
                                     *
                                     * @method generateRequest
                                     * @param {String} query The string currently being entered
                                     * @return {Object}
                                     */
                                    generateRequest: function(query) {
                                        return {
                                            request: query
                                        };
                                    },
                            
                                    /**
                                     * Handles the response for the display of the results. This is a callback method
                                     * that is fired by the sendRequest method so that results are ready to be accessed.
                                     *
                                     * @method handleResponse
                                     * @param {EventFacade} event
                                     */
                                    handleResponse: function(event) {
                                        var instance = this;
                            
                                        instance._populateList(event);
                            
                                        var iconClass = ICON_DEFAULT;
                            
                                        if (event.error) {
                                            iconClass = ICON_ERROR;
                                        }
                            
                                        instance.button.set(ICON, iconClass);
                                    },
                            
                                    /**
                                     * Sends a query request to the data source object.
                                     *
                                     * @method sendQuery
                                     * @param {String} query Query string
                                     */
                                    sendQuery: function(query) {
                                        var instance = this;
                            
                                        instance.set('focused', null);
                            
                                        var newQuery = query;
                            
                                        if (instance.get('delimChar')) {
                                            query = instance.inputNode.get('value') + query;
                                        }
                            
                                        instance._sendQuery(newQuery);
                                    },
                            
                                    /**
                                     * Clears the query interval
                                     *
                                     * @method _clearInterval
                                     * @private
                                     */
                                    _clearInterval: function() {
                                        var instance = this;
                            
                                        if (instance._queryIntervalId) {
                                            clearInterval(instance._queryIntervalId);
                            
                                            instance._queryIntervalId = null;
                                        }
                                    },
                            
                                    /**
                                     * When <a href="Autocomplete.html#config_forceSelection">forceSelection</a> is true and
                                     * the user tries to leave the input element without selecting an item from the results,
                                     * the user selection is cleared.
                                     *
                                     * @method _clearSelection
                                     * @protected
                                     */
                                    _clearSelection: function() {
                                        var instance = this;
                            
                                        var delimChar = instance.get('delimChar');
                                        var extraction = {
                                            previous: '',
                                            query: instance.inputNode.get('value')
                                        };
                            
                                        if (delimChar) {
                                            extraction = instance._extractQuery(instance.inputNode.get('value'));
                                        }
                            
                                        instance.fire('selectionEnforce', extraction.query);
                                    },
                            
                                    /**
                                     * Creates the data source object using the passed in <a href="Autocomplete.html#config_dataSource">dataSource</a>,
                                     * and if it is a string, will use the <a href="Autocomplete.html#config_dataSourceType">dataSourceType</a> to
                                     * create a new <a href="module_datasource.html">DataSource</a> object.
                                     *
                                     * @method _createDataSource
                                     * @protected
                                     * @return {String}
                                     */
                                    _createDataSource: function() {
                                        var instance = this;
                            
                                        instance._queryTask = A.debounce(instance.sendQuery, instance.get('queryDelay'), instance);
                            
                                        var dataSource = instance.get('dataSource');
                                        var data = dataSource;
                            
                                        var dataSourceType = instance.get('dataSourceType');
                            
                                        if (!(dataSource instanceof A.DataSource.Local)) {
                                            if (!dataSourceType) {
                                                dataSourceType = 'Local';
                            
                                                if (isFunction(data)) {
                                                    dataSourceType = 'Function';
                                                }
                                                else if (isString(data)) {
                                                    dataSourceType = 'IO';
                                                }
                                            }
                            
                                            dataSource = new A.DataSource[dataSourceType]({
                                                source: data
                                            });
                                        }
                            
                                        dataSource.on('error', instance.handleResponse, instance);
                                        dataSource.after('response', instance.handleResponse, instance);
                            
                                        dataSourceType = dataSource.name;
                            
                                        if (dataSourceType == 'dataSourceLocal') {
                                            instance.set('applyLocalFilter', true);
                                        }
                            
                                        instance.set('dataSource', dataSource);
                                        instance.set('dataSourceType', dataSourceType);
                            
                                        instance.dataSource = dataSource;
                            
                                        var schema = instance.get('schema');
                            
                                        if (schema) {
                                            if (schema.fn) {
                                                instance.dataSource.plug(schema);
                                            }
                                            else {
                                                var schemaType = instance.get('schemaType');
                            
                                                var schemaTypes = {
                                                    array: A.Plugin.DataSourceArraySchema,
                                                    json: A.Plugin.DataSourceJSONSchema,
                                                    text: A.Plugin.DataSourceTextSchema,
                                                    xml: A.Plugin.DataSourceXMLSchema
                                                };
                            
                                                schemaType = schemaType.toLowerCase() || 'array';
                            
                                                instance.dataSource.plug({
                                                    fn: schemaTypes[schemaType],
                                                    cfg: {
                                                        schema: schema
                                                    }
                                                });
                                            }
                                        }
                            
                                        instance.set('schema', schema);
                                    },
                            
                                    /**
                                     * Enables query interval detection for IME support.
                                     *
                                     * @method _enableIntervalDetection
                                     * @protected
                                     */
                                    _enableIntervalDetection: function() {
                                        var instance = this;
                            
                                        var queryInterval = instance.get('queryInterval');
                            
                                        if (!instance._queryIntervalId && queryInterval) {
                                            instance._queryInterval = setInterval(A.bind(instance._onInterval, instance), queryInterval);
                                        }
                                    },
                            
                                    /**
                                     * Extracts the right most query from the delimited string in the input.
                                     *
                                     * @method _extractQuery
                                     * @param {String} query String to parse
                                     * @protected
                                     * @return {String}
                                     */
                                    _extractQuery: function(query) {
                                        var instance = this;
                            
                                        var delimChar = instance.get('delimChar');
                                        var delimIndex = -1;
                                        var i = delimChar.length - 1;
                            
                                        var newIndex, queryStart, previous;
                            
                                        for (; i >= 0; i--) {
                                            newIndex = query.lastIndexOf(delimChar[i]);
                            
                                            if (newIndex > delimIndex) {
                                                delimIndex = newIndex;
                                            }
                                        }
                            
                                        if (delimChar[i] == ' ') {
                                            for (var j = delimChar.length - 1; j >= 0; j--) {
                                                if (query[delimIndex - 1] == delimChar[j]) {
                                                    delimIndex--;
                            
                                                    break;
                                                }
                                            }
                                        }
                            
                                        if (delimIndex > -1) {
                                            queryStart = delimIndex + 1;
                            
                                            while (query.charAt(queryStart) == ' ') {
                                                queryStart += 1;
                                            }
                            
                                            previous = query.substring(0, queryStart);
                            
                                            query = query.substring(queryStart);
                                        }
                                        else {
                                            previous = '';
                                        }
                            
                                        return {
                                            previous: previous,
                                            query: query
                                        };
                                    },
                            
                                    /**
                                     * Focuses the input element.
                                     *
                                     * @method _focus
                                     * @protected
                                     */
                                    _focus: function() {
                                        var instance = this;
                            
                                        setTimeout(
                                            function() {
                                                instance.inputNode.focus();
                                            },
                                            0
                                        );
                                    },
                            
                                    /**
                                     * If there is a currently selected item, the right arrow key will select
                                     * that item and jump to the end of the input element, otherwise the container is closed.
                                     *
                                     * @method _jumpSelection
                                     * @protected
                                     */
                                    _jumpSelection: function() {
                                        var instance = this;
                            
                                        if (instance._elCurListItem) {
                                            instance._selectItem(instance._elCurListItem);
                                        }
                                        else {
                                            instance._toggleContainer(false);
                                        }
                                    },
                            
                                    /**
                                     * Triggered by the up and down arrow keys, changes the currently selected list element item, and scrolls the
                                     * container if necessary.
                                     *
                                     * @method _moveSelection
                                     * @param {Number} keyCode The numeric code of the key pressed
                                     * @protected
                                     */
                                    _moveSelection: function(keyCode) {
                                        var instance = this;
                            
                                        if (instance.overlay.get('visible')) {
                                            var elCurListItem = instance._elCurListItem;
                                            var curItemIndex = -1;
                            
                                            if (elCurListItem) {
                                                curItemIndex = Number(elCurListItem.getAttribute('data-listItemIndex'));
                                            }
                            
                                            var newItemIndex = curItemIndex - 1;
                            
                                            if (KeyMap.isKey(keyCode, DOWN)) {
                                                newItemIndex = curItemIndex + 1;
                                            }
                            
                                            if (newItemIndex == -1) {
                                                newItemIndex = instance._displayedItems - 1;
                                            }
                            
                                            if (newItemIndex >= instance._displayedItems) {
                                                newItemIndex = 0;
                                            }
                            
                                            if (newItemIndex < -2) {
                                                return;
                                            }
                            
                                            if (elCurListItem) {
                                                instance._toggleHighlight(elCurListItem, 'from');
                            
                                                instance.fire('itemArrowFrom', elCurListItem);
                                            }
                            
                                            if (newItemIndex == -1) {
                                                if (instance.get('delimChar')) {
                                                    instance.inputNode.set('value', instance._pastSelections + instance._currentQuery);
                                                }
                                                else {
                                                    instance.inputNode.set('value', instance._currentQuery);
                                                }
                            
                                                return;
                                            }
                            
                                            if (newItemIndex == -2) {
                                                instance._toggleContainer(false);
                            
                                                return;
                                            }
                            
                                            var elNewListItem = instance.resultList.get('childNodes').item(newItemIndex);
                            
                                            var elContent = instance.overlay.get(CONTENT_BOX);
                            
                                            var contentOverflow = elContent.getStyle('overflow');
                                            var contentOverflowY = elContent.getStyle('overflowY');
                            
                                            var scrollOn = (contentOverflow == 'auto') || (contentOverflow == 'scroll') || (contentOverflowY ==
                                                'auto') || (contentOverflowY == 'scroll');
                            
                                            if (scrollOn &&
                                                (newItemIndex > -1) &&
                                                (newItemIndex < instance._displayedItems)) {
                            
                                                var newScrollTop = -1;
                                                var liTop = elNewListItem.get('offsetTop');
                                                var liBottom = liTop + elNewListItem.get('offsetHeight');
                            
                                                var contentHeight = elContent.get('offsetHeight');
                                                var contentScrollTop = elContent.get('scrollTop');
                                                var contentBottom = contentHeight + contentScrollTop;
                            
                                                if (KeyMap.isKey(keyCode, DOWN)) {
                                                    if (liBottom > contentBottom) {
                                                        newScrollTop = (liBottom - contentHeight);
                                                    }
                                                    else if (liBottom < contentScrollTop) {
                                                        newScrollTop = liTop;
                                                    }
                                                }
                                                else {
                                                    if (liTop < contentHeight) {
                                                        newScrollTop = liTop;
                                                    }
                                                    else if (liTop > contentBottom) {
                                                        newScrollTop = (liBottom - contentHeight);
                                                    }
                                                }
                            
                                                if (newScrollTop > -1) {
                                                    elContent.set('scrollTop', newScrollTop);
                                                }
                                            }
                            
                                            instance._toggleHighlight(elNewListItem, 'to');
                            
                                            instance.fire('itemArrowTo', elNewListItem);
                            
                                            if (instance.get('typeAhead')) {
                                                instance._updateValue(elNewListItem);
                                            }
                                        }
                                    },
                            
                                    /**
                                     * Called when the user mouses down on the button element in the combobox.
                                     *
                                     * @method _onButtonMouseDown
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _onButtonMouseDown: function(event) {
                                        var instance = this;
                            
                                        event.halt();
                            
                                        instance._focus();
                            
                                        instance._sendQuery(instance.inputNode.get('value') + '*');
                                    },
                            
                                    /**
                                     * Handles when a user clicks on the container.
                                     *
                                     * @method _onContainerClick
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _onContainerClick: function(event) {
                                        var instance = this;
                            
                                        var target = event.target;
                                        var tagName = target.get('nodeName').toLowerCase();
                            
                                        event.halt();
                            
                                        while (target && (tagName != 'table')) {
                                            switch (tagName) {
                                                case 'body':
                                                    return;
                            
                                                case 'li':
                                                    instance._toggleHighlight(target, 'to');
                                                    instance._selectItem(target);
                                                    return;
                            
                                                default:
                                                    break;
                                            }
                            
                                            target = target.get('parentNode');
                            
                                            if (target) {
                                                tagName = target.get('nodeName').toLowerCase();
                                            }
                                        }
                                    },
                            
                                    /**
                                     * Handles when a user mouses out of the container.
                                     *
                                     * @method _onContainerMouseout
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _onContainerMouseout: function(event) {
                                        var instance = this;
                            
                                        var target = event.target;
                                        var tagName = target.get('nodeName').toLowerCase();
                            
                                        while (target && (tagName != 'table')) {
                                            switch (tagName) {
                                                case 'body':
                                                    return;
                            
                                                case 'li':
                                                    instance._toggleHighlight(target, 'from');
                                                    instance.fire('itemMouseOut', target);
                                                    break;
                            
                                                case 'ul':
                                                    instance._toggleHighlight(instance._elCurListItem, 'to');
                                                    break;
                            
                                                case 'div':
                                                    if (target.hasClass(CSS_RESULTS_OVERLAY)) {
                                                        instance._overContainer = false;
                            
                                                        return;
                                                    }
                                                    break;
                            
                                                default:
                                                    break;
                                            }
                            
                                            target = target.get('parentNode');
                            
                                            if (target) {
                                                tagName = target.get('nodeName').toLowerCase();
                                            }
                                        }
                                    },
                            
                                    /**
                                     * Handles when a user mouses over the container.
                                     *
                                     * @method _onContainerMouseover
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _onContainerMouseover: function(event) {
                                        var instance = this;
                            
                                        var target = event.target;
                                        var tagName = target.get('nodeName').toLowerCase();
                            
                                        while (target && (tagName != 'table')) {
                                            switch (tagName) {
                                                case 'body':
                                                    return;
                            
                                                case 'li':
                                                    instance._toggleHighlight(target, 'to');
                                                    instance.fire('itemMouseOut', target);
                                                    break;
                            
                                                case 'div':
                                                    if (target.hasClass(CSS_RESULTS_OVERLAY)) {
                                                        instance._overContainer = true;
                                                        return;
                                                    }
                                                    break;
                            
                                                default:
                                                    break;
                                            }
                            
                                            target = target.get('parentNode');
                            
                                            if (target) {
                                                tagName = target.get('nodeName').toLowerCase();
                                            }
                                        }
                                    },
                            
                                    /**
                                     * Handles the container scroll events.
                                     *
                                     * @method _onContainerScroll
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _onContainerScroll: function(event) {
                                        var instance = this;
                            
                                        instance._focus();
                                    },
                            
                                    /**
                                     * Enables the query to be triggered based on detecting text input via intervals instead of via
                                     * key events.
                                     *
                                     * @method _onInterval
                                     * @protected
                                     */
                                    _onInterval: function() {
                                        var instance = this;
                            
                                        var curValue = instance.inputNode.get('value');
                                        var lastValue = instance._lastValue;
                            
                                        if (curValue != lastValue) {
                                            instance._lastValue = curValue;
                            
                                            instance._sendQuery(curValue);
                                        }
                                    },
                            
                                    /**
                                     * Handles the input element losing focus.
                                     *
                                     * @method _onTextboxBlur
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _onTextboxBlur: function(event) {
                                        var instance = this;
                            
                                        if (!instance._overContainer || KeyMap.isKey(instance._keyCode, TAB)) {
                                            if (!instance._itemSelected) {
                                                var elMatchListItem = instance._textMatchesOption();
                            
                                                var overlayVisible = instance.overlay.get('visible');
                            
                                                if (!overlayVisible || (overlayVisible && isNull(elMatchListItem))) {
                                                    if (instance.get('forceSelection')) {
                                                        instance._clearSelection();
                                                    }
                                                    else {
                                                        instance.fire('unmatchedItemSelect', instance._currentQuery);
                                                    }
                                                }
                                                else {
                                                    if (instance.get('forceSelection')) {
                                                        instance._selectItem(elMatchListItem);
                                                    }
                                                }
                                            }
                            
                                            instance._clearInterval();
                            
                                            instance.blur();
                            
                                            if (instance._initInputValue !== instance.inputNode.get('value')) {
                                                instance.fire('textboxChange');
                                            }
                            
                                            instance.fire('textboxBlur');
                            
                                            instance._toggleContainer(false);
                                        }
                                        else {
                                            instance._focus();
                                        }
                                    },
                            
                                    /**
                                     * Handles the input element gaining focus.
                                     *
                                     * @method _onTextboxFocus
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _onTextboxFocus: function(event) {
                                        var instance = this;
                            
                                        if (!instance.get('focused')) {
                                            instance.inputNode.setAttribute('autocomplete', 'off');
                                            instance.focus();
                                            instance._initInputValue = instance.inputNode.get('value');
                            
                                            instance.fire('textboxFocus');
                                        }
                                    },
                            
                                    /**
                                     * Handles the keydown events on the input element for functional keys.
                                     *
                                     * @method _onTextboxKeyDown
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _onTextboxKeyDown: function(event) {
                                        var instance = this;
                            
                                        var keyCode = event.keyCode;
                            
                                        if (instance._typeAheadDelayId != -1) {
                                            clearTimeout(instance._typeAheadDelayId);
                                        }
                            
                                        if (event.isKey(TAB)) {
                                            if (instance._elCurListItem) {
                                                if (instance.get('delimChar') && instance._keyCode != keyCode) {
                                                    if (instance.overlay.get('visible')) {
                                                        event.halt();
                                                    }
                                                }
                            
                                                instance._selectItem(instance._elCurListItem);
                                            }
                                            else {
                                                instance._toggleContainer(false);
                                            }
                                        }
                                        else if (event.isKey(ENTER)) {
                                            if (instance._elCurListItem) {
                                                if (instance._keyCode != keyCode) {
                                                    if (instance.overlay.get('visible')) {
                                                        event.halt();
                                                    }
                                                }
                            
                                                instance._selectItem(instance._elCurListItem);
                                            }
                                            else {
                                                instance._toggleContainer(false);
                                            }
                                        }
                                        else if (event.isKey(ESC)) {
                                            instance._toggleContainer(false);
                                        }
                                        else if (event.isKey(UP)) {
                                            if (instance.overlay.get('visible')) {
                                                event.halt();
                            
                                                instance._moveSelection(keyCode);
                                            }
                                        }
                                        else if (event.isKey(RIGHT)) {
                                            instance._jumpSelection();
                                        }
                                        else if (event.isKey(DOWN)) {
                                            if (instance.overlay.get('visible')) {
                                                event.halt();
                            
                                                instance._moveSelection(keyCode);
                                            }
                                        }
                                        else {
                                            instance._itemSelected = false;
                                            instance._toggleHighlight(instance._elCurListItem, 'from');
                            
                                            instance.fire('textboxKey', keyCode);
                                        }
                            
                                        if (event.isKey(ALT)) {
                                            instance._enableIntervalDetection();
                                        }
                            
                                        instance._keyCode = keyCode;
                                    },
                            
                                    /**
                                     * Handles the key press events of the input element.
                                     *
                                     * @method _onTextboxKeyPress
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _onTextboxKeyPress: function(event) {
                                        var instance = this;
                            
                                        var keyCode = event.keyCode;
                            
                                        if (event.isKey(TAB)) {
                                            if (instance.overlay.get('visible')) {
                                                if (instance.get('delimChar')) {
                                                    event.halt();
                                                }
                            
                                                if (instance._elCurListItem) {
                                                    instance._selectItem(instance._elCurListItem);
                                                }
                                                else {
                                                    instance._toggleContainer(false);
                                                }
                                            }
                                        }
                                        else if (event.isKey(ENTER)) {
                                            if (instance.overlay.get('visible')) {
                                                event.halt();
                            
                                                if (instance._elCurListItem) {
                                                    instance._selectItem(instance._elCurListItem);
                                                }
                                                else {
                                                    instance._toggleContainer(false);
                                                }
                                            }
                                        }
                            
                                        if (event.isKey(WIN_IME)) {
                                            instance._enableIntervalDetection();
                                        }
                                    },
                            
                                    /**
                                     * Handles the keyup events of the input element.
                                     *
                                     * @method _onTextboxKeyUp
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _onTextboxKeyUp: function(event) {
                                        var instance = this;
                            
                                        var input = instance.inputNode;
                            
                                        var value = input.get('value');
                            
                                        if (event.isSpecialKey() && !event.isKey(BACKSPACE)) {
                                            return;
                                        }
                            
                                        instance._queryTask(value);
                                    },
                            
                                    /**
                                     * Populates the container with list items of the query results.
                                     *
                                     * @method _populateList
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _populateList: function(event) {
                                        var instance = this;
                            
                                        if (instance._typeAheadDelayId != -1) {
                                            clearTimeout(instance._typeAheadDelayId);
                                        }
                            
                                        var query = event.request;
                                        var response = event.response;
                                        var callback = event.callback;
                                        var showAll = (query == '*');
                            
                                        if (callback && callback.argument && callback.argument.query) {
                                            event.request = query = callback.argument.query;
                                        }
                            
                                        var ok = instance.doBeforeLoadData(event);
                            
                                        if (ok && !event.error) {
                                            instance.fire('dataReturn', event);
                            
                                            var focused = instance.get('focused');
                            
                                            if (showAll || focused || focused === null) {
                                                var currentQuery = decodeURIComponent(query);
                            
                                                instance._currentQuery = currentQuery;
                                                instance._itemSelected = false;
                            
                                                var allResults = event.response.results;
                                                var itemsToShow = Math.min(allResults.length, instance.get('maxResultsDisplayed'));
                                                var fields = instance.get('schema.resultFields');
                                                var matchKey = instance.get('matchKey');
                            
                                                if (!matchKey && fields) {
                                                    matchKey = fields[0];
                                                }
                                                else {
                                                    matchKey = matchKey || 0;
                                                }
                            
                                                if (itemsToShow > 0) {
                                                    var allListItemEls = instance.resultList.get('childNodes');
                            
                                                    allListItemEls.each(
                                                        function(node, i, nodeList) {
                                                            if (i < itemsToShow) {
                                                                var result = allResults[i];
                            
                                                                var resultMatch = '';
                            
                                                                if (isString(result)) {
                                                                    resultMatch = result;
                                                                }
                                                                else if (isArray(result)) {
                                                                    resultMatch = result[0];
                                                                }
                                                                else {
                                                                    resultMatch = result[matchKey];
                                                                }
                            
                                                                node._resultMatch = resultMatch;
                            
                                                                node._resultData = result;
                                                                node.html(instance.formatResult(result, currentQuery, resultMatch));
                            
                                                                node.removeClass(CSS_HIDDEN);
                                                            }
                                                            else {
                                                                node.addClass(CSS_HIDDEN);
                                                            }
                                                        }
                                                    );
                            
                                                    instance._displayedItems = itemsToShow;
                            
                                                    instance.fire('containerPopulate', query, allResults);
                            
                                                    if (query != '*' && instance.get('autoHighlight')) {
                                                        var elFirstListItem = instance.resultList.get('firstChild');
                            
                                                        instance._toggleHighlight(elFirstListItem, 'to');
                                                        instance.fire('itemArrowTo', elFirstListItem);
                            
                                                        instance._typeAhead(elFirstListItem, query);
                                                    }
                                                    else {
                                                        instance._toggleHighlight(instance._elCurListItem, 'from');
                                                    }
                            
                                                    ok = instance.doBeforeExpandContainer(query, allResults);
                            
                                                    instance._toggleContainer(ok);
                                                }
                                                else {
                                                    instance._toggleContainer(false);
                                                }
                            
                                                return;
                                            }
                            
                                        }
                                        else {
                                            instance.fire('dataError', query);
                                        }
                                    },
                            
                                    /**
                                     * Realigns the container to the input element.
                                     *
                                     * @method _realignContainer
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _realignContainer: function(event) {
                                        var instance = this;
                            
                                        var overlayAlign = instance._overlayAlign;
                            
                                        if (event.newVal) {
                                            instance.overlay._uiSetAlign(overlayAlign.node, overlayAlign.points);
                                        }
                                    },
                            
                                    /**
                                     * Handles the rendering of the input element.
                                     *
                                     * @method _renderInput
                                     * @protected
                                     */
                                    _renderInput: function() {
                                        var instance = this;
                            
                                        var contentBox = instance.get(CONTENT_BOX);
                                        var input = instance.get('input');
                            
                                        var comboConfig = {
                                            field: {
                                                labelText: false
                                            },
                                            icons: [
                                                {
                                                    icon: 'icon-circle-arrow-down',
                                                    id: 'trigger',
                                                    handler: {
                                                        fn: instance._onButtonMouseDown,
                                                        context: instance
                                                    }
                                  }
                                 ]
                                        };
                            
                                        var inputReference = null;
                                        var inputParent = null;
                            
                                        if (input) {
                                            input = A.one(input);
                            
                                            comboConfig.field.node = input;
                            
                                            inputReference = input.next();
                                            inputParent = input.get('parentNode');
                                        }
                            
                                        var comboBox = new A.Combobox(comboConfig).render(contentBox);
                            
                                        if (inputParent) {
                                            var comboBoundingBox = comboBox.get('boundingBox');
                            
                                            inputParent.insertBefore(comboBoundingBox, inputReference);
                                        }
                            
                                        instance.inputNode = comboBox.get('node');
                                        instance.button = comboBox.icons.item(0);
                            
                                        instance.set('uniqueName', A.stamp(instance.inputNode));
                                    },
                            
                                    /**
                                     * Pre-populates the container with the
                                     * <a href="Autocomplete.html#config_maxResultsDisplayed">maxResultsDisplayed</a>
                                     * number of list items.
                                     *
                                     * @method _renderListElements
                                     * @protected
                                     */
                                    _renderListElements: function() {
                                        var instance = this;
                            
                                        var maxResultsDisplayed = instance.get('maxResultsDisplayed');
                            
                                        var resultList = instance.resultList;
                            
                                        var listItems = [];
                            
                                        while (maxResultsDisplayed--) {
                                            listItems[maxResultsDisplayed] = '<li class="' + CSS_HIDDEN + ' ' + CSS_LIST_ITEM +
                                                '" data-listItemIndex="' + maxResultsDisplayed + '"></li>';
                                        }
                            
                                        resultList.html(listItems.join(''));
                                    },
                            
                                    /**
                                     * Handles the creation of the overlay where the result list will be displayed.
                                     *
                                     * @method _renderOverlay
                                     * @protected
                                     */
                                    _renderOverlay: function() {
                                        var instance = this;
                            
                                        var overlayAlign = instance._overlayAlign;
                            
                                        overlayAlign.node = instance.inputNode;
                            
                                        var overlay = new A.OverlayBase({
                                            align: overlayAlign,
                                            bodyContent: '<ul></ul>',
                                            visible: false,
                                            width: instance.inputNode.get('offsetWidth'),
                                            zIndex: 1
                                        });
                            
                                        var contentBox = overlay.get(CONTENT_BOX);
                            
                                        overlay.get(BOUNDING_BOX).addClass(CSS_RESULTS_OVERLAY);
                            
                                        contentBox.addClass(CSS_RESULTS_OVERLAY_CONTENT);
                            
                                        overlay.render();
                            
                                        overlay.addTarget(instance);
                            
                                        instance.overlay = overlay;
                                        instance.resultList = contentBox.one('ul');
                            
                                        instance.resultList.addClass(CSS_RESULTS_LIST);
                            
                                        instance._renderListElements();
                                    },
                            
                                    /**
                                     * Selects a list item from the query results.
                                     *
                                     * @method _selectItem
                                     * @param {Node} elListItem The list item to select
                                     * @protected
                                     */
                                    _selectItem: function(elListItem) {
                                        var instance = this;
                            
                                        instance._itemSelected = true;
                            
                                        instance._updateValue(elListItem);
                            
                                        instance._pastSelections = instance.inputNode.get('value');
                            
                                        instance._clearInterval();
                            
                                        instance.fire('itemSelect', elListItem, elListItem._resultData);
                            
                                        instance._toggleContainer(false);
                                    },
                            
                                    /**
                                     * Makes a query request to the data source.
                                     *
                                     * @method _sendQuery
                                     * @param {String} query The query string
                                     * @protected
                                     */
                                    _sendQuery: function(query) {
                                        var instance = this;
                            
                                        if (instance.get('disabled')) {
                                            instance._toggleContainer(false);
                            
                                            return;
                                        }
                            
                                        var delimChar = instance.get('delimChar');
                                        var minQueryLength = instance.get('minQueryLength');
                            
                                        if (delimChar) {
                                            var extraction = instance._extractQuery(query);
                            
                                            query = extraction.query;
                            
                                            instance._pastSelections = extraction.previous;
                                        }
                            
                                        if ((query && (query.length < minQueryLength)) || (!query && minQueryLength > 0)) {
                                            instance._queryTask.cancel();
                            
                                            instance._toggleContainer(false);
                            
                                            return;
                                        }
                            
                                        query = encodeURIComponent(query);
                            
                                        if (instance.get('applyLocalFilter')) {
                                            instance.dataSource.on('response', instance.filterResults, instance);
                                        }
                            
                                        var request = instance.generateRequest(query);
                            
                                        instance.fire('dataRequest', query, request);
                            
                                        instance.dataSource.sendRequest(request);
                                    },
                            
                                    /**
                                     * Checks to see if the value typed by the user matches any of the
                                     * query results.
                                     *
                                     * @method _textMatchesOption
                                     * @protected
                                     */
                                    _textMatchesOption: function() {
                                        var instance = this;
                            
                                        var elMatch = null;
                                        var displayedItems = instance._displayedItems;
                                        var listItems = instance.resultList.get('childNodes');
                            
                                        for (var i = 0; i < displayedItems.length; i++) {
                                            var elListItem = listItems.item(i);
                            
                                            var match = ('' + elListItem._resultMatch).toLowerCase();
                            
                                            if (match == instance._currentQuery.toLowerCase()) {
                                                elMatch = elListItem;
                            
                                                break;
                                            }
                                        }
                            
                                        return elMatch;
                                    },
                            
                                    /**
                                     * Toggles the display of the results container.
                                     *
                                     * @method _toggleContainer
                                     * @param {Boolean} show Flag to force the showing or hiding of the container
                                     * @protected
                                     */
                                    _toggleContainer: function(show) {
                                        var instance = this;
                            
                                        var overlay = instance.overlay;
                            
                                        if (instance.get('alwaysShowContainer') && overlay.get('visible')) {
                                            return;
                                        }
                            
                                        if (!show) {
                                            instance._toggleHighlight(instance._elCurListItem, 'from');
                            
                                            instance._displayedItems = 0;
                                            instance._currentQuery = null;
                                        }
                            
                                        if (show) {
                                            overlay.show();
                                            instance.fire('containerExpand');
                                        }
                                        else {
                                            overlay.hide();
                                            instance.fire('containerCollapse');
                                        }
                                    },
                            
                                    /**
                                     * Toggles the highlighting of a list item, and removes the highlighting from the previous item
                                     *
                                     * @method _toggleHighlight
                                     * @param {Node} elNewListItem The item to be highlighted
                                     * @param {String} action Whether we are moving to or from an item. Valid values are "to" or "from".
                                     * @protected
                                     */
                                    _toggleHighlight: function(elNewListItem, action) {
                                        var instance = this;
                            
                                        if (elNewListItem) {
                                            if (instance._elCurListItem) {
                                                instance._elCurListItem.removeClass(CSS_HIGLIGHT);
                                                instance._elCurListItem = null;
                                            }
                            
                                            if (action == 'to') {
                                                elNewListItem.addClass(CSS_HIGLIGHT);
                            
                                                instance._elCurListItem = elNewListItem;
                                            }
                                        }
                                    },
                            
                                    /**
                                     * Updates in the input element with the first result as the user types,
                                     * selecting the text the user has not typed yet.
                                     *
                                     * @method _typeAhead
                                     * @param {Node} elListItem The selected list item
                                     * @param {String} query The query string
                                     * @protected
                                     */
                                    _typeAhead: function(elListItem, query) {
                                        var instance = this;
                            
                                        if (!instance.get('typeAhead') || KeyMap.isKey(instance._keyCode, BACKSPACE)) {
                                            return;
                                        }
                            
                                        var inputEl = A.Node.getDOMNode(instance.inputNode);
                            
                                        if (inputEl.setSelectionRange || inputEl.createTextRange) {
                                            instance._typeAheadDelayId = setTimeout(
                                                function() {
                                                    var value = inputEl.value;
                            
                                                    var start = value.length;
                            
                                                    instance._updateValue(elListItem);
                            
                                                    var end = inputEl.value.length;
                            
                                                    instance.inputNode.selectText(start, end);
                            
                                                    var prefill = inputEl.value.substr(start, end);
                            
                                                    instance.fire('typeAhead', query, prefill);
                                                },
                                                instance.get('typeAheadDelay')
                                            );
                                        }
                                    },
                            
                                    /**
                                     * Updates the input element with the selected query result. If
                                     * <a href="Autocomplete.html#config_delimChar">delimChar</a> has been set,
                                     * then the value gets appended with the delimiter.
                                     *
                                     * @method _updateValue
                                     * @param {Node} elListItem The selected list item
                                     * @protected
                                     */
                                    _updateValue: function(elListItem) {
                                        var instance = this;
                            
                                        if (!instance.get('suppressInputUpdate')) {
                                            var input = instance.inputNode;
                                            var resultMatch = elListItem._resultMatch;
                            
                                            var delimChar = instance.get('delimChar');
                            
                                            delimChar = (delimChar && delimChar[0]) || delimChar;
                            
                                            var newValue = '';
                            
                                            if (delimChar) {
                                                newValue = instance._pastSelections;
                            
                                                newValue += resultMatch + delimChar;
                            
                                                if (delimChar != ' ') {
                                                    newValue += ' ';
                                                }
                                            }
                                            else {
                                                newValue = resultMatch;
                                            }
                            
                                            input.set('value', newValue);
                            
                                            if (input.get('type') == 'textarea') {
                                                input.set('scrollTop', input.get('scrollHeight'));
                                            }
                            
                                            var end = newValue.length;
                            
                                            input.selectText(end, end);
                            
                                            instance._elCurListItem = elListItem;
                                        }
                                    },
                            
                                    _currentQuery: null,
                                    _displayedItems: 0,
                                    _elCurListItem: null,
                                    _initInputValue: null,
                                    _itemSelected: false,
                                    _keyCode: null,
                                    _lastValue: null,
                                    _overContainer: false,
                                    _pastSelections: '',
                                    _typeAheadDelayId: -1
                                }
                            });
                            
                            A.AutoCompleteDeprecated = AutoComplete;