]>
Commit | Line | Data |
---|---|---|
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 | |
62 | Ext.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 || ' ';\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 ' ')\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 |