Commit | Line | Data |
---|---|---|
78686995 AN |
1 | YUI.add('moodle-core-notification-dialogue', function (Y, NAME) { |
2 | ||
3 | var DIALOGUE_PREFIX, | |
4 | BASE, | |
78686995 AN |
5 | CONFIRMYES, |
6 | CONFIRMNO, | |
7 | TITLE, | |
8 | QUESTION, | |
9 | CSS; | |
10 | ||
11 | DIALOGUE_PREFIX = 'moodle-dialogue', | |
12 | BASE = 'notificationBase', | |
78686995 AN |
13 | CONFIRMYES = 'yesLabel', |
14 | CONFIRMNO = 'noLabel', | |
15 | TITLE = 'title', | |
16 | QUESTION = 'question', | |
17 | CSS = { | |
18 | BASE : 'moodle-dialogue-base', | |
19 | WRAP : 'moodle-dialogue-wrap', | |
20 | HEADER : 'moodle-dialogue-hd', | |
21 | BODY : 'moodle-dialogue-bd', | |
22 | CONTENT : 'moodle-dialogue-content', | |
23 | FOOTER : 'moodle-dialogue-ft', | |
24 | HIDDEN : 'hidden', | |
25 | LIGHTBOX : 'moodle-dialogue-lightbox' | |
26 | }; | |
27 | ||
28 | // Set up the namespace once. | |
29 | M.core = M.core || {}; | |
30 | /** | |
31 | * The generic dialogue class for use in Moodle. | |
32 | * | |
33 | * @module moodle-core-notification | |
34 | * @submodule moodle-core-notification-dialogue | |
35 | */ | |
36 | ||
37 | var DIALOGUE_NAME = 'Moodle dialogue', | |
bf7c86cf | 38 | DIALOGUE, |
f2b235cb SH |
39 | DIALOGUE_FULLSCREEN_CLASS = DIALOGUE_PREFIX + '-fullscreen', |
40 | DIALOGUE_HIDDEN_CLASS = DIALOGUE_PREFIX + '-hidden', | |
f2b235cb | 41 | DIALOGUE_SELECTOR =' [role=dialog]', |
586d393f | 42 | MENUBAR_SELECTOR = '[role=menubar]', |
ecf02bf5 BB |
43 | DOT = '.', |
44 | HAS_ZINDEX = 'moodle-has-zindex', | |
586d393f | 45 | CAN_RECEIVE_FOCUS_SELECTOR = 'input:not([type="hidden"]), a[href], button, textarea, select, [tabindex]'; |
78686995 AN |
46 | |
47 | /** | |
48 | * A re-usable dialogue box with Moodle classes applied. | |
49 | * | |
4246e5c7 | 50 | * @param {Object} c Object literal specifying the dialogue configuration properties. |
78686995 AN |
51 | * @constructor |
52 | * @class M.core.dialogue | |
1f777e5c | 53 | * @extends Panel |
78686995 | 54 | */ |
4246e5c7 AN |
55 | DIALOGUE = function(c) { |
56 | var config = Y.clone(c); | |
d10e6118 AN |
57 | config.COUNT = Y.stamp(this); |
58 | var id = 'moodle-dialogue-' + config.COUNT; | |
78686995 AN |
59 | config.notificationBase = |
60 | Y.Node.create('<div class="'+CSS.BASE+'">') | |
61 | .append(Y.Node.create('<div id="'+id+'" role="dialog" aria-labelledby="'+id+'-header-text" class="'+CSS.WRAP+'"></div>') | |
baffb422 | 62 | .append(Y.Node.create('<div id="'+id+'-header-text" class="'+CSS.HEADER+' yui3-widget-hd"></div>')) |
78686995 AN |
63 | .append(Y.Node.create('<div class="'+CSS.BODY+' yui3-widget-bd"></div>')) |
64 | .append(Y.Node.create('<div class="'+CSS.FOOTER+' yui3-widget-ft"></div>'))); | |
65 | Y.one(document.body).append(config.notificationBase); | |
b59f2e3b SH |
66 | |
67 | if (config.additionalBaseClass) { | |
68 | config.notificationBase.addClass(config.additionalBaseClass); | |
69 | } | |
70 | ||
78686995 | 71 | config.srcNode = '#'+id; |
78686995 | 72 | |
78686995 AN |
73 | // closeButton param to keep the stable versions API. |
74 | if (config.closeButton === false) { | |
75 | config.buttons = null; | |
76 | } else { | |
77 | config.buttons = [ | |
78 | { | |
79 | section: Y.WidgetStdMod.HEADER, | |
80 | classNames: 'closebutton', | |
81 | action: function () { | |
82 | this.hide(); | |
83 | } | |
84 | } | |
85 | ]; | |
86 | } | |
87 | DIALOGUE.superclass.constructor.apply(this, [config]); | |
88 | ||
89 | if (config.closeButton !== false) { | |
90 | // The buttons constructor does not allow custom attributes | |
91 | this.get('buttons').header[0].setAttribute('title', this.get('closeButtonTitle')); | |
92 | } | |
93 | }; | |
94 | Y.extend(DIALOGUE, Y.Panel, { | |
d61c96b6 DW |
95 | // Window resize event listener. |
96 | _resizeevent : null, | |
97 | // Orientation change event listener. | |
98 | _orientationevent : null, | |
1389bcd7 | 99 | _calculatedzindex : false, |
1f777e5c | 100 | |
bf7c86cf DW |
101 | /** |
102 | * Initialise the dialogue. | |
103 | * | |
104 | * @method initializer | |
bf7c86cf | 105 | */ |
2f5c1441 | 106 | initializer : function() { |
bf7c86cf DW |
107 | var bb; |
108 | ||
d9bf4be4 SH |
109 | if (this.get('render')) { |
110 | this.render(); | |
111 | } | |
ce5867a1 | 112 | this.makeResponsive(); |
bf7c86cf | 113 | this.after('visibleChange', this.visibilityChanged, this); |
2f5c1441 | 114 | if (this.get('center')) { |
dd66b6ab DW |
115 | this.centerDialogue(); |
116 | } | |
78686995 | 117 | |
73747aea AN |
118 | if (this.get('modal')) { |
119 | this.plug(Y.M.core.LockScroll); | |
120 | } | |
121 | ||
78686995 AN |
122 | // Workaround upstream YUI bug http://yuilibrary.com/projects/yui3/ticket/2532507 |
123 | // and allow setting of z-index in theme. | |
d61c96b6 | 124 | bb = this.get('boundingBox'); |
ecf02bf5 | 125 | bb.addClass(HAS_ZINDEX); |
bf7c86cf | 126 | |
2f5c1441 AN |
127 | // Add any additional classes that were specified. |
128 | Y.Array.each(this.get('extraClasses'), bb.addClass, bb); | |
129 | ||
130 | if (this.get('visible')) { | |
bf7c86cf DW |
131 | this.applyZIndex(); |
132 | } | |
1389bcd7 JF |
133 | // Recalculate the zIndex every time the modal is altered. |
134 | this.on('maskShow', this.applyZIndex); | |
ce5867a1 DW |
135 | // We must show - after the dialogue has been positioned, |
136 | // either by centerDialogue or makeResonsive. This is because the show() will trigger | |
137 | // a focus on the dialogue, which will scroll the page. If the dialogue has not | |
138 | // been positioned it will scroll back to the top of the page. | |
2f5c1441 | 139 | if (this.get('visible')) { |
ce5867a1 | 140 | this.show(); |
586d393f | 141 | this.keyDelegation(); |
ce5867a1 | 142 | } |
0860dd78 AN |
143 | |
144 | // Remove the dialogue from the DOM when it is destroyed. | |
145 | this.after('destroyedChange', function(){ | |
146 | this.get(BASE).remove(true); | |
147 | }, this); | |
bf7c86cf DW |
148 | }, |
149 | ||
150 | /** | |
151 | * Either set the zindex to the supplied value, or set it to one more than the highest existing | |
152 | * dialog in the page. | |
153 | * | |
1f777e5c | 154 | * @method applyZIndex |
bf7c86cf DW |
155 | */ |
156 | applyZIndex : function() { | |
1389bcd7 JF |
157 | var highestzindex = 1, |
158 | zindexvalue = 1, | |
f2b235cb | 159 | bb = this.get('boundingBox'), |
1389bcd7 | 160 | ol = this.get('maskNode'), |
f2b235cb | 161 | zindex = this.get('zIndex'); |
1389bcd7 | 162 | if (zindex !== 0 && !this._calculatedzindex) { |
bf7c86cf | 163 | // The zindex was specified so we should use that. |
f2b235cb | 164 | bb.setStyle('zIndex', zindex); |
bf7c86cf | 165 | } else { |
f2b235cb | 166 | // Determine the correct zindex by looking at all existing dialogs and menubars in the page. |
ecf02bf5 | 167 | Y.all(DIALOGUE_SELECTOR + ', ' + MENUBAR_SELECTOR + ', ' + DOT + HAS_ZINDEX).each(function (node) { |
f2b235cb SH |
168 | var zindex = this.findZIndex(node); |
169 | if (zindex > highestzindex) { | |
170 | highestzindex = zindex; | |
bf7c86cf | 171 | } |
f2b235cb | 172 | }, this); |
bf7c86cf | 173 | // Only set the zindex if we found a wrapper. |
1389bcd7 JF |
174 | zindexvalue = (highestzindex + 1).toString(); |
175 | bb.setStyle('zIndex', zindexvalue); | |
1389bcd7 | 176 | this.set('zIndex', zindexvalue); |
0ef60744 AN |
177 | if (this.get('modal')) { |
178 | ol.setStyle('zIndex', zindexvalue); | |
5298d02f | 179 | |
180 | // In IE8, the z-indexes do not take effect properly unless you toggle | |
181 | // the lightbox from 'fixed' to 'static' and back. This code does so | |
182 | // using the minimum setTimeouts that still actually work. | |
183 | if (Y.UA.ie && Y.UA.compareVersions(Y.UA.ie, 9) < 0) { | |
184 | setTimeout(function() { | |
185 | ol.setStyle('position', 'static'); | |
186 | setTimeout(function() { | |
187 | ol.setStyle('position', 'fixed'); | |
188 | }, 0); | |
189 | }, 0); | |
190 | } | |
0ef60744 | 191 | } |
1389bcd7 | 192 | this._calculatedzindex = true; |
bf7c86cf DW |
193 | } |
194 | }, | |
195 | ||
f2b235cb SH |
196 | /** |
197 | * Finds the zIndex of the given node or its parent. | |
198 | * | |
199 | * @method findZIndex | |
1f777e5c AN |
200 | * @param {Node} node The Node to apply the zIndex to. |
201 | * @return {Number} Either the zIndex, or 0 if one was not found. | |
f2b235cb SH |
202 | */ |
203 | findZIndex : function(node) { | |
204 | // In most cases the zindex is set on the parent of the dialog. | |
205 | var zindex = node.getStyle('zIndex') || node.ancestor().getStyle('zIndex'); | |
206 | if (zindex) { | |
207 | return parseInt(zindex, 10); | |
208 | } | |
209 | return 0; | |
210 | }, | |
211 | ||
bf7c86cf DW |
212 | /** |
213 | * Event listener for the visibility changed event. | |
214 | * | |
215 | * @method visibilityChanged | |
1f777e5c | 216 | * @param {EventFacade} e |
bf7c86cf | 217 | */ |
78686995 | 218 | visibilityChanged : function(e) { |
586d393f | 219 | var titlebar, bb; |
78686995 AN |
220 | if (e.attrName === 'visible') { |
221 | this.get('maskNode').addClass(CSS.LIGHTBOX); | |
d61c96b6 | 222 | if (e.prevVal && !e.newVal) { |
586d393f | 223 | bb = this.get('boundingBox'); |
d61c96b6 DW |
224 | if (this._resizeevent) { |
225 | this._resizeevent.detach(); | |
226 | this._resizeevent = null; | |
227 | } | |
228 | if (this._orientationevent) { | |
229 | this._orientationevent.detach(); | |
230 | this._orientationevent = null; | |
231 | } | |
586d393f | 232 | bb.detach('key', this.keyDelegation); |
d61c96b6 | 233 | } |
bf7c86cf DW |
234 | if (!e.prevVal && e.newVal) { |
235 | // This needs to be done each time the dialog is shown as new dialogs may have been opened. | |
236 | this.applyZIndex(); | |
237 | // This needs to be done each time the dialog is shown as the window may have been resized. | |
238 | this.makeResponsive(); | |
239 | if (!this.shouldResizeFullscreen()) { | |
240 | if (this.get('draggable')) { | |
241 | titlebar = '#' + this.get('id') + ' .' + CSS.HEADER; | |
242 | this.plug(Y.Plugin.Drag, {handles : [titlebar]}); | |
243 | Y.one(titlebar).setStyle('cursor', 'move'); | |
244 | } | |
245 | } | |
586d393f | 246 | this.keyDelegation(); |
bf7c86cf | 247 | } |
78686995 AN |
248 | if (this.get('center') && !e.prevVal && e.newVal) { |
249 | this.centerDialogue(); | |
250 | } | |
78686995 AN |
251 | } |
252 | }, | |
bf7c86cf DW |
253 | /** |
254 | * If the responsive attribute is set on the dialog, and the window size is | |
255 | * smaller than the responsive width - make the dialog fullscreen. | |
256 | * | |
257 | * @method makeResponsive | |
bf7c86cf DW |
258 | */ |
259 | makeResponsive : function() { | |
78686995 | 260 | var bb = this.get('boundingBox'), |
bf7c86cf DW |
261 | content; |
262 | ||
263 | if (this.shouldResizeFullscreen()) { | |
d61c96b6 DW |
264 | // Make this dialogue fullscreen on a small screen. |
265 | // Disable the page scrollbars. | |
bf7c86cf | 266 | |
d61c96b6 DW |
267 | // Size and position the fullscreen dialog. |
268 | ||
2a808cef DW |
269 | bb.addClass(DIALOGUE_FULLSCREEN_CLASS); |
270 | bb.setStyles({'left' : null, | |
271 | 'top' : null, | |
272 | 'width' : null, | |
273 | 'height' : null, | |
274 | 'right' : null, | |
275 | 'bottom' : null}); | |
d61c96b6 DW |
276 | |
277 | content = Y.one('#' + this.get('id') + ' .' + CSS.BODY); | |
d61c96b6 DW |
278 | } else { |
279 | if (this.get('responsive')) { | |
280 | // We must reset any of the fullscreen changes. | |
2a808cef DW |
281 | bb.removeClass(DIALOGUE_FULLSCREEN_CLASS) |
282 | .setStyles({'width' : this.get('width'), | |
bf7c86cf | 283 | 'height' : this.get('height')}); |
d61c96b6 | 284 | content = Y.one('#' + this.get('id') + ' .' + CSS.BODY); |
d61c96b6 | 285 | } |
d61c96b6 | 286 | } |
bf7c86cf DW |
287 | }, |
288 | /** | |
289 | * Center the dialog on the screen. | |
290 | * | |
291 | * @method centerDialogue | |
bf7c86cf DW |
292 | */ |
293 | centerDialogue : function() { | |
294 | var bb = this.get('boundingBox'), | |
295 | hidden = bb.hasClass(DIALOGUE_HIDDEN_CLASS), | |
296 | x, | |
297 | y; | |
298 | ||
299 | // Don't adjust the position if we are in full screen mode. | |
300 | if (this.shouldResizeFullscreen()) { | |
301 | return; | |
302 | } | |
303 | if (hidden) { | |
304 | bb.setStyle('top', '-1000px').removeClass(DIALOGUE_HIDDEN_CLASS); | |
305 | } | |
306 | x = Math.max(Math.round((bb.get('winWidth') - bb.get('offsetWidth'))/2), 15); | |
307 | y = Math.max(Math.round((bb.get('winHeight') - bb.get('offsetHeight'))/2), 15) + Y.one(window).get('scrollTop'); | |
308 | bb.setStyles({ 'left' : x, 'top' : y}); | |
78686995 AN |
309 | |
310 | if (hidden) { | |
bf7c86cf | 311 | bb.addClass(DIALOGUE_HIDDEN_CLASS); |
78686995 | 312 | } |
d61c96b6 | 313 | }, |
bf7c86cf | 314 | /** |
1f777e5c AN |
315 | * Return whether this dialogue should be fullscreen or not. |
316 | * | |
bf7c86cf DW |
317 | * Responsive attribute must be true and we should not be in an iframe and the screen width should |
318 | * be less than the responsive width. | |
319 | * | |
320 | * @method shouldResizeFullscreen | |
1f777e5c | 321 | * @return {Boolean} |
bf7c86cf DW |
322 | */ |
323 | shouldResizeFullscreen : function() { | |
324 | return (window === window.parent) && this.get('responsive') && | |
325 | Math.floor(Y.one(document.body).get('winWidth')) < this.get('responsiveWidth'); | |
2eaaae00 JF |
326 | }, |
327 | ||
2eaaae00 JF |
328 | show : function() { |
329 | var result = null, | |
330 | header = this.headerNode, | |
e5ddec38 | 331 | content = this.bodyNode, |
c1660772 | 332 | focusSelector = this.get('focusOnShowSelector'), |
e5ddec38 | 333 | focusNode = null; |
2eaaae00 | 334 | |
b959e508 AN |
335 | result = DIALOGUE.superclass.show.call(this); |
336 | ||
73747aea AN |
337 | // Lock scroll if the plugin is present. |
338 | if (this.lockScroll) { | |
b959e508 AN |
339 | // We need to force the scroll locking for full screen dialogues, even if they have a small vertical size to |
340 | // prevent the background scrolling while the dialogue is open. | |
341 | this.lockScroll.enableScrollLock(this.shouldResizeFullscreen()); | |
73747aea AN |
342 | } |
343 | ||
c1660772 DW |
344 | // Try and find a node to focus on using the focusOnShowSelector attribute. |
345 | if (focusSelector !== null) { | |
e5ddec38 | 346 | focusNode = this.get('boundingBox').one(focusSelector); |
2eaaae00 | 347 | } |
e5ddec38 DW |
348 | if (!focusNode) { |
349 | // Fall back to the header or the content if no focus node was found yet. | |
350 | if (header && header !== '') { | |
351 | focusNode = header; | |
352 | } else if (content && content !== '') { | |
353 | focusNode = content; | |
354 | } | |
355 | } | |
c1660772 DW |
356 | if (focusNode) { |
357 | focusNode.focus(); | |
358 | } | |
2eaaae00 | 359 | return result; |
586d393f | 360 | }, |
73747aea | 361 | |
bf24abd2 AN |
362 | hide: function(e) { |
363 | if (e) { | |
364 | // If the event was closed by an escape key event, then we need to check that this | |
365 | // dialogue is currently focused to prevent closing all dialogues in the stack. | |
366 | if (e.type === 'key' && e.keyCode === 27 && !this.get('focused')) { | |
367 | return; | |
368 | } | |
369 | } | |
370 | ||
73747aea AN |
371 | // Unlock scroll if the plugin is present. |
372 | if (this.lockScroll) { | |
373 | this.lockScroll.disableScrollLock(); | |
374 | } | |
375 | ||
376 | return DIALOGUE.superclass.hide.call(this, arguments); | |
377 | }, | |
586d393f | 378 | /** |
379 | * Setup key delegation to keep tabbing within the open dialogue. | |
380 | * | |
381 | * @method keyDelegation | |
382 | */ | |
383 | keyDelegation : function() { | |
384 | var bb = this.get('boundingBox'); | |
385 | bb.delegate('key', function(e){ | |
386 | var target = e.target; | |
387 | var direction = 'forward'; | |
388 | if (e.shiftKey) { | |
389 | direction = 'backward'; | |
390 | } | |
391 | if (this.trapFocus(target, direction)) { | |
392 | e.preventDefault(); | |
393 | } | |
394 | }, 'down:9', CAN_RECEIVE_FOCUS_SELECTOR, this); | |
395 | }, | |
1f777e5c | 396 | |
586d393f | 397 | /** |
398 | * Trap the tab focus within the open modal. | |
399 | * | |
1f777e5c AN |
400 | * @method trapFocus |
401 | * @param {string} target the element target | |
402 | * @param {string} direction tab key for forward and tab+shift for backward | |
403 | * @return {Boolean} The result of the focus action. | |
586d393f | 404 | */ |
405 | trapFocus : function(target, direction) { | |
406 | var bb = this.get('boundingBox'), | |
407 | firstitem = bb.one(CAN_RECEIVE_FOCUS_SELECTOR), | |
408 | lastitem = bb.all(CAN_RECEIVE_FOCUS_SELECTOR).pop(); | |
409 | ||
410 | if (target === lastitem && direction === 'forward') { // Tab key. | |
411 | return firstitem.focus(); | |
412 | } else if (target === firstitem && direction === 'backward') { // Tab+shift key. | |
413 | return lastitem.focus(); | |
414 | } | |
78686995 AN |
415 | } |
416 | }, { | |
417 | NAME : DIALOGUE_NAME, | |
418 | CSS_PREFIX : DIALOGUE_PREFIX, | |
419 | ATTRS : { | |
420 | notificationBase : { | |
421 | ||
422 | }, | |
423 | ||
424 | /** | |
425 | * Whether to display the dialogue modally and with a | |
426 | * lightbox style. | |
427 | * | |
428 | * @attribute lightbox | |
429 | * @type Boolean | |
430 | * @default true | |
cff3b8fe | 431 | * @deprecated Since Moodle 2.7. Please use modal instead. |
78686995 | 432 | */ |
cff3b8fe AN |
433 | lightbox: { |
434 | lazyAdd: false, | |
435 | setter: function(value) { | |
436 | Y.log("The lightbox attribute of M.core.dialogue has been deprecated since Moodle 2.7, please use the modal attribute instead", | |
437 | 'warn', 'moodle-core-notification-dialogue'); | |
438 | this.set('modal', value); | |
439 | } | |
78686995 AN |
440 | }, |
441 | ||
442 | /** | |
443 | * Whether to display a close button on the dialogue. | |
444 | * | |
445 | * Note, we do not recommend hiding the close button as this has | |
446 | * potential accessibility concerns. | |
447 | * | |
448 | * @attribute closeButton | |
449 | * @type Boolean | |
450 | * @default true | |
451 | */ | |
452 | closeButton : { | |
453 | validator : Y.Lang.isBoolean, | |
454 | value : true | |
455 | }, | |
456 | ||
457 | /** | |
458 | * The title for the close button if one is to be shown. | |
459 | * | |
460 | * @attribute closeButtonTitle | |
461 | * @type String | |
462 | * @default 'Close' | |
463 | */ | |
464 | closeButtonTitle : { | |
465 | validator : Y.Lang.isString, | |
0d1d5423 | 466 | value: M.util.get_string('closebuttontitle', 'moodle') |
78686995 AN |
467 | }, |
468 | ||
469 | /** | |
470 | * Whether to display the dialogue centrally on the screen. | |
471 | * | |
472 | * @attribute center | |
473 | * @type Boolean | |
474 | * @default true | |
475 | */ | |
476 | center : { | |
477 | validator : Y.Lang.isBoolean, | |
478 | value : true | |
479 | }, | |
480 | ||
481 | /** | |
482 | * Whether to make the dialogue movable around the page. | |
483 | * | |
484 | * @attribute draggable | |
485 | * @type Boolean | |
486 | * @default false | |
487 | */ | |
488 | draggable : { | |
489 | validator : Y.Lang.isBoolean, | |
490 | value : false | |
491 | }, | |
bf7c86cf DW |
492 | |
493 | /** | |
494 | * Used to generate a unique id for the dialogue. | |
495 | * | |
496 | * @attribute COUNT | |
d10e6118 AN |
497 | * @type String |
498 | * @default null | |
bf7c86cf | 499 | */ |
78686995 | 500 | COUNT: { |
d10e6118 | 501 | value: null |
d61c96b6 | 502 | }, |
bf7c86cf DW |
503 | |
504 | /** | |
505 | * Used to disable the fullscreen resizing behaviour if required. | |
506 | * | |
507 | * @attribute responsive | |
508 | * @type Boolean | |
509 | * @default true | |
510 | */ | |
d61c96b6 DW |
511 | responsive : { |
512 | validator : Y.Lang.isBoolean, | |
513 | value : true | |
514 | }, | |
bf7c86cf DW |
515 | |
516 | /** | |
517 | * The width that this dialogue should be resized to fullscreen. | |
518 | * | |
519 | * @attribute responsiveWidth | |
1f777e5c | 520 | * @type Number |
bf7c86cf DW |
521 | * @default 768 |
522 | */ | |
d61c96b6 DW |
523 | responsiveWidth : { |
524 | value : 768 | |
c1660772 DW |
525 | }, |
526 | ||
527 | /** | |
528 | * Selector to a node that should recieve focus when this dialogue is shown. | |
529 | * | |
530 | * The default behaviour is to focus on the header. | |
531 | * | |
532 | * @attribute focusOnShowSelector | |
533 | * @default null | |
534 | * @type String | |
535 | */ | |
536 | focusOnShowSelector: { | |
537 | value: null | |
78686995 | 538 | } |
c1660772 | 539 | |
78686995 AN |
540 | } |
541 | }); | |
542 | ||
16d02434 AN |
543 | Y.Base.modifyAttrs(DIALOGUE, { |
544 | /** | |
545 | * String with units, or number, representing the width of the Widget. | |
546 | * If a number is provided, the default unit, defined by the Widgets | |
547 | * DEF_UNIT, property is used. | |
548 | * | |
549 | * If a value of 'auto' is used, then an empty String is instead | |
550 | * returned. | |
551 | * | |
552 | * @attribute width | |
553 | * @default '400px' | |
554 | * @type {String|Number} | |
555 | */ | |
556 | width: { | |
557 | value: '400px', | |
558 | setter: function(value) { | |
559 | if (value === 'auto') { | |
560 | return ''; | |
561 | } | |
562 | return value; | |
563 | } | |
c46cca4f AN |
564 | }, |
565 | ||
566 | /** | |
567 | * Boolean indicating whether or not the Widget is visible. | |
568 | * | |
569 | * We override this from the default Widget attribute value. | |
570 | * | |
571 | * @attribute visible | |
572 | * @default false | |
573 | * @type Boolean | |
574 | */ | |
575 | visible: { | |
576 | value: false | |
a67233e7 AN |
577 | }, |
578 | ||
579 | /** | |
580 | * A convenience Attribute, which can be used as a shortcut for the | |
581 | * `align` Attribute. | |
582 | * | |
583 | * Note: We override this in Moodle such that it sets a value for the | |
584 | * `center` attribute if set. The `centered` will always return false. | |
585 | * | |
586 | * @attribute centered | |
587 | * @type Boolean|Node | |
588 | * @default false | |
589 | */ | |
590 | centered: { | |
591 | setter: function(value) { | |
592 | if (value) { | |
593 | this.set('center', true); | |
594 | } | |
595 | return false; | |
596 | } | |
d9bf4be4 SH |
597 | }, |
598 | ||
599 | /** | |
600 | * Boolean determining whether to render the widget during initialisation. | |
601 | * | |
602 | * We override this to change the default from false to true for the dialogue. | |
603 | * We then proceed to early render the dialogue during our initialisation rather than waiting | |
604 | * for YUI to render it after that. | |
605 | * | |
606 | * @attribute render | |
607 | * @type Boolean | |
608 | * @default true | |
609 | */ | |
610 | render : { | |
611 | value : true, | |
612 | writeOnce : true | |
2f5c1441 AN |
613 | }, |
614 | ||
615 | /** | |
616 | * Any additional classes to add to the boundingBox. | |
617 | * | |
1f777e5c | 618 | * @attribute extraClasses |
2f5c1441 AN |
619 | * @type Array |
620 | * @default [] | |
621 | */ | |
622 | extraClasses: { | |
623 | value: [] | |
16d02434 AN |
624 | } |
625 | }); | |
626 | ||
29ee3cf7 AN |
627 | Y.Base.mix(DIALOGUE, [Y.M.core.WidgetFocusAfterHide]); |
628 | ||
78686995 | 629 | M.core.dialogue = DIALOGUE; |
cfa770b4 AN |
630 | /** |
631 | * A dialogue type designed to display informative messages to users. | |
632 | * | |
633 | * @module moodle-core-notification | |
634 | */ | |
635 | ||
636 | /** | |
637 | * Extends core Dialogue to provide a type of dialogue which can be used | |
638 | * for informative message which are modal, and centered. | |
639 | * | |
640 | * @param {Object} config Object literal specifying the dialogue configuration properties. | |
641 | * @constructor | |
642 | * @class M.core.notification.info | |
643 | * @extends M.core.dialogue | |
644 | */ | |
645 | var INFO = function() { | |
646 | INFO.superclass.constructor.apply(this, arguments); | |
647 | }; | |
648 | ||
649 | Y.extend(INFO, M.core.dialogue, { | |
650 | }, { | |
651 | NAME: 'Moodle information dialogue', | |
652 | CSS_PREFIX: DIALOGUE_PREFIX | |
653 | }); | |
654 | ||
655 | Y.Base.modifyAttrs(INFO, { | |
656 | /** | |
657 | * Boolean indicating whether or not the Widget is visible. | |
658 | * | |
659 | * We override this from the default M.core.dialogue attribute value. | |
660 | * | |
661 | * @attribute visible | |
662 | * @default true | |
663 | * @type Boolean | |
664 | */ | |
665 | visible: { | |
666 | value: true | |
667 | }, | |
668 | ||
669 | /** | |
670 | * Whether the widget should be modal or not. | |
671 | * | |
672 | * We override this to change the default from false to true for a subset of dialogues. | |
673 | * | |
674 | * @attribute modal | |
675 | * @type Boolean | |
676 | * @default true | |
677 | */ | |
678 | modal: { | |
679 | validator: Y.Lang.isBoolean, | |
680 | value: true | |
681 | } | |
682 | }); | |
683 | ||
684 | M.core.notification = M.core.notification || {}; | |
685 | M.core.notification.info = INFO; | |
78686995 AN |
686 | |
687 | ||
29ee3cf7 AN |
688 | }, '@VERSION@', { |
689 | "requires": [ | |
690 | "base", | |
691 | "node", | |
692 | "panel", | |
cd6e149c | 693 | "escape", |
29ee3cf7 AN |
694 | "event-key", |
695 | "dd-plugin", | |
696 | "moodle-core-widget-focusafterclose", | |
697 | "moodle-core-lockscroll" | |
698 | ] | |
699 | }); |