/**
* Basic Toolbar class. Although the {@link Ext.container.Container#defaultType defaultType} for Toolbar is {@link Ext.button.Button button}, Toolbar
* elements (child items for the Toolbar container) may be virtually any type of Component. Toolbar elements can be created explicitly via their
* constructors, or implicitly via their xtypes, and can be {@link #add}ed dynamically.
*
* ## Some items have shortcut strings for creation:
*
* | Shortcut | xtype | Class | Description
* |:---------|:--------------|:------------------------------|:---------------------------------------------------
* | `->` | `tbfill` | {@link Ext.toolbar.Fill} | begin using the right-justified button container
* | `-` | `tbseparator` | {@link Ext.toolbar.Separator} | add a vertical separator bar between toolbar items
* | ` ` | `tbspacer` | {@link Ext.toolbar.Spacer} | add horiztonal space between elements
*
* @example
* Ext.create('Ext.toolbar.Toolbar', {
* renderTo: document.body,
* width : 500,
* items: [
* {
* // xtype: 'button', // default for Toolbars
* text: 'Button'
* },
* {
* xtype: 'splitbutton',
* text : 'Split Button'
* },
* // begin using the right-justified button container
* '->', // same as { xtype: 'tbfill' }
* {
* xtype : 'textfield',
* name : 'field1',
* emptyText: 'enter search term'
* },
* // add a vertical separator bar between toolbar items
* '-', // same as {xtype: 'tbseparator'} to create Ext.toolbar.Separator
* 'text 1', // same as {xtype: 'tbtext', text: 'text1'} to create Ext.toolbar.TextItem
* { xtype: 'tbspacer' },// same as ' ' to create Ext.toolbar.Spacer
* 'text 2',
* { xtype: 'tbspacer', width: 50 }, // add a 50px space
* 'text 3'
* ]
* });
*
* Toolbars have {@link #enable} and {@link #disable} methods which when called, will enable/disable all items within your toolbar.
*
* @example
* Ext.create('Ext.toolbar.Toolbar', {
* renderTo: document.body,
* width : 400,
* items: [
* {
* text: 'Button'
* },
* {
* xtype: 'splitbutton',
* text : 'Split Button'
* },
* '->',
* {
* xtype : 'textfield',
* name : 'field1',
* emptyText: 'enter search term'
* }
* ]
* });
*
* Example
*
* @example
* var enableBtn = Ext.create('Ext.button.Button', {
* text : 'Enable All Items',
* disabled: true,
* scope : this,
* handler : function() {
* //disable the enable button and enable the disable button
* enableBtn.disable();
* disableBtn.enable();
*
* //enable the toolbar
* toolbar.enable();
* }
* });
*
* var disableBtn = Ext.create('Ext.button.Button', {
* text : 'Disable All Items',
* scope : this,
* handler : function() {
* //enable the enable button and disable button
* disableBtn.disable();
* enableBtn.enable();
*
* //disable the toolbar
* toolbar.disable();
* }
* });
*
* var toolbar = Ext.create('Ext.toolbar.Toolbar', {
* renderTo: document.body,
* width : 400,
* margin : '5 0 0 0',
* items : [enableBtn, disableBtn]
* });
*
* Adding items to and removing items from a toolbar is as simple as calling the {@link #add} and {@link #remove} methods. There is also a {@link #removeAll} method
* which remove all items within the toolbar.
*
* @example
* var toolbar = Ext.create('Ext.toolbar.Toolbar', {
* renderTo: document.body,
* width : 700,
* items: [
* {
* text: 'Example Button'
* }
* ]
* });
*
* var addedItems = [];
*
* Ext.create('Ext.toolbar.Toolbar', {
* renderTo: document.body,
* width : 700,
* margin : '5 0 0 0',
* items : [
* {
* text : 'Add a button',
* scope : this,
* handler: function() {
* var text = prompt('Please enter the text for your button:');
* addedItems.push(toolbar.add({
* text: text
* }));
* }
* },
* {
* text : 'Add a text item',
* scope : this,
* handler: function() {
* var text = prompt('Please enter the text for your item:');
* addedItems.push(toolbar.add(text));
* }
* },
* {
* text : 'Add a toolbar seperator',
* scope : this,
* handler: function() {
* addedItems.push(toolbar.add('-'));
* }
* },
* {
* text : 'Add a toolbar spacer',
* scope : this,
* handler: function() {
* addedItems.push(toolbar.add('->'));
* }
* },
* '->',
* {
* text : 'Remove last inserted item',
* scope : this,
* handler: function() {
* if (addedItems.length) {
* toolbar.remove(addedItems.pop());
* } else if (toolbar.items.length) {
* toolbar.remove(toolbar.items.last());
* } else {
* alert('No items in the toolbar');
* }
* }
* },
* {
* text : 'Remove all items',
* scope : this,
* handler: function() {
* toolbar.removeAll();
* }
* }
* ]
* });
*
* @constructor
* Creates a new Toolbar
* @param {Object/Object[]} config A config object or an array of buttons to <code>{@link #add}</code>
* @docauthor Robert Dougan <[email protected]>
*/
Ext.define('Ext.toolbar.Toolbar', {
extend: 'Ext.container.Container',
requires: [
'Ext.toolbar.Fill',
'Ext.layout.container.HBox',
'Ext.layout.container.VBox',
'Ext.FocusManager'
],
uses: [
'Ext.toolbar.Separator'
],
alias: 'widget.toolbar',
alternateClassName: 'Ext.Toolbar',
isToolbar: true,
baseCls : Ext.baseCSSPrefix + 'toolbar',
ariaRole : 'toolbar',
defaultType: 'button',
/**
* @cfg {Boolean} vertical
* Set to `true` to make the toolbar vertical. The layout will become a `vbox`.
*/
vertical: false,
/**
* @cfg {String/Object} layout
* This class assigns a default layout (`layout: 'hbox'`).
* Developers _may_ override this configuration option if another layout
* is required (the constructor must be passed a configuration object in this
* case instead of an array).
* See {@link Ext.container.Container#layout} for additional information.
*/
/**
* @cfg {Boolean} enableOverflow
* Configure true to make the toolbar provide a button which activates a dropdown Menu to show
* items which overflow the Toolbar's width.
*/
enableOverflow: false,
* @cfg {String} menuTriggerCls
* Configure the icon class of the overflow button.
*/
menuTriggerCls: Ext.baseCSSPrefix + 'toolbar-more-icon',
trackMenus: true,
itemCls: Ext.baseCSSPrefix + 'toolbar-item',
initComponent: function() {
var me = this,
keys;
// check for simplified (old-style) overflow config:
if (!me.layout && me.enableOverflow) {
me.layout = { overflowHandler: 'Menu' };
}
if (me.dock === 'right' || me.dock === 'left') {
me.vertical = true;
}
me.layout = Ext.applyIf(Ext.isString(me.layout) ? {
type: me.layout
} : me.layout || {}, {
type: me.vertical ? 'vbox' : 'hbox',
align: me.vertical ? 'stretchmax' : 'middle',
clearInnerCtOnLayout: true
});
if (me.vertical) {
me.addClsWithUI('vertical');
}
// @TODO: remove this hack and implement a more general solution
if (me.ui === 'footer') {
me.ignoreBorderManagement = true;
}
me.callParent();
/**
* @event overflowchange
* Fires after the overflow state has changed.
* @param {Object} c The Container
* @param {Boolean} lastOverflow overflow state
*/
me.addEvents('overflowchange');
// Subscribe to Ext.FocusManager for key navigation
keys = me.vertical ? ['up', 'down'] : ['left', 'right'];
Ext.FocusManager.subscribe(me, {
keys: keys
});
},
getRefItems: function(deep) {
var me = this,
items = me.callParent(arguments),
layout = me.layout,
handler;
if (deep && me.enableOverflow) {
handler = layout.overflowHandler;
if (handler && handler.menu) {
items = items.concat(handler.menu.getRefItems(deep));
}
}
return items;
},
/**
* Adds element(s) to the toolbar -- this function takes a variable number of
* arguments of mixed type and adds them to the toolbar.
*
* **Note**: See the notes within {@link Ext.container.Container#add}.
*
* @param {Object...} args The following types of arguments are all valid:
* - `{@link Ext.button.Button config}`: A valid button config object
* - `HtmlElement`: Any standard HTML element
* - `Field`: Any form field
* - `Item`: Any subclass of {@link Ext.toolbar.Item}
* - `String`: Any generic string (gets wrapped in a {@link Ext.toolbar.TextItem}).
* Note that there are a few special strings that are treated differently as explained next.
* - `'-'`: Creates a separator element
* - `' '`: Creates a spacer element
* - `'->'`: Creates a fill element
*
* @method add
*/
// private
lookupComponent: function(c) {
if (Ext.isString(c)) {
var shortcut = Ext.toolbar.Toolbar.shortcuts[c];
if (shortcut) {
c = {
xtype: shortcut
};
} else {
c = {
xtype: 'tbtext',
text: c
};
}
this.applyDefaults(c);
}
return this.callParent(arguments);
},
// private
applyDefaults: function(c) {
if (!Ext.isString(c)) {
c = this.callParent(arguments);
var d = this.internalDefaults;
if (c.events) {
Ext.applyIf(c.initialConfig, d);
Ext.apply(c, d);
} else {
Ext.applyIf(c, d);
}
}
return c;
},
trackMenu: function(item, remove) {
if (this.trackMenus && item.menu) {
var method = remove ? 'mun' : 'mon',
me = this;
me[method](item, 'mouseover', me.onButtonOver, me);
me[method](item, 'menushow', me.onButtonMenuShow, me);
me[method](item, 'menuhide', me.onButtonMenuHide, me);
}
},
// private
constructButton: function(item) {
return item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
},
// private
onBeforeAdd: function(component) {
if (component.is('field') || (component.is('button') && this.ui != 'footer')) {
component.ui = component.ui + '-toolbar';
}
// Any separators needs to know if is vertical or not
if (component instanceof Ext.toolbar.Separator) {
component.setUI((this.vertical) ? 'vertical' : 'horizontal');
}
this.callParent(arguments);
},
// private
onAdd: function(component) {
this.callParent(arguments);
this.trackMenu(component);
if (this.disabled) {
component.disable();
}
},
// private
onRemove: function(c) {
this.callParent(arguments);
this.trackMenu(c, true);
},
// private
onButtonOver: function(btn){
if (this.activeMenuBtn && this.activeMenuBtn != btn) {
this.activeMenuBtn.hideMenu();
btn.showMenu();
this.activeMenuBtn = btn;
}
},
onButtonMenuShow: function(btn) {
this.activeMenuBtn = btn;
},
onButtonMenuHide: function(btn) {
delete this.activeMenuBtn;
}
}, function() {
this.shortcuts = {
'-' : 'tbseparator',
' ' : 'tbspacer',
'->': 'tbfill'
};
});