layout extjs extjs4 extjs4.1

layout - Implementación Custom overflowHandler en ExtJS 4



extjs4 extjs4.1 (1)

Necesitamos implementar overflowHandler para el diseño de la barra de herramientas, que agregará una segunda barra de herramientas y ajustará los componentes de la primera barra de herramientas a la segunda cuando no se puedan mostrar porque no hay suficiente ancho del contenedor de la barra de herramientas. Primero, debemos anular Ext.panel.Panel:

Ext4.override(Ext4.panel.Panel, { bridgeToolbars: function () { var toolbar; this.callParent(arguments); if (this.tbar2) { if (Ext4.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; } } }, /** * Creates, if not exists, and returns toolbar at passed position * @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, layout: { overflowHandler: ''Scroller'' } }; } else { tb = panel.getDockedItems(''toolbar[dock="'' + position + ''"]''); params = { dock: position }; if (tb.length > 0) { tb = tb[0]; } } if (!tb) { tb = Ext4.create(''Ext4.toolbar.Toolbar'', params); panel.addDocked(tb); if (position === ''tbar2'') { panel.tbar2 = tb; } } return tb; } });

A continuación, tenemos que crear la clase Ext4.layout.container.boxOverflow.TBar2 (tiene un nombre tan largo porque ExtJS busca handleOverflow (que es una instancia de String) en el espacio de nombres Ext4.layout.container.boxOverflow codificado).

/** * @class Ext4.layout.container.boxOverflow.TBar2 * Class for using as overflowHandler * @extends Ext.layout.container.boxOverflow.None */ Ext4.define(''Ext4.layout.container.boxOverflow.TBar2'', { extend: ''Ext4.layout.container.boxOverflow.None'', /** * @private * @property {Boolean} initialized */ initialized: false, constructor: function () { /** * @private * @property {Array} tbar2Items * List of moved components */ this.tbar2Items = []; return this.callParent(arguments); }, beginLayout: function (ownerContext) { if (!this.initialized) { this.layout.owner.ownerCt.on(''afterlayout'', this.createTBar2, this); this.initialized = true; } 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 Ext4.baseCSSPrefix + this.layout.direction + ''-box-overflow-body''; }, /** * @private * @property {Object} _asLayoutRoot */ _asLayoutRoot: { isRoot: true }, clearOverflow: function () { // If afterlayout is not processing and tbar2 already created, // we can to move components from tbar2 to first toolbar, because now // there isn''t any overflow if (!this.processing && this.tbar2) { this.tbar2.items.each(function (item) { this.tbar1.add(item); // change ui from saved property, or CSS will be incorrect item.ui = item.origUI; }, this); this.tbar2.removeAll(false); this.tbar2.hide(); } this.tbar2Items.length = 0; }, /** * @private * Creates tbar2 and does other routines */ createTBar2: function () { // if afterlayout event is still processing, // or we don''t need to handle toolbar overflow, just return from function if (this.processing || !this.doTbar2) { return; } this.processing = true; this.doTbar2 = false; var me = this, ownerContext = this.mOwnerContext, 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; me.tbar1 = owner; // save components which will be moved owner.suspendLayouts(); 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); // save original ui property comp.origUI = comp.ui; owner.remove(comp, false); } } owner.resumeLayouts(); // add tbar2 to the layout cycle (you can see very similar code in clearOverflow // method of Ext.layout.container.boxOverflow.Menu) tbarOwner.suspendLayouts(); me.tbar2 = tbarOwner.getDynamicTBar(''tbar2''); me.tbar2.show(); // moving components Ext4.each(me.tbar2Items, function (item, index) { me.tbar2.insert(index, item); item.ui = item.origUI; }); tbarOwner.resumeLayouts(this._asLayoutRoot); this.processing = false; }, handleOverflow: function (ownerContext) { // set flag and store context for later using this.doTbar2 = true; this.mOwnerContext = ownerContext; } });

Tenga en cuenta que utilizo el arranque ExtJS 4 (porque en mi aplicación web también existe ExtJD 2.3), por lo que en su código probablemente deba usar Ext. en lugar de Ext4.

Tengo un panel con dos toolbars . ¿Cómo puedo implementar una clase personalizada para usar como overflowHandler , que moverá los componentes a la segunda barra de herramientas en el desbordamiento de la primera barra de herramientas?

Traté de usar el código de Ext.layout.container.boxOverflow.Menu , pero mi segunda barra de herramientas simplemente se oculta.

Aquí está mi código, que se mezcló con el ejemplo de toolbar overflow de 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(); });