Button.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:27k
源码类别:

JavaScript

开发平台:

JavaScript

  1. /*!  * Ext JS Library 3.1.0  * Copyright(c) 2006-2009 Ext JS, LLC  * licensing@extjs.com  * http://www.extjs.com/license  */ /**
  2.  * @class Ext.Button
  3.  * @extends Ext.BoxComponent
  4.  * Simple Button class
  5.  * @cfg {String} text The button text to be used as innerHTML (html tags are accepted)
  6.  * @cfg {String} icon The path to an image to display in the button (the image will be set as the background-image
  7.  * CSS property of the button by default, so if you want a mixed icon/text button, set cls:'x-btn-text-icon')
  8.  * @cfg {Function} handler A function called when the button is clicked (can be used instead of click event).
  9.  * The handler is passed the following parameters:<div class="mdetail-params"><ul>
  10.  * <li><code>b</code> : Button<div class="sub-desc">This Button.</div></li>
  11.  * <li><code>e</code> : EventObject<div class="sub-desc">The click event.</div></li>
  12.  * </ul></div>
  13.  * @cfg {Number} minWidth The minimum width for this button (used to give a set of buttons a common width).
  14.  * See also {@link Ext.Panel}.<tt>{@link Ext.Panel#minButtonWidth minButtonWidth}</tt>.
  15.  * @cfg {String/Object} tooltip The tooltip for the button - can be a string to be used as innerHTML (html tags are accepted) or QuickTips config object
  16.  * @cfg {Boolean} hidden True to start hidden (defaults to false)
  17.  * @cfg {Boolean} disabled True to start disabled (defaults to false)
  18.  * @cfg {Boolean} pressed True to start pressed (only if enableToggle = true)
  19.  * @cfg {String} toggleGroup The group this toggle button is a member of (only 1 per group can be pressed)
  20.  * @cfg {Boolean/Object} repeat True to repeat fire the click event while the mouse is down. This can also be
  21.  * a {@link Ext.util.ClickRepeater ClickRepeater} config object (defaults to false).
  22.  * @constructor
  23.  * Create a new button
  24.  * @param {Object} config The config object
  25.  * @xtype button
  26.  */
  27. Ext.Button = Ext.extend(Ext.BoxComponent, {
  28.     /**
  29.      * Read-only. True if this button is hidden
  30.      * @type Boolean
  31.      */
  32.     hidden : false,
  33.     /**
  34.      * Read-only. True if this button is disabled
  35.      * @type Boolean
  36.      */
  37.     disabled : false,
  38.     /**
  39.      * Read-only. True if this button is pressed (only if enableToggle = true)
  40.      * @type Boolean
  41.      */
  42.     pressed : false,
  43.     /**
  44.      * @cfg {Number} tabIndex Set a DOM tabIndex for this button (defaults to undefined)
  45.      */
  46.     /**
  47.      * @cfg {Boolean} allowDepress
  48.      * False to not allow a pressed Button to be depressed (defaults to undefined). Only valid when {@link #enableToggle} is true.
  49.      */
  50.     /**
  51.      * @cfg {Boolean} enableToggle
  52.      * True to enable pressed/not pressed toggling (defaults to false)
  53.      */
  54.     enableToggle : false,
  55.     /**
  56.      * @cfg {Function} toggleHandler
  57.      * Function called when a Button with {@link #enableToggle} set to true is clicked. Two arguments are passed:<ul class="mdetail-params">
  58.      * <li><b>button</b> : Ext.Button<div class="sub-desc">this Button object</div></li>
  59.      * <li><b>state</b> : Boolean<div class="sub-desc">The next state of the Button, true means pressed.</div></li>
  60.      * </ul>
  61.      */
  62.     /**
  63.      * @cfg {Mixed} menu
  64.      * Standard menu attribute consisting of a reference to a menu object, a menu id or a menu config blob (defaults to undefined).
  65.      */
  66.     /**
  67.      * @cfg {String} menuAlign
  68.      * The position to align the menu to (see {@link Ext.Element#alignTo} for more details, defaults to 'tl-bl?').
  69.      */
  70.     menuAlign : 'tl-bl?',
  71.     /**
  72.      * @cfg {String} overflowText If used in a {@link Ext.Toolbar Toolbar}, the
  73.      * text to be used if this item is shown in the overflow menu. See also
  74.      * {@link Ext.Toolbar.Item}.<code>{@link Ext.Toolbar.Item#overflowText overflowText}</code>.
  75.      */
  76.     /**
  77.      * @cfg {String} iconCls
  78.      * A css class which sets a background image to be used as the icon for this button
  79.      */
  80.     /**
  81.      * @cfg {String} type
  82.      * submit, reset or button - defaults to 'button'
  83.      */
  84.     type : 'button',
  85.     // private
  86.     menuClassTarget : 'tr:nth(2)',
  87.     /**
  88.      * @cfg {String} clickEvent
  89.      * The DOM event that will fire the handler of the button. This can be any valid event name (dblclick, contextmenu).
  90.      * Defaults to <tt>'click'</tt>.
  91.      */
  92.     clickEvent : 'click',
  93.     /**
  94.      * @cfg {Boolean} handleMouseEvents
  95.      * False to disable visual cues on mouseover, mouseout and mousedown (defaults to true)
  96.      */
  97.     handleMouseEvents : true,
  98.     /**
  99.      * @cfg {String} tooltipType
  100.      * The type of tooltip to use. Either 'qtip' (default) for QuickTips or 'title' for title attribute.
  101.      */
  102.     tooltipType : 'qtip',
  103.     /**
  104.      * @cfg {String} buttonSelector
  105.      * <p>(Optional) A {@link Ext.DomQuery DomQuery} selector which is used to extract the active, clickable element from the
  106.      * DOM structure created.</p>
  107.      * <p>When a custom {@link #template} is used, you  must ensure that this selector results in the selection of
  108.      * a focussable element.</p>
  109.      * <p>Defaults to <b><tt>'button:first-child'</tt></b>.</p>
  110.      */
  111.     buttonSelector : 'button:first-child',
  112.     /**
  113.      * @cfg {String} scale
  114.      * <p>(Optional) The size of the Button. Three values are allowed:</p>
  115.      * <ul class="mdetail-params">
  116.      * <li>'small'<div class="sub-desc">Results in the button element being 16px high.</div></li>
  117.      * <li>'medium'<div class="sub-desc">Results in the button element being 24px high.</div></li>
  118.      * <li>'large'<div class="sub-desc">Results in the button element being 32px high.</div></li>
  119.      * </ul>
  120.      * <p>Defaults to <b><tt>'small'</tt></b>.</p>
  121.      */
  122.     scale : 'small',
  123.     /**
  124.      * @cfg {Object} scope The scope (<tt><b>this</b></tt> reference) in which the
  125.      * <code>{@link #handler}</code> and <code>{@link #toggleHandler}</code> is
  126.      * executed. Defaults to this Button.
  127.      */
  128.     /**
  129.      * @cfg {String} iconAlign
  130.      * <p>(Optional) The side of the Button box to render the icon. Four values are allowed:</p>
  131.      * <ul class="mdetail-params">
  132.      * <li>'top'<div class="sub-desc"></div></li>
  133.      * <li>'right'<div class="sub-desc"></div></li>
  134.      * <li>'bottom'<div class="sub-desc"></div></li>
  135.      * <li>'left'<div class="sub-desc"></div></li>
  136.      * </ul>
  137.      * <p>Defaults to <b><tt>'left'</tt></b>.</p>
  138.      */
  139.     iconAlign : 'left',
  140.     /**
  141.      * @cfg {String} arrowAlign
  142.      * <p>(Optional) The side of the Button box to render the arrow if the button has an associated {@link #menu}.
  143.      * Two values are allowed:</p>
  144.      * <ul class="mdetail-params">
  145.      * <li>'right'<div class="sub-desc"></div></li>
  146.      * <li>'bottom'<div class="sub-desc"></div></li>
  147.      * </ul>
  148.      * <p>Defaults to <b><tt>'right'</tt></b>.</p>
  149.      */
  150.     arrowAlign : 'right',
  151.     /**
  152.      * @cfg {Ext.Template} template (Optional)
  153.      * <p>A {@link Ext.Template Template} used to create the Button's DOM structure.</p>
  154.      * Instances, or subclasses which need a different DOM structure may provide a different
  155.      * template layout in conjunction with an implementation of {@link #getTemplateArgs}.
  156.      * @type Ext.Template
  157.      * @property template
  158.      */
  159.     /**
  160.      * @cfg {String} cls
  161.      * A CSS class string to apply to the button's main element.
  162.      */
  163.     /**
  164.      * @property menu
  165.      * @type Menu
  166.      * The {@link Ext.menu.Menu Menu} object associated with this Button when configured with the {@link #menu} config option.
  167.      */
  168.     initComponent : function(){
  169.         Ext.Button.superclass.initComponent.call(this);
  170.         this.addEvents(
  171.             /**
  172.              * @event click
  173.              * Fires when this button is clicked
  174.              * @param {Button} this
  175.              * @param {EventObject} e The click event
  176.              */
  177.             'click',
  178.             /**
  179.              * @event toggle
  180.              * Fires when the 'pressed' state of this button changes (only if enableToggle = true)
  181.              * @param {Button} this
  182.              * @param {Boolean} pressed
  183.              */
  184.             'toggle',
  185.             /**
  186.              * @event mouseover
  187.              * Fires when the mouse hovers over the button
  188.              * @param {Button} this
  189.              * @param {Event} e The event object
  190.              */
  191.             'mouseover',
  192.             /**
  193.              * @event mouseout
  194.              * Fires when the mouse exits the button
  195.              * @param {Button} this
  196.              * @param {Event} e The event object
  197.              */
  198.             'mouseout',
  199.             /**
  200.              * @event menushow
  201.              * If this button has a menu, this event fires when it is shown
  202.              * @param {Button} this
  203.              * @param {Menu} menu
  204.              */
  205.             'menushow',
  206.             /**
  207.              * @event menuhide
  208.              * If this button has a menu, this event fires when it is hidden
  209.              * @param {Button} this
  210.              * @param {Menu} menu
  211.              */
  212.             'menuhide',
  213.             /**
  214.              * @event menutriggerover
  215.              * If this button has a menu, this event fires when the mouse enters the menu triggering element
  216.              * @param {Button} this
  217.              * @param {Menu} menu
  218.              * @param {EventObject} e
  219.              */
  220.             'menutriggerover',
  221.             /**
  222.              * @event menutriggerout
  223.              * If this button has a menu, this event fires when the mouse leaves the menu triggering element
  224.              * @param {Button} this
  225.              * @param {Menu} menu
  226.              * @param {EventObject} e
  227.              */
  228.             'menutriggerout'
  229.         );
  230.         if(this.menu){
  231.             this.menu = Ext.menu.MenuMgr.get(this.menu);
  232.         }
  233.         if(Ext.isString(this.toggleGroup)){
  234.             this.enableToggle = true;
  235.         }
  236.     },
  237. /**
  238.   * <p>This method returns an Array which provides substitution parameters for the {@link #template Template} used
  239.   * to create this Button's DOM structure.</p>
  240.   * <p>Instances or subclasses which use a different Template to create a different DOM structure may need to provide their
  241.   * own implementation of this method.</p>
  242.   * <p>The default implementation which provides data for the default {@link #template} returns an Array containing the
  243.   * following items:</p><div class="mdetail-params"><ul>
  244.   * <li>The &lt;button&gt;'s {@link #type}</li>
  245.   * <li>A CSS class name applied to the Button's main &lt;tbody&gt; element which determines the button's scale and icon alignment.</li>
  246.   * <li>A CSS class to determine the presence and position of an arrow icon. (<code>'x-btn-arrow'</code> or <code>'x-btn-arrow-bottom'</code> or <code>''</code>)</li>
  247.   * <li>The {@link #cls} CSS class name applied to the button's wrapping &lt;table&gt; element.</li>
  248.   * <li>The Component id which is applied to the button's wrapping &lt;table&gt; element.</li>
  249.   * </ul></div>
  250.   * @return {Array} Substitution data for a Template.
  251.  */
  252.     getTemplateArgs : function(){
  253.         return [this.type, 'x-btn-' + this.scale + ' x-btn-icon-' + this.scale + '-' + this.iconAlign, this.getMenuClass(), this.cls, this.id];
  254.     },
  255.     // private
  256.     setButtonClass : function(){
  257.         if(this.useSetClass){
  258.             if(!Ext.isEmpty(this.oldCls)){
  259.                 this.el.removeClass([this.oldCls, 'x-btn-pressed']);
  260.             }
  261.             this.oldCls = (this.iconCls || this.icon) ? (this.text ? ' x-btn-text-icon' : ' x-btn-icon') : ' x-btn-noicon';
  262.             this.el.addClass([this.oldCls, this.pressed ? 'x-btn-pressed' : null]);
  263.         }
  264.     },
  265.     // protected
  266.     getMenuClass : function(){
  267.         return this.menu ? (this.arrowAlign != 'bottom' ? 'x-btn-arrow' : 'x-btn-arrow-bottom') : '';
  268.     },
  269.     // private
  270.     onRender : function(ct, position){
  271.         if(!this.template){
  272.             if(!Ext.Button.buttonTemplate){
  273.                 // hideous table template
  274.                 Ext.Button.buttonTemplate = new Ext.Template(
  275.                     '<table id="{4}" cellspacing="0" class="x-btn {3}"><tbody class="{1}">',
  276.                     '<tr><td class="x-btn-tl"><i>&#160;</i></td><td class="x-btn-tc"></td><td class="x-btn-tr"><i>&#160;</i></td></tr>',
  277.                     '<tr><td class="x-btn-ml"><i>&#160;</i></td><td class="x-btn-mc"><em class="{2}" unselectable="on"><button type="{0}"></button></em></td><td class="x-btn-mr"><i>&#160;</i></td></tr>',
  278.                     '<tr><td class="x-btn-bl"><i>&#160;</i></td><td class="x-btn-bc"></td><td class="x-btn-br"><i>&#160;</i></td></tr>',
  279.                     '</tbody></table>');
  280.                 Ext.Button.buttonTemplate.compile();
  281.             }
  282.             this.template = Ext.Button.buttonTemplate;
  283.         }
  284.         var btn, targs = this.getTemplateArgs();
  285.         if(position){
  286.             btn = this.template.insertBefore(position, targs, true);
  287.         }else{
  288.             btn = this.template.append(ct, targs, true);
  289.         }
  290.         /**
  291.          * An {@link Ext.Element Element} encapsulating the Button's clickable element. By default,
  292.          * this references a <tt>&lt;button&gt;</tt> element. Read only.
  293.          * @type Ext.Element
  294.          * @property btnEl
  295.          */
  296.         this.btnEl = btn.child(this.buttonSelector);
  297.         this.mon(this.btnEl, {
  298.             scope: this,
  299.             focus: this.onFocus,
  300.             blur: this.onBlur
  301.         });
  302.         this.initButtonEl(btn, this.btnEl);
  303.         Ext.ButtonToggleMgr.register(this);
  304.     },
  305.     // private
  306.     initButtonEl : function(btn, btnEl){
  307.         this.el = btn;
  308.         this.setIcon(this.icon);
  309.         this.setText(this.text);
  310.         this.setIconClass(this.iconCls);
  311.         if(Ext.isDefined(this.tabIndex)){
  312.             btnEl.dom.tabIndex = this.tabIndex;
  313.         }
  314.         if(this.tooltip){
  315.             this.setTooltip(this.tooltip, true);
  316.         }
  317.         if(this.handleMouseEvents){
  318.             this.mon(btn, {
  319.                 scope: this,
  320.                 mouseover: this.onMouseOver,
  321.                 mousedown: this.onMouseDown
  322.             });
  323.             // new functionality for monitoring on the document level
  324.             //this.mon(btn, 'mouseout', this.onMouseOut, this);
  325.         }
  326.         if(this.menu){
  327.             this.mon(this.menu, {
  328.                 scope: this,
  329.                 show: this.onMenuShow,
  330.                 hide: this.onMenuHide
  331.             });
  332.         }
  333.         if(this.repeat){
  334.             var repeater = new Ext.util.ClickRepeater(btn, Ext.isObject(this.repeat) ? this.repeat : {});
  335.             this.mon(repeater, 'click', this.onClick, this);
  336.         }
  337.         this.mon(btn, this.clickEvent, this.onClick, this);
  338.     },
  339.     // private
  340.     afterRender : function(){
  341.         Ext.Button.superclass.afterRender.call(this);
  342.         this.useSetClass = true;
  343.         this.setButtonClass();
  344.         this.doc = Ext.getDoc();
  345.         this.doAutoWidth();
  346.     },
  347.     /**
  348.      * Sets the CSS class that provides a background image to use as the button's icon.  This method also changes
  349.      * the value of the {@link iconCls} config internally.
  350.      * @param {String} cls The CSS class providing the icon image
  351.      * @return {Ext.Button} this
  352.      */
  353.     setIconClass : function(cls){
  354.         this.iconCls = cls;
  355.         if(this.el){
  356.             this.btnEl.dom.className = '';
  357.             this.btnEl.addClass(['x-btn-text', cls || '']);
  358.             this.setButtonClass();
  359.         }
  360.         return this;
  361.     },
  362.     /**
  363.      * Sets the tooltip for this Button.
  364.      * @param {String/Object} tooltip. This may be:<div class="mdesc-details"><ul>
  365.      * <li><b>String</b> : A string to be used as innerHTML (html tags are accepted) to show in a tooltip</li>
  366.      * <li><b>Object</b> : A configuration object for {@link Ext.QuickTips#register}.</li>
  367.      * </ul></div>
  368.      * @return {Ext.Button} this
  369.      */
  370.     setTooltip : function(tooltip, /* private */ initial){
  371.         if(this.rendered){
  372.             if(!initial){
  373.                 this.clearTip();
  374.             }
  375.             if(Ext.isObject(tooltip)){
  376.                 Ext.QuickTips.register(Ext.apply({
  377.                       target: this.btnEl.id
  378.                 }, tooltip));
  379.                 this.tooltip = tooltip;
  380.             }else{
  381.                 this.btnEl.dom[this.tooltipType] = tooltip;
  382.             }
  383.         }else{
  384.             this.tooltip = tooltip;
  385.         }
  386.         return this;
  387.     },
  388.     // private
  389.     clearTip : function(){
  390.         if(Ext.isObject(this.tooltip)){
  391.             Ext.QuickTips.unregister(this.btnEl);
  392.         }
  393.     },
  394.     // private
  395.     beforeDestroy : function(){
  396.         if(this.rendered){
  397.             this.clearTip();
  398.         }
  399.         if(this.menu && this.menu.autoDestroy) {
  400.             Ext.destroy(this.menu);
  401.         }
  402.         Ext.destroy(this.repeater);
  403.     },
  404.     // private
  405.     onDestroy : function(){
  406.         if(this.rendered){
  407.             this.doc.un('mouseover', this.monitorMouseOver, this);
  408.             this.doc.un('mouseup', this.onMouseUp, this);
  409.             delete this.doc;
  410.             delete this.btnEl;
  411.             Ext.ButtonToggleMgr.unregister(this);
  412.         }
  413.     },
  414.     // private
  415.     doAutoWidth : function(){
  416.         if(this.el && this.text && this.width === undefined){
  417.             this.el.setWidth('auto');
  418.             if(Ext.isIE7 && Ext.isStrict){
  419.                 var ib = this.btnEl;
  420.                 if(ib && ib.getWidth() > 20){
  421.                     ib.clip();
  422.                     ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
  423.                 }
  424.             }
  425.             if(this.minWidth){
  426.                 if(this.el.getWidth() < this.minWidth){
  427.                     this.el.setWidth(this.minWidth);
  428.                 }
  429.             }
  430.         }
  431.     },
  432.     /**
  433.      * Assigns this Button's click handler
  434.      * @param {Function} handler The function to call when the button is clicked
  435.      * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function is executed.
  436.      * Defaults to this Button.
  437.      * @return {Ext.Button} this
  438.      */
  439.     setHandler : function(handler, scope){
  440.         this.handler = handler;
  441.         this.scope = scope;
  442.         return this;
  443.     },
  444.     /**
  445.      * Sets this Button's text
  446.      * @param {String} text The button text
  447.      * @return {Ext.Button} this
  448.      */
  449.     setText : function(text){
  450.         this.text = text;
  451.         if(this.el){
  452.             this.btnEl.update(text || '&#160;');
  453.             this.setButtonClass();
  454.         }
  455.         this.doAutoWidth();
  456.         return this;
  457.     },
  458.     /**
  459.      * Sets the background image (inline style) of the button.  This method also changes
  460.      * the value of the {@link icon} config internally.
  461.      * @param {String} icon The path to an image to display in the button
  462.      * @return {Ext.Button} this
  463.      */
  464.     setIcon : function(icon){
  465.         this.icon = icon;
  466.         if(this.el){
  467.             this.btnEl.setStyle('background-image', icon ? 'url(' + icon + ')' : '');
  468.             this.setButtonClass();
  469.         }
  470.         return this;
  471.     },
  472.     /**
  473.      * Gets the text for this Button
  474.      * @return {String} The button text
  475.      */
  476.     getText : function(){
  477.         return this.text;
  478.     },
  479.     /**
  480.      * If a state it passed, it becomes the pressed state otherwise the current state is toggled.
  481.      * @param {Boolean} state (optional) Force a particular state
  482.      * @param {Boolean} supressEvent (optional) True to stop events being fired when calling this method.
  483.      * @return {Ext.Button} this
  484.      */
  485.     toggle : function(state, suppressEvent){
  486.         state = state === undefined ? !this.pressed : !!state;
  487.         if(state != this.pressed){
  488.             if(this.rendered){
  489.                 this.el[state ? 'addClass' : 'removeClass']('x-btn-pressed');
  490.             }
  491.             this.pressed = state;
  492.             if(!suppressEvent){
  493.                 this.fireEvent('toggle', this, state);
  494.                 if(this.toggleHandler){
  495.                     this.toggleHandler.call(this.scope || this, this, state);
  496.                 }
  497.             }
  498.         }
  499.         return this;
  500.     },
  501.     /**
  502.      * Focus the button
  503.      */
  504.     focus : function(){
  505.         this.btnEl.focus();
  506.     },
  507.     // private
  508.     onDisable : function(){
  509.         this.onDisableChange(true);
  510.     },
  511.     // private
  512.     onEnable : function(){
  513.         this.onDisableChange(false);
  514.     },
  515.     onDisableChange : function(disabled){
  516.         if(this.el){
  517.             if(!Ext.isIE6 || !this.text){
  518.                 this.el[disabled ? 'addClass' : 'removeClass'](this.disabledClass);
  519.             }
  520.             this.el.dom.disabled = disabled;
  521.         }
  522.         this.disabled = disabled;
  523.     },
  524.     /**
  525.      * Show this button's menu (if it has one)
  526.      */
  527.     showMenu : function(){
  528.         if(this.rendered && this.menu){
  529.             if(this.tooltip){
  530.                 Ext.QuickTips.getQuickTip().cancelShow(this.btnEl);
  531.             }
  532.             this.menu.show(this.el, this.menuAlign);
  533.         }
  534.         return this;
  535.     },
  536.     /**
  537.      * Hide this button's menu (if it has one)
  538.      */
  539.     hideMenu : function(){
  540.         if(this.menu){
  541.             this.menu.hide();
  542.         }
  543.         return this;
  544.     },
  545.     /**
  546.      * Returns true if the button has a menu and it is visible
  547.      * @return {Boolean}
  548.      */
  549.     hasVisibleMenu : function(){
  550.         return this.menu && this.menu.isVisible();
  551.     },
  552.     // private
  553.     onClick : function(e){
  554.         if(e){
  555.             e.preventDefault();
  556.         }
  557.         if(e.button !== 0){
  558.             return;
  559.         }
  560.         if(!this.disabled){
  561.             if(this.enableToggle && (this.allowDepress !== false || !this.pressed)){
  562.                 this.toggle();
  563.             }
  564.             if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
  565.                 this.showMenu();
  566.             }
  567.             this.fireEvent('click', this, e);
  568.             if(this.handler){
  569.                 //this.el.removeClass('x-btn-over');
  570.                 this.handler.call(this.scope || this, this, e);
  571.             }
  572.         }
  573.     },
  574.     // private
  575.     isMenuTriggerOver : function(e, internal){
  576.         return this.menu && !internal;
  577.     },
  578.     // private
  579.     isMenuTriggerOut : function(e, internal){
  580.         return this.menu && !internal;
  581.     },
  582.     // private
  583.     onMouseOver : function(e){
  584.         if(!this.disabled){
  585.             var internal = e.within(this.el,  true);
  586.             if(!internal){
  587.                 this.el.addClass('x-btn-over');
  588.                 if(!this.monitoringMouseOver){
  589.                     this.doc.on('mouseover', this.monitorMouseOver, this);
  590.                     this.monitoringMouseOver = true;
  591.                 }
  592.                 this.fireEvent('mouseover', this, e);
  593.             }
  594.             if(this.isMenuTriggerOver(e, internal)){
  595.                 this.fireEvent('menutriggerover', this, this.menu, e);
  596.             }
  597.         }
  598.     },
  599.     // private
  600.     monitorMouseOver : function(e){
  601.         if(e.target != this.el.dom && !e.within(this.el)){
  602.             if(this.monitoringMouseOver){
  603.                 this.doc.un('mouseover', this.monitorMouseOver, this);
  604.                 this.monitoringMouseOver = false;
  605.             }
  606.             this.onMouseOut(e);
  607.         }
  608.     },
  609.     // private
  610.     onMouseOut : function(e){
  611.         var internal = e.within(this.el) && e.target != this.el.dom;
  612.         this.el.removeClass('x-btn-over');
  613.         this.fireEvent('mouseout', this, e);
  614.         if(this.isMenuTriggerOut(e, internal)){
  615.             this.fireEvent('menutriggerout', this, this.menu, e);
  616.         }
  617.     },
  618.     focus : function() {
  619.         this.btnEl.focus();
  620.     },
  621.     blur : function() {
  622.         this.btnEl.blur();
  623.     },
  624.     // private
  625.     onFocus : function(e){
  626.         if(!this.disabled){
  627.             this.el.addClass('x-btn-focus');
  628.         }
  629.     },
  630.     // private
  631.     onBlur : function(e){
  632.         this.el.removeClass('x-btn-focus');
  633.     },
  634.     // private
  635.     getClickEl : function(e, isUp){
  636.        return this.el;
  637.     },
  638.     // private
  639.     onMouseDown : function(e){
  640.         if(!this.disabled && e.button === 0){
  641.             this.getClickEl(e).addClass('x-btn-click');
  642.             this.doc.on('mouseup', this.onMouseUp, this);
  643.         }
  644.     },
  645.     // private
  646.     onMouseUp : function(e){
  647.         if(e.button === 0){
  648.             this.getClickEl(e, true).removeClass('x-btn-click');
  649.             this.doc.un('mouseup', this.onMouseUp, this);
  650.         }
  651.     },
  652.     // private
  653.     onMenuShow : function(e){
  654.         this.menu.ownerCt = this;
  655.         this.ignoreNextClick = 0;
  656.         this.el.addClass('x-btn-menu-active');
  657.         this.fireEvent('menushow', this, this.menu);
  658.     },
  659.     // private
  660.     onMenuHide : function(e){
  661.         this.el.removeClass('x-btn-menu-active');
  662.         this.ignoreNextClick = this.restoreClick.defer(250, this);
  663.         this.fireEvent('menuhide', this, this.menu);
  664.         delete this.menu.ownerCt;
  665.     },
  666.     // private
  667.     restoreClick : function(){
  668.         this.ignoreNextClick = 0;
  669.     }
  670.     /**
  671.      * @cfg {String} autoEl @hide
  672.      */
  673. });
  674. Ext.reg('button', Ext.Button);
  675. // Private utility class used by Button
  676. Ext.ButtonToggleMgr = function(){
  677.    var groups = {};
  678.    function toggleGroup(btn, state){
  679.        if(state){
  680.            var g = groups[btn.toggleGroup];
  681.            for(var i = 0, l = g.length; i < l; i++){
  682.                if(g[i] != btn){
  683.                    g[i].toggle(false);
  684.                }
  685.            }
  686.        }
  687.    }
  688.    return {
  689.        register : function(btn){
  690.            if(!btn.toggleGroup){
  691.                return;
  692.            }
  693.            var g = groups[btn.toggleGroup];
  694.            if(!g){
  695.                g = groups[btn.toggleGroup] = [];
  696.            }
  697.            g.push(btn);
  698.            btn.on('toggle', toggleGroup);
  699.        },
  700.        unregister : function(btn){
  701.            if(!btn.toggleGroup){
  702.                return;
  703.            }
  704.            var g = groups[btn.toggleGroup];
  705.            if(g){
  706.                g.remove(btn);
  707.                btn.un('toggle', toggleGroup);
  708.            }
  709.        },
  710.        /**
  711.         * Gets the pressed button in the passed group or null
  712.         * @param {String} group
  713.         * @return Button
  714.         */
  715.        getPressed : function(group){
  716.            var g = groups[group];
  717.            if(g){
  718.                for(var i = 0, len = g.length; i < len; i++){
  719.                    if(g[i].pressed === true){
  720.                        return g[i];
  721.                    }
  722.                }
  723.            }
  724.            return null;
  725.        }
  726.    };
  727. }();