/** * @class Ext.CycleButton * @extends Ext.SplitButton * A specialized SplitButton that contains a menu of {@link Ext.menu.CheckItem} elements. The button automatically * cycles through each menu item on click, raising the button's {@link #change} event (or calling the button's * {@link #changeHandler} function, if supplied) for the active menu item. Clicking on the arrow section of the * button displays the dropdown menu just like a normal SplitButton. Example usage: *

var btn = new Ext.CycleButton({
    showText: true,
    prependText: 'View as ',
    items: [{
        text:'text only',
        iconCls:'view-text',
        checked:true
    },{
        text:'HTML',
        iconCls:'view-html'
    }],
    changeHandler:function(btn, item){
        Ext.Msg.alert('Change View', item.text);
    }
});
* @constructor * Create a new split button * @param {Object} config The config object * @xtype cycle */ Ext.CycleButton = Ext.extend(Ext.SplitButton, {
/** * @cfg {Array} items An array of {@link Ext.menu.CheckItem} config objects to be used when creating the * button's menu items (e.g., {text:'Foo', iconCls:'foo-icon'}) */
/** * @cfg {Boolean} showText True to display the active item's text as the button text (defaults to false) */
/** * @cfg {String} prependText A static string to prepend before the active item's text when displayed as the * button's text (only applies when showText = true, defaults to '') */
/** * @cfg {Function} changeHandler A callback function that will be invoked each time the active menu * item in the button's menu has changed. If this callback is not supplied, the SplitButton will instead * fire the {@link #change} event on active item change. The changeHandler function will be called with the * following argument list: (SplitButton this, Ext.menu.CheckItem item) */
/** * @cfg {String} forceIcon A css class which sets an image to be used as the static icon for this button. This * icon will always be displayed regardless of which item is selected in the dropdown list. This overrides the * default behavior of changing the button's icon to match the selected item's icon on change. */
/** * @property menu * @type Menu * The {@link Ext.menu.Menu Menu} object used to display the {@link Ext.menu.CheckItem CheckItems} representing the available choices. */ // private getItemText : function(item){ if(item && this.showText === true){ var text = ''; if(this.prependText){ text += this.prependText; } text += item.text; return text; } return undefined; },
/** * Sets the button's active menu item. * @param {Ext.menu.CheckItem} item The item to activate * @param {Boolean} suppressEvent True to prevent the button's change event from firing (defaults to false) */ setActiveItem : function(item, suppressEvent){ if(typeof item != 'object'){ item = this.menu.items.get(item); } if(item){ if(!this.rendered){ this.text = this.getItemText(item); this.iconCls = item.iconCls; }else{ var t = this.getItemText(item); if(t){ this.setText(t); } this.setIconClass(item.iconCls); } this.activeItem = item; if(!item.checked){ item.setChecked(true, true); } if(this.forceIcon){ this.setIconClass(this.forceIcon); } if(!suppressEvent){ this.fireEvent('change', this, item); } } },
/** * Gets the currently active menu item. * @return {Ext.menu.CheckItem} The active item */ getActiveItem : function(){ return this.activeItem; }, // private initComponent : function(){ this.addEvents(
/** * @event change * Fires after the button's active menu item has changed. Note that if a {@link #changeHandler} function * is set on this CycleButton, it will be called instead on active item change and this change event will * not be fired. * @param {Ext.CycleButton} this * @param {Ext.menu.CheckItem} item The menu item that was selected */ "change" ); if(this.changeHandler){ this.on('change', this.changeHandler, this.scope||this); delete this.changeHandler; } this.itemCount = this.items.length; this.menu = {cls:'x-cycle-menu', items:[]}; var checked; for(var i = 0, len = this.itemCount; i < len; i++){ var item = this.items[i]; item.group = item.group || this.id; item.itemIndex = i; item.checkHandler = this.checkHandler; item.scope = this; item.checked = item.checked || false; this.menu.items.push(item); if(item.checked){ checked = item; } } this.setActiveItem(checked, true); Ext.CycleButton.superclass.initComponent.call(this); this.on('click', this.toggleSelected, this); }, // private checkHandler : function(item, pressed){ if(pressed){ this.setActiveItem(item); } },
/** * This is normally called internally on button click, but can be called externally to advance the button's * active item programmatically to the next one in the menu. If the current item is the last one in the menu * the active item will be set to the first item in the menu. */ toggleSelected : function(){ this.menu.render(); var nextIdx, checkItem; for (var i = 1; i < this.itemCount; i++) { nextIdx = (this.activeItem.itemIndex + i) % this.itemCount; // check the potential item checkItem = this.menu.items.itemAt(nextIdx); // if its not disabled then check it. if (!checkItem.disabled) { checkItem.setChecked(true); break; } } } }); Ext.reg('cycle', Ext.CycleButton);