Show:
                            /**
                             * The ACE Editor AutoCompleteList Overlay
                             *
                             * @module aui-ace-editor
                             * @submodule aui-ace-autocomplete-list
                             */
                            
                            var Lang = A.Lang,
                                AArray = A.Array,
                                ANode = A.Node,
                                Do = A.Do,
                            
                                getCN = A.getClassName,
                            
                                CLASS_ENTRY = getCN('ace-autocomplete', 'entry'),
                                CLASS_ENTRY_CONTAINER = getCN('ace-autocomplete', 'entry', 'container'),
                                CLASS_ENTRY_CONTAINER_HIGHLIGHTED = getCN('ace-autocomplete', 'entry', 'container', 'highlighted'),
                                CLASS_ENTRY_EMPTY = getCN('ace-autocomplete', 'entry', 'empty'),
                                CLASS_ENTRY_LOADING = getCN('ace-autocomplete', 'entry', 'loading'),
                                CLASS_RESULTS_LIST = getCN('ace-autocomplete', 'results'),
                            
                                SELECTOR_ENTRY_CONTAINER = '.' + CLASS_ENTRY_CONTAINER,
                                SELECTOR_ENTRY_CONTAINER_SELECTED = SELECTOR_ENTRY_CONTAINER + '.' + 'selected',
                                SELECTOR_SELECTED_ENTRY = SELECTOR_ENTRY_CONTAINER_SELECTED + ' ' + '.' + CLASS_ENTRY,
                            
                                TPL_FRAGMENT = '<div></div>',
                            
                                KEY_DONW = 40,
                                KEY_END = 35,
                                KEY_PAGE_DOWN = 34,
                                KEY_PAGE_UP = 33,
                                KEY_START = 36,
                                KEY_UP = 38,
                            
                                PADDING_HORIZ = 5,
                                PADDING_VERT = 20,
                            
                                /**
                                 * A base class for AutoCompleteList.
                                 *
                                 * @class A.AceEditor.AutoCompleteList
                                 * @extends Overlay
                                 * @uses A.AceEditor.AutoCompleteBase, A.WidgetAutohide
                                 * @param {Object} config Object literal specifying widget configuration
                                 *     properties.
                                 * @constructor
                                 */
                                AutoCompleteList = A.Base.create('ace-autocomplete-list', A.Overlay, [
                                A.AceEditor.AutoCompleteBase,
                                A.WidgetAutohide
                            ], {
                            
                                    /**
                                     * Bind the events on the AutoCompleteList UI. Lifecycle.
                                     *
                                     * @method bindUI
                                     * @protected
                                     */
                                    bindUI: function() {
                                        var instance = this;
                            
                                        instance.on('addSuggestion', instance.hide, instance);
                                        instance.on('cursorChange', instance._onCursorChange, instance);
                                        instance.on('cursorOut', instance.hide, instance);
                                        instance.on('insertText', instance._onInsertText, instance);
                                        instance.on('match', instance._onMatch, instance);
                                        instance.on('removeText', instance._onRemoveText, instance);
                                        instance.on('resultsChange', instance._onResultsChange, instance);
                                        instance.on('resultsError', instance._setEmptyResults, instance);
                                        instance.on('showLoadingMessage', instance._onShowLoadingMessage, instance);
                                        instance.on('visibleChange', instance._onVisibleChange, instance);
                                    },
                            
                                    /**
                                     * Render the AutoCompleteList component instance. Lifecycle.
                                     *
                                     * @method renderUI
                                     * @protected
                                     */
                                    renderUI: function() {
                                        var instance = this,
                                            autoCompleteResultsList;
                            
                                        autoCompleteResultsList = instance.get('listNode');
                            
                                        if (!autoCompleteResultsList) {
                                            autoCompleteResultsList = instance._createListNode();
                                        }
                            
                                        autoCompleteResultsList.delegate(
                                            'click', instance._handleResultListClick, SELECTOR_ENTRY_CONTAINER, instance);
                            
                                        autoCompleteResultsList.delegate(
                                            'mouseenter', instance._onMouseEnter, SELECTOR_ENTRY_CONTAINER, instance);
                            
                                        autoCompleteResultsList.delegate('mouseleave', instance._onMouseLeave, SELECTOR_ENTRY_CONTAINER);
                            
                                        instance._autoCompleteResultsList = autoCompleteResultsList;
                                    },
                            
                                    /**
                                     *  Creates the main wrapper for the list of suggestions.
                                     *
                                     * @method _createListNode
                                     * @protected
                                     * @return {Node} The created node
                                     */
                                    _createListNode: function() {
                                        var instance = this,
                                            listNode;
                            
                                        listNode = A.Node.create(instance.TPL_LIST);
                            
                                        instance.get('contentBox').append(listNode);
                            
                                        return listNode;
                                    },
                            
                                    /**
                                     * Returns the number of entries which could be fit to the current list
                                     * viewport (page).
                                     *
                                     * @method _getEntriesPerPage
                                     * @protected
                                     * @return {Number} The number of calculated entries per page
                                     */
                                    _getEntriesPerPage: function() {
                                        var instance = this,
                                            autoCompleteResultsList,
                                            containerHeight,
                                            entriesPerPage,
                                            entryHeight;
                            
                                        entriesPerPage = instance._entriesPerPage;
                            
                                        if (!entriesPerPage) {
                                            autoCompleteResultsList = instance._autoCompleteResultsList;
                            
                                            entryHeight = autoCompleteResultsList.one(SELECTOR_ENTRY_CONTAINER).get('offsetHeight');
                            
                                            containerHeight = autoCompleteResultsList.get('offsetHeight');
                            
                                            entriesPerPage = Math.floor(containerHeight / entryHeight);
                            
                                            instance._entriesPerPage = entriesPerPage;
                                        }
                            
                                        return entriesPerPage;
                                    },
                            
                                    /**
                                     * Returns the currently selected entry.
                                     *
                                     * @method _getSelectedEntry
                                     * @protected
                                     * @return {String} The text of the currently selected entry
                                     */
                                    _getSelectedEntry: function() {
                                        var instance = this,
                                            entryText,
                                            selectedEntryNode;
                            
                                        selectedEntryNode = instance._autoCompleteResultsList.one(SELECTOR_SELECTED_ENTRY);
                            
                                        if (selectedEntryNode) {
                                            entryText = selectedEntryNode.text();
                                        }
                            
                                        return entryText;
                                    },
                            
                                    /**
                                     * Handles the arrows and executes different actions depending on the
                                     * pressed arrow. For example, pressing key down will scroll the list
                                     * bottom.
                                     *
                                     * @method _handleArrows
                                     * @param {Number} keyCode The code of the currently pressed arrow
                                     * @protected
                                     * @return {Do.Halt} Instance of Do.Halt in order to stop further
                                     *     function execution
                                     */
                                    _handleArrows: function(keyCode) {
                                        var instance = this,
                                            action,
                                            autoCompleteResultsList,
                                            entry,
                                            entryRegion,
                                            resultsListNodeRegion,
                                            selectedEntry;
                            
                                        if (keyCode === KEY_UP) {
                                            action = 'previous';
                                        }
                                        else if (keyCode === KEY_DONW) {
                                            action = 'next';
                                        }
                            
                                        if (action) {
                                            autoCompleteResultsList = instance._autoCompleteResultsList;
                            
                                            selectedEntry = autoCompleteResultsList.one(SELECTOR_ENTRY_CONTAINER_SELECTED);
                            
                                            if (selectedEntry) {
                                                entry = selectedEntry[action](SELECTOR_ENTRY_CONTAINER);
                            
                                                if (entry) {
                                                    selectedEntry.removeClass('selected');
                            
                                                    entry.addClass('selected');
                            
                                                    resultsListNodeRegion = autoCompleteResultsList.get('region');
                            
                                                    entryRegion = entry.get('region');
                            
                                                    if (action === 'previous') {
                                                        if (entryRegion.top < resultsListNodeRegion.top) {
                                                            entry.scrollIntoView(true);
                                                        }
                                                        else if (entryRegion.top > resultsListNodeRegion.bottom) {
                                                            entry.scrollIntoView();
                                                        }
                                                    }
                                                    else {
                                                        if (entryRegion.top + entryRegion.height > resultsListNodeRegion.bottom) {
                                                            entry.scrollIntoView();
                                                        }
                                                        else if (entryRegion.top + entryRegion.height < resultsListNodeRegion.top) {
                                                            entry.scrollIntoView(true);
                                                        }
                                                    }
                                                }
                                            }
                            
                                            return new Do.Halt(null);
                                        }
                                    },
                            
                                    /**
                                     * Handles key pressing and executes different actions depending on key
                                     * code.
                                     *
                                     * @method _handleKey
                                     * @param {CustomEvent} event The fired event
                                     * @param {Object} obj An internal object of ACE Editor
                                     * @param {Number} keyCode The code of currently pressed key
                                     * @protected
                                     * @return {Do.Halt} If valid code found, returns an instance of Do.Halt
                                     *     in order to stop further function execution
                                     */
                                    _handleKey: function(event, obj, keyCode) {
                                        var instance = this,
                                            result;
                            
                                        if (instance.get('visible')) {
                                            if (keyCode === KEY_UP || keyCode === KEY_DONW) {
                                                result = instance._handleArrows(keyCode);
                                            }
                                            else if (keyCode === KEY_PAGE_UP || keyCode === KEY_PAGE_DOWN) {
                                                result = instance._handlePageUpDown(keyCode);
                                            }
                                            else if (keyCode === KEY_END || keyCode === KEY_START) {
                                                result = instance._handleStartEnd(keyCode);
                                            }
                                        }
                            
                                        return result;
                                    },
                            
                                    /**
                                     * Handles scrolling page up or down.
                                     *
                                     * @method _handlePageUpDown
                                     * @param {Number} keyCode The code of currently pressed key. Could be
                                     *     one of: KEY_PAGE_DOWN = 34, KEY_PAGE_UP = 33,
                                     * @protected
                                     * @return {Do.Halt} Returns an instance of Do.Halt in order to stop
                                     *     further function execution
                                     */
                                    _handlePageUpDown: function(keyCode) {
                                        var instance = this,
                                            autoCompleteResultsList,
                                            entriesPerPage,
                                            nextSelectedEntry,
                                            nextSelectedEntryIndex,
                                            scrollTop,
                                            selectedEntry,
                                            selectedEntryIndex,
                                            sudoClass;
                            
                                        autoCompleteResultsList = instance._autoCompleteResultsList;
                            
                                        entriesPerPage = instance._getEntriesPerPage();
                            
                                        selectedEntry = autoCompleteResultsList.one(SELECTOR_ENTRY_CONTAINER_SELECTED);
                            
                                        selectedEntryIndex = Lang.toInt(selectedEntry.attr('data-index'));
                            
                                        sudoClass = '';
                            
                                        scrollTop = false;
                            
                                        if (keyCode === KEY_PAGE_UP) {
                                            nextSelectedEntryIndex = selectedEntryIndex - entriesPerPage;
                            
                                            scrollTop = true;
                                        }
                                        else if (keyCode === KEY_PAGE_DOWN) {
                                            nextSelectedEntryIndex = selectedEntryIndex + entriesPerPage;
                            
                                            sudoClass = ':last-child';
                                        }
                            
                                        nextSelectedEntry = autoCompleteResultsList.one(SELECTOR_ENTRY_CONTAINER + '[' + 'data-index' + '="' +
                                            nextSelectedEntryIndex + '"]');
                            
                                        if (!nextSelectedEntry) {
                                            nextSelectedEntry = autoCompleteResultsList.one(SELECTOR_ENTRY_CONTAINER + sudoClass);
                                        }
                            
                                        if (selectedEntry !== nextSelectedEntry) {
                                            selectedEntry.removeClass('selected');
                            
                                            nextSelectedEntry.addClass('selected');
                            
                                            nextSelectedEntry.scrollIntoView(scrollTop);
                                        }
                            
                                        return new Do.Halt(null);
                                    },
                            
                                    /**
                                     * Handles click on results and adds a suggestion to the editor.
                                     *
                                     * @method _handleResultListClick
                                     * @param {CustomEvent} event The fired event
                                     * @protected
                                     */
                                    _handleResultListClick: function(event) {
                                        var instance = this,
                                            content,
                                            entryNode,
                                            selectedEntry;
                            
                                        entryNode = event.currentTarget;
                            
                                        selectedEntry = instance._autoCompleteResultsList.one(SELECTOR_ENTRY_CONTAINER_SELECTED);
                            
                                        if (entryNode !== selectedEntry) {
                                            selectedEntry.removeClass('selected');
                            
                                            entryNode.addClass('selected');
                                        }
                            
                                        content = entryNode.text();
                            
                                        instance._addSuggestion(content);
                            
                                        instance.fire(
                                            'entrySelected', {
                                                content: content
                                            }
                                        );
                                    },
                            
                                    /**
                                     * Handles moving of the page to its first or last position.
                                     *
                                     * @method _handleStartEnd
                                     * @param {Number} keyCode The code of currently pressed key. Could be
                                     *     one of: KEY_END = 35 KEY_START = 36
                                     * @protected
                                     * @return {Do.Halt} Returns an instance of Do.Halt in order to stop
                                     *     further function execution
                                     */
                                    _handleStartEnd: function(keyCode) {
                                        var instance = this,
                                            autoCompleteResultsList,
                                            item,
                                            scrollTop,
                                            selectedEntry;
                            
                                        scrollTop = false;
                            
                                        autoCompleteResultsList = instance._autoCompleteResultsList;
                            
                                        if (keyCode === KEY_END) {
                                            item = autoCompleteResultsList.one(SELECTOR_ENTRY_CONTAINER + ':last-child');
                                        }
                                        else if (keyCode === KEY_START) {
                                            item = autoCompleteResultsList.one(SELECTOR_ENTRY_CONTAINER);
                            
                                            scrollTop = true;
                                        }
                            
                                        selectedEntry = autoCompleteResultsList.one(SELECTOR_ENTRY_CONTAINER_SELECTED);
                            
                                        if (item !== selectedEntry) {
                                            selectedEntry.removeClass('selected');
                            
                                            item.addClass('selected');
                            
                                            item.scrollIntoView(scrollTop);
                                        }
                            
                                        return new Do.Halt(null);
                                    },
                            
                                    /**
                                     * Prevents the execution of `cursorChange` defaultFn if the list is not
                                     * currently visible.
                                     *
                                     * @method _onCursorChange
                                     * @param {CustomEvent} event The fired event
                                     * @protected
                                     */
                                    _onCursorChange: function(event) {
                                        var instance = this;
                            
                                        if (!instance.get('visible')) {
                                            event.preventDefault();
                                        }
                                    },
                            
                                    /**
                                     * Hides the list when text is being inserted and start row is different
                                     * than the end row.
                                     *
                                     * @method _onInsertText
                                     * @param {CustomEvent} event The fired event
                                     * @protected
                                     */
                                    _onInsertText: function(event) {
                                        var instance = this;
                            
                                        if (event.startRow !== event.endRow && instance.get('visible')) {
                                            instance.hide();
                                        }
                                    },
                            
                                    /**
                                     * Shows and moves the list on the proper position in case of match and
                                     * available results or hides the list otherwise.
                                     *
                                     * @method _onMatch
                                     * @param {CustomEvent} event The fired event
                                     * @protected
                                     */
                                    _onMatch: function(event) {
                                        var instance = this,
                                            coords,
                                            hasResults,
                                            visible;
                            
                                        visible = instance.get('visible');
                            
                                        hasResults = instance._autoCompleteResultsList.hasChildNodes();
                            
                                        if (event.match) {
                                            if (hasResults) {
                                                if (!visible) {
                                                    coords = event.coords;
                            
                                                    instance.set('xy', [coords.pageX + PADDING_HORIZ, coords.pageY + PADDING_VERT]);
                            
                                                    instance.show();
                                                }
                                            }
                                            else if (visible) {
                                                instance.hide();
                                            }
                                        }
                                        else if (visible) {
                                            instance.hide();
                                        }
                                    },
                            
                                    /**
                                     * Highlights the current entry in case of mouse enter event.
                                     *
                                     * @method _onMouseEnter
                                     * @param {CustomEvent} event The fired event
                                     * @protected
                                     */
                                    _onMouseEnter: function(event) {
                                        event.currentTarget.addClass(CLASS_ENTRY_CONTAINER_HIGHLIGHTED);
                                    },
                            
                                    /**
                                     * Removes the highlighting from the current entry in case of mouse
                                     * leave event.
                                     *
                                     * @method _onMouseLeave
                                     * @param {CustomEvent} event The fired event
                                     * @protected
                                     */
                                    _onMouseLeave: function(event) {
                                        event.currentTarget.removeClass(CLASS_ENTRY_CONTAINER_HIGHLIGHTED);
                                    },
                            
                                    /**
                                     * On removing text, hides the list, if visible.
                                     *
                                     * @method _onRemoveText
                                     * @param {CustomEvent} event The fired event
                                     * @protected
                                     */
                                    _onRemoveText: function() {
                                        var instance = this;
                            
                                        if (instance.get('visible')) {
                                            instance.hide();
                                        }
                                    },
                            
                                    /**
                                     * Handles `resultsChange` event. Removes the current list of entries,
                                     * populates the new ones and selects the first entry.
                                     *
                                     * @method _onResultsChange
                                     * @param {CustomEvent} event The fired event
                                     * @protected
                                     */
                                    _onResultsChange: function(event) {
                                        var instance = this,
                                            autoCompleteResultsList,
                                            entryTemplate,
                                            firstEntry,
                                            results,
                                            tmpNode;
                            
                                        autoCompleteResultsList = instance._autoCompleteResultsList;
                            
                                        autoCompleteResultsList.empty();
                            
                                        results = event.newVal;
                            
                                        entryTemplate = instance.TPL_ENTRY;
                            
                                        tmpNode = ANode.create(TPL_FRAGMENT);
                            
                                        AArray.each(
                                            results,
                                            function(item, index) {
                                                tmpNode.appendChild(
                                                    Lang.sub(
                                                        entryTemplate, {
                                                            index: index,
                                                            value: item
                                                        }
                                                    )
                                                );
                                            }
                                        );
                            
                                        autoCompleteResultsList.setHTML(tmpNode.getHTML());
                            
                                        firstEntry = autoCompleteResultsList.one(SELECTOR_ENTRY_CONTAINER);
                            
                                        if (firstEntry) {
                                            firstEntry.addClass('selected');
                                        }
                                    },
                            
                                    /**
                                     * Displays a loading message in the list.
                                     *
                                     * @method _onShowLoadingMessage
                                     * @param {CustomEvent} event The fired event
                                     * @protected
                                     */
                                    _onShowLoadingMessage: function() {
                                        var instance = this,
                                            autoCompleteResultsList;
                            
                                        autoCompleteResultsList = instance._autoCompleteResultsList;
                            
                                        autoCompleteResultsList.empty();
                            
                                        autoCompleteResultsList.appendChild(
                                            Lang.sub(
                                                instance.TPL_LOADING, {
                                                    label: instance.get('loadingMessage')
                                                }
                                            )
                                        );
                            
                                        if (!instance.get('visible')) {
                                            instance.show();
                                        }
                                    },
                            
                                    /**
                                     * Overwrites editor commands before show or restores the original
                                     * behavior when hiding.
                                     *
                                     * @method _onVisibleChange
                                     * @param {CustomEvent} event The fired event
                                     * @protected
                                     */
                                    _onVisibleChange: function(event) {
                                        var instance = this;
                            
                                        if (event.newVal) {
                                            instance._overwriteCommands();
                                        }
                                        else {
                                            instance._removeAutoCompleteCommands();
                                        }
                                    },
                            
                                    /**
                                     * Sets and empty array as results.
                                     *
                                     * @method _setEmptyResults
                                     * @protected
                                     */
                                    _setEmptyResults: function() {
                                        var instance = this;
                            
                                        instance.set('results', []);
                                    },
                            
                                    TPL_ENTRY: '<li class="' + CLASS_ENTRY_CONTAINER + '" data-index="{index}">' + '<span class="' +
                                        CLASS_ENTRY + '">{value}</span>' + '</li>',
                            
                                    TPL_LIST: '<ul class="' + CLASS_RESULTS_LIST + '"/>',
                            
                                    TPL_LOADING: '<li class="' + CLASS_ENTRY_CONTAINER + '">' + '<span class="glyphicon glyphicon-loading ' +
                                        CLASS_ENTRY_LOADING + '">{label}</span>' + '</li>',
                            
                                    TPL_RESULTS_EMPTY: '<li class="' + CLASS_ENTRY_CONTAINER + '">' + '<span class="' + CLASS_ENTRY_EMPTY +
                                        '">{label}</span>' + '</li>'
                                }, {
                            
                                    /**
                                     * Static property which provides a string to identify the class.
                                     *
                                     * @property NAME
                                     * @type String
                                     * @static
                                     */
                                    NAME: 'ace-autocomplete-list',
                            
                                    /**
                                     * Static property provides a string to identify the namespace.
                                     *
                                     * @property NS
                                     * @type String
                                     * @static
                                     */
                                    NS: 'ace-autocomplete-list',
                            
                                    /**
                                     * Static property used to define the default attribute
                                     * configuration for the AutoCompleteList.
                                     *
                                     * @property ATTRS
                                     * @type Object
                                     * @static
                                     */
                                    ATTRS: {
                            
                                        /**
                                         * The Editor in which the current instance is plugged.
                                         *
                                         * @attribute host
                                         * @type Object
                                         */
                                        host: {
                                            validator: Lang.isObject
                                        },
                            
                                        /**
                                         * A Node in which results will be shown.
                                         *
                                         * @attribute listNode
                                         * @default null
                                         * @type Node
                                         */
                                        listNode: {
                                            value: null
                                        },
                            
                                        /**
                                         * A string, representing the loading message.
                                         *
                                         * @attribute loadingMessage
                                         * @default 'Loading'
                                         * @type String
                                         */
                                        loadingMessage: {
                                            validator: Lang.isString,
                                            value: 'Loading'
                                        },
                            
                                        /**
                                         * Contains the current set of results in the list.
                                         *
                                         * @attribute results
                                         * @type Array
                                         */
                                        results: {
                                            validator: Lang.isArray
                                        },
                            
                                        /**
                                         * Provides the currently selected entry.
                                         *
                                         * @attribute selectedEntry
                                         */
                                        selectedEntry: {
                                            getter: '_getSelectedEntry'
                                        },
                            
                                        /**
                                         * Collection of strings used to label elements of the UI.
                                         *
                                         * @attribute strings
                                         * @type Object
                                         */
                                        strings: {
                                            validator: Lang.isObject,
                                            value: {
                                                emptyMessage: 'No suggestions'
                                            }
                                        }
                                    },
                            
                                    /**
                                     * The prefix of all CSS Classes.
                                     *
                                     * @property CSS_PREFIX
                                     * @type String
                                     * @static
                                     */
                                    CSS_PREFIX: 'ace-autocomplete',
                            
                                    /**
                                     * Object hash, defining how attribute values are to be parsed from
                                     * markup contained in the widget's content box.
                                     *
                                     * @property HTML_PARSER
                                     * @static
                                     */
                                    HTML_PARSER: {
                                        listNode: '.' + CLASS_RESULTS_LIST
                                    }
                                });
                            
                            A.AceEditor.AutoCompleteList = AutoCompleteList;
                            A.AceEditor.AutoComplete = AutoCompleteList;