Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / window / MessageBox.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * Utility class for generating different styles of message boxes.  The singleton instance, Ext.MessageBox
17  * alias `Ext.Msg` can also be used.
18  *
19  * Note that a MessageBox is asynchronous.  Unlike a regular JavaScript `alert` (which will halt
20  * browser execution), showing a MessageBox will not cause the code to stop.  For this reason, if you have code
21  * that should only run *after* some user feedback from the MessageBox, you must use a callback function
22  * (see the `function` parameter for {@link #show} for more details).
23  *
24  * Basic alert
25  *
26  *     @example
27  *     Ext.Msg.alert('Status', 'Changes saved successfully.');
28  *
29  * Prompt for user data and process the result using a callback
30  *
31  *     @example
32  *     Ext.Msg.prompt('Name', 'Please enter your name:', function(btn, text){
33  *         if (btn == 'ok'){
34  *             // process text value and close...
35  *         }
36  *     });
37  *
38  * Show a dialog using config options
39  *
40  *     @example
41  *     Ext.Msg.show({
42  *          title:'Save Changes?',
43  *          msg: 'You are closing a tab that has unsaved changes. Would you like to save your changes?',
44  *          buttons: Ext.Msg.YESNOCANCEL,
45  *          icon: Ext.Msg.QUESTION
46  *     });
47  */
48 Ext.define('Ext.window.MessageBox', {
49     extend: 'Ext.window.Window',
50
51     requires: [
52         'Ext.toolbar.Toolbar',
53         'Ext.form.field.Text',
54         'Ext.form.field.TextArea',
55         'Ext.button.Button',
56         'Ext.layout.container.Anchor',
57         'Ext.layout.container.HBox',
58         'Ext.ProgressBar'
59     ],
60
61     alias: 'widget.messagebox',
62
63     /**
64      * Button config that displays a single OK button
65      * @type Number
66      */
67     OK : 1,
68     /**
69      * Button config that displays a single Yes button
70      * @type Number
71      */
72     YES : 2,
73     /**
74      * Button config that displays a single No button
75      * @type Number
76      */
77     NO : 4,
78     /**
79      * Button config that displays a single Cancel button
80      * @type Number
81      */
82     CANCEL : 8,
83     /**
84      * Button config that displays OK and Cancel buttons
85      * @type Number
86      */
87     OKCANCEL : 9,
88     /**
89      * Button config that displays Yes and No buttons
90      * @type Number
91      */
92     YESNO : 6,
93     /**
94      * Button config that displays Yes, No and Cancel buttons
95      * @type Number
96      */
97     YESNOCANCEL : 14,
98     /**
99      * The CSS class that provides the INFO icon image
100      * @type String
101      */
102     INFO : 'ext-mb-info',
103     /**
104      * The CSS class that provides the WARNING icon image
105      * @type String
106      */
107     WARNING : 'ext-mb-warning',
108     /**
109      * The CSS class that provides the QUESTION icon image
110      * @type String
111      */
112     QUESTION : 'ext-mb-question',
113     /**
114      * The CSS class that provides the ERROR icon image
115      * @type String
116      */
117     ERROR : 'ext-mb-error',
118
119     // hide it by offsets. Windows are hidden on render by default.
120     hideMode: 'offsets',
121     closeAction: 'hide',
122     resizable: false,
123     title: ' ',
124
125     width: 600,
126     height: 500,
127     minWidth: 250,
128     maxWidth: 600,
129     minHeight: 110,
130     maxHeight: 500,
131     constrain: true,
132
133     cls: Ext.baseCSSPrefix + 'message-box',
134
135     layout: {
136         type: 'anchor'
137     },
138
139     /**
140      * The default height in pixels of the message box's multiline textarea if displayed.
141      * @type Number
142      */
143     defaultTextHeight : 75,
144     /**
145      * The minimum width in pixels of the message box if it is a progress-style dialog.  This is useful
146      * for setting a different minimum width than text-only dialogs may need.
147      * @type Number
148      */
149     minProgressWidth : 250,
150     /**
151      * The minimum width in pixels of the message box if it is a prompt dialog.  This is useful
152      * for setting a different minimum width than text-only dialogs may need.
153      * @type Number
154      */
155     minPromptWidth: 250,
156     /**
157      * An object containing the default button text strings that can be overriden for localized language support.
158      * Supported properties are: ok, cancel, yes and no.  Generally you should include a locale-specific
159      * resource file for handling language support across the framework.
160      * Customize the default text like so: Ext.window.MessageBox.buttonText.yes = "oui"; //french
161      * @type Object
162      */
163     buttonText: {
164         ok: 'OK',
165         yes: 'Yes',
166         no: 'No',
167         cancel: 'Cancel'
168     },
169
170     buttonIds: [
171         'ok', 'yes', 'no', 'cancel'
172     ],
173
174     titleText: {
175         confirm: 'Confirm',
176         prompt: 'Prompt',
177         wait: 'Loading...',
178         alert: 'Attention'
179     },
180
181     iconHeight: 35,
182
183     makeButton: function(btnIdx) {
184         var btnId = this.buttonIds[btnIdx];
185         return Ext.create('Ext.button.Button', {
186             handler: this.btnCallback,
187             itemId: btnId,
188             scope: this,
189             text: this.buttonText[btnId],
190             minWidth: 75
191         });
192     },
193
194     btnCallback: function(btn) {
195         var me = this,
196             value,
197             field;
198
199         if (me.cfg.prompt || me.cfg.multiline) {
200             if (me.cfg.multiline) {
201                 field = me.textArea;
202             } else {
203                 field = me.textField;
204             }
205             value = field.getValue();
206             field.reset();
207         }
208
209         // Important not to have focus remain in the hidden Window; Interferes with DnD.
210         btn.blur();
211         me.hide();
212         me.userCallback(btn.itemId, value, me.cfg);
213     },
214
215     hide: function() {
216         var me = this;
217         me.dd.endDrag();
218         me.progressBar.reset();
219         me.removeCls(me.cfg.cls);
220         me.callParent();
221     },
222
223     initComponent: function() {
224         var me = this,
225             i, button;
226
227         me.title = ' ';
228
229         me.topContainer = Ext.create('Ext.container.Container', {
230             anchor: '100%',
231             style: {
232                 padding: '10px',
233                 overflow: 'hidden'
234             },
235             items: [
236                 me.iconComponent = Ext.create('Ext.Component', {
237                     cls: 'ext-mb-icon',
238                     width: 50,
239                     height: me.iconHeight,
240                     style: {
241                         'float': 'left'
242                     }
243                 }),
244                 me.promptContainer = Ext.create('Ext.container.Container', {
245                     layout: {
246                         type: 'anchor'
247                     },
248                     items: [
249                         me.msg = Ext.create('Ext.Component', {
250                             autoEl: { tag: 'span' },
251                             cls: 'ext-mb-text'
252                         }),
253                         me.textField = Ext.create('Ext.form.field.Text', {
254                             anchor: '100%',
255                             enableKeyEvents: true,
256                             listeners: {
257                                 keydown: me.onPromptKey,
258                                 scope: me
259                             }
260                         }),
261                         me.textArea = Ext.create('Ext.form.field.TextArea', {
262                             anchor: '100%',
263                             height: 75
264                         })
265                     ]
266                 })
267             ]
268         });
269         me.progressBar = Ext.create('Ext.ProgressBar', {
270             anchor: '-10',
271             style: 'margin-left:10px'
272         });
273
274         me.items = [me.topContainer, me.progressBar];
275
276         // Create the buttons based upon passed bitwise config
277         me.msgButtons = [];
278         for (i = 0; i < 4; i++) {
279             button = me.makeButton(i);
280             me.msgButtons[button.itemId] = button;
281             me.msgButtons.push(button);
282         }
283         me.bottomTb = Ext.create('Ext.toolbar.Toolbar', {
284             ui: 'footer',
285             dock: 'bottom',
286             layout: {
287                 pack: 'center'
288             },
289             items: [
290                 me.msgButtons[0],
291                 me.msgButtons[1],
292                 me.msgButtons[2],
293                 me.msgButtons[3]
294             ]
295         });
296         me.dockedItems = [me.bottomTb];
297
298         me.callParent();
299     },
300
301     onPromptKey: function(textField, e) {
302         var me = this,
303             blur;
304
305         if (e.keyCode === Ext.EventObject.RETURN || e.keyCode === 10) {
306             if (me.msgButtons.ok.isVisible()) {
307                 blur = true;
308                 me.msgButtons.ok.handler.call(me, me.msgButtons.ok);
309             } else if (me.msgButtons.yes.isVisible()) {
310                 me.msgButtons.yes.handler.call(me, me.msgButtons.yes);
311                 blur = true;
312             }
313
314             if (blur) {
315                 me.textField.blur();
316             }
317         }
318     },
319
320     reconfigure: function(cfg) {
321         var me = this,
322             buttons = cfg.buttons || 0,
323             hideToolbar = true,
324             initialWidth = me.maxWidth,
325             i;
326
327         cfg = cfg || {};
328         me.cfg = cfg;
329         if (cfg.width) {
330             initialWidth = cfg.width;
331         }
332
333         // Default to allowing the Window to take focus.
334         delete me.defaultFocus;
335
336         // clear any old animateTarget
337         me.animateTarget = cfg.animateTarget || undefined;
338
339         // Defaults to modal
340         me.modal = cfg.modal !== false;
341
342         // Show the title
343         if (cfg.title) {
344             me.setTitle(cfg.title||'&#160;');
345         }
346
347         if (!me.rendered) {
348             me.width = initialWidth;
349             me.render(Ext.getBody());
350         } else {
351             me.setSize(initialWidth, me.maxHeight);
352         }
353         me.setPosition(-10000, -10000);
354
355         // Hide or show the close tool
356         me.closable = cfg.closable && !cfg.wait;
357         me.header.child('[type=close]').setVisible(cfg.closable !== false);
358
359         // Hide or show the header
360         if (!cfg.title && !me.closable) {
361             me.header.hide();
362         } else {
363             me.header.show();
364         }
365
366         // Default to dynamic drag: drag the window, not a ghost
367         me.liveDrag = !cfg.proxyDrag;
368
369         // wrap the user callback
370         me.userCallback = Ext.Function.bind(cfg.callback ||cfg.fn || Ext.emptyFn, cfg.scope || Ext.global);
371
372         // Hide or show the icon Component
373         me.setIcon(cfg.icon);
374
375         // Hide or show the message area
376         if (cfg.msg) {
377             me.msg.update(cfg.msg);
378             me.msg.show();
379         } else {
380             me.msg.hide();
381         }
382
383         // Hide or show the input field
384         if (cfg.prompt || cfg.multiline) {
385             me.multiline = cfg.multiline;
386             if (cfg.multiline) {
387                 me.textArea.setValue(cfg.value);
388                 me.textArea.setHeight(cfg.defaultTextHeight || me.defaultTextHeight);
389                 me.textArea.show();
390                 me.textField.hide();
391                 me.defaultFocus = me.textArea;
392             } else {
393                 me.textField.setValue(cfg.value);
394                 me.textArea.hide();
395                 me.textField.show();
396                 me.defaultFocus = me.textField;
397             }
398         } else {
399             me.textArea.hide();
400             me.textField.hide();
401         }
402
403         // Hide or show the progress bar
404         if (cfg.progress || cfg.wait) {
405             me.progressBar.show();
406             me.updateProgress(0, cfg.progressText);
407             if(cfg.wait === true){
408                 me.progressBar.wait(cfg.waitConfig);
409             }
410         } else {
411             me.progressBar.hide();
412         }
413
414         // Hide or show buttons depending on flag value sent.
415         for (i = 0; i < 4; i++) {
416             if (buttons & Math.pow(2, i)) {
417
418                 // Default to focus on the first visible button if focus not already set
419                 if (!me.defaultFocus) {
420                     me.defaultFocus = me.msgButtons[i];
421                 }
422                 me.msgButtons[i].show();
423                 hideToolbar = false;
424             } else {
425                 me.msgButtons[i].hide();
426             }
427         }
428
429         // Hide toolbar if no buttons to show
430         if (hideToolbar) {
431             me.bottomTb.hide();
432         } else {
433             me.bottomTb.show();
434         }
435     },
436
437     /**
438      * Displays a new message box, or reinitializes an existing message box, based on the config options
439      * passed in. All display functions (e.g. prompt, alert, etc.) on MessageBox call this function internally,
440      * although those calls are basic shortcuts and do not support all of the config options allowed here.
441      * @param {Object} config The following config options are supported: <ul>
442      * <li><b>animateTarget</b> : String/Element<div class="sub-desc">An id or Element from which the message box should animate as it
443      * opens and closes (defaults to undefined)</div></li>
444      * <li><b>buttons</b> : Number<div class="sub-desc">A bitwise button specifier consisting of the sum of any of the following constants:<ul>
445      * <li>Ext.window.MessageBox.OK</li>
446      * <li>Ext.window.MessageBox.YES</li>
447      * <li>Ext.window.MessageBox.NO</li>
448      * <li>Ext.window.MessageBox.CANCEL</li>
449      * </ul>Or false to not show any buttons (defaults to false)</div></li>
450      * <li><b>closable</b> : Boolean<div class="sub-desc">False to hide the top-right close button (defaults to true). Note that
451      * progress and wait dialogs will ignore this property and always hide the close button as they can only
452      * be closed programmatically.</div></li>
453      * <li><b>cls</b> : String<div class="sub-desc">A custom CSS class to apply to the message box's container element</div></li>
454      * <li><b>defaultTextHeight</b> : Number<div class="sub-desc">The default height in pixels of the message box's multiline textarea
455      * if displayed (defaults to 75)</div></li>
456      * <li><b>fn</b> : Function<div class="sub-desc">A callback function which is called when the dialog is dismissed either
457      * by clicking on the configured buttons, or on the dialog close button, or by pressing
458      * the return button to enter input.
459      * <p>Progress and wait dialogs will ignore this option since they do not respond to user
460      * actions and can only be closed programmatically, so any required function should be called
461      * by the same code after it closes the dialog. Parameters passed:<ul>
462      * <li><b>buttonId</b> : String<div class="sub-desc">The ID of the button pressed, one of:<div class="sub-desc"><ul>
463      * <li><tt>ok</tt></li>
464      * <li><tt>yes</tt></li>
465      * <li><tt>no</tt></li>
466      * <li><tt>cancel</tt></li>
467      * </ul></div></div></li>
468      * <li><b>text</b> : String<div class="sub-desc">Value of the input field if either <tt><a href="#show-option-prompt" ext:member="show-option-prompt" ext:cls="Ext.window.MessageBox">prompt</a></tt>
469      * or <tt><a href="#show-option-multiline" ext:member="show-option-multiline" ext:cls="Ext.window.MessageBox">multiline</a></tt> is true</div></li>
470      * <li><b>opt</b> : Object<div class="sub-desc">The config object passed to show.</div></li>
471      * </ul></p></div></li>
472      * <li><b>scope</b> : Object<div class="sub-desc">The scope (<code>this</code> reference) in which the function will be executed.</div></li>
473      * <li><b>icon</b> : String<div class="sub-desc">A CSS class that provides a background image to be used as the body icon for the
474      * dialog (e.g. Ext.window.MessageBox.WARNING or 'custom-class') (defaults to '')</div></li>
475      * <li><b>iconCls</b> : String<div class="sub-desc">The standard {@link Ext.window.Window#iconCls} to
476      * add an optional header icon (defaults to '')</div></li>
477      * <li><b>maxWidth</b> : Number<div class="sub-desc">The maximum width in pixels of the message box (defaults to 600)</div></li>
478      * <li><b>minWidth</b> : Number<div class="sub-desc">The minimum width in pixels of the message box (defaults to 100)</div></li>
479      * <li><b>modal</b> : Boolean<div class="sub-desc">False to allow user interaction with the page while the message box is
480      * displayed (defaults to true)</div></li>
481      * <li><b>msg</b> : String<div class="sub-desc">A string that will replace the existing message box body text (defaults to the
482      * XHTML-compliant non-breaking space character '&amp;#160;')</div></li>
483      * <li><a id="show-option-multiline"></a><b>multiline</b> : Boolean<div class="sub-desc">
484      * True to prompt the user to enter multi-line text (defaults to false)</div></li>
485      * <li><b>progress</b> : Boolean<div class="sub-desc">True to display a progress bar (defaults to false)</div></li>
486      * <li><b>progressText</b> : String<div class="sub-desc">The text to display inside the progress bar if progress = true (defaults to '')</div></li>
487      * <li><a id="show-option-prompt"></a><b>prompt</b> : Boolean<div class="sub-desc">True to prompt the user to enter single-line text (defaults to false)</div></li>
488      * <li><b>proxyDrag</b> : Boolean<div class="sub-desc">True to display a lightweight proxy while dragging (defaults to false)</div></li>
489      * <li><b>title</b> : String<div class="sub-desc">The title text</div></li>
490      * <li><b>value</b> : String<div class="sub-desc">The string value to set into the active textbox element if displayed</div></li>
491      * <li><b>wait</b> : Boolean<div class="sub-desc">True to display a progress bar (defaults to false)</div></li>
492      * <li><b>waitConfig</b> : Object<div class="sub-desc">A {@link Ext.ProgressBar#wait} config object (applies only if wait = true)</div></li>
493      * <li><b>width</b> : Number<div class="sub-desc">The width of the dialog in pixels</div></li>
494      * </ul>
495      * Example usage:
496      * <pre><code>
497 Ext.Msg.show({
498 title: 'Address',
499 msg: 'Please enter your address:',
500 width: 300,
501 buttons: Ext.Msg.OKCANCEL,
502 multiline: true,
503 fn: saveAddress,
504 animateTarget: 'addAddressBtn',
505 icon: Ext.window.MessageBox.INFO
506 });
507 </code></pre>
508      * @return {Ext.window.MessageBox} this
509      */
510     show: function(cfg) {
511         var me = this;
512
513         me.reconfigure(cfg);
514         me.addCls(cfg.cls);
515         if (cfg.animateTarget) {
516             me.doAutoSize(true);
517             me.callParent();
518         } else {
519             me.callParent();
520             me.doAutoSize(true);
521         }
522         return me;
523     },
524
525     afterShow: function(){
526         if (this.animateTarget) {
527             this.center();
528         }
529         this.callParent(arguments);
530     },
531
532     doAutoSize: function(center) {
533         var me = this,
534             icon = me.iconComponent,
535             iconHeight = me.iconHeight;
536
537         if (!Ext.isDefined(me.frameWidth)) {
538             me.frameWidth = me.el.getWidth() - me.body.getWidth();
539         }
540
541         // reset to the original dimensions
542         icon.setHeight(iconHeight);
543
544         // Allow per-invocation override of minWidth
545         me.minWidth = me.cfg.minWidth || Ext.getClass(this).prototype.minWidth;
546
547         // Set best possible size based upon allowing the text to wrap in the maximized Window, and
548         // then constraining it to within the max with. Then adding up constituent element heights.
549         me.topContainer.doLayout();
550         if (Ext.isIE6 || Ext.isIEQuirks) {
551             // In IE quirks, the initial full width of the prompt fields will prevent the container element
552             // from collapsing once sized down, so temporarily force them to a small width. They'll get
553             // layed out to their final width later when setting the final window size.
554             me.textField.setCalculatedSize(9);
555             me.textArea.setCalculatedSize(9);
556         }
557         var width = me.cfg.width || me.msg.getWidth() + icon.getWidth() + 25, /* topContainer's layout padding */
558             height = (me.header.rendered ? me.header.getHeight() : 0) +
559             Math.max(me.promptContainer.getHeight(), icon.getHeight()) +
560             me.progressBar.getHeight() +
561             (me.bottomTb.rendered ? me.bottomTb.getHeight() : 0) + 20 ;/* topContainer's layout padding */
562
563         // Update to the size of the content, this way the text won't wrap under the icon.
564         icon.setHeight(Math.max(iconHeight, me.msg.getHeight()));
565         me.setSize(width + me.frameWidth, height + me.frameWidth);
566         if (center) {
567             me.center();
568         }
569         return me;
570     },
571
572     updateText: function(text) {
573         this.msg.update(text);
574         return this.doAutoSize(true);
575     },
576
577     /**
578      * Adds the specified icon to the dialog.  By default, the class 'ext-mb-icon' is applied for default
579      * styling, and the class passed in is expected to supply the background image url. Pass in empty string ('')
580      * to clear any existing icon. This method must be called before the MessageBox is shown.
581      * The following built-in icon classes are supported, but you can also pass in a custom class name:
582      * <pre>
583 Ext.window.MessageBox.INFO
584 Ext.window.MessageBox.WARNING
585 Ext.window.MessageBox.QUESTION
586 Ext.window.MessageBox.ERROR
587      *</pre>
588      * @param {String} icon A CSS classname specifying the icon's background image url, or empty string to clear the icon
589      * @return {Ext.window.MessageBox} this
590      */
591     setIcon : function(icon) {
592         var me = this;
593         me.iconComponent.removeCls(me.iconCls);
594         if (icon) {
595             me.iconComponent.show();
596             me.iconComponent.addCls(Ext.baseCSSPrefix + 'dlg-icon');
597             me.iconComponent.addCls(me.iconCls = icon);
598         } else {
599             me.iconComponent.removeCls(Ext.baseCSSPrefix + 'dlg-icon');
600             me.iconComponent.hide();
601         }
602         return me;
603     },
604
605     /**
606      * Updates a progress-style message box's text and progress bar. Only relevant on message boxes
607      * initiated via {@link Ext.window.MessageBox#progress} or {@link Ext.window.MessageBox#wait},
608      * or by calling {@link Ext.window.MessageBox#show} with progress: true.
609      * @param {Number} [value=0] Any number between 0 and 1 (e.g., .5)
610      * @param {String} [progressText=''] The progress text to display inside the progress bar.
611      * @param {String} [msg] The message box's body text is replaced with the specified string (defaults to undefined
612      * so that any existing body text will not get overwritten by default unless a new value is passed in)
613      * @return {Ext.window.MessageBox} this
614      */
615     updateProgress : function(value, progressText, msg){
616         this.progressBar.updateProgress(value, progressText);
617         if (msg){
618             this.updateText(msg);
619         }
620         return this;
621     },
622
623     onEsc: function() {
624         if (this.closable !== false) {
625             this.callParent(arguments);
626         }
627     },
628
629     /**
630      * Displays a confirmation message box with Yes and No buttons (comparable to JavaScript's confirm).
631      * If a callback function is passed it will be called after the user clicks either button,
632      * and the id of the button that was clicked will be passed as the only parameter to the callback
633      * (could also be the top-right close button).
634      * @param {String} title The title bar text
635      * @param {String} msg The message box body text
636      * @param {Function} fn (optional) The callback function invoked after the message box is closed
637      * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to the browser wnidow.
638      * @return {Ext.window.MessageBox} this
639      */
640     confirm: function(cfg, msg, fn, scope) {
641         if (Ext.isString(cfg)) {
642             cfg = {
643                 title: cfg,
644                 icon: 'ext-mb-question',
645                 msg: msg,
646                 buttons: this.YESNO,
647                 callback: fn,
648                 scope: scope
649             };
650         }
651         return this.show(cfg);
652     },
653
654     /**
655      * Displays a message box with OK and Cancel buttons prompting the user to enter some text (comparable to JavaScript's prompt).
656      * The prompt can be a single-line or multi-line textbox.  If a callback function is passed it will be called after the user
657      * clicks either button, and the id of the button that was clicked (could also be the top-right
658      * close button) and the text that was entered will be passed as the two parameters to the callback.
659      * @param {String} title The title bar text
660      * @param {String} msg The message box body text
661      * @param {Function} [fn] The callback function invoked after the message box is closed
662      * @param {Object} [scope] The scope (<code>this</code> reference) in which the callback is executed. Defaults to the browser wnidow.
663      * @param {Boolean/Number} [multiline=false] True to create a multiline textbox using the defaultTextHeight
664      * property, or the height in pixels to create the textbox/
665      * @param {String} [value=''] Default value of the text input element
666      * @return {Ext.window.MessageBox} this
667      */
668     prompt : function(cfg, msg, fn, scope, multiline, value){
669         if (Ext.isString(cfg)) {
670             cfg = {
671                 prompt: true,
672                 title: cfg,
673                 minWidth: this.minPromptWidth,
674                 msg: msg,
675                 buttons: this.OKCANCEL,
676                 callback: fn,
677                 scope: scope,
678                 multiline: multiline,
679                 value: value
680             };
681         }
682         return this.show(cfg);
683     },
684
685     /**
686      * Displays a message box with an infinitely auto-updating progress bar.  This can be used to block user
687      * interaction while waiting for a long-running process to complete that does not have defined intervals.
688      * You are responsible for closing the message box when the process is complete.
689      * @param {String} msg The message box body text
690      * @param {String} title (optional) The title bar text
691      * @param {Object} config (optional) A {@link Ext.ProgressBar#wait} config object
692      * @return {Ext.window.MessageBox} this
693      */
694     wait : function(cfg, title, config){
695         if (Ext.isString(cfg)) {
696             cfg = {
697                 title : title,
698                 msg : cfg,
699                 closable: false,
700                 wait: true,
701                 modal: true,
702                 minWidth: this.minProgressWidth,
703                 waitConfig: config
704             };
705         }
706         return this.show(cfg);
707     },
708
709     /**
710      * Displays a standard read-only message box with an OK button (comparable to the basic JavaScript alert prompt).
711      * If a callback function is passed it will be called after the user clicks the button, and the
712      * id of the button that was clicked will be passed as the only parameter to the callback
713      * (could also be the top-right close button).
714      * @param {String} title The title bar text
715      * @param {String} msg The message box body text
716      * @param {Function} fn (optional) The callback function invoked after the message box is closed
717      * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to the browser wnidow.
718      * @return {Ext.window.MessageBox} this
719      */
720     alert: function(cfg, msg, fn, scope) {
721         if (Ext.isString(cfg)) {
722             cfg = {
723                 title : cfg,
724                 msg : msg,
725                 buttons: this.OK,
726                 fn: fn,
727                 scope : scope,
728                 minWidth: this.minWidth
729             };
730         }
731         return this.show(cfg);
732     },
733
734     /**
735      * Displays a message box with a progress bar.  This message box has no buttons and is not closeable by
736      * the user.  You are responsible for updating the progress bar as needed via {@link Ext.window.MessageBox#updateProgress}
737      * and closing the message box when the process is complete.
738      * @param {String} title The title bar text
739      * @param {String} msg The message box body text
740      * @param {String} [progressText=''] The text to display inside the progress bar
741      * @return {Ext.window.MessageBox} this
742      */
743     progress : function(cfg, msg, progressText){
744         if (Ext.isString(cfg)) {
745             cfg = {
746                 title: cfg,
747                 msg: msg,
748                 progress: true,
749                 progressText: progressText
750             };
751         }
752         return this.show(cfg);
753     }
754 }, function() {
755     /**
756      * @class Ext.MessageBox
757      * @alternateClassName Ext.Msg
758      * @extends Ext.window.MessageBox
759      * @singleton
760      * Singleton instance of {@link Ext.window.MessageBox}.
761      */
762     Ext.MessageBox = Ext.Msg = new this();
763 });