Commit | Line | Data |
---|---|---|
ebaa29d1 ARN |
1 | YUI.add('moodle-course-toolboxes', function(Y) { |
2 | WAITICON = {'pix':"i/loading_small",'component':'moodle'}; | |
3 | // The CSS selectors we use | |
4 | var CSS = { | |
5 | ACTIVITYLI : 'li.activity', | |
537194ff | 6 | COMMANDSPAN : 'span.commands', |
b3c35188 | 7 | SPINNERCOMMANDSPAN : 'span.commands', |
eac3ed52 | 8 | CONTENTAFTERLINK : 'div.contentafterlink', |
ebaa29d1 ARN |
9 | DELETE : 'a.editing_delete', |
10 | DIMCLASS : 'dimmed', | |
eac3ed52 | 11 | DIMMEDTEXT : 'dimmed_text', |
7a9a07d2 | 12 | EDITTITLE : 'a.editing_title', |
ebaa29d1 ARN |
13 | EDITTITLECLASS : 'edittitle', |
14 | GENERICICONCLASS : 'iconsmall', | |
15 | GROUPSNONE : 'a.editing_groupsnone', | |
16 | GROUPSSEPARATE : 'a.editing_groupsseparate', | |
17 | GROUPSVISIBLE : 'a.editing_groupsvisible', | |
18 | HASLABEL : 'label', | |
19 | HIDE : 'a.editing_hide', | |
20 | HIGHLIGHT : 'a.editing_highlight', | |
21 | INSTANCENAME : 'span.instancename', | |
22 | LIGHTBOX : 'lightbox', | |
23 | MODINDENTCOUNT : 'mod-indent-', | |
24 | MODINDENTDIV : 'div.mod-indent', | |
95ef704d | 25 | MODINDENTHUGE : 'mod-indent-huge', |
ebaa29d1 ARN |
26 | MODULEIDPREFIX : 'module-', |
27 | MOVELEFT : 'a.editing_moveleft', | |
28 | MOVELEFTCLASS : 'editing_moveleft', | |
29 | MOVERIGHT : 'a.editing_moveright', | |
30 | PAGECONTENT : 'div#page-content', | |
31 | RIGHTDIV : 'div.right', | |
32 | SECTIONHIDDENCLASS : 'hidden', | |
33 | SECTIONIDPREFIX : 'section-', | |
34 | SECTIONLI : 'li.section', | |
35 | SHOW : 'a.editing_show', | |
36 | SHOWHIDE : 'a.editing_showhide' | |
37 | }; | |
38 | ||
39 | /** | |
40 | * The toolbox classes | |
41 | * | |
42 | * TOOLBOX is a generic class which should never be directly instantiated | |
43 | * RESOURCETOOLBOX is a class extending TOOLBOX containing code specific to resources | |
44 | * SECTIONTOOLBOX is a class extending TOOLBOX containing code specific to sections | |
45 | */ | |
46 | var TOOLBOX = function() { | |
47 | TOOLBOX.superclass.constructor.apply(this, arguments); | |
48 | } | |
49 | ||
50 | Y.extend(TOOLBOX, Y.Base, { | |
51 | /** | |
52 | * Replace the button click at the selector with the specified | |
53 | * callback | |
54 | * | |
55 | * @param toolboxtarget The selector of the working area | |
56 | * @param selector The 'button' to replace | |
57 | * @param callback The callback to apply | |
58 | * @param cursor An optional cursor style to apply | |
59 | */ | |
60 | replace_button : function(toolboxtarget, selector, callback, cursor) { | |
61 | if (!cursor) { | |
62 | // Set the default cursor type to pointer to match the | |
63 | // anchor | |
64 | cursor = 'pointer'; | |
65 | } | |
66 | var button = Y.one(toolboxtarget).all(selector) | |
ebaa29d1 ARN |
67 | .setStyle('cursor', cursor); |
68 | ||
69 | // on isn't chainable and will return an event | |
70 | button.on('click', callback, this); | |
71 | ||
72 | return button; | |
73 | }, | |
74 | /** | |
75 | * Toggle the visibility and availability for the specified | |
76 | * resource show/hide button | |
77 | */ | |
78 | toggle_hide_resource_ui : function(button) { | |
79 | var element = button.ancestor(CSS.ACTIVITYLI); | |
80 | var hideicon = button.one('img'); | |
81 | ||
82 | var dimarea; | |
83 | var toggle_class; | |
84 | if (this.is_label(element)) { | |
eac3ed52 | 85 | toggle_class = CSS.DIMMEDTEXT; |
ebaa29d1 ARN |
86 | dimarea = element.one(CSS.MODINDENTDIV + ' div'); |
87 | } else { | |
88 | toggle_class = CSS.DIMCLASS; | |
89 | dimarea = element.one('a'); | |
90 | } | |
91 | ||
92 | var status = ''; | |
93 | var value; | |
94 | if (dimarea.hasClass(toggle_class)) { | |
95 | status = 'hide'; | |
96 | value = 1; | |
97 | } else { | |
98 | status = 'show'; | |
99 | value = 0; | |
100 | } | |
101 | ||
102 | // Change the UI | |
103 | dimarea.toggleClass(toggle_class); | |
eac3ed52 ARN |
104 | // We need to toggle dimming on the description too |
105 | element.all(CSS.CONTENTAFTERLINK).toggleClass(CSS.DIMMEDTEXT); | |
ebaa29d1 ARN |
106 | var newstring = M.util.get_string(status, 'moodle'); |
107 | hideicon.setAttrs({ | |
108 | 'alt' : newstring, | |
109 | 'title' : newstring, | |
110 | 'src' : M.util.image_url('t/' + status) | |
111 | }); | |
112 | button.set('title', newstring); | |
113 | button.set('className', 'editing_'+status); | |
114 | ||
115 | return value; | |
116 | }, | |
117 | /** | |
118 | * Send a request using the REST API | |
119 | * | |
120 | * @param data The data to submit | |
45b364b9 | 121 | * @param statusspinner (optional) A statusspinner which may contain a section loader |
ebaa29d1 ARN |
122 | * @param optionalconfig (optional) Any additional configuration to submit |
123 | * @return response responseText field from responce | |
124 | */ | |
45b364b9 | 125 | send_request : function(data, statusspinner, optionalconfig) { |
ebaa29d1 ARN |
126 | // Default data structure |
127 | if (!data) { | |
128 | data = {}; | |
129 | } | |
130 | // Handle any variables which we must pass back through to | |
131 | var pageparams = this.get('config').pageparams; | |
132 | for (varname in pageparams) { | |
133 | data[varname] = pageparams[varname]; | |
134 | } | |
135 | ||
ebaa29d1 ARN |
136 | data.sesskey = M.cfg.sesskey; |
137 | data.courseId = this.get('courseid'); | |
138 | ||
139 | var uri = M.cfg.wwwroot + this.get('ajaxurl'); | |
140 | ||
141 | // Define the configuration to send with the request | |
142 | var responsetext = []; | |
143 | var config = { | |
144 | method: 'POST', | |
145 | data: data, | |
146 | on: { | |
147 | success: function(tid, response) { | |
148 | try { | |
149 | responsetext = Y.JSON.parse(response.responseText); | |
150 | if (responsetext.error) { | |
151 | new M.core.ajaxException(responsetext); | |
152 | } | |
153 | } catch (e) {} | |
45b364b9 | 154 | if (statusspinner) { |
ebaa29d1 | 155 | window.setTimeout(function(e) { |
45b364b9 ARN |
156 | statusspinner.hide(); |
157 | }, 400); | |
ebaa29d1 ARN |
158 | } |
159 | }, | |
160 | failure : function(tid, response) { | |
45b364b9 ARN |
161 | if (statusspinner) { |
162 | statusspinner.hide(); | |
ebaa29d1 ARN |
163 | } |
164 | new M.core.ajaxException(response); | |
165 | } | |
166 | }, | |
167 | context: this, | |
168 | sync: true | |
169 | } | |
170 | ||
171 | // Apply optional config | |
172 | if (optionalconfig) { | |
173 | for (varname in optionalconfig) { | |
174 | config[varname] = optionalconfig[varname]; | |
175 | } | |
176 | } | |
177 | ||
45b364b9 ARN |
178 | if (statusspinner) { |
179 | statusspinner.show(); | |
ebaa29d1 ARN |
180 | } |
181 | ||
182 | // Send the request | |
183 | Y.io(uri, config); | |
184 | return responsetext; | |
185 | }, | |
186 | is_label : function(target) { | |
187 | return target.hasClass(CSS.HASLABEL); | |
188 | }, | |
189 | /** | |
190 | * Return the module ID for the specified element | |
191 | * | |
192 | * @param element The <li> element to determine a module-id number for | |
193 | * @return string The module ID | |
194 | */ | |
195 | get_element_id : function(element) { | |
196 | return element.get('id').replace(CSS.MODULEIDPREFIX, ''); | |
197 | }, | |
198 | /** | |
199 | * Return the module ID for the specified element | |
200 | * | |
201 | * @param element The <li> element to determine a module-id number for | |
202 | * @return string The module ID | |
203 | */ | |
204 | get_section_id : function(section) { | |
205 | return section.get('id').replace(CSS.SECTIONIDPREFIX, ''); | |
ebaa29d1 ARN |
206 | } |
207 | }, | |
208 | { | |
209 | NAME : 'course-toolbox', | |
210 | ATTRS : { | |
211 | // The ID of the current course | |
212 | courseid : { | |
213 | 'value' : 0 | |
214 | }, | |
215 | ajaxurl : { | |
216 | 'value' : 0 | |
217 | }, | |
218 | config : { | |
219 | 'value' : 0 | |
220 | } | |
221 | } | |
222 | } | |
223 | ); | |
224 | ||
225 | ||
226 | var RESOURCETOOLBOX = function() { | |
227 | RESOURCETOOLBOX.superclass.constructor.apply(this, arguments); | |
228 | } | |
229 | ||
230 | Y.extend(RESOURCETOOLBOX, TOOLBOX, { | |
231 | // Variables | |
232 | GROUPS_NONE : 0, | |
233 | GROUPS_SEPARATE : 1, | |
234 | GROUPS_VISIBLE : 2, | |
235 | ||
236 | /** | |
237 | * Initialize the resource toolbox | |
238 | * | |
239 | * Updates all span.commands with relevant handlers and other required changes | |
240 | */ | |
241 | initializer : function(config) { | |
242 | this.setup_for_resource(); | |
243 | M.course.coursebase.register_module(this); | |
244 | }, | |
245 | ||
246 | /** | |
247 | * Update any span.commands within the scope of the specified | |
248 | * selector with AJAX equivelants | |
249 | * | |
250 | * @param baseselector The selector to limit scope to | |
251 | * @return void | |
252 | */ | |
253 | setup_for_resource : function(baseselector) { | |
254 | if (!baseselector) { | |
537194ff | 255 | var baseselector = CSS.PAGECONTENT + ' ' + CSS.ACTIVITYLI;; |
ebaa29d1 ARN |
256 | } |
257 | ||
258 | Y.all(baseselector).each(this._setup_for_resource, this); | |
259 | }, | |
260 | _setup_for_resource : function(toolboxtarget) { | |
7a9a07d2 ARN |
261 | // Edit Title |
262 | this.replace_button(toolboxtarget, CSS.COMMANDSPAN + ' ' + CSS.EDITTITLE, this.edit_resource_title); | |
263 | ||
ebaa29d1 ARN |
264 | // Move left and right |
265 | this.replace_button(toolboxtarget, CSS.COMMANDSPAN + ' ' + CSS.MOVELEFT, this.move_left); | |
266 | this.replace_button(toolboxtarget, CSS.COMMANDSPAN + ' ' + CSS.MOVERIGHT, this.move_right); | |
267 | ||
268 | // Delete | |
269 | this.replace_button(toolboxtarget, CSS.COMMANDSPAN + ' ' + CSS.DELETE, this.delete_resource); | |
270 | ||
271 | // Show/Hide | |
272 | var showhide = this.replace_button(toolboxtarget, CSS.COMMANDSPAN + ' ' + CSS.HIDE, this.toggle_hide_resource); | |
273 | var shown = this.replace_button(toolboxtarget, CSS.COMMANDSPAN + ' ' + CSS.SHOW, this.toggle_hide_resource); | |
274 | ||
275 | showhide = showhide.concat(shown); | |
276 | showhide.each(function(node) { | |
277 | var section = node.ancestor(CSS.SECTIONLI); | |
278 | if (section && section.hasClass(CSS.SECTIONHIDDENCLASS)) { | |
279 | node.setStyle('cursor', 'auto'); | |
280 | } | |
281 | }); | |
282 | ||
283 | // Change Group Mode | |
284 | var groups; | |
285 | groups = this.replace_button(toolboxtarget, CSS.COMMANDSPAN + ' ' + CSS.GROUPSNONE, this.toggle_groupmode); | |
286 | groups.setAttribute('groupmode', this.GROUPS_NONE); | |
287 | ||
288 | groups = this.replace_button(toolboxtarget, CSS.COMMANDSPAN + ' ' + CSS.GROUPSSEPARATE, this.toggle_groupmode); | |
289 | groups.setAttribute('groupmode', this.GROUPS_SEPARATE); | |
290 | ||
291 | groups = this.replace_button(toolboxtarget, CSS.COMMANDSPAN + ' ' + CSS.GROUPSVISIBLE, this.toggle_groupmode); | |
292 | groups.setAttribute('groupmode', this.GROUPS_VISIBLE); | |
293 | }, | |
294 | move_left : function(e) { | |
45b364b9 | 295 | this.move_leftright(e, -1); |
ebaa29d1 ARN |
296 | }, |
297 | move_right : function(e) { | |
45b364b9 | 298 | this.move_leftright(e, 1); |
ebaa29d1 | 299 | }, |
45b364b9 | 300 | move_leftright : function(e, direction) { |
5bd03e12 ARN |
301 | // Prevent the default button action |
302 | e.preventDefault(); | |
303 | ||
ebaa29d1 ARN |
304 | // Get the element we're working on |
305 | var element = e.target.ancestor(CSS.ACTIVITYLI); | |
306 | ||
307 | // And we need to determine the current and new indent level | |
308 | var indentdiv = element.one(CSS.MODINDENTDIV); | |
309 | var indent = indentdiv.getAttribute('class').match(/mod-indent-(\d{1,})/); | |
310 | ||
311 | if (indent) { | |
312 | var oldindent = parseInt(indent[1]); | |
313 | var newindent = Math.max(0, (oldindent + parseInt(direction))); | |
314 | indentdiv.removeClass(indent[0]); | |
315 | } else { | |
316 | var oldindent = 0; | |
317 | var newindent = 1; | |
318 | } | |
319 | ||
320 | // Perform the move | |
321 | indentdiv.addClass(CSS.MODINDENTCOUNT + newindent); | |
322 | var data = { | |
323 | 'class' : 'resource', | |
324 | 'field' : 'indent', | |
325 | 'value' : newindent, | |
326 | 'id' : this.get_element_id(element) | |
327 | }; | |
b3c35188 | 328 | var spinner = M.util.add_spinner(Y, element.one(CSS.SPINNERCOMMANDSPAN)); |
45b364b9 | 329 | this.send_request(data, spinner); |
ebaa29d1 ARN |
330 | |
331 | // Handle removal/addition of the moveleft button | |
332 | if (newindent == 0) { | |
45b364b9 | 333 | element.one(CSS.MOVELEFT).remove(); |
ebaa29d1 ARN |
334 | } else if (newindent == 1 && oldindent == 0) { |
335 | this.add_moveleft(element); | |
336 | } | |
95ef704d ARN |
337 | |
338 | // Handle massive indentation to match non-ajax display | |
339 | var hashugeclass = indentdiv.hasClass(CSS.MODINDENTHUGE); | |
340 | if (newindent > 15 && !hashugeclass) { | |
341 | indentdiv.addClass(CSS.MODINDENTHUGE); | |
342 | } else if (newindent <= 15 && hashugeclass) { | |
343 | indentdiv.removeClass(CSS.MODINDENTHUGE); | |
344 | } | |
ebaa29d1 ARN |
345 | }, |
346 | delete_resource : function(e) { | |
5bd03e12 ARN |
347 | // Prevent the default button action |
348 | e.preventDefault(); | |
349 | ||
ebaa29d1 ARN |
350 | // Get the element we're working on |
351 | var element = e.target.ancestor(CSS.ACTIVITYLI); | |
352 | ||
353 | var confirmstring = ''; | |
354 | if (this.is_label(element)) { | |
355 | // Labels are slightly different to other activities | |
356 | var plugindata = { | |
357 | type : M.util.get_string('pluginname', 'label') | |
358 | } | |
359 | confirmstring = M.util.get_string('deletechecktype', 'moodle', plugindata) | |
360 | } else { | |
361 | var plugindata = { | |
362 | type : M.util.get_string('pluginname', element.getAttribute('class').match(/modtype_([^\s]*)/)[1]), | |
363 | name : element.one(CSS.INSTANCENAME).get('firstChild').get('data') | |
364 | } | |
365 | confirmstring = M.util.get_string('deletechecktypename', 'moodle', plugindata); | |
366 | } | |
367 | ||
368 | // Confirm element removal | |
369 | if (!confirm(confirmstring)) { | |
370 | return false; | |
371 | } | |
372 | ||
373 | // Actually remove the element | |
374 | element.remove(); | |
375 | var data = { | |
376 | 'class' : 'resource', | |
377 | 'action' : 'DELETE', | |
378 | 'id' : this.get_element_id(element) | |
379 | }; | |
380 | this.send_request(data); | |
381 | }, | |
382 | toggle_hide_resource : function(e) { | |
5bd03e12 ARN |
383 | // Prevent the default button action |
384 | e.preventDefault(); | |
385 | ||
ebaa29d1 ARN |
386 | // Return early if the current section is hidden |
387 | var section = e.target.ancestor(CSS.SECTIONLI); | |
388 | if (section && section.hasClass(CSS.SECTIONHIDDENCLASS)) { | |
389 | return; | |
390 | } | |
391 | ||
392 | // Get the element we're working on | |
393 | var element = e.target.ancestor(CSS.ACTIVITYLI); | |
394 | ||
395 | var button = e.target.ancestor('a', true); | |
396 | ||
397 | var value = this.toggle_hide_resource_ui(button); | |
398 | ||
399 | // Send the request | |
400 | var data = { | |
401 | 'class' : 'resource', | |
402 | 'field' : 'visible', | |
403 | 'value' : value, | |
404 | 'id' : this.get_element_id(element) | |
405 | }; | |
b3c35188 | 406 | var spinner = M.util.add_spinner(Y, element.one(CSS.SPINNERCOMMANDSPAN)); |
45b364b9 | 407 | this.send_request(data, spinner); |
ebaa29d1 ARN |
408 | }, |
409 | toggle_groupmode : function(e) { | |
5bd03e12 ARN |
410 | // Prevent the default button action |
411 | e.preventDefault(); | |
412 | ||
ebaa29d1 ARN |
413 | // Get the element we're working on |
414 | var element = e.target.ancestor(CSS.ACTIVITYLI); | |
415 | ||
416 | var button = e.target.ancestor('a', true); | |
417 | var icon = button.one('img'); | |
418 | ||
419 | // Current Mode | |
420 | var groupmode = button.getAttribute('groupmode'); | |
421 | groupmode++; | |
422 | if (groupmode > 2) { | |
423 | groupmode = 0; | |
424 | } | |
425 | button.setAttribute('groupmode', groupmode); | |
426 | ||
427 | var newtitle = ''; | |
428 | var iconsrc = ''; | |
429 | switch (groupmode) { | |
430 | case this.GROUPS_NONE: | |
431 | newtitle = 'groupsnone'; | |
432 | iconsrc = M.util.image_url('t/groupn'); | |
433 | break; | |
434 | case this.GROUPS_SEPARATE: | |
435 | newtitle = 'groupsseparate'; | |
436 | iconsrc = M.util.image_url('t/groups'); | |
437 | break; | |
438 | case this.GROUPS_VISIBLE: | |
439 | newtitle = 'groupsvisible'; | |
440 | iconsrc = M.util.image_url('t/groupv'); | |
441 | break; | |
442 | } | |
443 | newtitle = M.util.get_string('clicktochangeinbrackets', 'moodle', | |
444 | M.util.get_string(newtitle, 'moodle')); | |
445 | ||
446 | // Change the UI | |
447 | icon.setAttrs({ | |
448 | 'alt' : newtitle, | |
449 | 'title' : newtitle, | |
450 | 'src' : iconsrc | |
451 | }); | |
452 | button.setAttribute('title', newtitle); | |
453 | ||
454 | // And send the request | |
455 | var data = { | |
456 | 'class' : 'resource', | |
457 | 'field' : 'groupmode', | |
458 | 'value' : groupmode, | |
459 | 'id' : this.get_element_id(element) | |
460 | }; | |
b3c35188 | 461 | var spinner = M.util.add_spinner(Y, element.one(CSS.SPINNERCOMMANDSPAN)); |
45b364b9 | 462 | this.send_request(data, spinner); |
ebaa29d1 ARN |
463 | }, |
464 | /** | |
465 | * Add the moveleft button | |
466 | * This is required after moving left from an initial position of 0 | |
467 | * | |
468 | * @param target The encapsulating <li> element | |
469 | */ | |
470 | add_moveleft : function(target) { | |
471 | var left_string = M.util.get_string('moveleft', 'moodle'); | |
472 | var newicon = Y.Node.create('<img />') | |
473 | .addClass(CSS.GENERICICONCLASS) | |
474 | .setAttrs({ | |
475 | 'src' : M.util.image_url('t/left', 'moodle'), | |
476 | 'title' : left_string, | |
477 | 'alt' : left_string | |
478 | }); | |
5bd03e12 ARN |
479 | var moveright = target.one(CSS.MOVERIGHT); |
480 | var newlink = moveright.getAttribute('href').replace('indent=1', 'indent=-1'); | |
ebaa29d1 ARN |
481 | var anchor = new Y.Node.create('<a />') |
482 | .setStyle('cursor', 'pointer') | |
483 | .addClass(CSS.MOVELEFTCLASS) | |
5bd03e12 ARN |
484 | .setAttribute('href', newlink) |
485 | .setAttribute('title', left_string); | |
ebaa29d1 ARN |
486 | anchor.appendChild(newicon); |
487 | anchor.on('click', this.move_left, this); | |
5bd03e12 | 488 | moveright.insert(anchor, 'before'); |
7a9a07d2 ARN |
489 | }, |
490 | /** | |
491 | * Edit the title for the resource | |
492 | */ | |
493 | edit_resource_title : function(e) { | |
494 | // Get the element we're working on | |
495 | var element = e.target.ancestor(CSS.ACTIVITYLI); | |
496 | var instancename = element.one(CSS.INSTANCENAME); | |
497 | var currenttitle = instancename.get('firstChild'); | |
498 | var oldtitle = currenttitle.get('data'); | |
499 | var titletext = oldtitle; | |
500 | var editbutton = element.one('a.' + CSS.EDITTITLECLASS + ' img'); | |
501 | ||
502 | // Disable the current href to prevent redirections when editing | |
503 | var anchor = instancename.ancestor('a'); | |
504 | anchor.setAttribute('oldhref', anchor.getAttribute('href')); | |
505 | anchor.removeAttribute('href'); | |
506 | ||
507 | var data = { | |
508 | 'class' : 'resource', | |
509 | 'field' : 'gettitle', | |
510 | 'id' : this.get_element_id(element) | |
511 | }; | |
512 | ||
513 | // Try to retrieve the existing string from the server | |
514 | var response = this.send_request(data, editbutton); | |
515 | if (response.instancename) { | |
516 | titletext = response.instancename; | |
517 | } | |
518 | ||
519 | // Create the editor and submit button | |
520 | var editor = Y.Node.create('<input />') | |
521 | .setAttrs({ | |
522 | 'name' : 'title', | |
523 | 'value' : titletext, | |
524 | 'autocomplete' : 'off' | |
525 | }) | |
526 | .addClass('titleeditor'); | |
527 | var editform = Y.Node.create('<form />') | |
528 | .setStyle('padding', '0') | |
529 | .setStyle('display', 'inline') | |
530 | .setAttribute('action', '#'); | |
531 | ||
532 | var editinstructions = Y.Node.create('<span />') | |
533 | .addClass('editinstructions') | |
534 | .set('innerHTML', M.util.get_string('edittitleinstructions', 'moodle')); | |
535 | ||
536 | // Clear the existing content and put the editor in | |
537 | currenttitle.set('data', ''); | |
538 | editform.appendChild(editor); | |
539 | instancename.appendChild(editform); | |
540 | element.appendChild(editinstructions); | |
541 | e.preventDefault(); | |
542 | ||
543 | // Focus and select the editor text | |
544 | editor.focus().select(); | |
545 | ||
546 | // Handle cancellation of the editor | |
547 | editor.on('blur', function(e) { | |
548 | // Detach the blur event before removing as some actions trigger multiple blurs in | |
549 | // some browser | |
550 | editor.detach('blur'); | |
551 | editform.remove(); | |
552 | editinstructions.remove(); | |
553 | ||
554 | // Set the title and anchor back to their previous settings | |
555 | currenttitle.set('data', oldtitle); | |
556 | anchor.setAttribute('href', anchor.getAttribute('oldhref')); | |
557 | anchor.removeAttribute('oldhref'); | |
558 | }); | |
559 | ||
560 | // Handle form submission | |
561 | editform.on('submit', function(e) { | |
562 | // We don't actually want to submit anything | |
563 | e.preventDefault(); | |
564 | ||
565 | // Detach the handlers to prevent multiple submissions | |
566 | editform.detach('submit'); | |
567 | editor.detach('blur'); | |
568 | ||
569 | // We only accept strings which have valid content | |
570 | var newtitle = Y.Lang.trim(editor.get('value')); | |
571 | if (newtitle != null && newtitle != "" && newtitle != titletext) { | |
572 | var data = { | |
573 | 'class' : 'resource', | |
574 | 'field' : 'updatetitle', | |
575 | 'title' : newtitle, | |
576 | 'id' : this.get_element_id(element) | |
577 | }; | |
578 | var response = this.send_request(data, editbutton); | |
579 | if (response.instancename) { | |
580 | currenttitle.set('data', response.instancename); | |
581 | } | |
582 | } else { | |
583 | // Invalid content. Set the title back to it's original contents | |
584 | currenttitle.set('data', oldtitle); | |
585 | } | |
586 | ||
587 | editform.remove(); | |
588 | editinstructions.remove(); | |
589 | ||
590 | // We need a timeout here otherwise hitting return to save in some browsers triggers | |
591 | // the anchor | |
592 | setTimeout(function(e) { | |
593 | anchor.setAttribute('href', anchor.getAttribute('oldhref')); | |
594 | anchor.removeAttribute('oldhref'); | |
595 | }, 500); | |
596 | }, this); | |
ebaa29d1 ARN |
597 | } |
598 | }, { | |
599 | NAME : 'course-resource-toolbox', | |
600 | ATTRS : { | |
601 | courseid : { | |
602 | 'value' : 0 | |
603 | }, | |
604 | format : { | |
605 | 'value' : 'topics' | |
606 | } | |
607 | } | |
608 | }); | |
609 | ||
610 | var SECTIONTOOLBOX = function() { | |
611 | SECTIONTOOLBOX.superclass.constructor.apply(this, arguments); | |
612 | } | |
613 | ||
614 | Y.extend(SECTIONTOOLBOX, TOOLBOX, { | |
615 | /** | |
616 | * Initialize the toolboxes module | |
617 | * | |
618 | * Updates all span.commands with relevant handlers and other required changes | |
619 | */ | |
620 | initializer : function(config) { | |
621 | this.setup_for_section(); | |
622 | M.course.coursebase.register_module(this); | |
623 | }, | |
624 | /** | |
625 | * Update any section areas within the scope of the specified | |
626 | * selector with AJAX equivelants | |
627 | * | |
628 | * @param baseselector The selector to limit scope to | |
629 | * @return void | |
630 | */ | |
631 | setup_for_section : function(baseselector) { | |
632 | if (!baseselector) { | |
633 | var baseselector = CSS.PAGECONTENT; | |
634 | } | |
635 | ||
636 | Y.all(baseselector).each(this._setup_for_section, this); | |
637 | }, | |
638 | _setup_for_section : function(toolboxtarget) { | |
639 | // Section Highlighting | |
640 | this.replace_button(toolboxtarget, CSS.RIGHTDIV + ' ' + CSS.HIGHLIGHT, this.toggle_highlight); | |
641 | ||
642 | // Section Visibility | |
643 | this.replace_button(toolboxtarget, CSS.RIGHTDIV + ' ' + CSS.SHOWHIDE, this.toggle_hide_section); | |
644 | }, | |
645 | toggle_hide_section : function(e) { | |
5bd03e12 ARN |
646 | // Prevent the default button action |
647 | e.preventDefault(); | |
648 | ||
ebaa29d1 ARN |
649 | // Get the section we're working on |
650 | var section = e.target.ancestor(CSS.SECTIONLI); | |
651 | var button = e.target.ancestor('a', true); | |
652 | var hideicon = button.one('img'); | |
653 | ||
654 | // The value to submit | |
655 | var value; | |
656 | // The status text for strings and images | |
657 | var status; | |
658 | ||
659 | if (!section.hasClass(CSS.SECTIONHIDDENCLASS)) { | |
660 | section.addClass(CSS.SECTIONHIDDENCLASS); | |
661 | value = 0; | |
662 | status = 'show'; | |
663 | ||
664 | } else { | |
665 | section.removeClass(CSS.SECTIONHIDDENCLASS); | |
666 | value = 1; | |
667 | status = 'hide'; | |
668 | } | |
669 | ||
670 | var newstring = M.util.get_string(status + 'fromothers', 'format_' + this.get('format')); | |
671 | hideicon.setAttrs({ | |
672 | 'alt' : newstring, | |
673 | 'title' : newstring, | |
674 | 'src' : M.util.image_url('i/' + status) | |
675 | }); | |
676 | button.set('title', newstring); | |
677 | ||
678 | // Change the highlight status | |
679 | var data = { | |
680 | 'class' : 'section', | |
681 | 'field' : 'visible', | |
682 | 'id' : this.get_section_id(section), | |
683 | 'value' : value | |
684 | }; | |
685 | ||
6a14c4ff | 686 | var lightbox = M.util.add_lightbox(Y, section); |
ebaa29d1 ARN |
687 | lightbox.show(); |
688 | ||
45b364b9 | 689 | var response = this.send_request(data, lightbox); |
ebaa29d1 ARN |
690 | |
691 | var activities = section.all(CSS.ACTIVITYLI); | |
692 | activities.each(function(node) { | |
693 | if (node.one(CSS.SHOW)) { | |
694 | var button = node.one(CSS.SHOW); | |
695 | } else { | |
696 | var button = node.one(CSS.HIDE); | |
697 | } | |
698 | var activityid = this.get_element_id(node); | |
699 | ||
700 | if (Y.Array.indexOf(response.resourcestotoggle, activityid) != -1) { | |
701 | this.toggle_hide_resource_ui(button); | |
702 | } | |
703 | ||
704 | if (value == 0) { | |
705 | button.setStyle('cursor', 'auto'); | |
706 | } else { | |
707 | button.setStyle('cursor', 'pointer'); | |
708 | } | |
709 | }, this); | |
710 | }, | |
711 | toggle_highlight : function(e) { | |
5bd03e12 ARN |
712 | // Prevent the default button action |
713 | e.preventDefault(); | |
714 | ||
ebaa29d1 ARN |
715 | // Get the section we're working on |
716 | var section = e.target.ancestor(CSS.SECTIONLI); | |
717 | var button = e.target.ancestor('a', true); | |
718 | var buttonicon = button.one('img'); | |
719 | ||
720 | // Determine whether the marker is currently set | |
721 | var togglestatus = section.hasClass('current'); | |
722 | var value = 0; | |
723 | ||
724 | // Set the current highlighted item text | |
725 | var old_string = M.util.get_string('markthistopic', 'moodle'); | |
726 | Y.one(CSS.PAGECONTENT) | |
727 | .all(CSS.SECTIONLI + '.current ' + CSS.HIGHLIGHT) | |
728 | .set('title', old_string); | |
729 | Y.one(CSS.PAGECONTENT) | |
730 | .all(CSS.SECTIONLI + '.current ' + CSS.HIGHLIGHT + ' img') | |
731 | .set('title', old_string) | |
732 | .set('alt', old_string) | |
733 | .set('src', M.util.image_url('i/marker')); | |
734 | ||
735 | // Remove the highlighting from all sections | |
736 | var allsections = Y.one(CSS.PAGECONTENT).all(CSS.SECTIONLI) | |
737 | .removeClass('current'); | |
738 | ||
739 | // Then add it if required to the selected section | |
740 | if (!togglestatus) { | |
741 | section.addClass('current'); | |
742 | value = this.get_section_id(section); | |
743 | var new_string = M.util.get_string('markedthistopic', 'moodle'); | |
744 | button | |
745 | .set('title', new_string); | |
746 | buttonicon | |
747 | .set('title', new_string) | |
748 | .set('alt', new_string) | |
749 | .set('src', M.util.image_url('i/marked')); | |
750 | } | |
751 | ||
752 | // Change the highlight status | |
753 | var data = { | |
754 | 'class' : 'course', | |
755 | 'field' : 'marker', | |
756 | 'value' : value | |
757 | }; | |
6a14c4ff | 758 | var lightbox = M.util.add_lightbox(Y, section); |
ebaa29d1 | 759 | lightbox.show(); |
45b364b9 | 760 | this.send_request(data, lightbox); |
ebaa29d1 ARN |
761 | } |
762 | }, { | |
763 | NAME : 'course-section-toolbox', | |
764 | ATTRS : { | |
765 | courseid : { | |
766 | 'value' : 0 | |
767 | }, | |
768 | format : { | |
769 | 'value' : 'topics' | |
770 | } | |
771 | } | |
772 | }); | |
773 | ||
774 | M.course = M.course || {}; | |
775 | ||
776 | M.course.init_resource_toolbox = function(config) { | |
777 | return new RESOURCETOOLBOX(config); | |
778 | }; | |
779 | ||
780 | M.course.init_section_toolbox = function(config) { | |
781 | return new SECTIONTOOLBOX(config); | |
782 | }; | |
783 | ||
784 | }, | |
785 | '@VERSION@', { | |
786 | requires : ['base', 'node', 'io', 'moodle-course-coursebase'] | |
787 | } | |
788 | ); |