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