Show:
                            /**
                            Traditional autocomplete dropdown list widget, just like Mom used to make.
                            
                            @module autocomplete
                            @submodule autocomplete-list
                            **/
                            
                            /**
                            Traditional autocomplete dropdown list widget, just like Mom used to make.
                            
                            @class AutoCompleteList
                            @extends Widget
                            @uses AutoCompleteBase
                            @uses WidgetPosition
                            @uses WidgetPositionAlign
                            @constructor
                            @param {Object} config Configuration object.
                            **/
                            
                            var Lang   = Y.Lang,
                                Node   = Y.Node,
                                YArray = Y.Array,
                            
                                // Whether or not we need an iframe shim.
                                useShim = Y.UA.ie && Y.UA.ie < 7,
                            
                                // keyCode constants.
                                KEY_TAB = 9,
                            
                                // String shorthand.
                                _CLASS_ITEM        = '_CLASS_ITEM',
                                _CLASS_ITEM_ACTIVE = '_CLASS_ITEM_ACTIVE',
                                _CLASS_ITEM_HOVER  = '_CLASS_ITEM_HOVER',
                                _SELECTOR_ITEM     = '_SELECTOR_ITEM',
                            
                                ACTIVE_ITEM      = 'activeItem',
                                ALWAYS_SHOW_LIST = 'alwaysShowList',
                                CIRCULAR         = 'circular',
                                HOVERED_ITEM     = 'hoveredItem',
                                ID               = 'id',
                                ITEM             = 'item',
                                LIST             = 'list',
                                RESULT           = 'result',
                                RESULTS          = 'results',
                                VISIBLE          = 'visible',
                                WIDTH            = 'width',
                            
                                // Event names.
                                EVT_SELECT = 'select',
                            
                            List = Y.Base.create('autocompleteList', Y.Widget, [
                                Y.AutoCompleteBase,
                                Y.WidgetPosition,
                                Y.WidgetPositionAlign
                            ], {
                                // -- Prototype Properties -------------------------------------------------
                                ARIA_TEMPLATE: '<div/>',
                                ITEM_TEMPLATE: '<li/>',
                                LIST_TEMPLATE: '<ul/>',
                            
                                // Widget automatically attaches delegated event handlers to everything in
                                // Y.Node.DOM_EVENTS, including synthetic events. Since Widget's event
                                // delegation won't work for the synthetic valuechange event, and since
                                // it creates a name collision between the backcompat "valueChange" synth
                                // event alias and AutoCompleteList's "valueChange" event for the "value"
                                // attr, this hack is necessary in order to prevent Widget from attaching
                                // valuechange handlers.
                                UI_EVENTS: (function () {
                                    var uiEvents = Y.merge(Y.Node.DOM_EVENTS);
                            
                                    delete uiEvents.valuechange;
                                    delete uiEvents.valueChange;
                            
                                    return uiEvents;
                                }()),
                            
                                // -- Lifecycle Prototype Methods ------------------------------------------
                                initializer: function () {
                                    var inputNode = this.get('inputNode');
                            
                                    if (!inputNode) {
                                        Y.error('No inputNode specified.');
                                        return;
                                    }
                            
                                    this._inputNode  = inputNode;
                                    this._listEvents = [];
                            
                                    // This ensures that the list is rendered inside the same parent as the
                                    // input node by default, which is necessary for proper ARIA support.
                                    this.DEF_PARENT_NODE = inputNode.get('parentNode');
                            
                                    // Cache commonly used classnames and selectors for performance.
                                    this[_CLASS_ITEM]        = this.getClassName(ITEM);
                                    this[_CLASS_ITEM_ACTIVE] = this.getClassName(ITEM, 'active');
                                    this[_CLASS_ITEM_HOVER]  = this.getClassName(ITEM, 'hover');
                                    this[_SELECTOR_ITEM]     = '.' + this[_CLASS_ITEM];
                            
                                    /**
                                    Fires when an autocomplete suggestion is selected from the list,
                                    typically via a keyboard action or mouse click.
                            
                                    @event select
                                    @param {Node} itemNode List item node that was selected.
                                    @param {Object} result AutoComplete result object.
                                    @preventable _defSelectFn
                                    **/
                                    this.publish(EVT_SELECT, {
                                        defaultFn: this._defSelectFn
                                    });
                                },
                            
                                destructor: function () {
                                    while (this._listEvents.length) {
                                        this._listEvents.pop().detach();
                                    }
                            
                                    if (this._ariaNode) {
                                        this._ariaNode.remove().destroy(true);
                                    }
                                },
                            
                                bindUI: function () {
                                    this._bindInput();
                                    this._bindList();
                                },
                            
                                renderUI: function () {
                                    var ariaNode    = this._createAriaNode(),
                                        boundingBox = this.get('boundingBox'),
                                        contentBox  = this.get('contentBox'),
                                        inputNode   = this._inputNode,
                                        listNode    = this._createListNode(),
                                        parentNode  = inputNode.get('parentNode');
                            
                                    inputNode.addClass(this.getClassName('input')).setAttrs({
                                        'aria-autocomplete': LIST,
                                        'aria-expanded'    : false,
                                        'aria-owns'        : listNode.get('id')
                                    });
                            
                                    // ARIA node must be outside the widget or announcements won't be made
                                    // when the widget is hidden.
                                    parentNode.append(ariaNode);
                            
                                    // Add an iframe shim for IE6.
                                    if (useShim) {
                                        boundingBox.plug(Y.Plugin.Shim);
                                    }
                            
                                    this._ariaNode    = ariaNode;
                                    this._boundingBox = boundingBox;
                                    this._contentBox  = contentBox;
                                    this._listNode    = listNode;
                                    this._parentNode  = parentNode;
                                },
                            
                                syncUI: function () {
                                    // No need to call _syncPosition() here; the other _sync methods will
                                    // call it when necessary.
                                    this._syncResults();
                                    this._syncVisibility();
                                },
                            
                                // -- Public Prototype Methods ---------------------------------------------
                            
                                /**
                                Hides the list, unless the `alwaysShowList` attribute is `true`.
                            
                                @method hide
                                @see show
                                @chainable
                                **/
                                hide: function () {
                                    return this.get(ALWAYS_SHOW_LIST) ? this : this.set(VISIBLE, false);
                                },
                            
                                /**
                                Selects the specified _itemNode_, or the current `activeItem` if _itemNode_
                                is not specified.
                            
                                @method selectItem
                                @param {Node} [itemNode] Item node to select.
                                @param {EventFacade} [originEvent] Event that triggered the selection, if
                                    any.
                                @chainable
                                **/
                                selectItem: function (itemNode, originEvent) {
                                    if (itemNode) {
                                        if (!itemNode.hasClass(this[_CLASS_ITEM])) {
                                            return this;
                                        }
                                    } else {
                                        itemNode = this.get(ACTIVE_ITEM);
                            
                                        if (!itemNode) {
                                            return this;
                                        }
                                    }
                            
                                    this.fire(EVT_SELECT, {
                                        itemNode   : itemNode,
                                        originEvent: originEvent || null,
                                        result     : itemNode.getData(RESULT)
                                    });
                            
                                    return this;
                                },
                            
                                // -- Protected Prototype Methods ------------------------------------------
                            
                                /**
                                Activates the next item after the currently active item. If there is no next
                                item and the `circular` attribute is `true`, focus will wrap back to the
                                input node.
                            
                                @method _activateNextItem
                                @chainable
                                @protected
                                **/
                                _activateNextItem: function () {
                                    var item = this.get(ACTIVE_ITEM),
                                        nextItem;
                            
                                    if (item) {
                                        nextItem = item.next(this[_SELECTOR_ITEM]) ||
                                                (this.get(CIRCULAR) ? null : item);
                                    } else {
                                        nextItem = this._getFirstItemNode();
                                    }
                            
                                    this.set(ACTIVE_ITEM, nextItem);
                            
                                    return this;
                                },
                            
                                /**
                                Activates the item previous to the currently active item. If there is no
                                previous item and the `circular` attribute is `true`, focus will wrap back
                                to the input node.
                            
                                @method _activatePrevItem
                                @chainable
                                @protected
                                **/
                                _activatePrevItem: function () {
                                    var item     = this.get(ACTIVE_ITEM),
                                        prevItem = item ? item.previous(this[_SELECTOR_ITEM]) :
                                                this.get(CIRCULAR) && this._getLastItemNode();
                            
                                    this.set(ACTIVE_ITEM, prevItem || null);
                            
                                    return this;
                                },
                            
                                /**
                                Appends the specified result _items_ to the list inside a new item node.
                            
                                @method _add
                                @param {Array|Node|HTMLElement|String} items Result item or array of
                                    result items.
                                @return {NodeList} Added nodes.
                                @protected
                                **/
                                _add: function (items) {
                                    var itemNodes = [];
                            
                                    YArray.each(Lang.isArray(items) ? items : [items], function (item) {
                                        itemNodes.push(this._createItemNode(item).setData(RESULT, item));
                                    }, this);
                            
                                    itemNodes = Y.all(itemNodes);
                                    this._listNode.append(itemNodes.toFrag());
                            
                                    return itemNodes;
                                },
                            
                                /**
                                Updates the ARIA live region with the specified message.
                            
                                @method _ariaSay
                                @param {String} stringId String id (from the `strings` attribute) of the
                                    message to speak.
                                @param {Object} [subs] Substitutions for placeholders in the string.
                                @protected
                                **/
                                _ariaSay: function (stringId, subs) {
                                    var message = this.get('strings.' + stringId);
                                    this._ariaNode.set('text', subs ? Lang.sub(message, subs) : message);
                                },
                            
                                /**
                                Binds `inputNode` events and behavior.
                            
                                @method _bindInput
                                @protected
                                **/
                                _bindInput: function () {
                                    var inputNode = this._inputNode,
                                        alignNode, alignWidth, tokenInput;
                            
                                    // Null align means we can auto-align. Set align to false to prevent
                                    // auto-alignment, or a valid alignment config to customize the
                                    // alignment.
                                    if (this.get('align') === null) {
                                        // If this is a tokenInput, align with its bounding box.
                                        // Otherwise, align with the inputNode. Bit of a cheat.
                                        tokenInput = this.get('tokenInput');
                                        alignNode  = (tokenInput && tokenInput.get('boundingBox')) || inputNode;
                            
                                        this.set('align', {
                                            node  : alignNode,
                                            points: ['tl', 'bl']
                                        });
                            
                                        // If no width config is set, attempt to set the list's width to the
                                        // width of the alignment node. If the alignment node's width is
                                        // falsy, do nothing.
                                        if (!this.get(WIDTH) && (alignWidth = alignNode.get('offsetWidth'))) {
                                            this.set(WIDTH, alignWidth);
                                        }
                                    }
                            
                                    // Attach inputNode events.
                                    this._listEvents = this._listEvents.concat([
                                        inputNode.after('blur',  this._afterListInputBlur, this),
                                        inputNode.after('focus', this._afterListInputFocus, this)
                                    ]);
                                },
                            
                                /**
                                Binds list events.
                            
                                @method _bindList
                                @protected
                                **/
                                _bindList: function () {
                                    this._listEvents = this._listEvents.concat([
                                        Y.one('doc').after('click', this._afterDocClick, this),
                                        Y.one('win').after('windowresize', this._syncPosition, this),
                            
                                        this.after({
                                            mouseover: this._afterMouseOver,
                                            mouseout : this._afterMouseOut,
                            
                                            activeItemChange    : this._afterActiveItemChange,
                                            alwaysShowListChange: this._afterAlwaysShowListChange,
                                            hoveredItemChange   : this._afterHoveredItemChange,
                                            resultsChange       : this._afterResultsChange,
                                            visibleChange       : this._afterVisibleChange
                                        }),
                            
                                        this._listNode.delegate('click', this._onItemClick,
                                                this[_SELECTOR_ITEM], this)
                                    ]);
                                },
                            
                                /**
                                Clears the contents of the tray.
                            
                                @method _clear
                                @protected
                                **/
                                _clear: function () {
                                    this.set(ACTIVE_ITEM, null);
                                    this._set(HOVERED_ITEM, null);
                            
                                    this._listNode.get('children').remove(true);
                                },
                            
                                /**
                                Creates and returns an ARIA live region node.
                            
                                @method _createAriaNode
                                @return {Node} ARIA node.
                                @protected
                                **/
                                _createAriaNode: function () {
                                    var ariaNode = Node.create(this.ARIA_TEMPLATE);
                            
                                    return ariaNode.addClass(this.getClassName('aria')).setAttrs({
                                        'aria-live': 'polite',
                                        role       : 'status'
                                    });
                                },
                            
                                /**
                                Creates and returns an item node with the specified _content_.
                            
                                @method _createItemNode
                                @param {Object} result Result object.
                                @return {Node} Item node.
                                @protected
                                **/
                                _createItemNode: function (result) {
                                    var itemNode = Node.create(this.ITEM_TEMPLATE);
                            
                                    return itemNode.addClass(this[_CLASS_ITEM]).setAttrs({
                                        id  : Y.stamp(itemNode),
                                        role: 'option'
                                    }).setAttribute('data-text', result.text).append(result.display);
                                },
                            
                                /**
                                Creates and returns a list node. If the `listNode` attribute is already set
                                to an existing node, that node will be used.
                            
                                @method _createListNode
                                @return {Node} List node.
                                @protected
                                **/
                                _createListNode: function () {
                                    var listNode = this.get('listNode') || Node.create(this.LIST_TEMPLATE);
                            
                                    listNode.addClass(this.getClassName(LIST)).setAttrs({
                                        id  : Y.stamp(listNode),
                                        role: 'listbox'
                                    });
                            
                                    this._set('listNode', listNode);
                                    this.get('contentBox').append(listNode);
                            
                                    return listNode;
                                },
                            
                                /**
                                Gets the first item node in the list, or `null` if the list is empty.
                            
                                @method _getFirstItemNode
                                @return {Node|null}
                                @protected
                                **/
                                _getFirstItemNode: function () {
                                    return this._listNode.one(this[_SELECTOR_ITEM]);
                                },
                            
                                /**
                                Gets the last item node in the list, or `null` if the list is empty.
                            
                                @method _getLastItemNode
                                @return {Node|null}
                                @protected
                                **/
                                _getLastItemNode: function () {
                                    return this._listNode.one(this[_SELECTOR_ITEM] + ':last-child');
                                },
                            
                                /**
                                Synchronizes the result list's position and alignment.
                            
                                @method _syncPosition
                                @protected
                                **/
                                _syncPosition: function () {
                                    // Force WidgetPositionAlign to refresh its alignment.
                                    this._syncUIPosAlign();
                            
                                    // Resize the IE6 iframe shim to match the list's dimensions.
                                    this._syncShim();
                                },
                            
                                /**
                                Synchronizes the results displayed in the list with those in the _results_
                                argument, or with the `results` attribute if an argument is not provided.
                            
                                @method _syncResults
                                @param {Array} [results] Results.
                                @protected
                                **/
                                _syncResults: function (results) {
                                    if (!results) {
                                        results = this.get(RESULTS);
                                    }
                            
                                    this._clear();
                            
                                    if (results.length) {
                                        this._add(results);
                                        this._ariaSay('items_available');
                                    }
                            
                                    this._syncPosition();
                            
                                    if (this.get('activateFirstItem') && !this.get(ACTIVE_ITEM)) {
                                        this.set(ACTIVE_ITEM, this._getFirstItemNode());
                                    }
                                },
                            
                                /**
                                Synchronizes the size of the iframe shim used for IE6 and lower. In other
                                browsers, this method is a noop.
                            
                                @method _syncShim
                                @protected
                                **/
                                _syncShim: useShim ? function () {
                                    var shim = this._boundingBox.shim;
                            
                                    if (shim) {
                                        shim.sync();
                                    }
                                } : function () {},
                            
                                /**
                                Synchronizes the visibility of the tray with the _visible_ argument, or with
                                the `visible` attribute if an argument is not provided.
                            
                                @method _syncVisibility
                                @param {Boolean} [visible] Visibility.
                                @protected
                                **/
                                _syncVisibility: function (visible) {
                                    if (this.get(ALWAYS_SHOW_LIST)) {
                                        visible = true;
                                        this.set(VISIBLE, visible);
                                    }
                            
                                    if (typeof visible === 'undefined') {
                                        visible = this.get(VISIBLE);
                                    }
                            
                                    this._inputNode.set('aria-expanded', visible);
                                    this._boundingBox.set('aria-hidden', !visible);
                            
                                    if (visible) {
                                        this._syncPosition();
                                    } else {
                                        this.set(ACTIVE_ITEM, null);
                                        this._set(HOVERED_ITEM, null);
                            
                                        // Force a reflow to work around a glitch in IE6 and 7 where some of
                                        // the contents of the list will sometimes remain visible after the
                                        // container is hidden.
                                        this._boundingBox.get('offsetWidth');
                                    }
                            
                                    // In some pages, IE7 fails to repaint the contents of the list after it
                                    // becomes visible. Toggling a bogus class on the body forces a repaint
                                    // that fixes the issue.
                                    if (Y.UA.ie === 7) {
                                        // Note: We don't actually need to use ClassNameManager here. This
                                        // class isn't applying any actual styles; it's just frobbing the
                                        // body element to force a repaint. The actual class name doesn't
                                        // really matter.
                                        Y.one('body')
                                            .addClass('yui3-ie7-sucks')
                                            .removeClass('yui3-ie7-sucks');
                                    }
                                },
                            
                                // -- Protected Event Handlers ---------------------------------------------
                            
                                /**
                                Handles `activeItemChange` events.
                            
                                @method _afterActiveItemChange
                                @param {EventFacade} e
                                @protected
                                **/
                                _afterActiveItemChange: function (e) {
                                    var inputNode = this._inputNode,
                                        newVal    = e.newVal,
                                        prevVal   = e.prevVal,
                                        node;
                            
                                    // The previous item may have disappeared by the time this handler runs,
                                    // so we need to be careful.
                                    if (prevVal && prevVal._node) {
                                        prevVal.removeClass(this[_CLASS_ITEM_ACTIVE]);
                                    }
                            
                                    if (newVal) {
                                        newVal.addClass(this[_CLASS_ITEM_ACTIVE]);
                                        inputNode.set('aria-activedescendant', newVal.get(ID));
                                    } else {
                                        inputNode.removeAttribute('aria-activedescendant');
                                    }
                            
                                    if (this.get('scrollIntoView')) {
                                        node = newVal || inputNode;
                            
                                        if (!node.inRegion(Y.DOM.viewportRegion(), true)
                                                || !node.inRegion(this._contentBox, true)) {
                            
                                            node.scrollIntoView();
                                        }
                                    }
                                },
                            
                                /**
                                Handles `alwaysShowListChange` events.
                            
                                @method _afterAlwaysShowListChange
                                @param {EventFacade} e
                                @protected
                                **/
                                _afterAlwaysShowListChange: function (e) {
                                    this.set(VISIBLE, e.newVal || this.get(RESULTS).length > 0);
                                },
                            
                                /**
                                Handles click events on the document. If the click is outside both the
                                input node and the bounding box, the list will be hidden.
                            
                                @method _afterDocClick
                                @param {EventFacade} e
                                @protected
                                @since 3.5.0
                                **/
                                _afterDocClick: function (e) {
                                    var boundingBox = this._boundingBox,
                                        target      = e.target;
                            
                                    if (target !== this._inputNode && target !== boundingBox &&
                                            !target.ancestor('#' + boundingBox.get('id'), true)){
                                        this.hide();
                                    }
                                },
                            
                                /**
                                Handles `hoveredItemChange` events.
                            
                                @method _afterHoveredItemChange
                                @param {EventFacade} e
                                @protected
                                **/
                                _afterHoveredItemChange: function (e) {
                                    var newVal  = e.newVal,
                                        prevVal = e.prevVal;
                            
                                    if (prevVal) {
                                        prevVal.removeClass(this[_CLASS_ITEM_HOVER]);
                                    }
                            
                                    if (newVal) {
                                        newVal.addClass(this[_CLASS_ITEM_HOVER]);
                                    }
                                },
                            
                                /**
                                Handles `inputNode` blur events.
                            
                                @method _afterListInputBlur
                                @protected
                                **/
                                _afterListInputBlur: function () {
                                    this._listInputFocused = false;
                            
                                    if (this.get(VISIBLE) &&
                                            !this._mouseOverList &&
                                            (this._lastInputKey !== KEY_TAB ||
                                                !this.get('tabSelect') ||
                                                !this.get(ACTIVE_ITEM))) {
                                        this.hide();
                                    }
                                },
                            
                                /**
                                Handles `inputNode` focus events.
                            
                                @method _afterListInputFocus
                                @protected
                                **/
                                _afterListInputFocus: function () {
                                    this._listInputFocused = true;
                                },
                            
                                /**
                                Handles `mouseover` events.
                            
                                @method _afterMouseOver
                                @param {EventFacade} e
                                @protected
                                **/
                                _afterMouseOver: function (e) {
                                    var itemNode = e.domEvent.target.ancestor(this[_SELECTOR_ITEM], true);
                            
                                    this._mouseOverList = true;
                            
                                    if (itemNode) {
                                        this._set(HOVERED_ITEM, itemNode);
                                    }
                                },
                            
                                /**
                                Handles `mouseout` events.
                            
                                @method _afterMouseOut
                                @param {EventFacade} e
                                @protected
                                **/
                                _afterMouseOut: function () {
                                    this._mouseOverList = false;
                                    this._set(HOVERED_ITEM, null);
                                },
                            
                                /**
                                Handles `resultsChange` events.
                            
                                @method _afterResultsChange
                                @param {EventFacade} e
                                @protected
                                **/
                                _afterResultsChange: function (e) {
                                    this._syncResults(e.newVal);
                            
                                    if (!this.get(ALWAYS_SHOW_LIST)) {
                                        this.set(VISIBLE, !!e.newVal.length);
                                    }
                                },
                            
                                /**
                                Handles `visibleChange` events.
                            
                                @method _afterVisibleChange
                                @param {EventFacade} e
                                @protected
                                **/
                                _afterVisibleChange: function (e) {
                                    this._syncVisibility(!!e.newVal);
                                },
                            
                                /**
                                Delegated event handler for item `click` events.
                            
                                @method _onItemClick
                                @param {EventFacade} e
                                @protected
                                **/
                                _onItemClick: function (e) {
                                    var itemNode = e.currentTarget;
                            
                                    this.set(ACTIVE_ITEM, itemNode);
                                    this.selectItem(itemNode, e);
                                },
                            
                                // -- Protected Default Event Handlers -------------------------------------
                            
                                /**
                                Default `select` event handler.
                            
                                @method _defSelectFn
                                @param {EventFacade} e
                                @protected
                                **/
                                _defSelectFn: function (e) {
                                    var text = e.result.text;
                            
                                    // TODO: support typeahead completion, etc.
                                    this._inputNode.focus();
                                    this._updateValue(text);
                                    this._ariaSay('item_selected', {item: text});
                                    this.hide();
                                }
                            }, {
                                ATTRS: {
                                    /**
                                    If `true`, the first item in the list will be activated by default when
                                    the list is initially displayed and when results change.
                            
                                    @attribute activateFirstItem
                                    @type Boolean
                                    @default false
                                    **/
                                    activateFirstItem: {
                                        value: false
                                    },
                            
                                    /**
                                    Item that's currently active, if any. When the user presses enter, this
                                    is the item that will be selected.
                            
                                    @attribute activeItem
                                    @type Node
                                    **/
                                    activeItem: {
                                        setter: Y.one,
                                        value: null
                                    },
                            
                                    /**
                                    If `true`, the list will remain visible even when there are no results
                                    to display.
                            
                                    @attribute alwaysShowList
                                    @type Boolean
                                    @default false
                                    **/
                                    alwaysShowList: {
                                        value: false
                                    },
                            
                                    /**
                                    If `true`, keyboard navigation will wrap around to the opposite end of
                                    the list when navigating past the first or last item.
                            
                                    @attribute circular
                                    @type Boolean
                                    @default true
                                    **/
                                    circular: {
                                        value: true
                                    },
                            
                                    /**
                                    Item currently being hovered over by the mouse, if any.
                            
                                    @attribute hoveredItem
                                    @type Node|null
                                    @readOnly
                                    **/
                                    hoveredItem: {
                                        readOnly: true,
                                        value: null
                                    },
                            
                                    /**
                                    Node that will contain result items.
                            
                                    @attribute listNode
                                    @type Node|null
                                    @initOnly
                                    **/
                                    listNode: {
                                        writeOnce: 'initOnly',
                                        value: null
                                    },
                            
                                    /**
                                    If `true`, the viewport will be scrolled to ensure that the active list
                                    item is visible when necessary.
                            
                                    @attribute scrollIntoView
                                    @type Boolean
                                    @default false
                                    **/
                                    scrollIntoView: {
                                        value: false
                                    },
                            
                                    /**
                                    Translatable strings used by the AutoCompleteList widget.
                            
                                    @attribute strings
                                    @type Object
                                    **/
                                    strings: {
                                        valueFn: function () {
                                            return Y.Intl.get('autocomplete-list');
                                        }
                                    },
                            
                                    /**
                                    If `true`, pressing the tab key while the list is visible will select
                                    the active item, if any.
                            
                                    @attribute tabSelect
                                    @type Boolean
                                    @default true
                                    **/
                                    tabSelect: {
                                        value: true
                                    },
                            
                                    // The "visible" attribute is documented in Widget.
                                    visible: {
                                        value: false
                                    }
                                },
                            
                                CSS_PREFIX: Y.ClassNameManager.getClassName('aclist')
                            });
                            
                            Y.AutoCompleteList = List;
                            
                            /**
                            Alias for <a href="AutoCompleteList.html">`AutoCompleteList`</a>. See that class
                            for API docs.
                            
                            @class AutoComplete
                            **/
                            
                            Y.AutoComplete = List;