Upgrade to ExtJS 3.1.1 - Released 02/08/2010
[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.destroyMenu !== false) {\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         Ext.Button.superclass.onDestroy.call(this);\r
457     },\r
458 \r
459     // private\r
460     doAutoWidth : function(){\r
461         if(this.el && this.text && this.width === undefined){\r
462             this.el.setWidth('auto');\r
463             if(Ext.isIE7 && Ext.isStrict){\r
464                 var ib = this.btnEl;\r
465                 if(ib && ib.getWidth() > 20){\r
466                     ib.clip();\r
467                     ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));\r
468                 }\r
469             }\r
470             if(this.minWidth){\r
471                 if(this.el.getWidth() < this.minWidth){\r
472                     this.el.setWidth(this.minWidth);\r
473                 }\r
474             }\r
475         }\r
476     },\r
477 \r
478     /**\r
479      * Assigns this Button's click handler\r
480      * @param {Function} handler The function to call when the button is clicked\r
481      * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function is executed.\r
482      * Defaults to this Button.\r
483      * @return {Ext.Button} this\r
484      */\r
485     setHandler : function(handler, scope){\r
486         this.handler = handler;\r
487         this.scope = scope;\r
488         return this;\r
489     },\r
490 \r
491     /**\r
492      * Sets this Button's text\r
493      * @param {String} text The button text\r
494      * @return {Ext.Button} this\r
495      */\r
496     setText : function(text){\r
497         this.text = text;\r
498         if(this.el){\r
499             this.btnEl.update(text || '&#160;');\r
500             this.setButtonClass();\r
501         }\r
502         this.doAutoWidth();\r
503         return this;\r
504     },\r
505 \r
506     /**\r
507      * Sets the background image (inline style) of the button.  This method also changes\r
508      * the value of the {@link icon} config internally.\r
509      * @param {String} icon The path to an image to display in the button\r
510      * @return {Ext.Button} this\r
511      */\r
512     setIcon : function(icon){\r
513         this.icon = icon;\r
514         if(this.el){\r
515             this.btnEl.setStyle('background-image', icon ? 'url(' + icon + ')' : '');\r
516             this.setButtonClass();\r
517         }\r
518         return this;\r
519     },\r
520 \r
521     /**\r
522      * Gets the text for this Button\r
523      * @return {String} The button text\r
524      */\r
525     getText : function(){\r
526         return this.text;\r
527     },\r
528 \r
529     /**\r
530      * If a state it passed, it becomes the pressed state otherwise the current state is toggled.\r
531      * @param {Boolean} state (optional) Force a particular state\r
532      * @param {Boolean} supressEvent (optional) True to stop events being fired when calling this method.\r
533      * @return {Ext.Button} this\r
534      */\r
535     toggle : function(state, suppressEvent){\r
536         state = state === undefined ? !this.pressed : !!state;\r
537         if(state != this.pressed){\r
538             if(this.rendered){\r
539                 this.el[state ? 'addClass' : 'removeClass']('x-btn-pressed');\r
540             }\r
541             this.pressed = state;\r
542             if(!suppressEvent){\r
543                 this.fireEvent('toggle', this, state);\r
544                 if(this.toggleHandler){\r
545                     this.toggleHandler.call(this.scope || this, this, state);\r
546                 }\r
547             }\r
548         }\r
549         return this;\r
550     },\r
551 \r
552     /**\r
553      * Focus the button\r
554      */\r
555     focus : function(){\r
556         this.btnEl.focus();\r
557     },\r
558 \r
559     // private\r
560     onDisable : function(){\r
561         this.onDisableChange(true);\r
562     },\r
563 \r
564     // private\r
565     onEnable : function(){\r
566         this.onDisableChange(false);\r
567     },\r
568 \r
569     onDisableChange : function(disabled){\r
570         if(this.el){\r
571             if(!Ext.isIE6 || !this.text){\r
572                 this.el[disabled ? 'addClass' : 'removeClass'](this.disabledClass);\r
573             }\r
574             this.el.dom.disabled = disabled;\r
575         }\r
576         this.disabled = disabled;\r
577     },\r
578 \r
579     /**\r
580      * Show this button's menu (if it has one)\r
581      */\r
582     showMenu : function(){\r
583         if(this.rendered && this.menu){\r
584             if(this.tooltip){\r
585                 Ext.QuickTips.getQuickTip().cancelShow(this.btnEl);\r
586             }\r
587             if(this.menu.isVisible()){\r
588                 this.menu.hide();\r
589             }\r
590             this.menu.ownerCt = this;\r
591             this.menu.show(this.el, this.menuAlign);\r
592         }\r
593         return this;\r
594     },\r
595 \r
596     /**\r
597      * Hide this button's menu (if it has one)\r
598      */\r
599     hideMenu : function(){\r
600         if(this.hasVisibleMenu()){\r
601             this.menu.hide();\r
602         }\r
603         return this;\r
604     },\r
605 \r
606     /**\r
607      * Returns true if the button has a menu and it is visible\r
608      * @return {Boolean}\r
609      */\r
610     hasVisibleMenu : function(){\r
611         return this.menu && this.menu.ownerCt == this && this.menu.isVisible();\r
612     },\r
613 \r
614     // private\r
615     onClick : function(e){\r
616         if(e){\r
617             e.preventDefault();\r
618         }\r
619         if(e.button !== 0){\r
620             return;\r
621         }\r
622         if(!this.disabled){\r
623             if(this.enableToggle && (this.allowDepress !== false || !this.pressed)){\r
624                 this.toggle();\r
625             }\r
626             if(this.menu && !this.hasVisibleMenu() && !this.ignoreNextClick){\r
627                 this.showMenu();\r
628             }\r
629             this.fireEvent('click', this, e);\r
630             if(this.handler){\r
631                 //this.el.removeClass('x-btn-over');\r
632                 this.handler.call(this.scope || this, this, e);\r
633             }\r
634         }\r
635     },\r
636 \r
637     // private\r
638     isMenuTriggerOver : function(e, internal){\r
639         return this.menu && !internal;\r
640     },\r
641 \r
642     // private\r
643     isMenuTriggerOut : function(e, internal){\r
644         return this.menu && !internal;\r
645     },\r
646 \r
647     // private\r
648     onMouseOver : function(e){\r
649         if(!this.disabled){\r
650             var internal = e.within(this.el,  true);\r
651             if(!internal){\r
652                 this.el.addClass('x-btn-over');\r
653                 if(!this.monitoringMouseOver){\r
654                     this.doc.on('mouseover', this.monitorMouseOver, this);\r
655                     this.monitoringMouseOver = true;\r
656                 }\r
657                 this.fireEvent('mouseover', this, e);\r
658             }\r
659             if(this.isMenuTriggerOver(e, internal)){\r
660                 this.fireEvent('menutriggerover', this, this.menu, e);\r
661             }\r
662         }\r
663     },\r
664 \r
665     // private\r
666     monitorMouseOver : function(e){\r
667         if(e.target != this.el.dom && !e.within(this.el)){\r
668             if(this.monitoringMouseOver){\r
669                 this.doc.un('mouseover', this.monitorMouseOver, this);\r
670                 this.monitoringMouseOver = false;\r
671             }\r
672             this.onMouseOut(e);\r
673         }\r
674     },\r
675 \r
676     // private\r
677     onMouseOut : function(e){\r
678         var internal = e.within(this.el) && e.target != this.el.dom;\r
679         this.el.removeClass('x-btn-over');\r
680         this.fireEvent('mouseout', this, e);\r
681         if(this.isMenuTriggerOut(e, internal)){\r
682             this.fireEvent('menutriggerout', this, this.menu, e);\r
683         }\r
684     },\r
685 \r
686     focus : function() {\r
687         this.btnEl.focus();\r
688     },\r
689 \r
690     blur : function() {\r
691         this.btnEl.blur();\r
692     },\r
693 \r
694     // private\r
695     onFocus : function(e){\r
696         if(!this.disabled){\r
697             this.el.addClass('x-btn-focus');\r
698         }\r
699     },\r
700     // private\r
701     onBlur : function(e){\r
702         this.el.removeClass('x-btn-focus');\r
703     },\r
704 \r
705     // private\r
706     getClickEl : function(e, isUp){\r
707        return this.el;\r
708     },\r
709 \r
710     // private\r
711     onMouseDown : function(e){\r
712         if(!this.disabled && e.button === 0){\r
713             this.getClickEl(e).addClass('x-btn-click');\r
714             this.doc.on('mouseup', this.onMouseUp, this);\r
715         }\r
716     },\r
717     // private\r
718     onMouseUp : function(e){\r
719         if(e.button === 0){\r
720             this.getClickEl(e, true).removeClass('x-btn-click');\r
721             this.doc.un('mouseup', this.onMouseUp, this);\r
722         }\r
723     },\r
724     // private\r
725     onMenuShow : function(e){\r
726         if(this.menu.ownerCt == this){\r
727             this.menu.ownerCt = this;\r
728             this.ignoreNextClick = 0;\r
729             this.el.addClass('x-btn-menu-active');\r
730             this.fireEvent('menushow', this, this.menu);\r
731         }\r
732     },\r
733     // private\r
734     onMenuHide : function(e){\r
735         if(this.menu.ownerCt == this){\r
736             this.el.removeClass('x-btn-menu-active');\r
737             this.ignoreNextClick = this.restoreClick.defer(250, this);\r
738             this.fireEvent('menuhide', this, this.menu);\r
739             delete this.menu.ownerCt;\r
740         }\r
741     },\r
742 \r
743     // private\r
744     restoreClick : function(){\r
745         this.ignoreNextClick = 0;\r
746     }\r
747 \r
748     /**\r
749      * @cfg {String} autoEl @hide\r
750      */\r
751     /**\r
752      * @cfg {String/Object} html @hide\r
753      */\r
754     /**\r
755      * @cfg {String} contentEl  @hide\r
756      */\r
757     /**\r
758      * @cfg {Mixed} data  @hide\r
759      */\r
760     /**\r
761      * @cfg {Mixed} tpl  @hide\r
762      */\r
763     /**\r
764      * @cfg {String} tplWriteMode  @hide\r
765      */\r
766 });\r
767 Ext.reg('button', Ext.Button);\r
768 \r
769 // Private utility class used by Button\r
770 Ext.ButtonToggleMgr = function(){\r
771    var groups = {};\r
772 \r
773    function toggleGroup(btn, state){\r
774        if(state){\r
775            var g = groups[btn.toggleGroup];\r
776            for(var i = 0, l = g.length; i < l; i++){\r
777                if(g[i] != btn){\r
778                    g[i].toggle(false);\r
779                }\r
780            }\r
781        }\r
782    }\r
783 \r
784    return {\r
785        register : function(btn){\r
786            if(!btn.toggleGroup){\r
787                return;\r
788            }\r
789            var g = groups[btn.toggleGroup];\r
790            if(!g){\r
791                g = groups[btn.toggleGroup] = [];\r
792            }\r
793            g.push(btn);\r
794            btn.on('toggle', toggleGroup);\r
795        },\r
796 \r
797        unregister : function(btn){\r
798            if(!btn.toggleGroup){\r
799                return;\r
800            }\r
801            var g = groups[btn.toggleGroup];\r
802            if(g){\r
803                g.remove(btn);\r
804                btn.un('toggle', toggleGroup);\r
805            }\r
806        },\r
807 \r
808        /**\r
809         * Gets the pressed button in the passed group or null\r
810         * @param {String} group\r
811         * @return Button\r
812         */\r
813        getPressed : function(group){\r
814            var g = groups[group];\r
815            if(g){\r
816                for(var i = 0, len = g.length; i < len; i++){\r
817                    if(g[i].pressed === true){\r
818                        return g[i];\r
819                    }\r
820                }\r
821            }\r
822            return null;\r
823        }\r
824    };\r
825 }();\r
826 </pre>    \r
827 </body>\r
828 </html>