MDL-30899 moodle-core-notification Adding focus to non modal windows
[moodle.git] / enrol / cohort / yui / quickenrolment / quickenrolment.js
1 YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
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',
11         DEFAULTCOHORTROLE = 'defaultCohortRole',
12         COHORTS = 'cohorts',
13         MORERESULTS = 'moreresults',
14         FIRSTPAGE = 'firstpage',
15         OFFSET = 'offset',
16         PANELID = 'qce-panel-',
17         REQUIREREFRESH = 'requiresRefresh',
18         SEARCH = 'search',
19         URL = 'url',
20         AJAXURL = 'ajaxurl',
21         MANUALENROLMENT = 'manualEnrolment',
22         CSS = {
23             CLOSEBTN : 'close-button',
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',
30             ENROLUSERS : 'canenrolusers',
31             FOOTER : 'qce-footer',
32             HIDDEN : 'hidden',
33             LIGHTBOX : 'qce-loading-lightbox',
34             LOADINGICON : 'loading-icon',
35             MORERESULTS : 'qce-more-results',
36             PANEL : 'qce-panel',
37             PANELCONTENT : 'qce-panel-content',
38             PANELCOHORTS : 'qce-enrollable-cohorts',
39             PANELROLES : 'qce-assignable-roles',
40             PANELCONTROLS : 'qce-panel-controls',
41             SEARCH : 'qce-search'
42         },
43         COUNT = 0;
46     var CONTROLLER = function(config) {
47         CONTROLLER.superclass.constructor.apply(this, arguments);
48     };
49     CONTROLLER.prototype = {
50         initializer : function(config) {
51             COUNT ++;
52             this.publish('assignablerolesloaded', {fireOnce:true});
53             this.publish('cohortsloaded');
54             this.publish('defaultcohortroleloaded', {fireOnce:true});
56             var finishbutton = Y.Node.create('<div class="'+CSS.CLOSEBTN+'"></div>')
57                                    .append(Y.Node.create('<input type="button" value="'+M.str.enrol.finishenrollingusers+'" />'));
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>')
62                     .append(Y.Node.create('<div class="'+CSS.SEARCH+'"><label for="enrolcohortsearch">'+M.str.enrol_cohort.cohortsearch+':</label></div>')
63                         .append(Y.Node.create('<input type="text" id="enrolcohortsearch" value="" />'))
64                     )
65                     .append(finishbutton)
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                 );
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),
76                 bodyContent : base,
77                 constrain : true,
78                 centered : true,
79                 id : PANELID+COUNT,
80                 visible : false
81             });
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);
91             this.set(SEARCH, base.one('#enrolcohortsearch'));
92             Y.on('key', this.getCohorts, this.get(SEARCH), 'down:13', this, false);
94             panel.get('boundingBox').addClass(CSS.PANEL);
95             panel.render(Y.one(document.body));
96             this.on('show', function(){
97                 this.set('centered', true);
98                 this.show();
99             }, panel);
100             this.on('hide', panel.hide, panel);
101             this.on('assignablerolesloaded', this.updateContent, this, panel);
102             this.on('cohortsloaded', this.updateContent, this, panel);
103             this.on('defaultcohortroleloaded', this.updateContent, this, panel);
104             Y.on('key', this.hide, document.body, 'down:27', this);
105             close.on('click', this.hide, this);
106             finishbutton.on('click', this.hide, this);
108             Y.all('.enrol_cohort_plugin input').each(function(node){
109                 if (node.getAttribute('type', 'submit')) {
110                     node.on('click', this.show, this);
111                 }
112             }, this);
114             base = panel.get('boundingBox');
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();
121             // prepare the data and display the window
122             this.getCohorts(e, false);
123             this.getAssignableRoles();
124             this.fire('show');
126             var rolesselect = Y.one('#id_enrol_cohort_assignable_roles');
127             if (rolesselect) {
128                 rolesselect.focus();
129             }
130         },
131         updateContent : function(e, panel) {
132             var content, i, roles, cohorts, count=0, supportmanual = this.get(MANUALENROLMENT), defaultrole;
133             switch (e.type.replace(/^[^:]+:/, '')) {
134                 case 'cohortsloaded' :
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();
145                     }
146                     // add cohorts items to the content
147                     cohorts = this.get(COHORTS);
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                     }
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                     }
164                     break;
165                 case 'assignablerolesloaded':
166                     roles = this.get(ASSIGNABLEROLES);
167                     content = Y.Node.create('<select id="id_enrol_cohort_assignable_roles"></select>');
168                     for (i in roles) {
169                         content.append(Y.Node.create('<option value="'+i+'">'+roles[i]+'</option>'));
170                     }
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));
173                     this.getDefaultCohortRole();
174                     Y.one('#id_enrol_cohort_assignable_roles').focus();
175                     break;
176                 case 'defaultcohortroleloaded':
177                     defaultrole = this.get(DEFAULTCOHORTROLE);
178                     panel.get('contentBox').one('.'+CSS.PANELROLES+' select').set('value', defaultrole);
179                     break;
180             }
181         },
182         hide : function() {
183             if (this.get(REQUIREREFRESH)) {
184                 window.location = this.get(URL);
185             }
186             this.fire('hide');
187         },
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;
205             Y.io(M.cfg.wwwroot+this.get(AJAXURL), {
206                 method:'POST',
207                 data:build_querystring(params),
208                 on: {
209                     complete: function(tid, outcome, args) {
210                         try {
211                             var cohorts = Y.JSON.parse(outcome.responseText);
212                             if (cohorts.error) {
213                                 new M.core.ajaxException(cohorts);
214                             } else {
215                                 this.setCohorts(cohorts.response);
216                             }
217                         } catch (e) {
218                             return new M.core.exception(e);
219                         }
220                         this.fire('cohortsloaded');
221                     }
222                 },
223                 context:this
224             });
225         },
226         setCohorts : function(response) {
227             this.set(MORERESULTS, response.more);
228             this.set(OFFSET, response.offset);
229             var rawcohorts = response.cohorts;
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) {
246                             return new M.core.exception(e);
247                         }
248                         this.getAssignableRoles = function() {
249                             this.fire('assignablerolesloaded');
250                         };
251                         this.getAssignableRoles();
252                     }
253                 },
254                 context:this
255             });
256         },
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         },
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
282             };
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);
290                             if (result.error) {
291                                 new M.core.ajaxException(result);
292                             } else {
293                                 if (result.response && result.response.message) {
294                                     var alertpanel = new M.core.alert(result.response);
295                                     Y.Node.one('#id_yuialertconfirm-' + alertpanel.COUNT).focus();
296                                 }
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);
300                             }
301                         } catch (e) {
302                             new M.core.exception(e);
303                         }
304                     }
305                 },
306                 context:this
307             });
308             return true;
309         }
310     };
311     Y.extend(CONTROLLER, Y.Base, CONTROLLER.prototype, {
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
332             },
333             defaultCohortRole : {
334                 value : null
335             },
336             requiresRefresh : {
337                 value : false,
338                 validator : Y.Lang.isBool
339             }
340         }
341     });
342     Y.augment(CONTROLLER, Y.EventTarget);
344     var COHORT = function(config) {
345         COHORT.superclass.constructor.apply(this, arguments);
346     };
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 {
354                 button = Y.Node.create('<div id="cohortid_'+this.get(COHORTID)+'"></div>');
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);
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>');
368             return result.append(button).append(name).append(users);
369         }
370     }, {
371         NAME : COHORTNAME,
372         ATTRS : {
373             cohortid : {
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);
389     M.enrol_cohort = M.enrol || {};
390     M.enrol_cohort.quickenrolment = {
391         init : function(cfg) {
392             new CONTROLLER(cfg);
393         }
394     }
396 }, '@VERSION@', {requires:['base','node', 'overlay', 'io-base', 'test', 'json-parse', 'event-delegate', 'dd-plugin', 'event-key', 'moodle-core-notification']});