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