/**
 * This component is used in {@link Ext.navigation.View} to control animations in the toolbar. You should never need to
 * interact with the component directly, unless you are subclassing it.
 * @private
 */
Ext.define('Ext.navigation.Bar', {
    extend: 'Ext.Container',

    requires: [
        'Ext.Button',
        'Ext.TitleBar',
        'Ext.Spacer',
        'Ext.util.SizeMonitor'
    ],

    // private
    isToolbar: true,

    config: {
        // @inherit
        baseCls: Ext.baseCSSPrefix + 'toolbar',

        // @inherit
        cls: Ext.baseCSSPrefix + 'navigation-bar',

        /**
         * @cfg {String} ui
         * Style options for Toolbar. Either 'light' or 'dark'.
         * @accessor
         */
        ui: 'dark',

        /**
         * @hide
         * The title of the toolbar. You should NEVER set this, it is used internally. You set the title of the
         * navigation bar by giving a navigation views children a title configuration.
         * @accessor
         */
        title: null,

        /**
         * @hide
         */
        defaultType: 'button',

        /**
         * @hide
         */
        layout: {
            type: 'hbox'
        },

        /**
         * @cfg {Array/Object} items The child items to add to this NavigationBar. The {@link #cfg-defaultType} of
         * a NavigationBar is {@link Ext.Button}, so you do not need to specify an `xtype` if you are adding
         * buttons.
         *
         * You can also give items a `align` configuration which will align the item to the `left` or `right` of
         * the NavigationBar.
         * @accessor
         * @hide
         */

        /**
         * @cfg {String} defaultBackButtonText
         * The text to be displayed on the back button if:
         * a) The previous view does not have a title
         * b) The {@link #useTitleForBackButtonText} configuration is true.
         * @hide
         */
        defaultBackButtonText: 'Back',

        /**
         * @cfg {Object} animations
         * @hide
         */
        animation: {
            duration: 300
        },

        /**
         * @cfg {Boolean} useTitleForBackButtonText
         * Set to false if you always want to display the {@link #defaultBackButtonText} as the text
         * on the back button. True if you want to use the previous views title.
         * @hide
         */
        useTitleForBackButtonText: false
    },

    /**
     * The minmum back button width allowed.
     * @private
     */
    minBackButtonWidth: 80,

    constructor: function(config) {
        config = config || {};

        if (!config.items) {
            config.items = [];
        }

        this.callParent([config]);
    },

    beforeInitialize: function() {
        this.backButtonStack = [];
        this.animating = false;

        this.onSizeMonitorChange = Ext.Function.createThrottled(this.onSizeMonitorChange, 50, this);
    },

    initialize: function() {
        var me = this;

        me.on({
            painted: 'onPainted',
            erased: 'onErased'
        });

        if (!me.backButton) {
            me.backButton = me.add({
                align: 'left',
                ui: 'back',
                hidden: true,
                listeners: {
                    scope: this,
                    tap: this.onBackButtonTap
                }
            });
        }

        me.onSizeMonitorChange();
    },

    onBackButtonTap: function() {
        this.fireEvent('back', this);
    },

    updateUseTitleForBackButtonText: function(newUseTitleForBackButtonText) {
        var backButton = this.backButton;

        if (backButton) {
            if (newUseTitleForBackButtonText) {
                backButton.setText(this.backButtonStack[this.backButtonStack.length - 1]);
            } else {
                backButton.setText(this.getDefaultBackButtonText());
            }
        }

        this.onSizeMonitorChange();
    },

    onPainted: function() {
        this.painted = true;

        this.sizeMonitor.refresh();

        this.onSizeMonitorChange();
    },

    onErased: function() {
        this.painted = false;
    },

    applyItems: function(items) {
        var me = this;

        if (!me.initialized) {
            var defaults = me.getDefaults() || {},
                leftBox, rightBox, spacer;

            me.leftBox = leftBox = me.add({
                xtype: 'container',
                style: 'position: relative',
                layout: {
                    type: 'hbox',
                    align: 'center'
                }
            });
            me.spacer = spacer = me.add({
                xtype: 'component',
                style: 'position: relative',
                flex: 1
            });
            me.rightBox = rightBox = me.add({
                xtype: 'container',
                style: 'position: relative',
                layout: {
                    type: 'hbox',
                    align: 'center'
                }
            });
            me.titleComponent = me.add({
                xtype: 'title',
                hidden: defaults.hidden,
                centered: true
            });

            me.sizeMonitor = new Ext.util.SizeMonitor({
                element: me.renderElement,
                callback: me.onSizeMonitorChange,
                scope: me
            });

            me.doAdd = me.doBoxAdd;
            me.doInsert = me.doBoxInsert;
        }

        me.callParent(arguments);
    },

    doBoxAdd: function(item) {
        if (item.config.align == 'right') {
            this.rightBox.add(item);
        }
        else {
            this.leftBox.add(item);
        }
    },

    doBoxInsert: function(index, item) {
        if (item.config.align == 'right') {
            this.rightBox.add(item);
        }
        else {
            this.leftBox.add(item);
        }
    },

    // @private
    updateTitle: function(newTitle) {
        this.titleComponent.setTitle(newTitle);
        this.updateNavigationBarProxy(newTitle);
    },

    /**
     * Called when any size of this component changes.
     * It refreshes the navigation bar proxy so that the title and back button is in the correct location.
     * @private
     */
    onSizeMonitorChange: function() {
        if (!this.rendered) {
            return;
        }

        var backButton = this.backButton,
            titleComponent = this.titleComponent;

        if (backButton && backButton.rendered) {
            backButton.renderElement.setWidth(null);
        }

        this.refreshNavigationBarProxy();

        var properties = this.getNavigationBarProxyProperties();

        if (backButton && backButton.rendered) {
            backButton.renderElement.setWidth(properties.backButton.width);
        }

        titleComponent.renderElement.setStyle('-webkit-transform', null);
        titleComponent.renderElement.setWidth(properties.title.width);
        titleComponent.renderElement.setLeft(properties.title.left);
    },

    /**
     * Calculates and returns the position values needed for the back button when you are pushing a title.
     * @private
     */
    getBackButtonAnimationProperties: function() {
        var me = this,
            element = me.renderElement,
            backButtonElement = me.backButton.renderElement,
            titleElement = me.titleComponent.renderElement,
            minButtonOffset = Math.min(element.getWidth() / 3, 200),
            proxyProperties = this.getNavigationBarProxyProperties(),
            buttonOffset, buttonGhostOffset;

        buttonOffset = titleElement.getX() - element.getX();
        buttonGhostOffset = element.getX() - backButtonElement.getX() - backButtonElement.getWidth();

        buttonOffset = Math.min(buttonOffset, minButtonOffset);

        return {
            element: {
                from: {
                    left: buttonOffset,
                    width: proxyProperties.backButton.width,
                    opacity: 0
                },
                to: {
                    left: 0,
                    width: proxyProperties.backButton.width,
                    opacity: 1
                }
            },

            ghost: {
                from: null,
                to: {
                    left: buttonGhostOffset,
                    opacity: 0
                }
            }
        };
    },

    /**
     * Calculates and returns the position values needed for the back button when you are popping a title.
     * @private
     */
    getBackButtonAnimationReverseProperties: function() {
        var me = this,
            element = me.renderElement,
            backButtonElement = me.backButton.renderElement,
            titleElement = me.titleComponent.renderElement,
            minButtonGhostOffset = Math.min(element.getWidth() / 3, 200),
            proxyProperties = this.getNavigationBarProxyProperties(),
            buttonOffset, buttonGhostOffset;

        buttonOffset = element.getX() - backButtonElement.getX() - backButtonElement.getWidth();
        buttonGhostOffset = titleElement.getX() - backButtonElement.getWidth();

        buttonGhostOffset = Math.min(buttonGhostOffset, minButtonGhostOffset);

        return {
            element: {
                from: {
                    left: buttonOffset,
                    width: proxyProperties.backButton.width,
                    opacity: 0
                },
                to: {
                    left: 0,
                    width: proxyProperties.backButton.width,
                    opacity: 1
                }
            },

            ghost: {
                from: null,
                to: {
                    left: buttonGhostOffset,
                    opacity: 0
                }
            }
        };
    },

    /**
     * Calculates and returns the position values needed for the title when you are pushing a title.
     * @private
     */
    getTitleAnimationProperties: function() {
        var me = this,
            element = me.renderElement,
            titleElement = me.titleComponent.renderElement,
            proxyProperties = this.getNavigationBarProxyProperties(),
            titleOffset, titleGhostOffset;

        titleOffset = element.getWidth() - titleElement.getX();
        titleGhostOffset = element.getX() - titleElement.getX() + proxyProperties.backButton.width;

        if ((proxyProperties.backButton.left + titleElement.getWidth()) > titleElement.getX()) {
            titleGhostOffset = element.getX() - titleElement.getX() - titleElement.getWidth();
        }

        return {
            element: {
                from: {
                    left: titleOffset,
                    width: proxyProperties.title.width,
                    opacity: 0
                },
                to: {
                    left: proxyProperties.title.left,
                    width: proxyProperties.title.width,
                    opacity: 1
                }
            },
            ghost: {
                from: titleElement.getLeft(),
                to: {
                    left: titleGhostOffset,
                    opacity: 0
                }
            }
        };
    },

    /**
     * Calculates and returns the position values needed for the title when you are popping a title.
     * @private
     */
    getTitleAnimationReverseProperties: function() {
        var me = this,
            element = me.renderElement,
            titleElement = me.titleComponent.renderElement,
            proxyProperties = this.getNavigationBarProxyProperties(),
            ghostLeft = 0,
            titleOffset, titleGhostOffset;

        ghostLeft = titleElement.getLeft();
        titleElement.setLeft(0);

        titleOffset = element.getX() - titleElement.getX() + proxyProperties.backButton.width;
        titleGhostOffset = element.getX() + element.getWidth();

        if ((proxyProperties.backButton.left + titleElement.getWidth()) > titleElement.getX()) {
            titleOffset = element.getX() - titleElement.getX() - titleElement.getWidth();
        }

        return {
            element: {
                from: {
                    left: titleOffset,
                    width: proxyProperties.title.width,
                    opacity: 0
                },
                to: {
                    left: proxyProperties.title.left,
                    width: proxyProperties.title.width,
                    opacity: 1
                }
            },
            ghost: {
                from: ghostLeft,
                to: {
                    left: titleGhostOffset,
                    opacity: 0
                }
            }
        };
    },

    /**
     * Helper method used to animate elements.
     * You pass it an element, objects for the from and to positions an option onEnd callback called when the animation is over.
     * Normally this method is passed configurations returned from the methods such as {@link #getTitleAnimationReverseProperties} etc.
     * It is called from the {@link #pushBackButtonAnimated}, {@link #pushTitleAnimated}, {@link #popBackButtonAnimated} and {@link #popTitleAnimated}
     * methods.
     *
     * If the current device is Android, it will use top/left to animate.
     * If it is anything else, it will use transform.
     * @private
     */
    animate: function(element, from, to, onEnd) {
        var config = {
            element: element,
            easing: 'ease-in-out',
            duration: this.getAnimation().duration
        };

        if (onEnd) {
            config.onEnd = onEnd;
        }

        //reset the left of the element
        element.setLeft(0);

        if (Ext.os.is.Android) {
            if (from) {
                config.from = {
                    left: from.left,
                    opacity: from.opacity
                };

                if (from.width) {
                    config.from.width = from.width;
                }
            }

            if (to) {
                config.to = {
                    left: to.left,
                    opacity: to.opacity
                };

                if (to.width) {
                    config.to.width = to.width;
                }
            }
        } else {
            if (from) {
                config.from = {
                    transform: {
                        translateX: from.left
                    },
                    opacity: from.opacity
                };

                if (from.width) {
                    config.from.width = from.width;
                }
            }

            if (to) {
                config.to = {
                    transform: {
                        translateX: to.left
                    },
                    opacity: to.opacity
                };

                if (to.width) {
                    config.to.width = to.width;
                }
            }
        }

        Ext.Animator.run(config);
    },

    /**
     * Returns the text needed for the current back button at anytime.
     * @private
     */
    getBackButtonText: function() {
        return (this.getUseTitleForBackButtonText()) ? this.backButtonStack[this.backButtonStack.length - 1] : this.getDefaultBackButtonText();
    },

    /**
     * The animated version of the push method. You simply pass it a title and it will update the bar accordingly.
     * IF you are currently animating, it will not do anything.
     * It just calls the appropriate methods to updates the navigation bar proxy, then animate the back btuton and title changes
     * @private
     */
    pushAnimated: function(title, config) {
        var me = this;

        if (me.animating) {
            return;
        }

        if (Ext.isObject(config)) {
            me.setAnimation(config);
        }

        me.animating = true;

        var backButtonText = this.titleComponent.getTitle() || me.getDefaultBackButtonText();

        me.backButtonStack.push(backButtonText);

        me.updateNavigationBarProxy(title, (backButtonText) ? me.getBackButtonText() : null);

        me.pushBackButtonAnimated(backButtonText);
        me.pushTitleAnimated(title);
    },

    /**
     * Method to push a new title into the stack of this bar.
     * It will never do anything if you are currently animating anything.
     * It just calls the appropriate methods to update the navigation bar proxy and then the back button and title.
     * @private
     */
    push: function(title) {
        var me = this;

        if (me.animating) {
            return;
        }

        var backButtonText = this.titleComponent.getTitle() || me.getDefaultBackButtonText();

        me.backButtonStack.push(backButtonText);

        me.updateNavigationBarProxy(title, (backButtonText) ? me.getBackButtonText() : null);

        me.pushBackButton((backButtonText) ? me.getBackButtonText() : null);
        me.pushTitle(title);
    },

    /**
     * The animated version of the {@link #pop} method. It will never do anything if you are currenlty animating.
     * It just updates the back button and title, updates the proxy and then animates.
     * @private
     */
    popAnimated: function(title, config) {
        var me = this;

        if (me.animating) {
            return;
        }

        if (Ext.isObject(config)) {
            me.setAnimation(config);
        }

        me.animating = true;

        me.backButtonStack.pop();

        var backButtonText = (me.backButtonStack.length == 1) ? null : me.backButtonStack[me.backButtonStack.length - 1];

        me.updateNavigationBarProxy(title, (backButtonText) ? me.getBackButtonText() : null);

        me.popBackButtonAnimated(backButtonText);
        me.popTitleAnimated(title);
    },

    /**
     * the pop method when a view is popped. it will always return and do nothing if you are currently animating.
     * all it does is update the navigation bar proxy and then pop the button and title if it needs too.
     * @private
     */
    pop: function(title) {
        var me = this;

        if (me.animating) {
            return;
        }

        me.backButtonStack.pop();

        var backButtonText = (me.backButtonStack.length == 1) ? null : me.backButtonStack[me.backButtonStack.length - 1];

        me.updateNavigationBarProxy(title, (backButtonText) ? me.getBackButtonText() : null);

        me.popBackButton(backButtonText);
        me.popTitle(title);
    },

    /**
     * Pushes a back button into the bar with no animations
     * @private
     */
    pushBackButton: function(title) {
        this.backButton.setText(title);
        this.backButton.show();

        var properties = this.getBackButtonAnimationProperties(),
            to = properties.element.to;

        if (to.left) {
            this.backButton.setLeft(to.left);
        }

        if (to.width) {
            this.backButton.setWidth(to.width);
        }
    },

    /**
     * Pushes a new back button into the bar with animations
     * @private
     */
    pushBackButtonAnimated: function(title) {
        var me = this;

        var backButton = me.backButton,
            previousTitle = backButton.getText(),
            backButtonElement = backButton.renderElement,
            properties = me.getBackButtonAnimationProperties(),
            buttonGhost;

        //if there is a previoustitle, there should be a buttonGhost. so create it.
        if (previousTitle) {
            buttonGhost = me.createProxy(backButton);
        }

        //update the back button, and make sure it is visible
        backButton.setText(this.getBackButtonText());
        backButton.show();

        //animate the backButton, which always has the new title
        me.animate(backButtonElement, properties.element.from, properties.element.to, function() {
            me.animating = false;
        });

        //if there is a buttonGhost, we must animate it too.
        if (buttonGhost) {
            me.animate(buttonGhost, properties.ghost.from, properties.ghost.to, function() {
                buttonGhost.destroy();
            });
        }
    },

    /**
     * Pops the back button with no animations
     * @private
     */
    popBackButton: function(title) {
        this.backButton.setText(null);

        if (title) {
            this.backButton.setText(this.getBackButtonText());
        } else {
            this.backButton.hide();
        }

        var properties = this.getBackButtonAnimationReverseProperties(),
            to = properties.element.to;

        if (to.left) {
            this.backButton.setLeft(to.left);
        }

        if (to.width) {
            this.backButton.setWidth(to.width);
        }
    },

    /**
     * Pops the current back button with animations.
     * It will automatically know whether or not it should show the previous backButton or not. And proceed accordingly
     * @private
     */
    popBackButtonAnimated: function(title) {
        var me = this;

        if (!me.backButton) {
            me.backButton = me.add({
                align: 'left',
                ui: 'back'
            });
        }

        var backButton = me.backButton,
            previousTitle = backButton.getText(),
            backButtonElement = backButton.renderElement,
            properties = me.getBackButtonAnimationReverseProperties(),
            buttonGhost;

        //if there is a previoustitle, there should be a buttonGhost. so create it.
        if (previousTitle) {
            buttonGhost = me.createProxy(backButton);
        }

        //update the back button, and make sure it is visible
        if (title && me.backButtonStack.length) {
            backButton.setText(this.getBackButtonText());
            backButton.show();

            me.animate(backButtonElement, properties.element.from, properties.element.to);
        } else {
            backButton.hide();
        }

        //if there is a buttonGhost, we must animate it too.
        if (buttonGhost) {
            me.animate(buttonGhost, properties.ghost.from, properties.ghost.to, function() {
                buttonGhost.destroy();

                if (!title) {
                    backButton.setText(null);
                }
            });
        }
    },

    /**
     * Pushes a new title into the bar without any animations
     * @private
     */
    pushTitle: function(newTitle) {
        var title = this.titleComponent,
            titleElement = title.renderElement,
            properties = this.getTitleAnimationProperties(),
            to = properties.element.to;

        title.setTitle(newTitle);

        if (to.left) {
            titleElement.setLeft(to.left);
        }

        if (to.width) {
            titleElement.setWidth(to.width);
        }
    },

    /**
     * Pushs a new title into the navigation bar, animating as it goes.
     * @private
     */
    pushTitleAnimated: function(newTitle) {
        var me = this;

        var backButton = me.backButton,
            previousTitle = (backButton) ? backButton.getText() : null,
            title = me.titleComponent,
            titleElement = title.renderElement,
            properties = me.getTitleAnimationProperties(),
            titleGhost;

        //if there is a previoustitle, there should be a buttonGhost. so create it.
        if (previousTitle) {
            titleGhost = me.createProxy(title, true);
        }

        title.setTitle(newTitle);

        //animate the new title
        me.animate(titleElement, properties.element.from, properties.element.to);

        //if there is a titleGhost, we must animate it too.
        if (titleGhost) {
            me.animate(titleGhost, properties.ghost.from, properties.ghost.to, function() {
                titleGhost.destroy();
            });
        }
    },

    /**
     * Pops the title without any animation.
     * Simply gets the correct positions for the title and sets it on the dom.
     * @private
     */
    popTitle: function(newTitle) {
        var title = this.titleComponent,
            titleElement = title.renderElement,
            properties = this.getTitleAnimationReverseProperties(),
            to = properties.element.to;

        title.setTitle(newTitle);

        if (to.left) {
            titleElement.setLeft(to.left);
        }

        if (to.width) {
            titleElement.setWidth(to.width);
        }
    },

    /**
     * Method which pops the current title and animates it. It will automatically know whether or not to use a titleGhost
     * element, and how to animate it.
     * @private
     */
    popTitleAnimated: function(newTitle) {
        var me = this;

        var backButton = me.backButton,
            previousTitle = me.titleComponent.getTitle(),
            title = me.titleComponent,
            titleElement = title.renderElement,
            properties = me.getTitleAnimationReverseProperties(),
            titleGhost;

        //if there is a previoustitle, there should be a buttonGhost. so create it.
        if (previousTitle) {
            titleGhost = me.createProxy(title, true);
        }

        title.setTitle(newTitle || '');

        //animate the new title
        me.animate(titleElement, properties.element.from, properties.element.to, function() {
            me.animating = false;
        });

        //if there is a titleGhost, we must animate it too.
        if (titleGhost) {
            me.animate(titleGhost, properties.ghost.from, properties.ghost.to, function() {
                titleGhost.destroy();
            });
        }
    },

    /**
     * This creates a proxy of the whole navigation bar and positions it out of the view.
     * This is used so we know where the back button and title needs to be at any time, either if we are
     * animating, not animating, or resizing.
     * @private
     */
    createNavigationBarProxy: function() {
        var proxy = this.proxy;

        if (proxy) {
            return;
        }

        //create a titlebar for the proxy
        this.proxy = proxy = Ext.create('Ext.TitleBar', {
            items: [
                {
                    xtype: 'button',
                    ui: 'back',
                    text: ''
                }
            ],
            title: this.backButtonStack[0]
        });

        proxy.backButton = proxy.down('button[ui=back]');

        //add the proxy to the body
        Ext.getBody().appendChild(proxy.renderElement);

        proxy.renderElement.setStyle('position', 'absolute');
        proxy.element.setStyle('visibility', 'hidden');
        proxy.renderElement.setX(0);
        proxy.renderElement.setY(-1000);
    },

    /**
     * A Simple helper method which returns the current positions and sizes of the title and back button
     * in the navigation bar proxy.
     * @private
     */
    getNavigationBarProxyProperties: function() {
        return {
            title: {
                left: this.proxy.titleComponent.renderElement.getLeft(),
                width: this.proxy.titleComponent.renderElement.getWidth()
            },
            backButton: {
                left: this.proxy.backButton.renderElement.getLeft(),
                width: this.proxy.backButton.renderElement.getWidth()
            }
        };
    },

    /**
     * This method syncs the navigation bar proxy with the navigation bar. Used anytime the data is changed in the view,
     * i.e. when something is pushed/popped.
     * @private
     */
    refreshNavigationBarProxy: function() {
        var proxy = this.proxy,
            renderElement = this.renderElement,
            backButton = this.backButton;

        if (!proxy) {
            this.createNavigationBarProxy();
            proxy = this.proxy;
        }

        proxy.renderElement.setWidth(renderElement.getWidth());
        proxy.renderElement.setHeight(renderElement.getHeight());

        if (proxy.backButton && backButton) {
            proxy.backButton.setText(backButton.getText());
        }

        proxy.refreshTitlePosition();
    },

    /**
     * Method which updates the navigaiton bar proxy with new data. This is used when the active view is changed.
     * If you push a new view, it will have the newTitle and show it. Then put the oldtitle as the back button.
     * It will also refresh all proxy positions.
     * @private
     */
    updateNavigationBarProxy: function(newTitle, oldTitle) {
        var proxy = this.proxy,
            renderElement = this.renderElement;

        if (!proxy) {
            this.createNavigationBarProxy();
            proxy = this.proxy;
        }

        proxy.renderElement.setWidth(renderElement.getWidth());
        proxy.renderElement.setHeight(renderElement.getHeight());

        proxy.setTitle(newTitle);

        if (oldTitle) {
            proxy.backButton.setText(oldTitle);
            proxy.backButton.show();
        } else {
            proxy.backButton.hide();
        }

        proxy.refreshTitlePosition();
    },

    /**
     * Handles removing back button stacks from this bar
     * @private
     */
    onBeforePop: function(count) {
        count--;
        for (var i = 0; i < count; i++) {
            this.backButtonStack.pop();
        }
    },

    /**
     * We override the hidden method because we don't want to remove it from the view using display:none. Instead we just position it off
     * the scren, much like the navigation bar proxy. This means that all animations, pushing, popping etc. all still work when if you hide/show
     * this bar at any time.
     * @private
     */
    doSetHidden: function(hidden) {
        if (!hidden) {
            this.element.setStyle({
                position: 'relative',
                top: 'auto',
                left: 'auto',
                width: 'auto'
            });
        } else {
            this.element.setStyle({
                position: 'absolute',
                top: '-1000px',
                left: '-1000px',
                width: this.element.getWidth() + 'px'
            });
        }
    },

    /**
     * Creates a proxy element of the passed element, and positions it in the same position, using absolute positioning.
     * The createNavigationBarProxy method uses this to create proxies of the backButton and the title elements.
     * @private
     */
    createProxy: function(component, useParent) {
        var element = (useParent) ? component.element.getParent() : component.element;

        var ghost = element.dom.cloneNode(true);
        ghost.id = element.id + '-proxy';

        //insert it into the toolbar
        element.getParent().dom.appendChild(ghost);

        //set the x/y
        ghost = Ext.get(ghost);
        ghost.setStyle('position', 'absolute');
        ghost.setY(element.getY());
        ghost.setX(element.getX());

        return ghost;
    }
});