    /**
     * A mechanism for displaying data using custom layout templates and formatting.
     *
     * The View uses an {@link Ext.XTemplate} as its internal templating mechanism, and is bound to an
     * {@link Ext.data.Store} so that as the data in the store changes the view is automatically updated
     * to reflect the changes. The view also provides built-in behavior for many common events that can
     * occur for its contained items including click, doubleclick, mouseover, mouseout, etc. as well as a
     * built-in selection model. **In order to use these features, an {@link #itemSelector} config must
     * be provided for the View to determine what nodes it will be working with.**
     *
     * The example below binds a View to a {@link Ext.data.Store} and renders it into an {@link Ext.panel.Panel}.
     *
     *     @example
     *     Ext.define('Image', {
     *         extend: 'Ext.data.Model',
     *         fields: [
     *             { name:'src', type:'string' },
     *             { name:'caption', type:'string' }
     *         ]
     *     });
     *
     *     Ext.create('Ext.data.Store', {
     *         id:'imagesStore',
     *         model: 'Image',
     *         data: [
     *             { src:'http://www.sencha.com/img/20110215-feat-drawing.png', caption:'Drawing & Charts' },
     *             { src:'http://www.sencha.com/img/20110215-feat-data.png', caption:'Advanced Data' },
     *             { src:'http://www.sencha.com/img/20110215-feat-html5.png', caption:'Overhauled Theme' },
     *             { src:'http://www.sencha.com/img/20110215-feat-perf.png', caption:'Performance Tuned' }
     *         ]
     *     });
     *
     *     var imageTpl = new Ext.XTemplate(
     *         '<tpl for=".">',
     *             '<div style="margin-bottom: 10px;" class="thumb-wrap">',
     *               '<img src="{src}" />',
     *               '<br/><span>{caption}</span>',
     *             '</div>',
     *         '</tpl>'
     *     );
     *
     *     Ext.create('Ext.view.View', {
     *         store: Ext.data.StoreManager.lookup('imagesStore'),
     *         tpl: imageTpl,
     *         itemSelector: 'div.thumb-wrap',
     *         emptyText: 'No images available',
     *         renderTo: Ext.getBody()
     *     });
     */
    Ext.define('Ext.view.View', {
        extend: 'Ext.view.AbstractView',
        alternateClassName: 'Ext.DataView',
        alias: 'widget.dataview',

        // private delay to buffer row highlighting/unhighlighting on mouse move.
        // This is ignored if the public mouseOverOutBuffer remains a non-zero value
        deferHighlight: Ext.isIE7m ? 100 : 0,

        /**
         * @cfg {Number} [mouseOverOutBuffer=20]
         * The number of milliseconds to buffer mouseover and mouseout event handling on view items.
         *
         * Configure this as `false` to process mouseover and mouseout events immediately.
         */
        mouseOverOutBuffer: 20,

        inputTagRe: /^textarea$|^input$/i,

        inheritableStatics: {
            EventMap: {
                mousedown: 'MouseDown',
                mouseup: 'MouseUp',
                click: 'Click',
                dblclick: 'DblClick',
                contextmenu: 'ContextMenu',
                mouseover: 'MouseOver',
                mouseout: 'MouseOut',
                mouseenter: 'MouseEnter',
                mouseleave: 'MouseLeave',
                keydown: 'KeyDown',
                focus: 'Focus'
            }
        },

        initComponent: function() {
            var me = this;
            me.callParent();

            //
            if (me.mouseOverOutBuffer) {
                me.handleMouseOverOrOut =
                    Ext.Function.createBuffered(me.handleMouseOverOrOut, me.mouseOverOutBuffer, me);
                me.lastMouseOverOutEvent = new Ext.EventObjectImpl();
            }

            // Not buffering mouse over/out handling - buffer item highlighting.
            else if (me.deferHighlight){
                me.setHighlightedItem =
                    Ext.Function.createBuffered(me.setHighlightedItem, me.deferHighlight, me);
            }
        },

        addCmpEvents: function() {
            this.addEvents(
                /**
                 * @event beforeitemmousedown
                 * Fires before the mousedown event on an item is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object
                 */
                'beforeitemmousedown',
                /**
                 * @event beforeitemmouseup
                 * Fires before the mouseup event on an item is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object
                 */
                'beforeitemmouseup',
                /**
                 * @event beforeitemmouseenter
                 * Fires before the mouseenter event on an item is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object
                 */
                'beforeitemmouseenter',
                /**
                 * @event beforeitemmouseleave
                 * Fires before the mouseleave event on an item is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object
                 */
                'beforeitemmouseleave',
                /**
                 * @event beforeitemclick
                 * Fires before the click event on an item is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object
                 */
                'beforeitemclick',
                /**
                 * @event beforeitemdblclick
                 * Fires before the dblclick event on an item is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object
                 */
                'beforeitemdblclick',
                /**
                 * @event beforeitemcontextmenu
                 * Fires before the contextmenu event on an item is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object
                 */
                'beforeitemcontextmenu',
                /**
                 * @event beforeitemkeydown
                 * Fires before the keydown event on an item is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object. Use {@link Ext.EventObject#getKey getKey()} to retrieve the key that was pressed.
                 */
                'beforeitemkeydown',
                /**
                 * @event itemmousedown
                 * Fires when there is a mouse down on an item
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object
                 */
                'itemmousedown',
                /**
                 * @event itemmouseup
                 * Fires when there is a mouse up on an item
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object
                 */
                'itemmouseup',
                /**
                 * @event itemmouseenter
                 * Fires when the mouse enters an item.
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object
                 */
                'itemmouseenter',
                /**
                 * @event itemmouseleave
                 * Fires when the mouse leaves an item.
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object
                 */
                'itemmouseleave',
                /**
                 * @event itemclick
                 * Fires when an item is clicked.
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object
                 */
                'itemclick',
                /**
                 * @event itemdblclick
                 * Fires when an item is double clicked.
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object
                 */
                'itemdblclick',
                /**
                 * @event itemcontextmenu
                 * Fires when an item is right clicked.
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object
                 */
                'itemcontextmenu',
                /**
                 * @event itemkeydown
                 * Fires when a key is pressed while an item is currently selected.
                 * @param {Ext.view.View} this
                 * @param {Ext.data.Model} record The record that belongs to the item
                 * @param {HTMLElement} item The item's element
                 * @param {Number} index The item's index
                 * @param {Ext.EventObject} e The raw event object. Use {@link Ext.EventObject#getKey getKey()} to retrieve the key that was pressed.
                 */
                'itemkeydown',
                /**
                 * @event beforecontainermousedown
                 * Fires before the mousedown event on the container is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.EventObject} e The raw event object
                 */
                'beforecontainermousedown',
                /**
                 * @event beforecontainermouseup
                 * Fires before the mouseup event on the container is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.EventObject} e The raw event object
                 */
                'beforecontainermouseup',
                /**
                 * @event beforecontainermouseover
                 * Fires before the mouseover event on the container is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.EventObject} e The raw event object
                 */
                'beforecontainermouseover',
                /**
                 * @event beforecontainermouseout
                 * Fires before the mouseout event on the container is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.EventObject} e The raw event object
                 */
                'beforecontainermouseout',
                /**
                 * @event beforecontainerclick
                 * Fires before the click event on the container is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.EventObject} e The raw event object
                 */
                'beforecontainerclick',
                /**
                 * @event beforecontainerdblclick
                 * Fires before the dblclick event on the container is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.EventObject} e The raw event object
                 */
                'beforecontainerdblclick',
                /**
                 * @event beforecontainercontextmenu
                 * Fires before the contextmenu event on the container is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.EventObject} e The raw event object
                 */
                'beforecontainercontextmenu',
                /**
                 * @event beforecontainerkeydown
                 * Fires before the keydown event on the container is processed. Returns false to cancel the default action.
                 * @param {Ext.view.View} this
                 * @param {Ext.EventObject} e The raw event object. Use {@link Ext.EventObject#getKey getKey()} to retrieve the key that was pressed.
                 */
                'beforecontainerkeydown',
                /**
                 * @event containermouseup
                 * Fires when there is a mouse up on the container
                 * @param {Ext.view.View} this
                 * @param {Ext.EventObject} e The raw event object
                 */
                'containermouseup',
                /**
                 * @event containermouseover
                 * Fires when you move the mouse over the container.
                 * @param {Ext.view.View} this
                 * @param {Ext.EventObject} e The raw event object
                 */
                'containermouseover',
                /**
                 * @event containermouseout
                 * Fires when you move the mouse out of the container.
                 * @param {Ext.view.View} this
                 * @param {Ext.EventObject} e The raw event object
                 */
                'containermouseout',
                /**
                 * @event containerclick
                 * Fires when the container is clicked.
                 * @param {Ext.view.View} this
                 * @param {Ext.EventObject} e The raw event object
                 */
                'containerclick',
                /**
                 * @event containerdblclick
                 * Fires when the container is double clicked.
                 * @param {Ext.view.View} this
                 * @param {Ext.EventObject} e The raw event object
                 */
                'containerdblclick',
                /**
                 * @event containercontextmenu
                 * Fires when the container is right clicked.
                 * @param {Ext.view.View} this
                 * @param {Ext.EventObject} e The raw event object
                 */
                'containercontextmenu',
                /**
                 * @event containerkeydown
                 * Fires when a key is pressed while the container is focused, and no item is currently selected.
                 * @param {Ext.view.View} this
                 * @param {Ext.EventObject} e The raw event object. Use {@link Ext.EventObject#getKey getKey()} to retrieve the key that was pressed.
                 */
                'containerkeydown',

                /**
                 * @event
                 * @inheritdoc Ext.selection.DataViewModel#selectionchange
                 */
                'selectionchange',
                /**
                 * @event
                 * @inheritdoc Ext.selection.DataViewModel#beforeselect
                 */
                'beforeselect',
                /**
                 * @event
                 * @inheritdoc Ext.selection.DataViewModel#beforedeselect
                 */
                'beforedeselect',
                /**
                 * @event
                 * @inheritdoc Ext.selection.DataViewModel#select
                 */
                'select',
                /**
                 * @event
                 * @inheritdoc Ext.selection.DataViewModel#deselect
                 */
                'deselect',
                /**
                 * @event
                 * @inheritdoc Ext.selection.DataViewModel#focuschange
                 */
                'focuschange',

                /**
                 * @event highlightitem
                 * Fires when a node is highlighted using keyboard navigation, or mouseover.
                 * @param {Ext.view.View} view This View Component.
                 * @param {Ext.Element} node The highlighted node.
                 */
                'highlightitem',

                /**
                 * @event unhighlightitem
                 * Fires when a node is unhighlighted using keyboard navigation, or mouseout.
                 * @param {Ext.view.View} view This View Component.
                 * @param {Ext.Element} node The previously highlighted node.
                 */
                'unhighlightitem'
            );
        },

        getFocusEl: function() {
            return this.getTargetEl();
        },

        // @private
        afterRender: function(){
            var me = this,
                onMouseOverOut = me.mouseOverOutBuffer ? me.onMouseOverOut : me.handleMouseOverOrOut;

            me.callParent();
            me.mon(me.getTargetEl(), {
                scope: me,
                /*
                 * We need to make copies of this since some of the events fired here will end up triggering
                 * a new event to be called and the shared event object will be mutated. In future we should
                 * investigate if there are any issues with creating a new event object for each event that
                 * is fired.
                 */
                freezeEvent: true,
                click: me.handleEvent,
                mousedown: me.handleEvent,
                mouseup: me.handleEvent,
                dblclick: me.handleEvent,
                contextmenu: me.handleEvent,
                keydown: me.handleEvent,
                mouseover: onMouseOverOut,
                mouseout:  onMouseOverOut
            });
        },

        onMouseOverOut: function(e) {
            var me = this;

            // Determining if we are entering or leaving view items is deferred until
            // mouse move churn settles down.
            me.lastMouseOverOutEvent.setEvent(e.browserEvent, true);
            me.handleMouseOverOrOut(me.lastMouseOverOutEvent);
        },

        handleMouseOverOrOut: function(e) {
            var me = this,
                isMouseout = e.type === 'mouseout',
                method = isMouseout ? e.getRelatedTarget : e.getTarget,
                nowOverItem = method.call(e, me.itemSelector) || method.call(e, me.dataRowSelector);

            // If the mouse event of whatever type tells use that we are no longer over the current mouseOverItem...
            if (!me.mouseOverItem || nowOverItem !== me.mouseOverItem) {

                // First fire mouseleave for the item we just left
                if (me.mouseOverItem) {
                    e.item = me.mouseOverItem;
                    e.newType = 'mouseleave';
                    me.handleEvent(e);
                }

                // If we are over an item, fire the mouseenter
                me.mouseOverItem = nowOverItem;
                if (me.mouseOverItem) {
                    e.item = me.mouseOverItem;
                    e.newType = 'mouseenter';
                    me.handleEvent(e);
                }
            }
        },

        handleEvent: function(e) {
            var me = this,
                key = e.type == 'keydown' && e.getKey();

            if (me.processUIEvent(e) !== false) {
                me.processSpecialEvent(e);
            }

            // After all listeners have processed the event, then unless the user is typing into an input field,
            // prevent browser's default action on SPACE which is to focus the event's target element.
            // Focusing causes the browser to attempt to scroll the element into view.
            if (key === e.SPACE) {
                if (!me.inputTagRe.test(e.getTarget().tagName)) {
                    e.stopEvent();
                }
            }
        },

        // Private template method
        processItemEvent: Ext.emptyFn,
        processContainerEvent: Ext.emptyFn,
        processSpecialEvent: Ext.emptyFn,

        processUIEvent: function(e) {

            // If the target event has been removed from the body (data update causing view DOM to be updated),
            // do not process. isAncestor uses native methods to check.
            if (!Ext.getBody().isAncestor(e.target)) {
                return;
            }

            var me = this,
                item = e.getTarget(me.getItemSelector(), me.getTargetEl()),
                map = this.statics().EventMap,
                index, record,
                type = e.type,
                newType = e.type,
                sm;

            // If the event is a mouseover/mouseout event converted to a mouseenter/mouseleave,
            // use that event type and ensure that the item is correct.
            if (e.newType) {
                newType = e.newType;
                item = e.item;
            }

            // For keydown events, try to get either the last focused item or the selected item.
            // If we have not focused an item, we'll just fire a container keydown event.
            if (!item && type == 'keydown') {
                sm = me.getSelectionModel();
                record = sm.lastFocused || sm.getLastSelected();
                if (record) {
                    item = me.getNode(record, true);
                }
            }

            if (item) {
                if (!record) {
                    record = me.getRecord(item);
                }
                index = me.indexInStore ? me.indexInStore(record) : me.indexOf(item);

                // It is possible for an event to arrive for which there is no record... this
                // can happen with dblclick where the clicks are on removal actions (think a
                // grid w/"delete row" action column)
                if (!record || me.processItemEvent(record, item, index, e) === false) {
                    return false;
                }

                if (
                    (me['onBeforeItem' + map[newType]](record, item, index, e) === false) ||
                    (me.fireEvent('beforeitem' + newType, me, record, item, index, e) === false) ||
                    (me['onItem' + map[newType]](record, item, index, e) === false)
                ) {
                    return false;
                }

                me.fireEvent('item' + newType, me, record, item, index, e);
            }
            else {
                if (
                    (me.processContainerEvent(e) === false) ||
                    (me['onBeforeContainer' + map[type]](e) === false) ||
                    (me.fireEvent('beforecontainer' + type, me, e) === false) ||
                    (me['onContainer' + map[type]](e) === false)
                ) {
                    return false;
                }

                me.fireEvent('container' + type, me, e);
            }

            return true;
        },

        // @private
        onItemMouseEnter: function(record, item, index, e) {
            if (this.trackOver) {
                this.highlightItem(item);
            }
        },

        // @private
        onItemMouseLeave : function(record, item, index, e) {
            if (this.trackOver) {
                this.clearHighlight();
            }
        },

        // private, template methods
        onItemMouseDown: Ext.emptyFn,
        onItemMouseUp: Ext.emptyFn,
        onItemFocus: Ext.emptyFn,
        onItemClick: Ext.emptyFn,
        onItemDblClick: Ext.emptyFn,
        onItemContextMenu: Ext.emptyFn,
        onItemKeyDown: Ext.emptyFn,
        onBeforeItemMouseDown: Ext.emptyFn,
        onBeforeItemMouseUp: Ext.emptyFn,
        onBeforeItemFocus: Ext.emptyFn,
        onBeforeItemMouseEnter: Ext.emptyFn,
        onBeforeItemMouseLeave: Ext.emptyFn,
        onBeforeItemClick: Ext.emptyFn,
        onBeforeItemDblClick: Ext.emptyFn,
        onBeforeItemContextMenu: Ext.emptyFn,
        onBeforeItemKeyDown: Ext.emptyFn,

        // private, template methods
        onContainerMouseDown: Ext.emptyFn,
        onContainerMouseUp: Ext.emptyFn,
        onContainerMouseOver: Ext.emptyFn,
        onContainerMouseOut: Ext.emptyFn,
        onContainerClick: Ext.emptyFn,
        onContainerDblClick: Ext.emptyFn,
        onContainerContextMenu: Ext.emptyFn,
        onContainerKeyDown: Ext.emptyFn,
        onBeforeContainerMouseDown: Ext.emptyFn,
        onBeforeContainerMouseUp: Ext.emptyFn,
        onBeforeContainerMouseOver: Ext.emptyFn,
        onBeforeContainerMouseOut: Ext.emptyFn,
        onBeforeContainerClick: Ext.emptyFn,
        onBeforeContainerDblClick: Ext.emptyFn,
        onBeforeContainerContextMenu: Ext.emptyFn,
        onBeforeContainerKeyDown: Ext.emptyFn,

        // @private
        setHighlightedItem: function(item){
            var me = this,
                highlighted = me.highlightedItem,
                overItemCls = me.overItemCls,
                beforeOverItemCls = me.beforeOverItemCls,
                previous;

            if (highlighted != item){
                if (highlighted) {
                    Ext.fly(highlighted).removeCls(overItemCls);
                    previous = highlighted.previousSibling;
                    if (beforeOverItemCls && previous) {
                        Ext.fly(previous).removeCls(beforeOverItemCls);
                    }
                    me.fireEvent('unhighlightitem', me, highlighted);
                }

                me.highlightedItem = item;

                if (item) {
                    Ext.fly(item).addCls(me.overItemCls);
                    previous = item.previousSibling;
                    if (beforeOverItemCls && previous) {
                        Ext.fly(previous).addCls(beforeOverItemCls);
                    }
                    me.fireEvent('highlightitem', me, item);
                }
            }
        },

        /**
         * Highlights a given item in the View. This is called by the mouseover handler if {@link #overItemCls}
         * and {@link #trackOver} are configured, but can also be called manually by other code, for instance to
         * handle stepping through the list via keyboard navigation.
         * @param {HTMLElement} item The item to highlight
         */
        highlightItem: function(item) {
            this.setHighlightedItem(item);
        },

        /**
         * Un-highlights the currently highlighted item, if any.
         */
        clearHighlight: function() {
            this.setHighlightedItem(undefined);
        },

        onUpdate: function(store, record){
            var me = this,
                node,
                newNode,
                highlighted;

            if (me.viewReady) {
                node = me.getNode(record);
                newNode = me.callParent(arguments);
                highlighted = me.highlightedItem;

                if (highlighted && highlighted === node) {
                    delete me.highlightedItem;
                    if (newNode) {
                        me.highlightItem(newNode);
                    }
                }
            }
        },

        refresh: function() {
            this.clearHighlight();
            this.callParent(arguments);
        },

        /**
         * Focuses a node in the view.
         * @param {Ext.data.Model} rec The record associated to the node that is to be focused.
         */
        focusNode: function(rec){
            var me          = this,
                node        = me.getNode(rec, true),
                el          = me.el,
                adjustmentY = 0,
                adjustmentX = 0,
                elRegion    = el.getRegion(),
                nodeRegion;

            // Viewable region must not include scrollbars, so use
            // DOM client dimensions
            elRegion.bottom = elRegion.top + el.dom.clientHeight;
            elRegion.right = elRegion.left + el.dom.clientWidth;
            if (node) {
                nodeRegion = Ext.fly(node).getRegion();
                // node is above
                if (nodeRegion.top < elRegion.top) {
                    adjustmentY = nodeRegion.top - elRegion.top;
                // node is below
                } else if (nodeRegion.bottom > elRegion.bottom) {
                    adjustmentY = nodeRegion.bottom - elRegion.bottom;
                }

                // node is left
                if (nodeRegion.left < elRegion.left) {
                    adjustmentX = nodeRegion.left - elRegion.left;
                // node is right
                } else if (nodeRegion.right > elRegion.right) {
                    adjustmentX = nodeRegion.right - elRegion.right;
                }

                if (adjustmentX || adjustmentY) {
                    me.scrollBy(adjustmentX, adjustmentY, false);
                }
                el.focus();
            }
        }
    });