/**
* Utility class for generating different styles of message boxes. The framework provides a global singleton
* {@link Ext.Msg} for common usage.
*
* Note that the MessageBox is asynchronous. Unlike a regular JavaScript `alert` (which will halt browser execution),
* showing a MessageBox will not cause the code to stop. For this reason, if you have code that should only run _after_
* some user feedback from the MessageBox, you must use a callback function (see the `fn` configuration option parameter
* for the {@link #show show} method for more details).
*
* # Example usage:
*
* Basic alert:
*
* @example preview
* Ext.Msg.alert('Title', 'The quick brown fox jumped over the lazy dog.', Ext.emptyFn);
*
* Prompt for user data and process the result using a callback:
*
* @example preview
* Ext.Msg.prompt('Name', 'Please enter your name:', function(text) {
* // process text value and close...
* });
*
* Confirmation alert:
*
* @example preview
* Ext.Msg.confirm("Confirmation", "Are you sure you want to do that?", Ext.emptyFn);
*
*/
Ext.define('Ext.MessageBox', {
extend : 'Ext.Sheet',
requires: [
'Ext.Toolbar',
'Ext.field.Text',
'Ext.field.TextArea'
],
config: {
// @inherit
ui: 'dark',
// @inherit
baseCls: Ext.baseCSSPrefix + 'msgbox',
// @inherit
cls: Ext.baseCSSPrefix + 'panel',
/**
* @cfg {String} iconCls
* CSS class for the icon When null disables the icon.
* @accessor
*/
iconCls: null,
/**
* @cfg {String/Mixed} enterAnimation
* Effect when the message box is being displayed.
* @todo not implemented
*/
enterAnimation: 'pop',
/**
* @cfg {String/Mixed} exitAnimation
* Effect when the message box is being hidden.
* @todo not implemented
*/
exitAnimation: 'pop',
/**
* @cfg {Number} defaultTextHeight
* The default height in pixels of the message box's multiline textarea if displayed.
* @accessor
*/
defaultTextHeight: 75,
/**
* @cfg {String} title
* The title of this {@link Ext.MessageBox}.
* @accessor
*/
title: null,
/**
* @cfg {Array/Object} buttons
* An array of buttons, or an object of a button to be displayed in the toolbar of this {@link Ext.MessageBox}.
*/
buttons: null,
/**
* @cfg {String} msg
* The message to be displayed in the {@link Ext.MessageBox}.
* @accessor
*/
msg: null,
/**
* @cfg {Object} promptConfig
* The configuration to be passed if you want an {@link Ext.field.Text} or {@link Ext.field.TextArea} field
* in your {@link Ext.MessageBox}.
* Pass an object with the property "multiline" with a value of true, if you want the prompt to use a TextArea.
* @accessor
*/
promptConfig: null,
// @inherit
layout: {
type: 'vbox',
pack: 'center'
}
},
statics: {
OK : {text: 'OK', itemId: 'ok', ui: 'action'},
YES : {text: 'Yes', itemId: 'yes', ui: 'action'},
NO : {text: 'No', itemId: 'no'},
CANCEL: {text: 'Cancel', itemId: 'cancel'},
INFO : Ext.baseCSSPrefix + 'msgbox-info',
WARNING : Ext.baseCSSPrefix + 'msgbox-warning',
QUESTION: Ext.baseCSSPrefix + 'msgbox-question',
ERROR : Ext.baseCSSPrefix + 'msgbox-error',
OKCANCEL: [
{text: 'Cancel', itemId: 'cancel'},
{text: 'OK', itemId: 'ok', ui : 'action'}
],
YESNOCANCEL: [
{text: 'Cancel', itemId: 'cancel'},
{text: 'No', itemId: 'no'},
{text: 'Yes', itemId: 'yes', ui: 'action'}
],
YESNO: [
{text: 'No', itemId: 'no'},
{text: 'Yes', itemId: 'yes', ui: 'action'}
]
},
// @inherit
constructor: function(config) {
config = config || {};
if (config.hasOwnProperty('prompt')) {
Ext.applyIf(config, {
promptConfig: config.prompt
});
delete config.prompt;
}
if (config.hasOwnProperty('multiline') || config.hasOwnProperty('multiLine')) {
config.promptConfig = config.promptConfig || {};
Ext.applyIf(config.promptConfig, {
multiLine: config.multiline || config.multiLine
});
delete config.multiline;
delete config.multiLine;
}
this.callParent([config]);
},
/**
* Creates a new {@link Ext.Toolbar} instance using {@link Ext.Factory}
* @private
*/
applyTitle: function(config) {
if (typeof config == "string") {
config = {
title: config
};
}
Ext.applyIf(config, {
docked: 'top',
cls : this.getBaseCls() + '-title'
});
return Ext.factory(config, Ext.Toolbar, this.getTitle());
},
/**
* Adds the new {@link Ext.Toolbar} instance into this container
* @private
*/
updateTitle: function(newTitle) {
if (newTitle) {
this.add(newTitle);
}
},
/**
* Adds the new {@link Ext.Toolbar} instance into this container
* @private
*/
updateButtons: function(newButtons) {
var me = this;
if (newButtons) {
if (me.buttonsToolbar) {
me.buttonsToolbar.removeAll();
me.buttonsToolbar.setItems(newButtons);
} else {
me.buttonsToolbar = Ext.create('Ext.Toolbar', {
docked : 'bottom',
defaultType: 'button',
layout : {
type: 'hbox',
pack: 'center'
},
ui : me.getUi(),
cls : me.getBaseCls() + '-buttons',
items : newButtons
});
me.add(me.buttonsToolbar);
}
}
},
/**
* @private
*/
applyMsg: function(config) {
config = {
html : config,
cls : this.getBaseCls() + '-text'
};
return Ext.factory(config, Ext.Component, this.getMsg());
},
/**
* @private
*/
updateMsg: function(newMsg) {
if (newMsg) {
this.add(newMsg);
}
},
/**
* @private
*/
updateIconCls: function(newIconCls, oldIconCls) {
if (newIconCls) {
var cfg = {
xtype : 'component',
docked: 'left',
width : 40,
height: 40,
cls : newIconCls
};
// this.add(cfg);
}
},
/**
* @private
*/
applyPromptConfig: function(prompt) {
if (prompt) {
var config = {
label: false
};
if (typeof prompt == "object") {
Ext.apply(config, prompt);
}
if (config.multiLine) {
config.height = Ext.isNumber(config.multiLine) ? parseFloat(config.multiLine) : this.getDefaultTextHeight();
return Ext.factory(config, Ext.field.TextArea, this.getPromptConfig());
} else {
return Ext.factory(config, Ext.field.Text, this.getPromptConfig());
}
}
return prompt;
},
/**
* @private
*/
updatePromptConfig: function(newPrompt, oldPrompt) {
if (newPrompt) {
this.add(newPrompt);
}
if (oldPrompt) {
this.remove(oldPrompt);
}
},
// @private
// pass `fn` config to show method instead
onClick: function(button) {
if (button) {
var config = button.userConfig || {};
if (typeof config.fn == 'function') {
config.fn.call(
config.scope || null,
button.itemId || button.text,
config.input ? config.input.dom.value : null,
config
);
}
if (config.cls) {
this.el.removeCls(config.cls);
}
if (config.input) {
config.input.dom.blur();
}
}
this.hide();
},
/**
* Displays a new message box, or reinitializes an existing message box, based on the config options passed in. All
* display functions (e.g. prompt, alert, etc.) on MessageBox call this function internally, although those calls
* are basic shortcuts and do not support all of the config options allowed here.
*
* Example usage:
*
* Ext.Msg.show({
* title: 'Address',
* msg: 'Please enter your address:',
* width: 300,
* buttons: Ext.MessageBox.OKCANCEL,
* multiLine: true,
* prompt : { maxlength : 180, autocapitalize : true },
* fn: saveAddress,
* iconCls: Ext.MessageBox.INFO
* });
*
* @param {Object} config An object with the following config options:
*
* @param {Object/Array} [config.buttons=false]
* A button config object or Array of the same(e.g., `Ext.MessageBox.OKCANCEL` or `{text:'Foo', itemId:'cancel'}`),
* or false to not show any buttons.
*
* @param {String} config.cls
* A custom CSS class to apply to the message box's container element.
*
* @param {Number} [config.defaultTextHeight=75]
* The default height in pixels of the message box's multiline textarea if displayed.
*
* @param {Function} config.fn
* A callback function which is called when the dialog is dismissed by clicking on the configured buttons.
* @param {String} config.fn.buttonId The itemId of the button pressed, one of: 'ok', 'yes', 'no', 'cancel'.
* @param {String} config.fn.value Value of the input field if either `prompt` or `multiline` option is true.
* @param {Object} config.fn.opt The config object passed to show.
*
* @param {Number} [config.width='auto']
* A fixed width for the MessageBox.
*
* @param {Number} [config.height='auto']
* A fixed height for the MessageBox.
*
* @param {Object} config.scope
* The scope of the callback function
*
* @param {String} [config.icon='']
* A CSS class that provides a background image to be used as the body icon for the dialog
* (e.g. Ext.MessageBox.WARNING or 'custom-class').
*
* @param {Boolean} [config.modal=true]
* False to allow user interaction with the page while the message box is displayed.
*
* @param {String} config.msg
* A string that will replace the existing message box body text.
* Defaults to the XHTML-compliant non-breaking space character ` `.
*
* @param {Boolean} [config.multiline=false]
* True to prompt the user to enter multi-line text.
*
* @param {Boolean} [config.prompt=false]
* True to prompt the user to enter single-line text (defaults to false)
*
* @param {String} config.title
* The title text.
*
* @param {String} config.value
* The string value to set into the active textbox element if displayed.
*
* @return {Ext.MessageBox} this
*/
show: function(initialConfig) {
if (!initialConfig) {
return this.callParent();
}
var config = Ext.Object.merge({}, {
value: ''
}, initialConfig);
var buttons = initialConfig.buttons || Ext.MessageBox.OK || [],
buttonBarItems = [],
userConfig = initialConfig;
Ext.each(buttons, function(buttonConfig) {
if (!buttonConfig) {
return;
}
buttonBarItems.push(Ext.apply({
userConfig: userConfig,
scope : this,
handler : 'onClick'
}, buttonConfig));
}, this);
config.buttons = buttonBarItems;
this.setConfig(config);
var prompt = this.getPromptConfig();
if (prompt) {
prompt.setValue('');
}
this.callParent();
return this;
},
/**
* Displays a standard read-only message box with an OK button (comparable to the basic JavaScript alert prompt). If
* a callback function is passed it will be called after the user clicks the button, and the itemId of the button
* that was clicked will be passed as the only parameter to the callback.
*
* @param {String} title The title bar text
* @param {String} msg The message box body text
* @param {Function} fn The callback function invoked after the message box is closed
* @param {Object} [scope] The scope (`this` reference) in which the callback is executed.
* Defaults to the browser window.
* @return {Ext.MessageBox} this
*/
alert: function(title, msg, fn, scope) {
return this.show({
title : title,
msg : msg,
buttons : Ext.MessageBox.OK,
promptConfig: false,
fn : fn,
scope : scope,
iconCls : Ext.MessageBox.INFO
});
},
/**
* Displays a confirmation message box with Yes and No buttons (comparable to JavaScript's confirm). If a callback
* function is passed it will be called after the user clicks either button, and the id of the button that was
* clicked will be passed as the only parameter to the callback (could also be the top-right close button).
*
* @param {String} title The title bar text
* @param {String} msg The message box body text
* @param {Function} fn The callback function invoked when user taps on the OK/Cancel button.
* The button is passed as the first argument.
* @param {Object} [scope] The scope (`this` reference) in which the callback is executed.
* Defaults to the browser window.
* @return {Ext.MessageBox} this
*/
confirm: function(title, msg, fn, scope) {
return this.show({
title : title,
msg : msg,
buttons : Ext.MessageBox.YESNO,
promptConfig: false,
scope : scope,
iconCls : Ext.MessageBox.QUESTION,
fn: function(button) {
fn.call(scope, button);
}
});
},
/**
* Displays a message box with OK and Cancel buttons prompting the user to enter some text (comparable to
* JavaScript's prompt). The prompt can be a single-line or multi-line textbox. If a callback function is passed it
* will be called after the user clicks either button, and the id of the button that was clicked (could also be the
* top-right close button) and the text that was entered will be passed as the two parameters to the callback.
*
* Example usage:
*
* Ext.Msg.prompt(
* 'Welcome!',
* 'What\'s your name going to be today?',
* function(value){
* console.log(value)
* },
* null,
* false,
* null,
* { autocapitalize : true, placeholder : 'First-name please...' }
* );
*
* @param {String} title The title bar text
* @param {String} msg The message box body text
* @param {Function} fn The callback function invoked when the user taps on the OK/Cancel button, the button is
* passed as the first argument, the entered string value is passed as the second argument
* @param {Object} [scope] The scope (`this` reference) in which the callback is executed.
* Defaults to the browser window.
* @param {Boolean/Number} [multiLine=false] True to create a multiline textbox using the defaultTextHeight property,
* or the height in pixels to create the textbox.
* @param {String} [value=''] Default value of the text input element.
* @param {Object} [promptConfig] A hash collection of input attribute values.
*
* @param {Boolean} [promptConfig.focus=false]
* True to assert initial input focus.
*
* @param {String} [promptConfig.placeholder='']
* String value rendered when the input field is empty.
*
* @param {String/Boolean} [promptConfig.autocapitalize='off']
* True/on to capitalize the first letter of each word in the input value.
*
* @param {String/Boolean} [promptConfig.autocorrect='off']
* True/on to enable spell-checking/autocorrect features if supported by the browser.
*
* @param {String/Boolean} [promptConfig.autocomplete='off']
* True/on to enable autoCompletion of supplied text input values if supported by the browser.
*
* @param {Number} [promptConfig.maxlength=0]
* Maximum number of characters allowed in the input if supported by the browser.
*
* @param {String} [promptConfig.type='text']
* The type of input field. Possible values (if supported by the browser) may include (text, search, number, range,
* color, tel, url, email, date, month, week, time, datetime) (defaults to 'text')
*
* @return {Ext.MessageBox} this
*/
prompt: function(title, msg, fn, scope, multiLine, value, promptConfig) {
return this.show({
title : title,
msg : msg,
buttons : Ext.MessageBox.OKCANCEL,
scope : scope,
iconCls : Ext.MessageBox.QUESTION,
promptConfig: promptConfig || true,
multiLine : multiLine,
value : value,
fn: function(button, inputValue) {
fn.call(scope, button, inputValue);
}
});
}
}, function() {
// <deprecated product=touch since=2.0>
this.override({
/**
* @cfg {String} icon
* CSS class Use {@link #iconCls} instead.
*/
/**
* @param {String} icon A CSS classname or empty string to clear the icon
* @return {Ext.MessageBox} this
*/
setIcon: function(iconCls, doLayout){
//<debug warn>
Ext.Logger.deprecate("Ext.MessageBox#setIcon is deprecated, use setIconCls instead", 2);
//</debug>
this.setIconCls(iconCls);
if (doLayout) {
this.doComponentLayout();
}
return this;
}
});
// </deprecated>
/**
* @class Ext.Msg
* @singleton
*
* A global shared singleton instance of the {@link Ext.MessageBox} class. See {@link Ext.MessageBox} for
* documentation.
*/
Ext.Msg = Ext.create('Ext.MessageBox');
});