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 * Utility class for generating different styles of message boxes. The singleton instance, Ext.MessageBox
17 * alias `Ext.Msg` can also be used.
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).
27 * Ext.Msg.alert('Status', 'Changes saved successfully.');
29 * Prompt for user data and process the result using a callback
32 * Ext.Msg.prompt('Name', 'Please enter your name:', function(btn, text){
34 * // process text value and close...
38 * 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,
45 * icon: Ext.Msg.QUESTION
48 Ext.define('Ext.window.MessageBox', {
49 extend: 'Ext.window.Window',
52 'Ext.toolbar.Toolbar',
53 'Ext.form.field.Text',
54 'Ext.form.field.TextArea',
56 'Ext.layout.container.Anchor',
57 'Ext.layout.container.HBox',
61 alias: 'widget.messagebox',
64 * Button config that displays a single OK button
69 * Button config that displays a single Yes button
74 * Button config that displays a single No button
79 * Button config that displays a single Cancel button
84 * Button config that displays OK and Cancel buttons
89 * Button config that displays Yes and No buttons
94 * Button config that displays Yes, No and Cancel buttons
99 * The CSS class that provides the INFO icon image
102 INFO : 'ext-mb-info',
104 * The CSS class that provides the WARNING icon image
107 WARNING : 'ext-mb-warning',
109 * The CSS class that provides the QUESTION icon image
112 QUESTION : 'ext-mb-question',
114 * The CSS class that provides the ERROR icon image
117 ERROR : 'ext-mb-error',
119 // hide it by offsets. Windows are hidden on render by default.
133 cls: Ext.baseCSSPrefix + 'message-box',
140 * The default height in pixels of the message box's multiline textarea if displayed.
143 defaultTextHeight : 75,
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.
149 minProgressWidth : 250,
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.
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
171 'ok', 'yes', 'no', 'cancel'
183 makeButton: function(btnIdx) {
184 var btnId = this.buttonIds[btnIdx];
185 return Ext.create('Ext.button.Button', {
186 handler: this.btnCallback,
189 text: this.buttonText[btnId],
194 btnCallback: function(btn) {
199 if (me.cfg.prompt || me.cfg.multiline) {
200 if (me.cfg.multiline) {
203 field = me.textField;
205 value = field.getValue();
209 // Important not to have focus remain in the hidden Window; Interferes with DnD.
212 me.userCallback(btn.itemId, value, me.cfg);
218 me.progressBar.reset();
219 me.removeCls(me.cfg.cls);
223 initComponent: function() {
229 me.topContainer = Ext.create('Ext.container.Container', {
236 me.iconComponent = Ext.create('Ext.Component', {
239 height: me.iconHeight,
244 me.promptContainer = Ext.create('Ext.container.Container', {
249 me.msg = Ext.create('Ext.Component', {
250 autoEl: { tag: 'span' },
253 me.textField = Ext.create('Ext.form.field.Text', {
255 enableKeyEvents: true,
257 keydown: me.onPromptKey,
261 me.textArea = Ext.create('Ext.form.field.TextArea', {
269 me.progressBar = Ext.create('Ext.ProgressBar', {
271 style: 'margin-left:10px'
274 me.items = [me.topContainer, me.progressBar];
276 // Create the buttons based upon passed bitwise config
278 for (i = 0; i < 4; i++) {
279 button = me.makeButton(i);
280 me.msgButtons[button.itemId] = button;
281 me.msgButtons.push(button);
283 me.bottomTb = Ext.create('Ext.toolbar.Toolbar', {
296 me.dockedItems = [me.bottomTb];
301 onPromptKey: function(textField, e) {
305 if (e.keyCode === Ext.EventObject.RETURN || e.keyCode === 10) {
306 if (me.msgButtons.ok.isVisible()) {
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);
320 reconfigure: function(cfg) {
322 buttons = cfg.buttons || 0,
324 initialWidth = me.maxWidth,
330 initialWidth = cfg.width;
333 // Default to allowing the Window to take focus.
334 delete me.defaultFocus;
336 // clear any old animateTarget
337 me.animateTarget = cfg.animateTarget || undefined;
340 me.modal = cfg.modal !== false;
344 me.setTitle(cfg.title||' ');
348 me.width = initialWidth;
349 me.render(Ext.getBody());
351 me.setSize(initialWidth, me.maxHeight);
353 me.setPosition(-10000, -10000);
355 // Hide or show the close tool
356 me.closable = cfg.closable && !cfg.wait;
357 me.header.child('[type=close]').setVisible(cfg.closable !== false);
359 // Hide or show the header
360 if (!cfg.title && !me.closable) {
366 // Default to dynamic drag: drag the window, not a ghost
367 me.liveDrag = !cfg.proxyDrag;
369 // wrap the user callback
370 me.userCallback = Ext.Function.bind(cfg.callback ||cfg.fn || Ext.emptyFn, cfg.scope || Ext.global);
372 // Hide or show the icon Component
373 me.setIcon(cfg.icon);
375 // Hide or show the message area
377 me.msg.update(cfg.msg);
383 // Hide or show the input field
384 if (cfg.prompt || cfg.multiline) {
385 me.multiline = cfg.multiline;
387 me.textArea.setValue(cfg.value);
388 me.textArea.setHeight(cfg.defaultTextHeight || me.defaultTextHeight);
391 me.defaultFocus = me.textArea;
393 me.textField.setValue(cfg.value);
396 me.defaultFocus = me.textField;
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);
411 me.progressBar.hide();
414 // Hide or show buttons depending on flag value sent.
415 for (i = 0; i < 4; i++) {
416 if (buttons & Math.pow(2, i)) {
418 // Default to focus on the first visible button if focus not already set
419 if (!me.defaultFocus) {
420 me.defaultFocus = me.msgButtons[i];
422 me.msgButtons[i].show();
425 me.msgButtons[i].hide();
429 // Hide toolbar if no buttons to show
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 '&#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>
499 msg: 'Please enter your address:',
501 buttons: Ext.Msg.OKCANCEL,
504 animateTarget: 'addAddressBtn',
505 icon: Ext.window.MessageBox.INFO
508 * @return {Ext.window.MessageBox} this
510 show: function(cfg) {
515 if (cfg.animateTarget) {
525 afterShow: function(){
526 if (this.animateTarget) {
529 this.callParent(arguments);
532 doAutoSize: function(center) {
534 icon = me.iconComponent,
535 iconHeight = me.iconHeight;
537 if (!Ext.isDefined(me.frameWidth)) {
538 me.frameWidth = me.el.getWidth() - me.body.getWidth();
541 // reset to the original dimensions
542 icon.setHeight(iconHeight);
544 // Allow per-invocation override of minWidth
545 me.minWidth = me.cfg.minWidth || Ext.getClass(this).prototype.minWidth;
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);
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 */
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);
572 updateText: function(text) {
573 this.msg.update(text);
574 return this.doAutoSize(true);
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:
583 Ext.window.MessageBox.INFO
584 Ext.window.MessageBox.WARNING
585 Ext.window.MessageBox.QUESTION
586 Ext.window.MessageBox.ERROR
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
591 setIcon : function(icon) {
593 me.iconComponent.removeCls(me.iconCls);
595 me.iconComponent.show();
596 me.iconComponent.addCls(Ext.baseCSSPrefix + 'dlg-icon');
597 me.iconComponent.addCls(me.iconCls = icon);
599 me.iconComponent.removeCls(Ext.baseCSSPrefix + 'dlg-icon');
600 me.iconComponent.hide();
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
615 updateProgress : function(value, progressText, msg){
616 this.progressBar.updateProgress(value, progressText);
618 this.updateText(msg);
624 if (this.closable !== false) {
625 this.callParent(arguments);
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
640 confirm: function(cfg, msg, fn, scope) {
641 if (Ext.isString(cfg)) {
644 icon: 'ext-mb-question',
651 return this.show(cfg);
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
668 prompt : function(cfg, msg, fn, scope, multiline, value){
669 if (Ext.isString(cfg)) {
673 minWidth: this.minPromptWidth,
675 buttons: this.OKCANCEL,
678 multiline: multiline,
682 return this.show(cfg);
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
694 wait : function(cfg, title, config){
695 if (Ext.isString(cfg)) {
702 minWidth: this.minProgressWidth,
706 return this.show(cfg);
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
720 alert: function(cfg, msg, fn, scope) {
721 if (Ext.isString(cfg)) {
728 minWidth: this.minWidth
731 return this.show(cfg);
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
743 progress : function(cfg, msg, progressText){
744 if (Ext.isString(cfg)) {
749 progressText: progressText
752 return this.show(cfg);
756 * @class Ext.MessageBox
757 * @alternateClassName Ext.Msg
758 * @extends Ext.window.MessageBox
760 * Singleton instance of {@link Ext.window.MessageBox}.
762 Ext.MessageBox = Ext.Msg = new this();