MDL-35959 Correct footer for M.core.dialogue
[moodle.git] / enrol / yui / notification / notification.js
1 YUI.add('moodle-enrol-notification', function(Y) {
3 var DIALOGUE_NAME = 'Moodle dialogue',
4     DIALOGUE_PREFIX = 'moodle-dialogue',
5     CONFIRM_NAME = 'Moodle confirmation dialogue',
6     EXCEPTION_NAME = 'Moodle exception',
7     AJAXEXCEPTION_NAME = 'Moodle AJAX exception',
8     ALERT_NAME = 'Moodle alert',
9     C = Y.Node.create,
10     BASE = 'notificationBase',
11     LIGHTBOX = 'lightbox',
12     NODELIGHTBOX = 'nodeLightbox',
13     COUNT = 0,
14     CONFIRMYES = 'yesLabel',
15     CONFIRMNO = 'noLabel',
16     TITLE = 'title',
17     QUESTION = 'question',
18     CSS = {
19         BASE : 'moodle-dialogue-base',
20         WRAP : 'moodle-dialogue-wrap',
21         HEADER : 'moodle-dialogue-hd',
22         BODY : 'moodle-dialogue-bd',
23         CONTENT : 'moodle-dialogue-content',
24         FOOTER : 'moodle-dialogue-ft',
25         HIDDEN : 'hidden',
26         LIGHTBOX : 'moodle-dialogue-lightbox'
27     };
29 var DIALOGUE = function(config) {
30     COUNT++;
31     var id = 'moodle-dialogue-'+COUNT;
32     config.notificationBase =
33         C('<div class="'+CSS.BASE+'">')
34             .append(C('<div class="'+CSS.LIGHTBOX+' '+CSS.HIDDEN+'"></div>'))
35             .append(C('<div id="'+id+'" class="'+CSS.WRAP+'"></div>')
36                 .append(C('<div class="'+CSS.HEADER+' yui3-widget-hd"></div>'))
37                 .append(C('<div class="'+CSS.BODY+' yui3-widget-bd"></div>'))
38                 .append(C('<div class="'+CSS.FOOTER+' yui3-widget-ft"></div>')));
39     Y.one(document.body).append(config.notificationBase);
40     config.srcNode =    '#'+id;
41     config.width =      config.width || '400px';
42     config.visible =    config.visible || false;
43     config.center =     config.centered || true;
44     config.centered =   false;
45     DIALOGUE.superclass.constructor.apply(this, [config]);
46 };
47 Y.extend(DIALOGUE, Y.Overlay, {
48     initializer : function(config) {
49         this.set(NODELIGHTBOX, this.get(BASE).one('.'+CSS.LIGHTBOX).setStyle('opacity', 0.5));
50         this.after('visibleChange', this.visibilityChanged, this);
51         this.after('headerContentChange', function(e){
52             var h = (this.get('closeButton'))?this.get(BASE).one('.'+CSS.HEADER):false;
53             if (h && !h.one('.closebutton')) {
54                 var c = C('<div class="closebutton"></div>');
55                 c.on('click', this.hide, this);
56                 h.append(c);
57             }
58         }, this);
59         this.render();
60         this.show();
61     },
62     visibilityChanged : function(e) {
63         switch (e.attrName) {
64             case 'visible':
65                 if (this.get(LIGHTBOX)) {
66                     var l = this.get(NODELIGHTBOX);
67                     if (!e.prevVal && e.newVal) {
68                         l.setStyle('height',l.get('docHeight')+'px').removeClass(CSS.HIDDEN);
69                     } else if (e.prevVal && !e.newVal) {
70                         l.addClass(CSS.HIDDEN);
71                     }
72                 }
73                 if (this.get('center') && !e.prevVal && e.newVal) {
74                     this.centerDialogue();
75                 }
76                 if (this.get('draggable')) {
77                     var titlebar = '#' + this.get('id') + ' .' + CSS.HEADER;
78                     this.plug(Y.Plugin.Drag, {handles : [titlebar]});
79                     this.dd.addInvalid('div.closebutton');
80                     Y.one(titlebar).setStyle('cursor', 'move');
81                 }
82                 break;
83         }
84     },
85     centerDialogue : function() {
86         var bb = this.get('boundingBox'), hidden = bb.hasClass(DIALOGUE_PREFIX+'-hidden');
87         if (hidden) {
88             bb.setStyle('top', '-1000px').removeClass(DIALOGUE_PREFIX+'-hidden');
89         }
90         var x = Math.max(Math.round((bb.get('winWidth') - bb.get('offsetWidth'))/2), 15);
91         var y = Math.max(Math.round((bb.get('winHeight') - bb.get('offsetHeight'))/2), 15) + Y.one(window).get('scrollTop');
93         if (hidden) {
94             bb.addClass(DIALOGUE_PREFIX+'-hidden');
95         }
96         bb.setStyle('left', x).setStyle('top', y);
97     }
98 }, {
99     NAME : DIALOGUE_NAME,
100     CSS_PREFIX : DIALOGUE_PREFIX,
101     ATTRS : {
102         notificationBase : {
104         },
105         nodeLightbox : {
106             value : null
107         },
108         lightbox : {
109             validator : Y.Lang.isBoolean,
110             value : true
111         },
112         closeButton : {
113             validator : Y.Lang.isBoolean,
114             value : true
115         },
116         center : {
117             validator : Y.Lang.isBoolean,
118             value : true
119         },
120         draggable : {
121             validator : Y.Lang.isBoolean,
122             value : false
123         }
124     }
125 });
127 var ALERT = function(config) {
128     config.closeButton = false;
129     ALERT.superclass.constructor.apply(this, [config]);
130 };
131 Y.extend(ALERT, DIALOGUE, {
132     _enterKeypress : null,
133     initializer : function(config) {
134         this.publish('complete');
135         var yes = C('<input type="button" value="'+this.get(CONFIRMYES)+'" />'),
136             content = C('<div class="confirmation-dialogue"></div>')
137                     .append(C('<div class="confirmation-message">'+this.get('message')+'</div>'))
138                     .append(C('<div class="confirmation-buttons"></div>')
139                             .append(yes));
140         this.get(BASE).addClass('moodle-dialogue-confirm');
141         this.setStdModContent(Y.WidgetStdMod.BODY, content, Y.WidgetStdMod.REPLACE);
142         this.setStdModContent(Y.WidgetStdMod.HEADER, this.get(TITLE), Y.WidgetStdMod.REPLACE);
143         this.after('destroyedChange', function(){this.get(BASE).remove();}, this);
144         this._enterKeypress = Y.on('key', this.submit, window, 'down:13', this);
145         yes.on('click', this.submit, this);
146     },
147     submit : function(e, outcome) {
148         this._enterKeypress.detach();
149         this.fire('complete');
150         this.hide();
151         this.destroy();
152     }
153 }, {
154     NAME : ALERT_NAME,
155     CSS_PREFIX : DIALOGUE_PREFIX,
156     ATTRS : {
157         title : {
158             validator : Y.Lang.isString,
159             value : 'Alert'
160         },
161         message : {
162             validator : Y.Lang.isString,
163             value : 'Confirm'
164         },
165         yesLabel : {
166             validator : Y.Lang.isString,
167             setter : function(txt) {
168                 if (!txt) {
169                     txt = 'Ok';
170                 }
171                 return txt;
172             },
173             value : 'Ok'
174         }
175     }
176 });
178 var CONFIRM = function(config) {
179     CONFIRM.superclass.constructor.apply(this, [config]);
180 };
181 Y.extend(CONFIRM, DIALOGUE, {
182     _enterKeypress : null,
183     _escKeypress : null,
184     initializer : function(config) {
185         this.publish('complete');
186         this.publish('complete-yes');
187         this.publish('complete-no');
188         var yes = C('<input type="button" value="'+this.get(CONFIRMYES)+'" />'),
189             no = C('<input type="button" value="'+this.get(CONFIRMNO)+'" />'),
190             content = C('<div class="confirmation-dialogue"></div>')
191                         .append(C('<div class="confirmation-message">'+this.get(QUESTION)+'</div>'))
192                         .append(C('<div class="confirmation-buttons"></div>')
193                             .append(yes)
194                             .append(no));
195         this.get(BASE).addClass('moodle-dialogue-confirm');
196         this.setStdModContent(Y.WidgetStdMod.BODY, content, Y.WidgetStdMod.REPLACE);
197         this.setStdModContent(Y.WidgetStdMod.HEADER, this.get(TITLE), Y.WidgetStdMod.REPLACE);
198         this.after('destroyedChange', function(){this.get(BASE).remove();}, this);
199         this._enterKeypress = Y.on('key', this.submit, window, 'down:13', this, true);
200         this._escKeypress = Y.on('key', this.submit, window, 'down:27', this, false);
201         yes.on('click', this.submit, this, true);
202         no.on('click', this.submit, this, false);
203     },
204     submit : function(e, outcome) {
205         this._enterKeypress.detach();
206         this._escKeypress.detach();
207         this.fire('complete', outcome);
208         if (outcome) {
209             this.fire('complete-yes');
210         } else {
211             this.fire('complete-no');
212         }
213         this.hide();
214         this.destroy();
215     }
216 }, {
217     NAME : CONFIRM_NAME,
218     CSS_PREFIX : DIALOGUE_PREFIX,
219     ATTRS : {
220         yesLabel : {
221             validator : Y.Lang.isString,
222             value : 'Yes'
223         },
224         noLabel : {
225             validator : Y.Lang.isString,
226             value : 'No'
227         },
228         title : {
229             validator : Y.Lang.isString,
230             value : 'Confirm'
231         },
232         question : {
233             validator : Y.Lang.isString,
234             value : 'Are you sure?'
235         }
236     }
237 });
238 Y.augment(CONFIRM, Y.EventTarget);
240 var EXCEPTION = function(config) {
241     config.width = config.width || (M.cfg.developerdebug)?Math.floor(Y.one(document.body).get('winWidth')/3)+'px':null;
242     config.closeButton = true;
243     EXCEPTION.superclass.constructor.apply(this, [config]);
244 };
245 Y.extend(EXCEPTION, DIALOGUE, {
246     _hideTimeout : null,
247     _keypress : null,
248     initializer : function(config) {
249         this.get(BASE).addClass('moodle-dialogue-exception');
250         this.setStdModContent(Y.WidgetStdMod.HEADER, config.name, Y.WidgetStdMod.REPLACE);
251         var content = C('<div class="moodle-exception"></div>')
252                     .append(C('<div class="moodle-exception-message">'+this.get('message')+'</div>'))
253                     .append(C('<div class="moodle-exception-param hidden param-filename"><label>File:</label> '+this.get('fileName')+'</div>'))
254                     .append(C('<div class="moodle-exception-param hidden param-linenumber"><label>Line:</label> '+this.get('lineNumber')+'</div>'))
255                     .append(C('<div class="moodle-exception-param hidden param-stacktrace"><label>Stack trace:</label> <pre>'+this.get('stack')+'</pre></div>'));
256         if (M.cfg.developerdebug) {
257             content.all('.moodle-exception-param').removeClass('hidden');
258         }
259         this.setStdModContent(Y.WidgetStdMod.BODY, content, Y.WidgetStdMod.REPLACE);
261         var self = this;
262         var delay = this.get('hideTimeoutDelay');
263         if (delay) {
264             this._hideTimeout = setTimeout(function(){self.hide();}, delay);
265         }
266         this.after('visibleChange', this.visibilityChanged, this);
267         this.after('destroyedChange', function(){this.get(BASE).remove();}, this);
268         this._keypress = Y.on('key', this.hide, window, 'down:13,27', this);
269         this.centerDialogue();
270     },
271     visibilityChanged : function(e) {
272         if (e.attrName == 'visible' && e.prevVal && !e.newVal) {
273             if (this._keypress) this._keypress.detach();
274             var self = this;
275             setTimeout(function(){self.destroy();}, 1000);
276         }
277     }
278 }, {
279     NAME : EXCEPTION_NAME,
280     CSS_PREFIX : DIALOGUE_PREFIX,
281     ATTRS : {
282         message : {
283             value : ''
284         },
285         name : {
286             value : ''
287         },
288         fileName : {
289             value : ''
290         },
291         lineNumber : {
292             value : ''
293         },
294         stack : {
295             setter : function(str) {
296                 var lines = str.split("\n");
297                 var pattern = new RegExp('^(.+)@('+M.cfg.wwwroot+')?(.{0,75}).*:(\\d+)$');
298                 for (var i in lines) {
299                     lines[i] = lines[i].replace(pattern, "<div class='stacktrace-line'>ln: $4</div><div class='stacktrace-file'>$3</div><div class='stacktrace-call'>$1</div>");
300                 }
301                 return lines.join('');
302             },
303             value : ''
304         },
305         hideTimeoutDelay : {
306             validator : Y.Lang.isNumber,
307             value : null
308         }
309     }
310 });
312 var AJAXEXCEPTION = function(config) {
313     config.name = config.name || 'Error';
314     config.closeButton = true;
315     AJAXEXCEPTION.superclass.constructor.apply(this, [config]);
316 };
317 Y.extend(AJAXEXCEPTION, DIALOGUE, {
318     _keypress : null,
319     initializer : function(config) {
320         this.get(BASE).addClass('moodle-dialogue-exception');
321         this.setStdModContent(Y.WidgetStdMod.HEADER, config.name, Y.WidgetStdMod.REPLACE);
322         var content = C('<div class="moodle-ajaxexception"></div>')
323                     .append(C('<div class="moodle-exception-message">'+this.get('error')+'</div>'))
324                     .append(C('<div class="moodle-exception-param hidden param-debuginfo"><label>URL:</label> '+this.get('reproductionlink')+'</div>'))
325                     .append(C('<div class="moodle-exception-param hidden param-debuginfo"><label>Debug info:</label> '+this.get('debuginfo')+'</div>'))
326                     .append(C('<div class="moodle-exception-param hidden param-stacktrace"><label>Stack trace:</label> <pre>'+this.get('stacktrace')+'</pre></div>'));
327         if (M.cfg.developerdebug) {
328             content.all('.moodle-exception-param').removeClass('hidden');
329         }
330         this.setStdModContent(Y.WidgetStdMod.BODY, content, Y.WidgetStdMod.REPLACE);
332         var self = this;
333         var delay = this.get('hideTimeoutDelay');
334         if (delay) {
335             this._hideTimeout = setTimeout(function(){self.hide();}, delay);
336         }
337         this.after('visibleChange', this.visibilityChanged, this);
338         this._keypress = Y.on('key', this.hide, window, 'down:13, 27', this);
339         this.centerDialogue();
340     },
341     visibilityChanged : function(e) {
342         if (e.attrName == 'visible' && e.prevVal && !e.newVal) {
343             var self = this;
344             this._keypress.detach();
345             setTimeout(function(){self.destroy();}, 1000);
346         }
347     }
348 }, {
349     NAME : AJAXEXCEPTION_NAME,
350     CSS_PREFIX : DIALOGUE_PREFIX,
351     ATTRS : {
352         error : {
353             validator : Y.Lang.isString,
354             value : 'Unknown error'
355         },
356         debuginfo : {
357             value : null
358         },
359         stacktrace : {
360             value : null
361         },
362         reproductionlink : {
363             setter : function(link) {
364                 if (link !== null) {
365                     link = '<a href="'+link+'">'+link.replace(M.cfg.wwwroot, '')+'</a>';
366                 }
367                 return link;
368             },
369             value : null
370         },
371         hideTimeoutDelay : {
372             validator : Y.Lang.isNumber,
373             value : null
374         }
375     }
376 });
378 M.core = M.core || {};
379 M.core.dialogue = DIALOGUE;
380 M.core.alert = ALERT;
381 M.core.confirm = CONFIRM;
382 M.core.exception = EXCEPTION;
383 M.core.ajaxException = AJAXEXCEPTION;
385 }, '@VERSION@', {requires:['base','node','overlay','event-key', 'moodle-enrol-notification-skin', 'dd-plugin']});