MDL-39851 filepicker: Fix for toolbar display wrapping on small screens
[moodle.git] / lib / yui / src / notification / js / dialogue.js
CommitLineData
78686995
AN
1/**
2 * The generic dialogue class for use in Moodle.
3 *
4 * @module moodle-core-notification
5 * @submodule moodle-core-notification-dialogue
6 */
7
8var DIALOGUE_NAME = 'Moodle dialogue',
9 DIALOGUE;
10
11/**
12 * A re-usable dialogue box with Moodle classes applied.
13 *
14 * @param {Object} config Object literal specifying the dialogue configuration properties.
15 * @constructor
16 * @class M.core.dialogue
17 * @extends Y.Panel
18 */
19DIALOGUE = function(config) {
20 COUNT++;
d61c96b6
DW
21 var id = 'moodle-dialogue-'+COUNT, inputSrcNode = false, contentNode;
22
23 if (config.srcNode) {
24 // We need to reparent this source node to the dialog.
25 inputSrcNode = config.srcNode;
26 }
78686995
AN
27 config.notificationBase =
28 Y.Node.create('<div class="'+CSS.BASE+'">')
29 .append(Y.Node.create('<div id="'+id+'" role="dialog" aria-labelledby="'+id+'-header-text" class="'+CSS.WRAP+'"></div>')
baffb422 30 .append(Y.Node.create('<div id="'+id+'-header-text" class="'+CSS.HEADER+' yui3-widget-hd"></div>'))
78686995
AN
31 .append(Y.Node.create('<div class="'+CSS.BODY+' yui3-widget-bd"></div>'))
32 .append(Y.Node.create('<div class="'+CSS.FOOTER+' yui3-widget-ft"></div>')));
33 Y.one(document.body).append(config.notificationBase);
b59f2e3b
SH
34
35 if (config.additionalBaseClass) {
36 config.notificationBase.addClass(config.additionalBaseClass);
37 }
38
78686995
AN
39 config.srcNode = '#'+id;
40 config.width = config.width || '400px';
41 config.visible = config.visible || false;
42 config.center = config.centered || true;
43 config.centered = false;
44 config.COUNT = COUNT;
45
b59f2e3b
SH
46 if (config.width === 'auto') {
47 delete config.width;
48 }
49
78686995
AN
50 // lightbox param to keep the stable versions API.
51 if (config.lightbox !== false) {
52 config.modal = true;
53 }
54 delete config.lightbox;
55
56 // closeButton param to keep the stable versions API.
57 if (config.closeButton === false) {
58 config.buttons = null;
59 } else {
60 config.buttons = [
61 {
62 section: Y.WidgetStdMod.HEADER,
63 classNames: 'closebutton',
64 action: function () {
65 this.hide();
66 }
67 }
68 ];
69 }
d61c96b6
DW
70 if (inputSrcNode) {
71 contentNode = Y.one(inputSrcNode);
72 // Do we need to remove it?
73 contentNode.get('parentNode').removeChild(contentNode);
74 Y.one('#' + id + ' .' + CSS.BODY).append(contentNode);
75 }
78686995
AN
76 DIALOGUE.superclass.constructor.apply(this, [config]);
77
78 if (config.closeButton !== false) {
79 // The buttons constructor does not allow custom attributes
80 this.get('buttons').header[0].setAttribute('title', this.get('closeButtonTitle'));
81 }
82};
83Y.extend(DIALOGUE, Y.Panel, {
d61c96b6
DW
84 // Window resize event listener.
85 _resizeevent : null,
86 // Orientation change event listener.
87 _orientationevent : null,
88
78686995 89 initializer : function() {
d61c96b6 90 var bb, classes, extraclass;
78686995
AN
91 this.after('visibleChange', this.visibilityChanged, this);
92 this.render();
93 this.show();
94 this.set('COUNT', COUNT);
95
96 // Workaround upstream YUI bug http://yuilibrary.com/projects/yui3/ticket/2532507
97 // and allow setting of z-index in theme.
d61c96b6
DW
98 bb = this.get('boundingBox');
99 bb.setStyle('zIndex', null);
100
101 // Add the list of extra classes to the bounding box for this dialog (for styling).
102 classes = this.get('extraClasses').split(' ');
103 extraclass = classes.pop();
104 while (typeof extraclass !== "undefined") {
105 bb.addClass(extraclass);
106 extraclass = classes.shift();
107 }
78686995
AN
108 },
109 visibilityChanged : function(e) {
110 var titlebar;
111 if (e.attrName === 'visible') {
112 this.get('maskNode').addClass(CSS.LIGHTBOX);
d61c96b6
DW
113 if (e.prevVal && !e.newVal) {
114 if (this._resizeevent) {
115 this._resizeevent.detach();
116 this._resizeevent = null;
117 }
118 if (this._orientationevent) {
119 this._orientationevent.detach();
120 this._orientationevent = null;
121 }
122 }
78686995
AN
123 if (this.get('center') && !e.prevVal && e.newVal) {
124 this.centerDialogue();
125 }
126 if (this.get('draggable')) {
127 titlebar = '#' + this.get('id') + ' .' + CSS.HEADER;
128 this.plug(Y.Plugin.Drag, {handles : [titlebar]});
129 Y.one(titlebar).setStyle('cursor', 'move');
130 }
131 }
132 },
133 centerDialogue : function() {
134 var bb = this.get('boundingBox'),
135 hidden = bb.hasClass(DIALOGUE_PREFIX+'-hidden'),
d61c96b6 136 content, x, y;
78686995
AN
137 if (hidden) {
138 bb.setStyle('top', '-1000px').removeClass(DIALOGUE_PREFIX+'-hidden');
139 }
d61c96b6
DW
140 if (this.get('fullscreen')) {
141 // Make this dialogue fullscreen on a small screen.
142 // Disable the page scrollbars.
143 if (Y.UA.ie > 0) {
144 Y.one('html').setStyle('overflow', 'hidden');
145 } else {
146 Y.one('body').setStyle('overflow', 'hidden');
147 }
148 // Size and position the fullscreen dialog.
149
150 bb.addClass(DIALOGUE_PREFIX+'-fullscreen');
151 bb.setStyle('left', '0px')
152 .setStyle('top', '0px')
153 .setStyle('width', '100%')
154 .setStyle('height', '100%')
155 .setStyle('overflow', 'auto');
156
157 content = Y.one('#' + this.get('id') + ' .' + CSS.BODY);
158 content.setStyle('overflow', 'auto');
159 window.scrollTo(0, 0);
160 } else {
161 if (this.get('responsive')) {
162 // We must reset any of the fullscreen changes.
163 bb.removeClass(DIALOGUE_PREFIX+'-fullscreen')
164 .setStyle('overflow', 'inherit')
165 .setStyle('width', this.get('width'))
166 .setStyle('height', this.get('height'));
167 content = Y.one('#' + this.get('id') + ' .' + CSS.BODY);
168 content.setStyle('overflow', 'inherit');
169
170 if (Y.UA.ie > 0) {
171 Y.one('html').setStyle('overflow', 'auto');
172 } else {
173 Y.one('body').setStyle('overflow', 'auto');
174 }
175 }
176 x = Math.max(Math.round((bb.get('winWidth') - bb.get('offsetWidth'))/2), 15);
177 y = Math.max(Math.round((bb.get('winHeight') - bb.get('offsetHeight'))/2), 15) + Y.one(window).get('scrollTop');
178 bb.setStyle('left', x).setStyle('top', y);
179 }
78686995
AN
180
181 if (hidden) {
182 bb.addClass(DIALOGUE_PREFIX+'-hidden');
183 }
d61c96b6
DW
184 },
185 hide : function() {
186 if (Y.UA.ie > 0) {
187 Y.one('html').setStyle('overflow', 'auto');
188 } else {
189 Y.one('body').setStyle('overflow', 'auto');
190 }
191 return this.set("visible", false);
78686995
AN
192 }
193}, {
194 NAME : DIALOGUE_NAME,
195 CSS_PREFIX : DIALOGUE_PREFIX,
196 ATTRS : {
197 notificationBase : {
198
199 },
200
201 /**
202 * Whether to display the dialogue modally and with a
203 * lightbox style.
204 *
205 * @attribute lightbox
206 * @type Boolean
207 * @default true
208 */
209 lightbox : {
210 validator : Y.Lang.isBoolean,
211 value : true
212 },
213
214 /**
215 * Whether to display a close button on the dialogue.
216 *
217 * Note, we do not recommend hiding the close button as this has
218 * potential accessibility concerns.
219 *
220 * @attribute closeButton
221 * @type Boolean
222 * @default true
223 */
224 closeButton : {
225 validator : Y.Lang.isBoolean,
226 value : true
227 },
228
229 /**
230 * The title for the close button if one is to be shown.
231 *
232 * @attribute closeButtonTitle
233 * @type String
234 * @default 'Close'
235 */
236 closeButtonTitle : {
237 validator : Y.Lang.isString,
238 value : 'Close'
239 },
240
241 /**
242 * Whether to display the dialogue centrally on the screen.
243 *
244 * @attribute center
245 * @type Boolean
246 * @default true
247 */
248 center : {
249 validator : Y.Lang.isBoolean,
250 value : true
251 },
252
253 /**
254 * Whether to make the dialogue movable around the page.
255 *
256 * @attribute draggable
257 * @type Boolean
258 * @default false
259 */
260 draggable : {
261 validator : Y.Lang.isBoolean,
262 value : false
263 },
264 COUNT: {
265 value: 0
d61c96b6
DW
266 },
267 responsive : {
268 validator : Y.Lang.isBoolean,
269 value : true
270 },
271 responsiveWidth : {
272 value : 768
273 },
274 extraClasses : {
275 validator : Y.Lang.isString,
276 value : ''
277 },
278 fullscreen : {
279 getter : function() {
280 return this.get('responsive') &&
281 Math.floor(Y.one(document.body).get('winWidth')) < this.get('responsiveWidth');
282 }
78686995
AN
283 }
284 }
285});
286
287M.core.dialogue = DIALOGUE;