]> git.proxmox.com Git - extjs.git/blame - extjs/classic/classic/src/window/MessageBox.js
add extjs 6.0.1 sources
[extjs.git] / extjs / classic / classic / src / window / MessageBox.js
CommitLineData
6527f429
DM
1// @define Ext.MessageBox, Ext.Msg\r
2\r
3/**\r
4 * Utility class for generating different styles of message boxes. The singleton instance, Ext.MessageBox\r
5 * alias `Ext.Msg` can also be used.\r
6 *\r
7 * Note that a MessageBox is asynchronous. Unlike a regular JavaScript `alert` (which will halt\r
8 * browser execution), showing a MessageBox will not cause the code to stop. For this reason, if you have code\r
9 * that should only run *after* some user feedback from the MessageBox, you must use a callback function\r
10 * (see the `function` parameter for {@link #method-show} for more details).\r
11 *\r
12 * Basic alert\r
13 *\r
14 * @example\r
15 * Ext.Msg.alert('Status', 'Changes saved successfully.');\r
16 *\r
17 * Prompt for user data and process the result using a callback\r
18 *\r
19 * @example\r
20 * Ext.Msg.prompt('Name', 'Please enter your name:', function(btn, text){\r
21 * if (btn == 'ok'){\r
22 * // process text value and close...\r
23 * }\r
24 * });\r
25 *\r
26 * Show a dialog using config options\r
27 *\r
28 * @example\r
29 * Ext.Msg.show({\r
30 * title:'Save Changes?',\r
31 * message: 'You are closing a tab that has unsaved changes. Would you like to save your changes?',\r
32 * buttons: Ext.Msg.YESNOCANCEL,\r
33 * icon: Ext.Msg.QUESTION,\r
34 * fn: function(btn) {\r
35 * if (btn === 'yes') {\r
36 * console.log('Yes pressed');\r
37 * } else if (btn === 'no') {\r
38 * console.log('No pressed');\r
39 * } else {\r
40 * console.log('Cancel pressed');\r
41 * } \r
42 * }\r
43 * });\r
44 * \r
45 * Showing Ext.Msg while it's already shown will cause the visible instance to be \r
46 * overwritten with the newly passed config. While this may be the desired outcome, you \r
47 * can also create a new MessageBox that can exist alongside the Ext.Msg \r
48 * singleton instance.\r
49 * \r
50 * @example\r
51 * var myMsg = Ext.create('Ext.window.MessageBox', {\r
52 * // set closeAction to 'destroy' if this instance is not\r
53 * // intended to be reused by the application\r
54 * closeAction: 'destroy'\r
55 * }).show({\r
56 * title: 'Custom MessageBox Instance',\r
57 * message: 'I can exist along with Ext.Msg'\r
58 * });\r
59 * \r
60 * Ext.Msg.alert('Overlapping', 'Ext.Msg instance');\r
61 */\r
62Ext.define('Ext.window.MessageBox', {\r
63 extend: 'Ext.window.Window',\r
64\r
65 requires: [\r
66 'Ext.toolbar.Toolbar',\r
67 'Ext.form.field.Text',\r
68 'Ext.form.field.TextArea',\r
69 'Ext.button.Button',\r
70 'Ext.layout.container.Anchor',\r
71 'Ext.layout.container.HBox',\r
72 'Ext.ProgressBar'\r
73 ],\r
74\r
75 alias: 'widget.messagebox',\r
76\r
77 /**\r
78 * @property\r
79 * Button config that displays a single OK button\r
80 */\r
81 OK : 1,\r
82 /**\r
83 * @property\r
84 * Button config that displays a single Yes button\r
85 */\r
86 YES : 2,\r
87 /**\r
88 * @property\r
89 * Button config that displays a single No button\r
90 */\r
91 NO : 4,\r
92 /**\r
93 * @property\r
94 * Button config that displays a single Cancel button\r
95 */\r
96 CANCEL : 8,\r
97 /**\r
98 * @property\r
99 * Button config that displays OK and Cancel buttons\r
100 */\r
101 OKCANCEL : 9,\r
102 /**\r
103 * @property\r
104 * Button config that displays Yes and No buttons\r
105 */\r
106 YESNO : 6,\r
107 /**\r
108 * @property\r
109 * Button config that displays Yes, No and Cancel buttons\r
110 */\r
111 YESNOCANCEL : 14,\r
112 /**\r
113 * @property\r
114 * The CSS class that provides the INFO icon image\r
115 */\r
116 INFO : Ext.baseCSSPrefix + 'message-box-info',\r
117 /**\r
118 * @property\r
119 * The CSS class that provides the WARNING icon image\r
120 */\r
121 WARNING : Ext.baseCSSPrefix + 'message-box-warning',\r
122 /**\r
123 * @property\r
124 * The CSS class that provides the QUESTION icon image\r
125 */\r
126 QUESTION : Ext.baseCSSPrefix + 'message-box-question',\r
127 /**\r
128 * @property\r
129 * The CSS class that provides the ERROR icon image\r
130 */\r
131 ERROR : Ext.baseCSSPrefix + 'message-box-error',\r
132\r
133 // hide it by offsets. Windows are hidden on render by default.\r
134 hideMode: 'offsets',\r
135 closeAction: 'hide',\r
136 resizable: false,\r
137 scrollable: true,\r
138 title: ' ',\r
139\r
140 defaultMinWidth: 250,\r
141 defaultMaxWidth: 600,\r
142 defaultMinHeight: 110,\r
143 defaultMaxHeight: 500,\r
144 \r
145 // Forcibly set these to null on the prototype to override anything set higher in\r
146 // the hierarchy\r
147 minWidth: null,\r
148 maxWidth: null,\r
149 minHeight: null,\r
150 maxHeight: null,\r
151 constrain: true,\r
152\r
153 cls: [Ext.baseCSSPrefix + 'message-box', Ext.baseCSSPrefix + 'hidden-offsets'],\r
154\r
155 layout: {\r
156 type: 'vbox',\r
157 align: 'stretch'\r
158 },\r
159\r
160 // We want to shrinkWrap around all docked items\r
161 shrinkWrapDock: true,\r
162\r
163 /**\r
164 * @property\r
165 * The default height in pixels of the message box's multiline textarea if displayed.\r
166 */\r
167 defaultTextHeight : 75,\r
168 /**\r
169 * @property\r
170 * The minimum width in pixels of the message box if it is a progress-style dialog. This is useful\r
171 * for setting a different minimum width than text-only dialogs may need.\r
172 */\r
173 minProgressWidth : 250,\r
174 /**\r
175 * @property\r
176 * The minimum width in pixels of the message box if it is a prompt dialog. This is useful\r
177 * for setting a different minimum width than text-only dialogs may need.\r
178 */\r
179 minPromptWidth: 250,\r
180 //<locale type="object">\r
181 /**\r
182 * @property\r
183 * An object containing the default button text strings that can be overriden for localized language support.\r
184 * Supported properties are: ok, cancel, yes and no. Generally you should include a locale-specific\r
185 * resource file for handling language support across the framework.\r
186 * Customize the default text like so:\r
187 *\r
188 * Ext.window.MessageBox.buttonText.yes = "oui"; //french\r
189 */\r
190 buttonText: {\r
191 ok: 'OK',\r
192 yes: 'Yes',\r
193 no: 'No',\r
194 cancel: 'Cancel'\r
195 },\r
196 //</locale>\r
197\r
198 buttonIds: [\r
199 'ok', 'yes', 'no', 'cancel'\r
200 ],\r
201\r
202 //<locale type="object">\r
203 titleText: {\r
204 confirm: 'Confirm',\r
205 prompt: 'Prompt',\r
206 wait: 'Loading...',\r
207 alert: 'Attention'\r
208 },\r
209 //</locale>\r
210\r
211 baseIconCls: Ext.baseCSSPrefix + 'message-box-icon',\r
212 \r
213 ariaRole: 'alertdialog',\r
214\r
215 makeButton: function(btnIdx) {\r
216 var btnId = this.buttonIds[btnIdx];\r
217 return new Ext.button.Button({\r
218 handler: this.btnCallback,\r
219 itemId: btnId,\r
220 scope: this,\r
221 text: this.buttonText[btnId],\r
222 minWidth: 75\r
223 });\r
224 },\r
225\r
226 btnCallback: function(btn, event) {\r
227 var me = this,\r
228 value,\r
229 field;\r
230\r
231 // If this is caused by a keydown event (eg: SPACE on a Button), then the\r
232 // hide will throw focus back to the previously focused element which will\r
233 // then recieve an unexpected keyup event.\r
234 // So defer callback handling until the upcoming keyup event.\r
235 if (event && event.type === 'keydown' && !event.isSpecialKey()) {\r
236 event.getTarget(null, null, true).on({\r
237 keyup: function(e) {\r
238 me.btnCallback(btn, e);\r
239 },\r
240 single: true\r
241 });\r
242 return;\r
243 }\r
244\r
245 if (me.cfg.prompt || me.cfg.multiline) {\r
246 if (me.cfg.multiline) {\r
247 field = me.textArea;\r
248 } else {\r
249 field = me.textField;\r
250 }\r
251 value = field.getValue();\r
252 field.reset();\r
253 }\r
254\r
255 // Component.onHide blurs the active element if the Component contains the active element\r
256 me.hide();\r
257 me.userCallback(btn.itemId, value, me.cfg);\r
258 },\r
259\r
260 hide: function() {\r
261 var me = this,\r
262 cls = me.cfg ? me.cfg.cls : '';\r
263\r
264 me.progressBar.reset();\r
265 if (cls) {\r
266 me.removeCls(cls);\r
267 }\r
268 me.callParent(arguments);\r
269 },\r
270\r
271 /**\r
272 * @private\r
273 */\r
274 constructor: function(cfg) {\r
275 var me = this;\r
276\r
277 me.callParent(arguments);\r
278\r
279 // set the default min/max/Width/Height to the initially configured min/max/Width/Height\r
280 // so that it will be used as the default when reconfiguring.\r
281 me.minWidth = me.defaultMinWidth = (me.minWidth || me.defaultMinWidth);\r
282 me.maxWidth = me.defaultMaxWidth = (me.maxWidth || me.defaultMaxWidth);\r
283 me.minHeight = me.defaultMinHeight = (me.minHeight || me.defaultMinHeight);\r
284 me.maxHeight = me.defaultMaxHeight = (me.maxHeight || me.defaultMaxHeight);\r
285 },\r
286\r
287 initComponent: function(cfg) {\r
288 var me = this,\r
289 baseId = me.id,\r
290 i, button;\r
291\r
292 // A title or iconCls could have been passed in the config to the constructor.\r
293 me.title = me.title || '&#160;';\r
294 me.iconCls = me.iconCls || '';\r
295\r
296 me.topContainer = new Ext.container.Container({\r
297 layout: 'hbox',\r
298 padding: 10,\r
299 style: {\r
300 overflow: 'hidden'\r
301 },\r
302 items: [\r
303 me.iconComponent = new Ext.Component({\r
304 cls: me.baseIconCls\r
305 }),\r
306 me.promptContainer = new Ext.container.Container({\r
307 flex: 1,\r
308 layout: {\r
309 type: 'vbox',\r
310 align: 'stretch'\r
311 },\r
312 items: [\r
313 me.msg = new Ext.Component({\r
314 id: baseId + '-msg',\r
315 cls: me.baseCls + '-text'\r
316 }),\r
317 me.textField = new Ext.form.field.Text({\r
318 id: baseId + '-textfield',\r
319 enableKeyEvents: true,\r
320 listeners: {\r
321 keydown: me.onPromptKey,\r
322 scope: me\r
323 }\r
324 }),\r
325 me.textArea = new Ext.form.field.TextArea({\r
326 id: baseId + '-textarea',\r
327 height: 75\r
328 })\r
329 ]\r
330 })\r
331 ]\r
332 });\r
333\r
334 me.progressBar = new Ext.ProgressBar({\r
335 id: baseId + '-progressbar',\r
336 margin: '0 10 10 10'\r
337 });\r
338\r
339 me.items = [me.topContainer, me.progressBar];\r
340\r
341 // Create the buttons based upon passed bitwise config\r
342 me.msgButtons = [];\r
343 for (i = 0; i < 4; i++) {\r
344 button = me.makeButton(i);\r
345 me.msgButtons[button.itemId] = button;\r
346 me.msgButtons.push(button);\r
347 }\r
348 me.bottomTb = new Ext.toolbar.Toolbar({\r
349 id: baseId + '-toolbar',\r
350 ui: 'footer',\r
351 dock: 'bottom',\r
352 layout: {\r
353 pack: 'center'\r
354 },\r
355 items: [\r
356 me.msgButtons[0],\r
357 me.msgButtons[1],\r
358 me.msgButtons[2],\r
359 me.msgButtons[3]\r
360 ]\r
361 });\r
362 me.dockedItems = [me.bottomTb];\r
363 me.on('close', me.onClose, me);\r
364 me.callParent();\r
365 },\r
366\r
367 onClose: function(){\r
368 var btn = this.header.child('[type=close]');\r
369 \r
370 if (btn) {\r
371 // Give a temporary itemId so it can act like the cancel button\r
372 btn.itemId = 'cancel';\r
373 this.btnCallback(btn);\r
374 delete btn.itemId;\r
375 }\r
376 },\r
377\r
378 onPromptKey: function(textField, e) {\r
379 var me = this;\r
380\r
381 if (e.keyCode === e.RETURN || e.keyCode === 10) {\r
382 if (me.msgButtons.ok.isVisible()) {\r
383 me.msgButtons.ok.handler.call(me, me.msgButtons.ok);\r
384 } else if (me.msgButtons.yes.isVisible()) {\r
385 me.msgButtons.yes.handler.call(me, me.msgButtons.yes);\r
386 }\r
387 }\r
388 },\r
389\r
390 reconfigure: function(cfg) {\r
391 var me = this,\r
392 buttons = 0,\r
393 hideToolbar = true,\r
394 oldButtonText = me.buttonText,\r
395 resizer = me.resizer,\r
396 header = me.header,\r
397 headerCfg = header && !header.isHeader,\r
398 message = cfg && (cfg.message || cfg.msg),\r
399 resizeTracker, width, height, i, textArea,\r
400 textField, msg, progressBar, msgButtons, wait, tool;\r
401\r
402 // Restore default buttonText before reconfiguring.\r
403 me.updateButtonText();\r
404\r
405 me.cfg = cfg = cfg || {};\r
406\r
407 wait = cfg.wait;\r
408 if (cfg.width) {\r
409 width = cfg.width;\r
410 }\r
411\r
412 if (cfg.height) {\r
413 height = cfg.height;\r
414 }\r
415\r
416 me.minWidth = cfg.minWidth || me.defaultMinWidth;\r
417 me.maxWidth = cfg.maxWidth || me.defaultMaxWidth;\r
418 me.minHeight = cfg.minHeight || me.defaultMinHeight;\r
419 me.maxHeight = cfg.maxHeight || me.defaultMaxHeight;\r
420\r
421 if (resizer) {\r
422 resizeTracker = resizer.resizeTracker;\r
423 resizer.minWidth = resizeTracker.minWidth = me.minWidth;\r
424 resizer.maxWidth = resizeTracker.maxWidth = me.maxWidth;\r
425 resizer.minHeight = resizeTracker.minHeight = me.minHeight;\r
426 resizer.maxHeight = resizeTracker.maxHeight = me.maxHeight;\r
427 }\r
428\r
429 // Default to allowing the Window to take focus.\r
430 delete me.defaultFocus;\r
431 if (cfg.defaultFocus) {\r
432 me.defaultFocus = cfg.defaultFocus;\r
433 }\r
434\r
435 // clear any old animateTarget\r
436 me.animateTarget = cfg.animateTarget || undefined;\r
437\r
438 // Defaults to modal\r
439 me.modal = cfg.modal !== false;\r
440\r
441 // Show the title/icon if a title/iconCls config was passed in the config to either the constructor\r
442 // or the show() method. Note that anything passed in the config should win.\r
443 //\r
444 // Note that if there is no title/iconCls in the config, check the headerCfg and default to the instance\r
445 // properties. This works because there are default values defined in initComponent.\r
446 me.setTitle(cfg.title || (headerCfg && header.title) || me.title);\r
447 me.setIconCls(cfg.iconCls || (headerCfg && header.iconCls) || me.iconCls);\r
448\r
449 // Extract button configs\r
450 if (Ext.isObject(cfg.buttons)) {\r
451 me.buttonText = cfg.buttons;\r
452 buttons = 0;\r
453 } else {\r
454 me.buttonText = cfg.buttonText || me.buttonText;\r
455 buttons = Ext.isNumber(cfg.buttons) ? cfg.buttons : 0;\r
456 }\r
457\r
458 // Apply custom-configured buttonText\r
459 // Infer additional buttons from the specified property names in the buttonText object\r
460 buttons = buttons | me.updateButtonText();\r
461\r
462 // Restore buttonText. Next run of reconfigure will restore to prototype's buttonText\r
463 me.buttonText = oldButtonText;\r
464\r
465 // During the on render, or size resetting layouts, and in subsequent hiding and showing, we need to\r
466 // suspend layouts, and flush at the end when the Window's children are at their final visibility.\r
467 Ext.suspendLayouts();\r
468 me.width = me.height = null;\r
469 if (width || height) {\r
470 if (width) {\r
471 me.setWidth(width);\r
472 }\r
473\r
474 if (height) {\r
475 me.setHeight(height);\r
476 }\r
477 }\r
478 me.hidden = false;\r
479 if (!me.rendered) {\r
480 me.render(Ext.getBody());\r
481 }\r
482\r
483 // Hide or show the close tool\r
484 me.closable = cfg.closable !== false && !wait;\r
485\r
486 // We need to redefine `header` because me.setIconCls() could create a Header instance.\r
487 header = me.header;\r
488\r
489 if (header) {\r
490 tool = header.child('[type=close]');\r
491 \r
492 if (tool) {\r
493 tool.setVisible(me.closable);\r
494 }\r
495\r
496 // Hide or show the header\r
497 if (!cfg.title && !me.closable && !cfg.iconCls) {\r
498 header.hide();\r
499 } else {\r
500 header.show();\r
501 }\r
502 }\r
503\r
504 // Default to dynamic drag: drag the window, not a ghost\r
505 me.liveDrag = !cfg.proxyDrag;\r
506\r
507 // wrap the user callback\r
508 me.userCallback = Ext.Function.bindCallback(cfg.callback ||cfg.fn || Ext.emptyFn,\r
509 cfg.scope || Ext.global);\r
510\r
511 // Hide or show the icon Component\r
512 me.setIcon(cfg.icon);\r
513\r
514 // Hide or show the message area\r
515 msg = me.msg;\r
516 if (message) {\r
517 msg.setHtml(message);\r
518 msg.show();\r
519 } else {\r
520 msg.hide();\r
521 }\r
522\r
523 // Hide or show the input field\r
524 textArea = me.textArea;\r
525 textField = me.textField;\r
526 if (cfg.prompt || cfg.multiline) {\r
527 me.multiline = cfg.multiline;\r
528 if (cfg.multiline) {\r
529 textArea.setValue(cfg.value);\r
530 textArea.setHeight(cfg.defaultTextHeight || me.defaultTextHeight);\r
531 textArea.show();\r
532 textField.hide();\r
533 me.defaultFocus = textArea;\r
534 } else {\r
535 textField.setValue(cfg.value);\r
536 textArea.hide();\r
537 textField.show();\r
538 me.defaultFocus = textField;\r
539 }\r
540 } else {\r
541 textArea.hide();\r
542 textField.hide();\r
543 }\r
544\r
545 // Hide or show the progress bar\r
546 progressBar = me.progressBar;\r
547 if (cfg.progress || wait) {\r
548 progressBar.show();\r
549 me.updateProgress(0, cfg.progressText);\r
550 if (wait) {\r
551 progressBar.wait(wait === true ? cfg.waitConfig : wait);\r
552 }\r
553 } else {\r
554 progressBar.hide();\r
555 }\r
556\r
557 // Hide or show buttons depending on flag value sent.\r
558 msgButtons = me.msgButtons;\r
559 for (i = 0; i < 4; i++) {\r
560 if (buttons & Math.pow(2, i)) {\r
561\r
562 // Default to focus on the first visible button if focus not already set\r
563 if (!me.defaultFocus) {\r
564 me.defaultFocus = msgButtons[i];\r
565 }\r
566 msgButtons[i].show();\r
567 hideToolbar = false;\r
568 } else {\r
569 msgButtons[i].hide();\r
570 }\r
571 }\r
572\r
573 // Hide toolbar if no buttons to show\r
574 if (hideToolbar) {\r
575 me.bottomTb.hide();\r
576 } else {\r
577 me.bottomTb.show();\r
578 }\r
579 Ext.resumeLayouts(true);\r
580 },\r
581\r
582 /**\r
583 * @private\r
584 * Set button text according to current buttonText property object\r
585 * @return {Number} The buttons bitwise flag based upon the button IDs specified in the buttonText property.\r
586 */\r
587 updateButtonText: function() {\r
588 var me = this,\r
589 buttonText = me.buttonText,\r
590 buttons = 0,\r
591 btnId,\r
592 btn;\r
593\r
594 for (btnId in buttonText) {\r
595 if (buttonText.hasOwnProperty(btnId)) {\r
596 btn = me.msgButtons[btnId];\r
597 if (btn) {\r
598 if (me.cfg && me.cfg.buttonText) {\r
599 buttons = buttons | Math.pow(2, Ext.Array.indexOf(me.buttonIds, btnId));\r
600 }\r
601 if (btn.text !== buttonText[btnId]) {\r
602 btn.setText(buttonText[btnId]);\r
603 }\r
604 }\r
605 }\r
606 }\r
607 return buttons;\r
608 },\r
609\r
610 /**\r
611 * Displays a new message box, or reinitializes an existing message box, based on the config options passed in. All\r
612 * display functions (e.g. prompt, alert, etc.) on MessageBox call this function internally, although those calls\r
613 * are basic shortcuts and do not support all of the config options allowed here.\r
614 *\r
615 * Example usage:\r
616 *\r
617 * Ext.Msg.show({\r
618 * title: 'Address',\r
619 * message: 'Please enter your address:',\r
620 * width: 300,\r
621 * buttons: Ext.Msg.OKCANCEL,\r
622 * multiline: true,\r
623 * fn: saveAddress,\r
624 * animateTarget: 'addAddressBtn',\r
625 * icon: Ext.window.MessageBox.INFO\r
626 * });\r
627 *\r
628 * @param {Object} config The following config options are supported:\r
629 *\r
630 * @param {String/Ext.dom.Element} config.animateTarget\r
631 * An id or Element from which the message box should animate as it opens and closes.\r
632 *\r
633 * @param {Number} [config.buttons=false]\r
634 * A bitwise button specifier consisting of the sum of any of the following constants:\r
635 *\r
636 * - Ext.MessageBox.OK\r
637 * - Ext.MessageBox.YES\r
638 * - Ext.MessageBox.NO\r
639 * - Ext.MessageBox.CANCEL\r
640 *\r
641 * Some common combinations have already been predefined:\r
642 *\r
643 * - Ext.MessageBox.OKCANCEL\r
644 * - Ext.MessageBox.YESNO\r
645 * - Ext.MessageBox.YESNOCANCEL\r
646 *\r
647 * Or false to not show any buttons.\r
648 *\r
649 * This may also be specified as an object hash containing custom button text in the same format as the\r
650 * {@link #buttonText} config. Button IDs present as property names will be made visible.\r
651 *\r
652 * @param {Boolean} config.closable\r
653 * False to hide the top-right close button (defaults to true). Note that progress and wait dialogs will ignore this\r
654 * property and always hide the close button as they can only be closed programmatically.\r
655 *\r
656 * @param {String} config.cls\r
657 * A custom CSS class to apply to the message box's container element\r
658 *\r
659 * @param {Number} [config.defaultTextHeight=75]\r
660 * The default height in pixels of the message box's multiline textarea if displayed.\r
661 *\r
662 * @param {Function} config.fn\r
663 * A callback function which is called when the dialog is dismissed either by clicking on the configured buttons, or\r
664 * on the dialog close button, or by pressing the return button to enter input.\r
665 *\r
666 * Progress and wait dialogs will ignore this option since they do not respond to user actions and can only be\r
667 * closed programmatically, so any required function should be called by the same code after it closes the dialog.\r
668 * Parameters passed:\r
669 *\r
670 * @param {String} config.fn.buttonId The ID of the button pressed, one of:\r
671 *\r
672 * - ok\r
673 * - yes\r
674 * - no\r
675 * - cancel\r
676 *\r
677 * @param {String} config.fn.text Value of the input field if either `prompt` or `multiline` is true\r
678 * @param {Object} config.fn.opt The config object passed to show.\r
679 *\r
680 * @param {Object} config.buttonText\r
681 * An object containing string properties which override the system-supplied button text values just for this\r
682 * invocation. The property names are:\r
683 *\r
684 * - ok\r
685 * - yes\r
686 * - no\r
687 * - cancel\r
688 *\r
689 * @param {Object} config.scope\r
690 * The scope (`this` reference) in which the function will be executed.\r
691 *\r
692 * @param {String} config.icon\r
693 * A CSS class that provides a background image to be used as the body icon for the dialog.\r
694 * One can use a predefined icon class:\r
695 *\r
696 * - Ext.MessageBox.INFO\r
697 * - Ext.MessageBox.WARNING\r
698 * - Ext.MessageBox.QUESTION\r
699 * - Ext.MessageBox.ERROR\r
700 *\r
701 * or use just any `'custom-class'`. Defaults to empty string.\r
702 *\r
703 * @param {String} config.iconCls\r
704 * The standard {@link Ext.window.Window#iconCls} to add an optional header icon (defaults to '')\r
705 * \r
706 * @param {String} config.defaultFocus\r
707 * The button to focus when showing the dialog. If not specified, defaults to\r
708 * the first visible button.\r
709 *\r
710 * @param {Number} config.maxWidth\r
711 * The maximum width in pixels of the message box (defaults to 600)\r
712 *\r
713 * @param {Number} config.minWidth\r
714 * The minimum width in pixels of the message box (defaults to 100)\r
715 *\r
716 * @param {Boolean} config.modal\r
717 * False to allow user interaction with the page while the message box is displayed (defaults to true)\r
718 *\r
719 * @param {String} config.message\r
720 * A string that will replace the existing message box body text (defaults to the XHTML-compliant non-breaking space\r
721 * character '&#160;')\r
722 *\r
723 * @param {Boolean} config.multiline\r
724 * True to prompt the user to enter multi-line text (defaults to false)\r
725 *\r
726 * @param {Boolean} config.progress\r
727 * True to display a progress bar (defaults to false)\r
728 *\r
729 * @param {String} config.progressText\r
730 * The text to display inside the progress bar if progress = true (defaults to '')\r
731 *\r
732 * @param {Boolean} config.prompt\r
733 * True to prompt the user to enter single-line text (defaults to false)\r
734 *\r
735 * @param {Boolean} config.proxyDrag\r
736 * True to display a lightweight proxy while dragging (defaults to false)\r
737 *\r
738 * @param {String} config.title\r
739 * The title text\r
740 *\r
741 * @param {String} config.value\r
742 * The string value to set into the active textbox element if displayed\r
743 *\r
744 * @param {Object/Boolean} [config.wait=false]\r
745 * `true` to display a progress bar, or a configuration for {@link Ext.ProgressBar#wait}.\r
746 *\r
747 * @param {Object} config.waitConfig\r
748 * A {@link Ext.ProgressBar#wait} config object (applies only if wait = true)\r
749 *\r
750 * @param {Number} config.width\r
751 * The width of the dialog in pixels\r
752 *\r
753 * @return {Ext.window.MessageBox} this\r
754 */\r
755 show: function(cfg) {\r
756 var me = this,\r
757 visibleFocusables;\r
758\r
759 cfg = cfg || {};\r
760\r
761 // If called during global layout suspension, make the call after layout resumption\r
762 if (Ext.Component.layoutSuspendCount) {\r
763 Ext.on({\r
764 resumelayouts: function() {\r
765 me.show(cfg);\r
766 },\r
767 single: true\r
768 });\r
769 return me;\r
770 }\r
771\r
772 me.reconfigure(cfg);\r
773 if (cfg.cls) {\r
774 me.addCls(cfg.cls);\r
775 }\r
776\r
777 // Do not steal focus from anything that may be focused if the MessageBox has no visible focusable\r
778 // items. For example, a "wait" message box should not get focus.\r
779 visibleFocusables = me.query('textfield:not([hidden]),textarea:not([hidden]),button:not([hidden])');\r
780 me.preventFocusOnActivate = !visibleFocusables.length;\r
781\r
782 // Set the flag, so that the parent show method performs the show procedure that we need.\r
783 // ie: animation from animTarget, onShow processing and focusing.\r
784 me.hidden = true;\r
785 me.callParent();\r
786 return me;\r
787 },\r
788\r
789 onShow: function() {\r
790 this.callParent(arguments);\r
791 this.center();\r
792 },\r
793\r
794 updateText: function(text) {\r
795 this.msg.setHtml(text);\r
796 },\r
797\r
798 /**\r
799 * Adds the specified icon to the dialog. By default, the class 'x-messagebox-icon' is applied for default\r
800 * styling, and the class passed in is expected to supply the background image url. Pass in empty string ('')\r
801 * to clear any existing icon. This method must be called before the MessageBox is shown.\r
802 * The following built-in icon classes are supported, but you can also pass in a custom class name:\r
803 *\r
804 * Ext.window.MessageBox.INFO\r
805 * Ext.window.MessageBox.WARNING\r
806 * Ext.window.MessageBox.QUESTION\r
807 * Ext.window.MessageBox.ERROR\r
808 *\r
809 * @param {String} icon A CSS classname specifying the icon's background image url, or empty string to clear the icon\r
810 * @param {Number} [width] The width of the icon. If not specified, the default is used\r
811 * @param {Number} [height] The height of the icon. If not specified, the default is used\r
812 * @return {Ext.window.MessageBox} this\r
813 */\r
814 setIcon : function(icon, width, height) {\r
815 var me = this,\r
816 iconCmp = me.iconComponent,\r
817 cls = me.messageIconCls;\r
818\r
819 if (cls) {\r
820 iconCmp.removeCls(cls);\r
821 }\r
822\r
823 if (icon) {\r
824 iconCmp.show();\r
825 if (width || height) {\r
826 iconCmp.setSize(width || iconCmp.getWidth(), height || iconCmp.getHeight());\r
827 }\r
828 iconCmp.addCls(Ext.baseCSSPrefix + 'dlg-icon');\r
829 iconCmp.addCls(me.messageIconCls = icon);\r
830 } else {\r
831 iconCmp.removeCls(Ext.baseCSSPrefix + 'dlg-icon');\r
832 iconCmp.hide();\r
833 }\r
834 return me;\r
835 },\r
836\r
837 /**\r
838 * Updates a progress-style message box's text and progress bar. Only relevant on message boxes\r
839 * initiated via {@link Ext.window.MessageBox#progress} or {@link Ext.window.MessageBox#wait},\r
840 * or by calling {@link Ext.window.MessageBox#method-show} with progress: true.\r
841 *\r
842 * @param {Number} [value=0] Any number between 0 and 1 (e.g., .5)\r
843 * @param {String} [progressText=''] The progress text to display inside the progress bar.\r
844 * @param {String} [message] The message box's body text is replaced with the specified string (defaults to undefined\r
845 * so that any existing body text will not get overwritten by default unless a new value is passed in)\r
846 * @return {Ext.window.MessageBox} this\r
847 */\r
848 updateProgress : function(value, progressText, message){\r
849 this.progressBar.updateProgress(value, progressText);\r
850 if (message){\r
851 this.updateText(message);\r
852 }\r
853 return this;\r
854 },\r
855\r
856 onEsc: function() {\r
857 if (this.closable !== false) {\r
858 this.callParent(arguments);\r
859 }\r
860 },\r
861\r
862 /**\r
863 * Displays a confirmation message box with Yes and No buttons (comparable to JavaScript's confirm).\r
864 * If a callback function is passed it will be called after the user clicks either button,\r
865 * and the id of the button that was clicked will be passed as the only parameter to the callback\r
866 * (could also be the top-right close button, which will always report as "cancel").\r
867 *\r
868 * @param {String} title The title bar text\r
869 * @param {String} message The message box body text\r
870 * @param {Function} [fn] The callback function invoked after the message box is closed.\r
871 * See {@link #method-show} method for details.\r
872 * @param {Object} [scope=window] The scope (`this` reference) in which the callback is executed.\r
873 * @return {Ext.window.MessageBox} this\r
874 */\r
875 confirm: function(cfg, message, fn, scope) {\r
876 if (Ext.isString(cfg)) {\r
877 cfg = {\r
878 title: cfg,\r
879 icon: this.QUESTION,\r
880 message: message,\r
881 buttons: this.YESNO,\r
882 callback: fn,\r
883 scope: scope\r
884 };\r
885 }\r
886 return this.show(cfg);\r
887 },\r
888\r
889 /**\r
890 * Displays a message box with OK and Cancel buttons prompting the user to enter some text (comparable to JavaScript's prompt).\r
891 * The prompt can be a single-line or multi-line textbox. If a callback function is passed it will be called after the user\r
892 * clicks either button, and the id of the button that was clicked (could also be the top-right\r
893 * close button, which will always report as "cancel") and the text that was entered will be passed as the two parameters to the callback.\r
894 *\r
895 * @param {String} title The title bar text\r
896 * @param {String} message The message box body text\r
897 * @param {Function} [fn] The callback function invoked after the message box is closed.\r
898 * See {@link #method-show} method for details.\r
899 * @param {Object} [scope=window] The scope (`this` reference) in which the callback is executed.\r
900 * @param {Boolean/Number} [multiline=false] True to create a multiline textbox using the defaultTextHeight\r
901 * property, or the height in pixels to create the textbox/\r
902 * @param {String} [value=''] Default value of the text input element\r
903 * @return {Ext.window.MessageBox} this\r
904 */\r
905 prompt : function(title, message, fn, scope, multiline, value){\r
906 if (Ext.isString(title)) {\r
907 title = {\r
908 prompt: true,\r
909 title: title,\r
910 minWidth: this.minPromptWidth,\r
911 message: message,\r
912 buttons: this.OKCANCEL,\r
913 callback: fn,\r
914 scope: scope,\r
915 multiline: multiline,\r
916 value: value\r
917 };\r
918 }\r
919 return this.show(title);\r
920 },\r
921\r
922 /**\r
923 * Displays a message box with an infinitely auto-updating progress bar. This can be used to block user\r
924 * interaction while waiting for a long-running process to complete that does not have defined intervals.\r
925 * You are responsible for closing the message box when the process is complete.\r
926 *\r
927 * @param {String} message The message box body text\r
928 * @param {String} [title] The title bar text\r
929 * @param {Object} [config] A {@link Ext.ProgressBar#wait} config object\r
930 * @return {Ext.window.MessageBox} this\r
931 */\r
932 wait : function(message, title, config){\r
933 if (Ext.isString(message)) {\r
934 message = {\r
935 title : title,\r
936 message : message,\r
937 closable: false,\r
938 wait: true,\r
939 modal: true,\r
940 minWidth: this.minProgressWidth,\r
941 waitConfig: config\r
942 };\r
943 }\r
944 return this.show(message);\r
945 },\r
946\r
947 /**\r
948 * Displays a standard read-only message box with an OK button (comparable to the basic JavaScript alert prompt).\r
949 * If a callback function is passed it will be called after the user clicks the button, and the\r
950 * id of the button that was clicked will be passed as the only parameter to the callback\r
951 * (could also be the top-right close button, which will always report as "cancel").\r
952 *\r
953 * @param {String} title The title bar text\r
954 * @param {String} message The message box body text\r
955 * @param {Function} [fn] The callback function invoked after the message box is closed.\r
956 * See {@link #method-show} method for details.\r
957 * @param {Object} [scope=window] The scope (<code>this</code> reference) in which the callback is executed.\r
958 * @return {Ext.window.MessageBox} this\r
959 */\r
960 alert: function(title, message, fn, scope) {\r
961 if (Ext.isString(title)) {\r
962 title = {\r
963 title: title,\r
964 message: message,\r
965 buttons: this.OK,\r
966 fn: fn,\r
967 scope : scope,\r
968 minWidth: this.minWidth\r
969 };\r
970 }\r
971 return this.show(title);\r
972 },\r
973\r
974 /**\r
975 * Displays a message box with a progress bar.\r
976 *\r
977 * You are responsible for updating the progress bar as needed via {@link Ext.window.MessageBox#updateProgress}\r
978 * and closing the message box when the process is complete.\r
979 *\r
980 * @param {String} title The title bar text\r
981 * @param {String} message The message box body text\r
982 * @param {String} [progressText=''] The text to display inside the progress bar\r
983 * @return {Ext.window.MessageBox} this\r
984 */\r
985 progress : function(title, message, progressText){\r
986 if (Ext.isString(title)) {\r
987 title = {\r
988 title: title,\r
989 message: message,\r
990 progress: true,\r
991 progressText: progressText\r
992 };\r
993 }\r
994 return this.show(title);\r
995 }\r
996}, function(MessageBox) {\r
997 /**\r
998 * @class Ext.MessageBox\r
999 * @alternateClassName Ext.Msg\r
1000 * @extends Ext.window.MessageBox\r
1001 * @singleton\r
1002 * @inheritdoc Ext.window.MessageBox\r
1003 */\r
1004 // We want to defer creating Ext.MessageBox and Ext.Msg instances\r
1005 // until overrides have been applied.\r
1006 Ext.onInternalReady(function() {\r
1007 Ext.MessageBox = Ext.Msg = new MessageBox();\r
1008 });\r
1009});\r