MDL-37413 Use correct variable in chooserdialogue
[moodle.git] / lib / yui / chooserdialogue / chooserdialogue.js
CommitLineData
01e0e704
ARN
1YUI.add('moodle-core-chooserdialogue', function(Y) {
2
3 var CHOOSERDIALOGUE = function() {
4 CHOOSERDIALOGUE.superclass.constructor.apply(this, arguments);
5 }
6
7 Y.extend(CHOOSERDIALOGUE, Y.Base, {
2a88835d
DM
8 // The panel widget
9 panel: null,
01e0e704
ARN
10
11 // The submit button - we disable this until an element is set
12 submitbutton : null,
13
14 // The chooserdialogue container
15 container : null,
16
d9bd472b
ARN
17 // Any event listeners we may need to cancel later
18 listenevents : [],
19
b95b0508
ARN
20 // The initial overflow setting
21 initialoverflow : '',
22
8516492c
ARN
23 bodycontent : null,
24 headercontent : null,
25 instanceconfig : null,
26
01e0e704 27 setup_chooser_dialogue : function(bodycontent, headercontent, config) {
8516492c
ARN
28 this.bodycontent = bodycontent;
29 this.headercontent = headercontent;
30 this.instanceconfig = config;
31 },
32
33 prepare_chooser : function () {
0a7c94b3 34 if (this.panel) {
8516492c
ARN
35 return;
36 }
37
01e0e704
ARN
38 // Set Default options
39 var params = {
8516492c
ARN
40 bodyContent : this.bodycontent.get('innerHTML'),
41 headerContent : this.headercontent.get('innerHTML'),
984ec46e 42 draggable : true,
49ca3188
DM
43 visible : false, // Hide by default
44 zindex : 100, // Display in front of other items
45 lightbox : true, // This dialogue should be modal
46 shim : true,
47 closeButtonTitle : this.get('closeButtonTitle')
01e0e704
ARN
48 }
49
50 // Override with additional options
8516492c
ARN
51 for (paramkey in this.instanceconfig) {
52 params[paramkey] = this.instanceconfig[paramkey];
01e0e704
ARN
53 }
54
2a88835d
DM
55 // Create the panel
56 this.panel = new M.core.dialogue(params);
01e0e704
ARN
57
58 // Remove the template for the chooser
8516492c
ARN
59 this.bodycontent.remove();
60 this.headercontent.remove();
01e0e704 61
2a88835d
DM
62 // Hide and then render the panel
63 this.panel.hide();
64 this.panel.render();
01e0e704
ARN
65
66 // Set useful links
2a88835d 67 this.container = this.panel.get('boundingBox').one('.choosercontainer');
01e0e704 68 this.options = this.container.all('.option input[type=radio]');
255dd8d1
ARN
69
70 // Add the chooserdialogue class to the container for styling
2a88835d 71 this.panel.get('boundingBox').addClass('chooserdialogue');
01e0e704 72 },
d9bd472b 73
01e0e704
ARN
74 /**
75 * Display the module chooser
76 *
77 * @param e Event Triggering Event
78 * @return void
79 */
80 display_chooser : function (e) {
8516492c
ARN
81 this.prepare_chooser();
82
01e0e704
ARN
83 // Stop the default event actions before we proceed
84 e.preventDefault();
85
2a88835d 86 var bb = this.panel.get('boundingBox');
01e0e704
ARN
87 var dialogue = this.container.one('.alloptions');
88
b95b0508
ARN
89 // Get the overflow setting when the chooser was opened - we
90 // may need this later
91 if (Y.UA.ie > 0) {
92 this.initialoverflow = Y.one('html').getStyle('overflow');
93 } else {
94 this.initialoverflow = Y.one('body').getStyle('overflow');
95 }
96
d9bd472b
ARN
97 var thisevent;
98
baca9096
ARN
99 // This will detect a change in orientation and retrigger centering
100 thisevent = Y.one('document').on('orientationchange', function(e) {
101 this.center_dialogue(dialogue);
102 }, this);
103 this.listenevents.push(thisevent);
104
105 // Detect window resizes (most browsers)
106 thisevent = Y.one('window').on('resize', function(e) {
107 this.center_dialogue(dialogue);
108 }, this);
109 this.listenevents.push(thisevent);
110
01e0e704 111 // These will trigger a check_options call to display the correct help
d9bd472b
ARN
112 thisevent = this.container.on('click', this.check_options, this);
113 this.listenevents.push(thisevent);
114 thisevent = this.container.on('key_up', this.check_options, this);
115 this.listenevents.push(thisevent);
116 thisevent = this.container.on('dblclick', function(e) {
01e0e704
ARN
117 if (e.target.ancestor('div.option')) {
118 this.check_options();
d9bd472b
ARN
119
120 // Prevent duplicate submissions
121 this.submitbutton.setAttribute('disabled', 'disabled');
122 this.options.setAttribute('disabled', 'disabled');
123 this.cancel_listenevents();
124
01e0e704
ARN
125 this.container.one('form').submit();
126 }
127 }, this);
d9bd472b
ARN
128 this.listenevents.push(thisevent);
129
130 this.container.one('form').on('submit', function(e) {
131 // Prevent duplicate submissions on submit
132 this.submitbutton.setAttribute('disabled', 'disabled');
133 this.options.setAttribute('disabled', 'disabled');
134 this.cancel_listenevents();
135 }, this);
01e0e704
ARN
136
137 // Hook onto the cancel button to hide the form
605f92ca
ARN
138 thisevent = this.container.one('#addcancel').on('click', this.cancel_popup, this);
139 this.listenevents.push(thisevent);
2a88835d
DM
140
141 // Hide will be managed by cancel_popup after restoring the body overflow
142 thisevent = bb.one('button.closebutton').on('click', this.cancel_popup, this);
605f92ca 143 this.listenevents.push(thisevent);
01e0e704
ARN
144
145 // Grab global keyup events and handle them
605f92ca
ARN
146 thisevent = Y.one('document').on('keyup', this.handle_key_press, this);
147 this.listenevents.push(thisevent);
01e0e704
ARN
148
149 // Add references to various elements we adjust
150 this.jumplink = this.container.one('#jump');
151 this.submitbutton = this.container.one('#submitbutton');
152
153 // Disable the submit element until the user makes a selection
154 this.submitbutton.set('disabled', 'true');
155
d9bd472b
ARN
156 // Ensure that the options are shown
157 this.options.removeAttribute('disabled');
158
2a88835d
DM
159 // Display the panel
160 this.panel.show();
01e0e704 161
af75421c
ARN
162 // Re-centre the dialogue after we've shown it.
163 this.center_dialogue(dialogue);
164
01e0e704
ARN
165 // Finally, focus the first radio element - this enables form selection via the keyboard
166 this.container.one('.option input[type=radio]').focus();
167
168 // Trigger check_options to set the initial jumpurl
169 this.check_options();
170 },
d9bd472b
ARN
171
172 /**
173 * Cancel any listen events in the listenevents queue
174 *
175 * Several locations add event handlers which should only be called before the form is submitted. This provides
176 * a way of cancelling those events.
177 *
178 * @return void
179 */
180 cancel_listenevents : function () {
181 // Detach all listen events to prevent duplicate triggers
182 var thisevent;
183 while (thisevent = this.listenevents.shift()) {
184 thisevent.detach();
185 }
186 },
187
01e0e704
ARN
188 /**
189 * Calculate the optimum height of the chooser dialogue
190 *
191 * This tries to set a sensible maximum and minimum to ensure that some options are always shown, and preferably
d9bd472b 192 * all, whilst fitting the box within the current viewport.
01e0e704
ARN
193 *
194 * @param dialogue Y.Node The dialogue
195 * @return void
196 */
af75421c 197 center_dialogue : function(dialogue) {
2a88835d 198 var bb = this.panel.get('boundingBox');
af75421c
ARN
199
200 var winheight = bb.get('winHeight');
7db27680 201 var winwidth = bb.get('winWidth');
af75421c 202 var offsettop = 0;
01e0e704
ARN
203
204 // Try and set a sensible max-height -- this must be done before setting the top
205 // Set a default height of 640px
206 var newheight = this.get('maxheight');
207 if (winheight <= newheight) {
208 // Deal with smaller window sizes
209 if (winheight <= this.get('minheight')) {
210 newheight = this.get('minheight');
211 } else {
212 newheight = winheight;
213 }
214 }
215
216 // Set a fixed position if the window is large enough
217 if (newheight > this.get('minheight')) {
af75421c 218 bb.setStyle('position', 'fixed');
b95b0508
ARN
219 // Disable the page scrollbars
220 if (Y.UA.ie > 0) {
221 Y.one('html').setStyle('overflow', 'hidden');
222 } else {
223 Y.one('body').setStyle('overflow', 'hidden');
224 }
01e0e704 225 } else {
af75421c
ARN
226 bb.setStyle('position', 'absolute');
227 offsettop = Y.one('window').get('scrollTop');
b95b0508
ARN
228 // Ensure that the page scrollbars are enabled
229 if (Y.UA.ie > 0) {
230 Y.one('html').setStyle('overflow', this.initialoverflow);
231 } else {
232 Y.one('body').setStyle('overflow', this.initialoverflow);
233 }
01e0e704
ARN
234 }
235
236 // Take off 15px top and bottom for borders, plus 40px each for the title and button area before setting the
237 // new max-height
af75421c 238 var totalheight = newheight;
01e0e704
ARN
239 newheight = newheight - (15 + 15 + 40 + 40);
240 dialogue.setStyle('max-height', newheight + 'px');
af75421c 241 dialogue.setStyle('height', newheight + 'px');
01e0e704
ARN
242
243 // Re-calculate the location now that we've changed the size
af75421c
ARN
244 var dialoguetop = Math.max(12, ((winheight - totalheight) / 2)) + offsettop;
245
246 // We need to set the height for the yui3-widget - can't work
247 // out what we're setting at present -- shoud be the boudingBox
248 bb.setStyle('top', dialoguetop + 'px');
7db27680
ARN
249
250 // Calculate the left location of the chooser
251 // We don't set a minimum width in the same way as we do height as the width would be far lower than the
252 // optimal width for moodle anyway.
253 var dialoguewidth = bb.get('offsetWidth');
254 var dialogueleft = (winwidth - dialoguewidth) / 2;
255 bb.setStyle('left', dialogueleft + 'px');
01e0e704 256 },
d9bd472b 257
01e0e704
ARN
258 handle_key_press : function(e) {
259 if (e.keyCode == 27) {
260 this.cancel_popup(e);
261 }
262 },
d9bd472b 263
01e0e704
ARN
264 cancel_popup : function (e) {
265 // Prevent normal form submission before hiding
266 e.preventDefault();
267 this.hide();
268 },
d9bd472b 269
01e0e704 270 hide : function() {
dfe15e0e
ARN
271 // Cancel all listen events
272 this.cancel_listenevents();
b95b0508
ARN
273
274 // Re-enable the page scrollbars
275 if (Y.UA.ie > 0) {
276 Y.one('html').setStyle('overflow', this.initialoverflow);
277 } else {
278 Y.one('body').setStyle('overflow', this.initialoverflow);
279 }
280
01e0e704 281 this.container.detachAll();
2a88835d 282 this.panel.hide();
01e0e704 283 },
d9bd472b 284
01e0e704
ARN
285 check_options : function(e) {
286 // Check which options are set, and change the parent class
287 // to show/hide help as required
288 this.options.each(function(thisoption) {
289 var optiondiv = thisoption.get('parentNode').get('parentNode');
290 if (thisoption.get('checked')) {
291 optiondiv.addClass('selected');
292
293 // Trigger any events for this option
294 this.option_selected(thisoption);
295
296 // Ensure that the form may be submitted
297 this.submitbutton.removeAttribute('disabled');
298
299 // Ensure that the radio remains focus so that keyboard navigation is still possible
300 thisoption.focus();
301 } else {
302 optiondiv.removeClass('selected');
303 }
304 }, this);
305 },
d9bd472b 306
01e0e704
ARN
307 option_selected : function(e) {
308 }
309 },
310 {
311 NAME : 'moodle-core-chooserdialogue',
312 ATTRS : {
313 minheight : {
314 value : 300
315 },
316 maxheight : {
317 value : 660
49ca3188
DM
318 },
319 closeButtonTitle : {
320 validator : Y.Lang.isString,
321 value : 'Close'
01e0e704
ARN
322 }
323 }
324 });
325 M.core = M.core || {};
326 M.core.chooserdialogue = CHOOSERDIALOGUE;
327},
328'@VERSION@', {
2a88835d 329 requires:['base', 'panel', 'moodle-enrol-notification']
01e0e704
ARN
330}
331);