MDL-30899 moodle-core-notification Adding focus to non modal windows
[moodle.git] / enrol / cohort / yui / quickenrolment / quickenrolment.js
CommitLineData
b69ca6be 1YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
2ec702c9
SH
2
3 var CONTROLLERNAME = 'Quick cohort enrolment controller',
4 COHORTNAME = 'Cohort',
5 COHORTID = 'cohortid',
6 ENROLLED = 'enrolled',
7 NAME = 'name',
8 USERS = 'users',
9 COURSEID = 'courseid',
10 ASSIGNABLEROLES = 'assignableRoles',
f9e29573 11 DEFAULTCOHORTROLE = 'defaultCohortRole',
2ec702c9 12 COHORTS = 'cohorts',
22a811be
RK
13 MORERESULTS = 'moreresults',
14 FIRSTPAGE = 'firstpage',
15 OFFSET = 'offset',
2ec702c9 16 PANELID = 'qce-panel-',
22a811be
RK
17 REQUIREREFRESH = 'requiresRefresh',
18 SEARCH = 'search',
2ec702c9
SH
19 URL = 'url',
20 AJAXURL = 'ajaxurl',
21 MANUALENROLMENT = 'manualEnrolment',
22 CSS = {
f068cac1 23 CLOSEBTN : 'close-button',
2ec702c9
SH
24 COHORT : 'qce-cohort',
25 COHORTS : 'qce-cohorts',
26 COHORTBUTTON : 'qce-cohort-button',
27 COHORTENROLLED : 'qce-cohort-enrolled',
28 COHORTNAME : 'qce-cohort-name',
29 COHORTUSERS : 'qce-cohort-users',
22a811be
RK
30 ENROLUSERS : 'canenrolusers',
31 FOOTER : 'qce-footer',
32 HIDDEN : 'hidden',
33 LIGHTBOX : 'qce-loading-lightbox',
34 LOADINGICON : 'loading-icon',
35 MORERESULTS : 'qce-more-results',
2ec702c9
SH
36 PANEL : 'qce-panel',
37 PANELCONTENT : 'qce-panel-content',
38 PANELCOHORTS : 'qce-enrollable-cohorts',
39 PANELROLES : 'qce-assignable-roles',
40 PANELCONTROLS : 'qce-panel-controls',
22a811be 41 SEARCH : 'qce-search'
2ec702c9
SH
42 },
43 COUNT = 0;
44
45
46 var CONTROLLER = function(config) {
47 CONTROLLER.superclass.constructor.apply(this, arguments);
8505d925 48 };
f9e29573 49 CONTROLLER.prototype = {
2ec702c9
SH
50 initializer : function(config) {
51 COUNT ++;
f9e29573 52 this.publish('assignablerolesloaded', {fireOnce:true});
2ec702c9 53 this.publish('cohortsloaded');
f9e29573 54 this.publish('defaultcohortroleloaded', {fireOnce:true});
8505d925 55
f068cac1
DM
56 var finishbutton = Y.Node.create('<div class="'+CSS.CLOSEBTN+'"></div>')
57 .append(Y.Node.create('<input type="button" value="'+M.str.enrol.finishenrollingusers+'" />'));
22a811be
RK
58 var base = Y.Node.create('<div class="'+CSS.PANELCONTENT+'"></div>')
59 .append(Y.Node.create('<div class="'+CSS.PANELROLES+'"></div>'))
60 .append(Y.Node.create('<div class="'+CSS.PANELCOHORTS+'"></div>'))
61 .append(Y.Node.create('<div class="'+CSS.FOOTER+'"></div>')
f068cac1 62 .append(Y.Node.create('<div class="'+CSS.SEARCH+'"><label for="enrolcohortsearch">'+M.str.enrol_cohort.cohortsearch+':</label></div>')
22a811be
RK
63 .append(Y.Node.create('<input type="text" id="enrolcohortsearch" value="" />'))
64 )
f068cac1 65 .append(finishbutton)
22a811be
RK
66 )
67 .append(Y.Node.create('<div class="'+CSS.LIGHTBOX+' '+CSS.HIDDEN+'"></div>')
68 .append(Y.Node.create('<img alt="loading" class="'+CSS.LOADINGICON+'" />')
69 .setAttribute('src', M.util.image_url('i/loading', 'moodle')))
70 .setStyle('opacity', 0.5)
71 );
72
2ec702c9
SH
73 var close = Y.Node.create('<div class="close"></div>');
74 var panel = new Y.Overlay({
75 headerContent : Y.Node.create('<div></div>').append(Y.Node.create('<h2>'+M.str.enrol.enrolcohort+'</h2>')).append(close),
22a811be 76 bodyContent : base,
2ec702c9
SH
77 constrain : true,
78 centered : true,
79 id : PANELID+COUNT,
80 visible : false
81 });
22a811be
RK
82
83 // display the wheel on ajax events
84 Y.on('io:start', function() {
85 base.one('.'+CSS.LIGHTBOX).removeClass(CSS.HIDDEN);
86 }, this);
87 Y.on('io:end', function() {
88 base.one('.'+CSS.LIGHTBOX).addClass(CSS.HIDDEN);
89 }, this);
90
91 this.set(SEARCH, base.one('#enrolcohortsearch'));
92 Y.on('key', this.getCohorts, this.get(SEARCH), 'down:13', this, false);
93
2ec702c9
SH
94 panel.get('boundingBox').addClass(CSS.PANEL);
95 panel.render(Y.one(document.body));
23cee7a4
SH
96 this.on('show', function(){
97 this.set('centered', true);
98 this.show();
99 }, panel);
57e8a936 100 this.on('hide', panel.hide, panel);
2ec702c9
SH
101 this.on('assignablerolesloaded', this.updateContent, this, panel);
102 this.on('cohortsloaded', this.updateContent, this, panel);
f9e29573 103 this.on('defaultcohortroleloaded', this.updateContent, this, panel);
22a811be 104 Y.on('key', this.hide, document.body, 'down:27', this);
2ec702c9 105 close.on('click', this.hide, this);
f068cac1 106 finishbutton.on('click', this.hide, this);
2ec702c9 107
b69ca6be 108 Y.all('.enrol_cohort_plugin input').each(function(node){
2ec702c9
SH
109 if (node.getAttribute('type', 'submit')) {
110 node.on('click', this.show, this);
111 }
112 }, this);
113
22a811be 114 base = panel.get('boundingBox');
2ec702c9
SH
115 base.plug(Y.Plugin.Drag);
116 base.dd.addHandle('.yui3-widget-hd h2');
117 base.one('.yui3-widget-hd h2').setStyle('cursor', 'move');
118 },
119 show : function(e) {
120 e.preventDefault();
22a811be
RK
121 // prepare the data and display the window
122 this.getCohorts(e, false);
2ec702c9
SH
123 this.getAssignableRoles();
124 this.fire('show');
f068cac1
DM
125
126 var rolesselect = Y.one('#id_enrol_cohort_assignable_roles');
127 if (rolesselect) {
128 rolesselect.focus();
129 }
2ec702c9
SH
130 },
131 updateContent : function(e, panel) {
f9e29573 132 var content, i, roles, cohorts, count=0, supportmanual = this.get(MANUALENROLMENT), defaultrole;
2ec702c9
SH
133 switch (e.type.replace(/^[^:]+:/, '')) {
134 case 'cohortsloaded' :
22a811be
RK
135 if (this.get(FIRSTPAGE)) {
136 // we are on the page 0, create new element for cohorts list
137 content = Y.Node.create('<div class="'+CSS.COHORTS+'"></div>');
138 if (supportmanual) {
139 content.addClass(CSS.ENROLUSERS);
140 }
141 } else {
142 // we are adding cohorts to existing list
143 content = Y.Node.one('.'+CSS.PANELCOHORTS+' .'+CSS.COHORTS);
144 content.one('.'+CSS.MORERESULTS).remove();
2ec702c9 145 }
22a811be
RK
146 // add cohorts items to the content
147 cohorts = this.get(COHORTS);
2ec702c9
SH
148 for (i in cohorts) {
149 count++;
150 cohorts[i].on('enrolchort', this.enrolCohort, this, cohorts[i], panel.get('contentBox'), false);
151 cohorts[i].on('enrolusers', this.enrolCohort, this, cohorts[i], panel.get('contentBox'), true);
152 content.append(cohorts[i].toHTML(supportmanual).addClass((count%2)?'even':'odd'));
153 }
22a811be
RK
154 // add the next link if there are more items expected
155 if (this.get(MORERESULTS)) {
156 var fetchmore = Y.Node.create('<div class="'+CSS.MORERESULTS+'"><a href="#">'+M.str.enrol_cohort.ajaxmore+'</a></div>');
157 fetchmore.on('click', this.getCohorts, this, true);
158 content.append(fetchmore);
159 }
160 // finally assing the content to the block
161 if (this.get(FIRSTPAGE)) {
162 panel.get('contentBox').one('.'+CSS.PANELCOHORTS).setContent(content);
163 }
2ec702c9
SH
164 break;
165 case 'assignablerolesloaded':
166 roles = this.get(ASSIGNABLEROLES);
f068cac1 167 content = Y.Node.create('<select id="id_enrol_cohort_assignable_roles"></select>');
2ec702c9
SH
168 for (i in roles) {
169 content.append(Y.Node.create('<option value="'+i+'">'+roles[i]+'</option>'));
170 }
f068cac1 171 panel.get('contentBox').one('.'+CSS.PANELROLES).setContent(Y.Node.create('<div><label for="id_enrol_cohort_assignable_roles">'+M.str.role.assignroles+':</label></div>').append(content));
f9e29573
SH
172
173 this.getDefaultCohortRole();
f068cac1 174 Y.one('#id_enrol_cohort_assignable_roles').focus();
f9e29573
SH
175 break;
176 case 'defaultcohortroleloaded':
177 defaultrole = this.get(DEFAULTCOHORTROLE);
7757237c 178 panel.get('contentBox').one('.'+CSS.PANELROLES+' select').set('value', defaultrole);
2ec702c9
SH
179 break;
180 }
181 },
182 hide : function() {
22a811be
RK
183 if (this.get(REQUIREREFRESH)) {
184 window.location = this.get(URL);
185 }
2ec702c9
SH
186 this.fire('hide');
187 },
22a811be
RK
188 getCohorts : function(e, append) {
189 if (e) {
190 e.preventDefault();
191 }
192 if (append) {
193 this.set(FIRSTPAGE, false);
194 } else {
195 this.set(FIRSTPAGE, true);
196 this.set(OFFSET, 0);
197 }
198 var params = [];
199 params['id'] = this.get(COURSEID);
200 params['offset'] = this.get(OFFSET);
201 params['search'] = this.get(SEARCH).get('value');
202 params['action'] = 'getcohorts';
203 params['sesskey'] = M.cfg.sesskey;
204
2ec702c9
SH
205 Y.io(M.cfg.wwwroot+this.get(AJAXURL), {
206 method:'POST',
22a811be 207 data:build_querystring(params),
2ec702c9
SH
208 on: {
209 complete: function(tid, outcome, args) {
210 try {
211 var cohorts = Y.JSON.parse(outcome.responseText);
6db3eee0
SH
212 if (cohorts.error) {
213 new M.core.ajaxException(cohorts);
214 } else {
215 this.setCohorts(cohorts.response);
216 }
2ec702c9 217 } catch (e) {
6db3eee0 218 return new M.core.exception(e);
2ec702c9 219 }
22a811be 220 this.fire('cohortsloaded');
2ec702c9
SH
221 }
222 },
223 context:this
224 });
225 },
22a811be
RK
226 setCohorts : function(response) {
227 this.set(MORERESULTS, response.more);
228 this.set(OFFSET, response.offset);
229 var rawcohorts = response.cohorts;
2ec702c9
SH
230 var cohorts = [], i=0;
231 for (i in rawcohorts) {
232 cohorts[rawcohorts[i].cohortid] = new COHORT(rawcohorts[i]);
233 }
234 this.set(COHORTS, cohorts);
235 },
236 getAssignableRoles : function() {
237 Y.io(M.cfg.wwwroot+this.get(AJAXURL), {
238 method:'POST',
239 data:'id='+this.get(COURSEID)+'&action=getassignable&sesskey='+M.cfg.sesskey,
240 on: {
241 complete: function(tid, outcome, args) {
242 try {
243 var roles = Y.JSON.parse(outcome.responseText);
244 this.set(ASSIGNABLEROLES, roles.response);
245 } catch (e) {
6db3eee0 246 return new M.core.exception(e);
2ec702c9
SH
247 }
248 this.getAssignableRoles = function() {
249 this.fire('assignablerolesloaded');
8505d925 250 };
2ec702c9
SH
251 this.getAssignableRoles();
252 }
253 },
254 context:this
255 });
256 },
f9e29573
SH
257 getDefaultCohortRole : function() {
258 Y.io(M.cfg.wwwroot+this.get(AJAXURL), {
259 method:'POST',
260 data:'id='+this.get(COURSEID)+'&action=getdefaultcohortrole&sesskey='+M.cfg.sesskey,
261 on: {
262 complete: function(tid, outcome, args) {
263 try {
264 var roles = Y.JSON.parse(outcome.responseText);
265 this.set(DEFAULTCOHORTROLE, roles.response);
266 } catch (e) {
267 return new M.core.exception(e);
268 }
269 this.fire('defaultcohortroleloaded');
270 }
271 },
272 context:this
273 });
274 },
2ec702c9
SH
275 enrolCohort : function(e, cohort, node, usersonly) {
276 var params = {
277 id : this.get(COURSEID),
278 roleid : node.one('.'+CSS.PANELROLES+' select').get('value'),
279 cohortid : cohort.get(COHORTID),
280 action : (usersonly)?'enrolcohortusers':'enrolcohort',
281 sesskey : M.cfg.sesskey
8505d925 282 };
2ec702c9
SH
283 Y.io(M.cfg.wwwroot+this.get(AJAXURL), {
284 method:'POST',
285 data:build_querystring(params),
286 on: {
287 complete: function(tid, outcome, args) {
288 try {
289 var result = Y.JSON.parse(outcome.responseText);
6db3eee0
SH
290 if (result.error) {
291 new M.core.ajaxException(result);
292 } else {
6db3eee0 293 if (result.response && result.response.message) {
f068cac1
DM
294 var alertpanel = new M.core.alert(result.response);
295 Y.Node.one('#id_yuialertconfirm-' + alertpanel.COUNT).focus();
2ec702c9 296 }
22a811be
RK
297 var enrolled = Y.Node.create('<div class="'+CSS.COHORTBUTTON+' alreadyenrolled">'+M.str.enrol.synced+'</div>');
298 node.one('.'+CSS.COHORT+' #cohortid_'+cohort.get(COHORTID)).replace(enrolled);
299 this.set(REQUIREREFRESH, true);
2ec702c9
SH
300 }
301 } catch (e) {
6db3eee0 302 new M.core.exception(e);
2ec702c9
SH
303 }
304 }
305 },
306 context:this
307 });
6db3eee0 308 return true;
2ec702c9 309 }
f9e29573
SH
310 };
311 Y.extend(CONTROLLER, Y.Base, CONTROLLER.prototype, {
2ec702c9
SH
312 NAME : CONTROLLERNAME,
313 ATTRS : {
314 url : {
315 validator : Y.Lang.isString
316 },
317 ajaxurl : {
318 validator : Y.Lang.isString
319 },
320 courseid : {
321 value : null
322 },
323 cohorts : {
324 validator : Y.Lang.isArray,
325 value : null
326 },
327 assignableRoles : {
328 value : null
329 },
330 manualEnrolment : {
331 value : false
f9e29573
SH
332 },
333 defaultCohortRole : {
334 value : null
22a811be
RK
335 },
336 requiresRefresh : {
337 value : false,
338 validator : Y.Lang.isBool
2ec702c9
SH
339 }
340 }
341 });
342 Y.augment(CONTROLLER, Y.EventTarget);
343
344 var COHORT = function(config) {
345 COHORT.superclass.constructor.apply(this, arguments);
8505d925 346 };
2ec702c9
SH
347 Y.extend(COHORT, Y.Base, {
348 toHTML : function(supportmanualenrolment){
349 var button, result, name, users, syncbutton, usersbutton;
350 result = Y.Node.create('<div class="'+CSS.COHORT+'"></div>');
351 if (this.get(ENROLLED)) {
352 button = Y.Node.create('<div class="'+CSS.COHORTBUTTON+' alreadyenrolled">'+M.str.enrol.synced+'</div>');
353 } else {
22a811be 354 button = Y.Node.create('<div id="cohortid_'+this.get(COHORTID)+'"></div>');
2ec702c9
SH
355
356 syncbutton = Y.Node.create('<a class="'+CSS.COHORTBUTTON+' notenrolled enrolcohort">'+M.str.enrol.enrolcohort+'</a>');
357 syncbutton.on('click', function(){this.fire('enrolchort');}, this);
358 button.append(syncbutton);
359
360 if (supportmanualenrolment) {
361 usersbutton = Y.Node.create('<a class="'+CSS.COHORTBUTTON+' notenrolled enrolusers">'+M.str.enrol.enrolcohortusers+'</a>');
362 usersbutton.on('click', function(){this.fire('enrolusers');}, this);
363 button.append(usersbutton);
364 }
365 }
366 name = Y.Node.create('<div class="'+CSS.COHORTNAME+'">'+this.get(NAME)+'</div>');
367 users = Y.Node.create('<div class="'+CSS.COHORTUSERS+'">'+this.get(USERS)+'</div>');
2ec702c9
SH
368 return result.append(button).append(name).append(users);
369 }
370 }, {
371 NAME : COHORTNAME,
372 ATTRS : {
373 cohortid : {
8505d925 374
2ec702c9
SH
375 },
376 name : {
377 validator : Y.Lang.isString
378 },
379 enrolled : {
380 value : false
381 },
382 users : {
383 value : 0
384 }
385 }
386 });
387 Y.augment(COHORT, Y.EventTarget);
388
b69ca6be
SH
389 M.enrol_cohort = M.enrol || {};
390 M.enrol_cohort.quickenrolment = {
2ec702c9
SH
391 init : function(cfg) {
392 new CONTROLLER(cfg);
393 }
394 }
395
d2a27ab0 396}, '@VERSION@', {requires:['base','node', 'overlay', 'io-base', 'test', 'json-parse', 'event-delegate', 'dd-plugin', 'event-key', 'moodle-core-notification']});