PDA

View Full Version : Some questions about floating components & best practice



suamikim
5 Aug 2012, 11:39 PM
Hi there,

i need a custom panel which always holds a button at a specified position (e.g. always bottom-right).
I've already achieved this but i'm not sure if there ain't no better way to do it:

http://jsfiddle.net/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 unter 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

friend
6 Aug 2012, 6:02 AM
It might be easier to use 'dockedItems' and a Toolbar with a right-aligned button, noting that you'll have to jump though some SASS/CSS hoops if you want the button to appear 'raised':



Ext.create('Ext.window.Window', {
height: 200,
layout: 'fit',
width: 400,
items: [{
xtype: 'panel',
dockedItems: [{
xtype: 'toolbar',
dock: 'bottom',
items: [
'->',
{
text: 'Some Button'
}]
}]
}]
}).show()

suamikim
6 Aug 2012, 6:41 AM
Yes, the dockedItem would be easier to use but i think it's no option for me. The button at the lower right is just an example. It could also be horizontally & vertically centerd in the panel which wouldn't be possible at all...

friend
6 Aug 2012, 10:44 AM
dockedItems and a Toolbar are fairly flexible. For horizontal centering, you can do this:



Ext.create('Ext.window.Window', {
height: 200,
layout: 'fit',
width: 400,
items: [{
xtype: 'panel',
dockedItems: [{
xtype: 'toolbar',
layout: {
type: 'hbox',
pack: 'center'
},
dock: 'bottom',
items: [
{
text: 'Some Button'
}]
}]
}]
}).show()


As for vertical centering, that can easily be done with a layout also.

If you mean that you want the button horizontally and vertically centered in the same panel, then you're right; a Toolbar is not your best bet. You could do that with simple nested vbox/hbox panels or via a few other layout options.

suamikim
6 Aug 2012, 10:07 PM
Ok, maybe the button needs to be centered vertically & horizontally at the same time. The main points are the following:

1)
The position needs to be as flexible as possible. Theoretically it could be everywhere inside my panel. The use case changes constantly. Would this be possible with the nested hbox & vbox layout or the few other layout options you mentioned?
What would those other layout options be and could you give me a short example? I can't really imagine what you mean...

2)
The button needs to be "free" inside the panel (floating...). There must not be any other container around it like a toolbar!

Thanks