3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
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.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * @class Ext.window.MessageBox
17 * @extends Ext.window.Window
19 Utility class for generating different styles of message boxes. The singleton instance, `Ext.Msg` can also be used.
20 Note that a MessageBox is asynchronous. Unlike a regular JavaScript `alert` (which will halt
21 browser execution), showing a MessageBox will not cause the code to stop. For this reason, if you have code
22 that should only run *after* some user feedback from the MessageBox, you must use a callback function
23 (see the `function` parameter for {@link #show} for more details).
25 {@img Ext.window.MessageBox/messagebox1.png alert MessageBox}
26 {@img Ext.window.MessageBox/messagebox2.png prompt MessageBox}
27 {@img Ext.window.MessageBox/messagebox3.png show MessageBox}
31 Ext.Msg.alert('Status', 'Changes saved successfully.');
33 // Prompt for user data and process the result using a callback:
34 Ext.Msg.prompt('Name', 'Please enter your name:', function(btn, text){
36 // process text value and close...
40 // Show a dialog using config options:
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,
46 animateTarget: 'elId',
47 icon: Ext.window.MessageBox.QUESTION
53 Ext.define('Ext.window.MessageBox', {
54 extend: 'Ext.window.Window',
57 'Ext.toolbar.Toolbar',
58 'Ext.form.field.Text',
59 'Ext.form.field.TextArea',
61 'Ext.layout.container.Anchor',
62 'Ext.layout.container.HBox',
66 alternateClassName: 'Ext.MessageBox',
68 alias: 'widget.messagebox',
71 * Button config that displays a single OK button
76 * Button config that displays a single Yes button
81 * Button config that displays a single No button
86 * Button config that displays a single Cancel button
91 * Button config that displays OK and Cancel buttons
96 * Button config that displays Yes and No buttons
101 * Button config that displays Yes, No and Cancel buttons
106 * The CSS class that provides the INFO icon image
109 INFO : 'ext-mb-info',
111 * The CSS class that provides the WARNING icon image
114 WARNING : 'ext-mb-warning',
116 * The CSS class that provides the QUESTION icon image
119 QUESTION : 'ext-mb-question',
121 * The CSS class that provides the ERROR icon image
124 ERROR : 'ext-mb-error',
126 // hide it by offsets. Windows are hidden on render by default.
140 cls: Ext.baseCSSPrefix + 'message-box',
147 * The default height in pixels of the message box's multiline textarea if displayed (defaults to 75)
150 defaultTextHeight : 75,
152 * The minimum width in pixels of the message box if it is a progress-style dialog. This is useful
153 * for setting a different minimum width than text-only dialogs may need (defaults to 250).
156 minProgressWidth : 250,
158 * The minimum width in pixels of the message box if it is a prompt dialog. This is useful
159 * for setting a different minimum width than text-only dialogs may need (defaults to 250).
164 * An object containing the default button text strings that can be overriden for localized language support.
165 * Supported properties are: ok, cancel, yes and no. Generally you should include a locale-specific
166 * resource file for handling language support across the framework.
167 * Customize the default text like so: Ext.window.MessageBox.buttonText.yes = "oui"; //french
178 'ok', 'yes', 'no', 'cancel'
190 makeButton: function(btnIdx) {
191 var btnId = this.buttonIds[btnIdx];
192 return Ext.create('Ext.button.Button', {
193 handler: this.btnCallback,
196 text: this.buttonText[btnId],
201 btnCallback: function(btn) {
206 if (me.cfg.prompt || me.cfg.multiline) {
207 if (me.cfg.multiline) {
210 field = me.textField;
212 value = field.getValue();
216 // Important not to have focus remain in the hidden Window; Interferes with DnD.
219 me.userCallback(btn.itemId, value, me.cfg);
225 me.progressBar.reset();
226 me.removeCls(me.cfg.cls);
230 initComponent: function() {
236 me.topContainer = Ext.create('Ext.container.Container', {
243 me.iconComponent = Ext.create('Ext.Component', {
246 height: me.iconHeight,
251 me.promptContainer = Ext.create('Ext.container.Container', {
256 me.msg = Ext.create('Ext.Component', {
257 autoEl: { tag: 'span' },
260 me.textField = Ext.create('Ext.form.field.Text', {
262 enableKeyEvents: true,
264 keydown: me.onPromptKey,
268 me.textArea = Ext.create('Ext.form.field.TextArea', {
276 me.progressBar = Ext.create('Ext.ProgressBar', {
278 style: 'margin-left:10px'
281 me.items = [me.topContainer, me.progressBar];
283 // Create the buttons based upon passed bitwise config
285 for (i = 0; i < 4; i++) {
286 button = me.makeButton(i);
287 me.msgButtons[button.itemId] = button;
288 me.msgButtons.push(button);
290 me.bottomTb = Ext.create('Ext.toolbar.Toolbar', {
303 me.dockedItems = [me.bottomTb];
308 onPromptKey: function(textField, e) {
312 if (e.keyCode === Ext.EventObject.RETURN || e.keyCode === 10) {
313 if (me.msgButtons.ok.isVisible()) {
315 me.msgButtons.ok.handler.call(me, me.msgButtons.ok);
316 } else if (me.msgButtons.yes.isVisible()) {
317 me.msgButtons.yes.handler.call(me, me.msgButtons.yes);
327 reconfigure: function(cfg) {
329 buttons = cfg.buttons || 0,
331 initialWidth = me.maxWidth,
337 initialWidth = cfg.width;
340 // Default to allowing the Window to take focus.
341 delete me.defaultFocus;
343 // clear any old animateTarget
344 me.animateTarget = cfg.animateTarget || undefined;
347 me.modal = cfg.modal !== false;
351 me.setTitle(cfg.title||' ');
355 me.width = initialWidth;
356 me.render(Ext.getBody());
359 me.setSize(initialWidth, me.maxHeight);
361 me.setPosition(-10000, -10000);
363 // Hide or show the close tool
364 me.closable = cfg.closable && !cfg.wait;
365 if (cfg.closable === false) {
366 me.tools.close.hide();
368 me.tools.close.show();
371 // Hide or show the header
372 if (!cfg.title && !me.closable) {
378 // Default to dynamic drag: drag the window, not a ghost
379 me.liveDrag = !cfg.proxyDrag;
381 // wrap the user callback
382 me.userCallback = Ext.Function.bind(cfg.callback ||cfg.fn || Ext.emptyFn, cfg.scope || Ext.global);
384 // Hide or show the icon Component
385 me.setIcon(cfg.icon);
387 // Hide or show the message area
389 me.msg.update(cfg.msg);
395 // Hide or show the input field
396 if (cfg.prompt || cfg.multiline) {
397 me.multiline = cfg.multiline;
399 me.textArea.setValue(cfg.value);
400 me.textArea.setHeight(cfg.defaultTextHeight || me.defaultTextHeight);
403 me.defaultFocus = me.textArea;
405 me.textField.setValue(cfg.value);
408 me.defaultFocus = me.textField;
415 // Hide or show the progress bar
416 if (cfg.progress || cfg.wait) {
417 me.progressBar.show();
418 me.updateProgress(0, cfg.progressText);
419 if(cfg.wait === true){
420 me.progressBar.wait(cfg.waitConfig);
423 me.progressBar.hide();
426 // Hide or show buttons depending on flag value sent.
427 for (i = 0; i < 4; i++) {
428 if (buttons & Math.pow(2, i)) {
430 // Default to focus on the first visible button if focus not already set
431 if (!me.defaultFocus) {
432 me.defaultFocus = me.msgButtons[i];
434 me.msgButtons[i].show();
437 me.msgButtons[i].hide();
441 // Hide toolbar if no buttons to show
451 * Displays a new message box, or reinitializes an existing message box, based on the config options
452 * passed in. All display functions (e.g. prompt, alert, etc.) on MessageBox call this function internally,
453 * although those calls are basic shortcuts and do not support all of the config options allowed here.
454 * @param {Object} config The following config options are supported: <ul>
455 * <li><b>animateTarget</b> : String/Element<div class="sub-desc">An id or Element from which the message box should animate as it
456 * opens and closes (defaults to undefined)</div></li>
457 * <li><b>buttons</b> : Number<div class="sub-desc">A bitwise button specifier consisting of the sum of any of the following constants:<ul>
458 * <li>Ext.window.MessageBox.OK</li>
459 * <li>Ext.window.MessageBox.YES</li>
460 * <li>Ext.window.MessageBox.NO</li>
461 * <li>Ext.window.MessageBox.CANCEL</li>
462 * </ul>Or false to not show any buttons (defaults to false)</div></li>
463 * <li><b>closable</b> : Boolean<div class="sub-desc">False to hide the top-right close button (defaults to true). Note that
464 * progress and wait dialogs will ignore this property and always hide the close button as they can only
465 * be closed programmatically.</div></li>
466 * <li><b>cls</b> : String<div class="sub-desc">A custom CSS class to apply to the message box's container element</div></li>
467 * <li><b>defaultTextHeight</b> : Number<div class="sub-desc">The default height in pixels of the message box's multiline textarea
468 * if displayed (defaults to 75)</div></li>
469 * <li><b>fn</b> : Function<div class="sub-desc">A callback function which is called when the dialog is dismissed either
470 * by clicking on the configured buttons, or on the dialog close button, or by pressing
471 * the return button to enter input.
472 * <p>Progress and wait dialogs will ignore this option since they do not respond to user
473 * actions and can only be closed programmatically, so any required function should be called
474 * by the same code after it closes the dialog. Parameters passed:<ul>
475 * <li><b>buttonId</b> : String<div class="sub-desc">The ID of the button pressed, one of:<div class="sub-desc"><ul>
476 * <li><tt>ok</tt></li>
477 * <li><tt>yes</tt></li>
478 * <li><tt>no</tt></li>
479 * <li><tt>cancel</tt></li>
480 * </ul></div></div></li>
481 * <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>
482 * or <tt><a href="#show-option-multiline" ext:member="show-option-multiline" ext:cls="Ext.window.MessageBox">multiline</a></tt> is true</div></li>
483 * <li><b>opt</b> : Object<div class="sub-desc">The config object passed to show.</div></li>
484 * </ul></p></div></li>
485 * <li><b>scope</b> : Object<div class="sub-desc">The scope (<code>this</code> reference) in which the function will be executed.</div></li>
486 * <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
487 * dialog (e.g. Ext.window.MessageBox.WARNING or 'custom-class') (defaults to '')</div></li>
488 * <li><b>iconCls</b> : String<div class="sub-desc">The standard {@link Ext.window.Window#iconCls} to
489 * add an optional header icon (defaults to '')</div></li>
490 * <li><b>maxWidth</b> : Number<div class="sub-desc">The maximum width in pixels of the message box (defaults to 600)</div></li>
491 * <li><b>minWidth</b> : Number<div class="sub-desc">The minimum width in pixels of the message box (defaults to 100)</div></li>
492 * <li><b>modal</b> : Boolean<div class="sub-desc">False to allow user interaction with the page while the message box is
493 * displayed (defaults to true)</div></li>
494 * <li><b>msg</b> : String<div class="sub-desc">A string that will replace the existing message box body text (defaults to the
495 * XHTML-compliant non-breaking space character '&#160;')</div></li>
496 * <li><a id="show-option-multiline"></a><b>multiline</b> : Boolean<div class="sub-desc">
497 * True to prompt the user to enter multi-line text (defaults to false)</div></li>
498 * <li><b>progress</b> : Boolean<div class="sub-desc">True to display a progress bar (defaults to false)</div></li>
499 * <li><b>progressText</b> : String<div class="sub-desc">The text to display inside the progress bar if progress = true (defaults to '')</div></li>
500 * <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>
501 * <li><b>proxyDrag</b> : Boolean<div class="sub-desc">True to display a lightweight proxy while dragging (defaults to false)</div></li>
502 * <li><b>title</b> : String<div class="sub-desc">The title text</div></li>
503 * <li><b>value</b> : String<div class="sub-desc">The string value to set into the active textbox element if displayed</div></li>
504 * <li><b>wait</b> : Boolean<div class="sub-desc">True to display a progress bar (defaults to false)</div></li>
505 * <li><b>waitConfig</b> : Object<div class="sub-desc">A {@link Ext.ProgressBar#waitConfig} object (applies only if wait = true)</div></li>
506 * <li><b>width</b> : Number<div class="sub-desc">The width of the dialog in pixels</div></li>
512 msg: 'Please enter your address:',
514 buttons: Ext.window.MessageBox.OKCANCEL,
517 animateTarget: 'addAddressBtn',
518 icon: Ext.window.MessageBox.INFO
521 * @return {Ext.window.MessageBox} this
523 show: function(cfg) {
528 if (cfg.animateTarget) {
529 me.doAutoSize(false);
538 afterShow: function(){
539 if (this.animateTarget) {
542 this.callParent(arguments);
545 doAutoSize: function(center) {
547 icon = me.iconComponent,
548 iconHeight = me.iconHeight;
550 if (!Ext.isDefined(me.frameWidth)) {
551 me.frameWidth = me.el.getWidth() - me.body.getWidth();
554 // reset to the original dimensions
555 icon.setHeight(iconHeight);
557 // Allow per-invocation override of minWidth
558 me.minWidth = me.cfg.minWidth || Ext.getClass(this).prototype.minWidth;
560 // Set best possible size based upon allowing the text to wrap in the maximized Window, and
561 // then constraining it to within the max with. Then adding up constituent element heights.
562 me.topContainer.doLayout();
563 if (Ext.isIE6 || Ext.isIEQuirks) {
564 // In IE quirks, the initial full width of the prompt fields will prevent the container element
565 // from collapsing once sized down, so temporarily force them to a small width. They'll get
566 // layed out to their final width later when setting the final window size.
567 me.textField.setCalculatedSize(9);
568 me.textArea.setCalculatedSize(9);
570 var width = me.cfg.width || me.msg.getWidth() + icon.getWidth() + 25, /* topContainer's layout padding */
571 height = (me.header.rendered ? me.header.getHeight() : 0) +
572 Math.max(me.promptContainer.getHeight(), icon.getHeight()) +
573 me.progressBar.getHeight() +
574 (me.bottomTb.rendered ? me.bottomTb.getHeight() : 0) + 20 ;/* topContainer's layout padding */
576 // Update to the size of the content, this way the text won't wrap under the icon.
577 icon.setHeight(Math.max(iconHeight, me.msg.getHeight()));
578 me.setSize(width + me.frameWidth, height + me.frameWidth);
585 updateText: function(text) {
586 this.msg.update(text);
587 return this.doAutoSize(true);
591 * Adds the specified icon to the dialog. By default, the class 'ext-mb-icon' is applied for default
592 * styling, and the class passed in is expected to supply the background image url. Pass in empty string ('')
593 * to clear any existing icon. This method must be called before the MessageBox is shown.
594 * The following built-in icon classes are supported, but you can also pass in a custom class name:
596 Ext.window.MessageBox.INFO
597 Ext.window.MessageBox.WARNING
598 Ext.window.MessageBox.QUESTION
599 Ext.window.MessageBox.ERROR
601 * @param {String} icon A CSS classname specifying the icon's background image url, or empty string to clear the icon
602 * @return {Ext.window.MessageBox} this
604 setIcon : function(icon) {
606 me.iconComponent.removeCls(me.iconCls);
608 me.iconComponent.show();
609 me.iconComponent.addCls(Ext.baseCSSPrefix + 'dlg-icon');
610 me.iconComponent.addCls(me.iconCls = icon);
612 me.iconComponent.removeCls(Ext.baseCSSPrefix + 'dlg-icon');
613 me.iconComponent.hide();
619 * Updates a progress-style message box's text and progress bar. Only relevant on message boxes
620 * initiated via {@link Ext.window.MessageBox#progress} or {@link Ext.window.MessageBox#wait},
621 * or by calling {@link Ext.window.MessageBox#show} with progress: true.
622 * @param {Number} value Any number between 0 and 1 (e.g., .5, defaults to 0)
623 * @param {String} progressText The progress text to display inside the progress bar (defaults to '')
624 * @param {String} msg The message box's body text is replaced with the specified string (defaults to undefined
625 * so that any existing body text will not get overwritten by default unless a new value is passed in)
626 * @return {Ext.window.MessageBox} this
628 updateProgress : function(value, progressText, msg){
629 this.progressBar.updateProgress(value, progressText);
631 this.updateText(msg);
637 if (this.closable !== false) {
638 this.callParent(arguments);
643 * Displays a confirmation message box with Yes and No buttons (comparable to JavaScript's confirm).
644 * If a callback function is passed it will be called after the user clicks either button,
645 * and the id of the button that was clicked will be passed as the only parameter to the callback
646 * (could also be the top-right close button).
647 * @param {String} title The title bar text
648 * @param {String} msg The message box body text
649 * @param {Function} fn (optional) The callback function invoked after the message box is closed
650 * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to the browser wnidow.
651 * @return {Ext.window.MessageBox} this
653 confirm: function(cfg, msg, fn, scope) {
654 if (Ext.isString(cfg)) {
657 icon: 'ext-mb-question',
664 return this.show(cfg);
668 * Displays a message box with OK and Cancel buttons prompting the user to enter some text (comparable to JavaScript's prompt).
669 * The prompt can be a single-line or multi-line textbox. If a callback function is passed it will be called after the user
670 * clicks either button, and the id of the button that was clicked (could also be the top-right
671 * close button) and the text that was entered will be passed as the two parameters to the callback.
672 * @param {String} title The title bar text
673 * @param {String} msg The message box body text
674 * @param {Function} fn (optional) The callback function invoked after the message box is closed
675 * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to the browser wnidow.
676 * @param {Boolean/Number} multiline (optional) True to create a multiline textbox using the defaultTextHeight
677 * property, or the height in pixels to create the textbox (defaults to false / single-line)
678 * @param {String} value (optional) Default value of the text input element (defaults to '')
679 * @return {Ext.window.MessageBox} this
681 prompt : function(cfg, msg, fn, scope, multiline, value){
682 if (Ext.isString(cfg)) {
686 minWidth: this.minPromptWidth,
688 buttons: this.OKCANCEL,
691 multiline: multiline,
695 return this.show(cfg);
699 * Displays a message box with an infinitely auto-updating progress bar. This can be used to block user
700 * interaction while waiting for a long-running process to complete that does not have defined intervals.
701 * You are responsible for closing the message box when the process is complete.
702 * @param {String} msg The message box body text
703 * @param {String} title (optional) The title bar text
704 * @param {Object} config (optional) A {@link Ext.ProgressBar#waitConfig} object
705 * @return {Ext.window.MessageBox} this
707 wait : function(cfg, title, config){
708 if (Ext.isString(cfg)) {
715 minWidth: this.minProgressWidth,
719 return this.show(cfg);
723 * Displays a standard read-only message box with an OK button (comparable to the basic JavaScript alert prompt).
724 * If a callback function is passed it will be called after the user clicks the button, and the
725 * id of the button that was clicked will be passed as the only parameter to the callback
726 * (could also be the top-right close button).
727 * @param {String} title The title bar text
728 * @param {String} msg The message box body text
729 * @param {Function} fn (optional) The callback function invoked after the message box is closed
730 * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to the browser wnidow.
731 * @return {Ext.window.MessageBox} this
733 alert: function(cfg, msg, fn, scope) {
734 if (Ext.isString(cfg)) {
741 minWidth: this.minWidth
744 return this.show(cfg);
748 * Displays a message box with a progress bar. This message box has no buttons and is not closeable by
749 * the user. You are responsible for updating the progress bar as needed via {@link Ext.window.MessageBox#updateProgress}
750 * and closing the message box when the process is complete.
751 * @param {String} title The title bar text
752 * @param {String} msg The message box body text
753 * @param {String} progressText (optional) The text to display inside the progress bar (defaults to '')
754 * @return {Ext.window.MessageBox} this
756 progress : function(cfg, msg, progressText){
757 if (Ext.isString(cfg)) {
761 progressText: progressText
764 return this.show(cfg);
767 Ext.MessageBox = Ext.Msg = new this();