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