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
2 Answers
Reset to default 1Try 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/