最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Floating components in ExtJS - Stack Overflow

programmeradmin1浏览0评论

i need a custom panel which always holds a button at a specified position (e.g. always bottom-right).

The position needs to be as flexible as possible (but statically defined). Theoretically it could be everywhere within the panel (left-centered, center-center, left + 10px & bottom - 50px, ...) and it needs to be "free". So it must not be surrounded by any other element like a toolbar (floating...).

I've already achieved this but there's still a bug in it and i'm not sure if there ain't no better way to do it:

/

Ext.onReady(function() {
    var floatBtn, toolbar, win;

    Ext.define('PanelWithFloatButton', {
        extend: 'Ext.panel.Panel',

        items: [],

        constructor: function(config) {
            // region private variables (no getter & setter available)
            this._floatingBtn = undefined;
            // endregion private variables

            // region private events
            this._afterRender = function() {
                this._floatingBtn.show();
            };
            // endregion private events

            // region private functions
            this._updateFloatBtnPos = function() {
                var bodySize = this.body.getSize(),
                    btnSize = this._floatingBtn.getSize();

                if (this._floatingBtn && this._floatingBtn.el) {
                    this._floatingBtn.setPosition(bodySize.width - btnSize.width - 10, bodySize.height - btnSize.height - 10);
                }
            };
            // endregion private functions

            return this.callParent(arguments);
        },

        initComponent: function() {
            // Create floating button
            this._floatingBtn = Ext.create('Ext.button.Button', {
                text: 'Floating button, always bottom-right...',
                floating: true,
                style: {
                    'z-index': 1
                }
            });

            // Add items
            this.add(this._floatingBtn);

            // Add listeners
            this.addListener('afterrender', this._afterRender, this);
            this.addListener('resize', this._updateFloatBtnPos, this);

            this.addListener('beforedestroy', function() {
                this._floatingBtn.destroy();
            }, this);

            this.addListener('beforehide', function() {
                this._floatingBtn.hide();
            }, this);

            this.addListener('show', function() {
                this._floatingBtn.show();
            }, this);

            return this.callParent(arguments);
        }
    });

    btnParent = Ext.create('PanelWithFloatButton', {
        title: 'Button-Parent',
        layout: {
            type: 'vbox',
            align: 'stretch'
        }
    });

    toolbar = Ext.create('Ext.toolbar.Toolbar', {
        region: 'north',
        defaultType: 'button',
        items: [{
                text: 'Toggle visibility of Button-Parent',
                handler: function() {
                    try {
                        btnParent.setVisible(!btnParent.isVisible());
                    } catch (e) {
                        // btnParent is already destroyed
                    }
                }
            }, '|', {
                text: 'Destroy Button-Parent',
                handler: function() {
                    try {
                        btnParent.up().remove(btnParent);
                    } catch (e) {
                        // btnParent is already destroyed
                    }
                }
            }, '|', {
                text: 'Add subpanel',
                handler: function() {
                    btnParent.add(Ext.create('Ext.panel.Panel', {
                        title: 'Sub-Panel',
                        height: 200,
                        style: {
                            'z-index': 2
                        }
                    }));
                }
        }]
    });

    win = Ext.create('Ext.window.Window', {
        width: 500,
        height: 500,
        layout: 'border',
        items: [
            toolbar, 
            {
                xtype: 'panel',
                region: 'center',
                layout: 'fit',
                items: btnParent
        }]
    }).show();
});  

Some specific questions:

1.) Why is the button positioned correctely only after the window has been moved manualy for the first time and not right from the start?

2.) Is there a better way to make the button always stay at it's position than by catching the resize-event and recalculating manually?

3.) Is there a way to make the button automatically show/hide/destroy with it's parent-panel like normal sub-items (not floating) do?

4.) Is there a way to automatically hide the floating button under other child-items of the buttons parent? After adding 2 more subpanels by pressing "Add subpanel" it should hide automatically under the second panel. I thought that this could be easily achieved by setting the z-index but this seems to be overwritten by the Ext-Framework because when i look at the DOM there is a realy big z-index (> 19000) set at element-level which can't be overwritten that easy with css.

5.) Is my approach (Extending the panel, creating the button and adding listeners in initComponent, ...) basically correct for what i want to achieve or are there any major flaws in my code?

Thanks & best regards,

Mike

i need a custom panel which always holds a button at a specified position (e.g. always bottom-right).

The position needs to be as flexible as possible (but statically defined). Theoretically it could be everywhere within the panel (left-centered, center-center, left + 10px & bottom - 50px, ...) and it needs to be "free". So it must not be surrounded by any other element like a toolbar (floating...).

I've already achieved this but there's still a bug in it and i'm not sure if there ain't no better way to do it:

http://jsfiddle/suamikim/uQDDu/1/

Ext.onReady(function() {
    var floatBtn, toolbar, win;

    Ext.define('PanelWithFloatButton', {
        extend: 'Ext.panel.Panel',

        items: [],

        constructor: function(config) {
            // region private variables (no getter & setter available)
            this._floatingBtn = undefined;
            // endregion private variables

            // region private events
            this._afterRender = function() {
                this._floatingBtn.show();
            };
            // endregion private events

            // region private functions
            this._updateFloatBtnPos = function() {
                var bodySize = this.body.getSize(),
                    btnSize = this._floatingBtn.getSize();

                if (this._floatingBtn && this._floatingBtn.el) {
                    this._floatingBtn.setPosition(bodySize.width - btnSize.width - 10, bodySize.height - btnSize.height - 10);
                }
            };
            // endregion private functions

            return this.callParent(arguments);
        },

        initComponent: function() {
            // Create floating button
            this._floatingBtn = Ext.create('Ext.button.Button', {
                text: 'Floating button, always bottom-right...',
                floating: true,
                style: {
                    'z-index': 1
                }
            });

            // Add items
            this.add(this._floatingBtn);

            // Add listeners
            this.addListener('afterrender', this._afterRender, this);
            this.addListener('resize', this._updateFloatBtnPos, this);

            this.addListener('beforedestroy', function() {
                this._floatingBtn.destroy();
            }, this);

            this.addListener('beforehide', function() {
                this._floatingBtn.hide();
            }, this);

            this.addListener('show', function() {
                this._floatingBtn.show();
            }, this);

            return this.callParent(arguments);
        }
    });

    btnParent = Ext.create('PanelWithFloatButton', {
        title: 'Button-Parent',
        layout: {
            type: 'vbox',
            align: 'stretch'
        }
    });

    toolbar = Ext.create('Ext.toolbar.Toolbar', {
        region: 'north',
        defaultType: 'button',
        items: [{
                text: 'Toggle visibility of Button-Parent',
                handler: function() {
                    try {
                        btnParent.setVisible(!btnParent.isVisible());
                    } catch (e) {
                        // btnParent is already destroyed
                    }
                }
            }, '|', {
                text: 'Destroy Button-Parent',
                handler: function() {
                    try {
                        btnParent.up().remove(btnParent);
                    } catch (e) {
                        // btnParent is already destroyed
                    }
                }
            }, '|', {
                text: 'Add subpanel',
                handler: function() {
                    btnParent.add(Ext.create('Ext.panel.Panel', {
                        title: 'Sub-Panel',
                        height: 200,
                        style: {
                            'z-index': 2
                        }
                    }));
                }
        }]
    });

    win = Ext.create('Ext.window.Window', {
        width: 500,
        height: 500,
        layout: 'border',
        items: [
            toolbar, 
            {
                xtype: 'panel',
                region: 'center',
                layout: 'fit',
                items: btnParent
        }]
    }).show();
});  

Some specific questions:

1.) Why is the button positioned correctely only after the window has been moved manualy for the first time and not right from the start?

2.) Is there a better way to make the button always stay at it's position than by catching the resize-event and recalculating manually?

3.) Is there a way to make the button automatically show/hide/destroy with it's parent-panel like normal sub-items (not floating) do?

4.) Is there a way to automatically hide the floating button under other child-items of the buttons parent? After adding 2 more subpanels by pressing "Add subpanel" it should hide automatically under the second panel. I thought that this could be easily achieved by setting the z-index but this seems to be overwritten by the Ext-Framework because when i look at the DOM there is a realy big z-index (> 19000) set at element-level which can't be overwritten that easy with css.

5.) Is my approach (Extending the panel, creating the button and adding listeners in initComponent, ...) basically correct for what i want to achieve or are there any major flaws in my code?

Thanks & best regards,

Mike

Share Improve this question asked Aug 7, 2012 at 6:28 suamikimsuamikim 5,35910 gold badges44 silver badges81 bronze badges 5
  • Not sure I understand your problem in full, but is there any particular reason to make that button floating? I would probably use absolute layout on the panel and place the button at the coordinates I need. – Alex Tokarev Commented Aug 7, 2012 at 16:53
  • 1 Have you considered using a CSS class extension? Layouts including positioning are usually best dealt with by Stylesheets. Maybe post on CSS3 for some tips? – Eric Commented Aug 8, 2012 at 18:13
  • @AlexanderTokarev: I need the possibility to add other items than the button to the panel (see the jsfiddle-example and press the "Add subpanel"-button in the toolbar). AND the layout of those items needs to be exchangable too. In the example it is an hbox-layout but it could also be any other layout... – suamikim Commented Aug 9, 2012 at 5:22
  • @Eric: Thanks for the input, i haven't considered this before and going to have a look at it. – suamikim Commented Aug 9, 2012 at 5:26
  • In Ext JS terms, a floating ponent is a ponent that has no parent container and "floats" against document body. An example of a typical floating ponent is Ext.window.Window. In your case, using floating ponents is not necessary; you can go by with properly chosen layout and some event handlers. There's no need to make things more plicated than they have to be. – Alex Tokarev Commented Aug 10, 2012 at 22:35
Add a ment  | 

2 Answers 2

Reset to default 1

Try this http://jsfiddle/uQDDu/13/

Javascript

    ...
    Line 48 this.addListener('afterrender', this._afterRender, this);
    Line 49 this.addListener('afterlayout', this._updateFloatBtnPos, this); //added
    ...

Does this work for you? http://jsfiddle/dbrin/XuQg4/21/

发布评论

评论列表(0)

  1. 暂无评论