2012-09-29 13 views
6

Ich habe Panel mit zwei toolbars. Wie kann ich benutzerdefinierte Klassen für die Verwendung als overflowHandler implementieren, die Komponenten in die zweite Symbolleiste auf der ersten Symbolleiste Überlauf verschieben?Benutzerdefinierte ÜberlaufHandler-Implementierung in ExtJS 4

Ich habe versucht, Code von Ext.layout.container.boxOverflow.Menu zu verwenden, aber meine zweite Symbolleiste versteckt sich einfach.

Hier ist mein Code, der mit toolbar overflow Beispiel aus ExtJS 4 distributive gemischt wurde.

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(); 
}); 
+0

welche genaue Version r u verwenden verwenden müssen? – dbrin

+0

Meine Version von ExtJS ist 4.1.2 –

Antwort

3

Wir brauchen overflowHandler für Symbolleiste Layout zu implementieren, die zweite Symbolleiste hinzufügen und wickelt Komponenten aus der ersten Symbolleiste Sekunde, wenn sie nicht angezeigt werden, da es nicht genügend Breite der Symbolleiste des Containers ist. Zuerst müssen wir Ext.panel.Panel außer Kraft zu setzen:

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; 
    } 
}); 

Als nächstes müssen wir Klasse Ext4.layout.container.boxOverflow.TBar2 schaffen (es hat so lange Namen, weil ExtJS sucht handleOverflow (die Instanz von String) im hartcodierten Namespace Ext4.layout.container.boxOverflow).

/** 
* @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; 
    } 

}); 

Bitte beachten Sie verwende ich ExtJS 4 Bootstrapping (weil in meiner Web-app es ExtJD 2.3 auch ist), so in Ihrem Code, den Sie wahrscheinlich Ext. statt Ext4.