I have panel with two toolbars. How can I to implement custom class for using as overflowHandler, which will move components to second toolbar on first toolbar’s overflow?
I tried to use code of Ext.layout.container.boxOverflow.Menu, but my second toolbar simply hides.
Here is my code, which was mixed with toolbar overflow example from ExtJS 4 distributive.
Ext.require(['Ext.window.Window', 'Ext.toolbar.Toolbar', 'Ext.menu.ColorPicker', 'Ext.form.field.Date']);
Ext.onReady(function(){
/**
* Override for implementing tbar2
*/
Ext.override(Ext.panel.Panel, {
bridgeToolbars : function () {
var toolbar;
this.callParent(arguments);
if (this.tbar2) {
if (Ext.isArray(this.tbar2)) {
toolbar = {
xtype : 'toolbar',
items : this.tbar2
};
}
else if (!toolbar.xtype) {
toolbar.xtype = 'toolbar';
}
toolbar.dock = 'top';
toolbar.isTbar2 = true;
this.dockedItems = this.dockedItems.concat(toolbar);
this.tbar2 = null;
}
},
onRender : function () {
this.callParent(arguments);
var topBars = this.getDockedItems('toolbar[dock="top"]'),
i,
len;
for (i = 0, len = topBars.length; i < len; i++) {
if (topBars[i].isTbar2) {
this.tbar2 = topBars[i];
break;
}
}
},
/**
* Lazy creates new toolbar and returns it
* @param {Ext.panel.Panel} panel
* @param {String} position
* @return {Ext.toolbar.Toolbar}
*/
getDynamicTBar : function (position) {
var panel = this,
params,
tb;
position = position || 'top';
if (position === 'tbar2') {
tb = panel.tbar2;
params = {dock : 'top', isTbar2 : true};
}
else {
tb = panel.getDockedItems('toolbar[dock="' + position + '"]');
params = {dock : position};
if (tb.length > 0) {
tb = tb[0];
}
}
if (!tb) {
console.log('created tb at ' + position);
tb = Ext.create('Ext.toolbar.Toolbar', params);
panel.addDocked(tb);
}
return tb;
}
});
Ext.define('Ext.layout.container.boxOverflow.TBar2', {
extend : 'Ext.layout.container.boxOverflow.None',
constructor : function () {
this.tbar2Items = [];
return this.callParent(arguments);
},
beginLayout : function (ownerContext) {
this.callParent(arguments);
this.clearOverflow(ownerContext);
},
beginLayoutCycle : function (ownerContext, firstCycle) {
this.callParent(arguments);
if (!firstCycle) {
this.clearOverflow(ownerContext);
this.layout.cacheChildItems(ownerContext);
}
},
getOverflowCls : function () {
return Ext.baseCSSPrefix + this.layout.direction + '-box-overflow-body';
},
_asLayoutRoot : { isRoot : true },
clearOverflow : function () {
if (this.tbar2) {
this.tbar2.suspendLayouts();
this.tbar2.hide();
this.tbar2.resumeLayouts(this._asLayoutRoot);
}
this.tbar2Items.length = 0;
},
handleOverflow : function (ownerContext) {
var me = this,
layout = me.layout,
owner = layout.owner,
names = layout.getNames(),
startProp = names.x,
sizeProp = names.width,
plan = ownerContext.state.boxPlan,
available = plan.targetSize[sizeProp],
childItems = ownerContext.childItems,
len = childItems.length,
childContext,
comp, i, props,
tbarOwner = owner.ownerCt;
owner.suspendLayouts();
// Hide all items which are off the end, and store them to allow them to be restored
// before each layout operation.
me.tbar2Items.length = 0;
for (i = 0; i < len; i++) {
childContext = childItems[i];
props = childContext.props;
if (props[startProp] + props[sizeProp] > available) {
comp = childContext.target;
me.tbar2Items.push(comp);
owner.remove(comp, false);
}
}
owner.resumeLayouts();
if (!me.tbar2 && (tbarOwner instanceof Ext.panel.Panel)) {
me.tbar2 = tbarOwner.getDynamicTBar('tbar2');
}
me.tbar2.suspendLayouts();
me.tbar2.show();
Ext.each(me.tbar2Items, function(item, index) {
me.tbar2.add(item);
});
me.tbar2.resumeLayouts(me._asLayoutRoot);
}
});
var handleAction = function(action){
Ext.example.msg('<b>Action</b>', 'You clicked "' + action + '"');
};
var colorMenu = Ext.create('Ext.menu.ColorPicker', {
handler: function(cm, color){
Ext.example.msg('Color Selected', '<span style="color:#' + color + ';">You choose {0}.</span>', color);
}
});
var showDate = function(d, value) {
Ext.example.msg('<b>Action date</b>', 'You picked ' + Ext.Date.format(value, d.format));
};
var fromPicker = false;
Ext.create('Ext.window.Window', {
title: 'Standard',
closable: false,
height:250,
width: 500,
bodyStyle: 'padding:10px',
contentEl: 'content',
autoScroll: true,
tbar: Ext.create('Ext.toolbar.Toolbar', {
layout: {
overflowHandler: 'TBar2'
},
items: [{
xtype:'splitbutton',
text: 'Menu Button',
iconCls: 'add16',
handler: Ext.Function.pass(handleAction, 'Menu Button'),
menu: [{text: 'Menu Item 1', handler: Ext.Function.pass(handleAction, 'Menu Item 1')}]
},'-',{
xtype:'splitbutton',
text: 'Cut',
iconCls: 'add16',
handler: Ext.Function.pass(handleAction, 'Cut'),
menu: [{text: 'Cut menu', handler: Ext.Function.pass(handleAction, 'Cut menu')}]
},{
text: 'Copy',
iconCls: 'add16',
handler: Ext.Function.pass(handleAction, 'Copy')
},{
text: 'Paste',
iconCls: 'add16',
menu: [{text: 'Paste menu', handler: Ext.Function.pass(handleAction, 'Paste menu')}]
},'-',{
text: 'Format',
iconCls: 'add16',
handler: Ext.Function.pass(handleAction, 'Format')
},'->', {
fieldLabel: 'Action',
labelWidth: 70,
width: 180,
xtype: 'datefield',
labelSeparator: '',
enableKeyEvents: true,
listeners: {
expand: function(){
fromPicker = true;
},
collapse: function(){
fromPicker = false;
},
change: function(d, newVal, oldVal) {
if (fromPicker || !d.isVisible()) {
showDate(d, newVal);
}
},
keypress: {
buffer: 500,
fn: function(field){
var value = field.getValue();
if (value !== null && field.isValid()) {
showDate(field, value);
}
}
}
}
}, {
text: 'Sell',
iconCls: 'money-down',
enableToggle: true,
toggleHandler: function(button, pressed) {
Ext.example.msg('<b>Action</b>', 'Right ToggleButton ' + (pressed ? 'Buy' : 'Sell'));
button.setText(pressed ? 'Buy' : 'Sell')
button.setIconCls(pressed ? 'money-up' : 'money-down')
}
}, {
text: 'Choose a Color',
menu: colorMenu // <-- submenu by reference
}]
})
}).show();
});
We need to implement overflowHandler for toolbar layout, which will add second toolbar and wraps components from first toolbar to second when them cannot be displayed because there isn’t enough width of toolbar’s container.
First, we need to override Ext.panel.Panel:
Next, we need to create class Ext4.layout.container.boxOverflow.TBar2 (it has so long name because ExtJS searches handleOverflow (which is instance of String) in hardcoded Ext4.layout.container.boxOverflow namespace).
Please note I use ExtJS 4 bootstrapping (because in my web app there is ExtJD 2.3 too), so in your code you must probably use
Ext.instead ofExt4.