Button.js
上传用户:shuoshiled
上传日期:2018-01-28
资源大小:10124k
文件大小:25k
源码类别:

中间件编程

开发平台:

JavaScript

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