[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 YUI.add('moodle-mod_quiz-toolboxes', function (Y, NAME) { 2 3 /** 4 * Resource and activity toolbox class. 5 * 6 * This class is responsible for managing AJAX interactions with activities and resources 7 * when viewing a course in editing mode. 8 * 9 * @module moodle-course-toolboxes 10 * @namespace M.course.toolboxes 11 */ 12 13 // The CSS classes we use. 14 var CSS = { 15 ACTIVITYINSTANCE : 'activityinstance', 16 AVAILABILITYINFODIV : 'div.availabilityinfo', 17 CONTENTWITHOUTLINK : 'contentwithoutlink', 18 CONDITIONALHIDDEN : 'conditionalhidden', 19 DIMCLASS : 'dimmed', 20 DIMMEDTEXT : 'dimmed_text', 21 EDITINSTRUCTIONS : 'editinstructions', 22 EDITINGMAXMARK: 'editor_displayed', 23 HIDE : 'hide', 24 JOIN: 'page_join', 25 MODINDENTCOUNT : 'mod-indent-', 26 MODINDENTHUGE : 'mod-indent-huge', 27 MODULEIDPREFIX : 'slot-', 28 PAGE: 'page', 29 SECTIONHIDDENCLASS : 'hidden', 30 SECTIONIDPREFIX : 'section-', 31 SLOT : 'slot', 32 SHOW : 'editing_show', 33 TITLEEDITOR : 'titleeditor' 34 }, 35 // The CSS selectors we use. 36 SELECTOR = { 37 ACTIONAREA: '.actions', 38 ACTIONLINKTEXT : '.actionlinktext', 39 ACTIVITYACTION : 'a.cm-edit-action[data-action], a.editing_maxmark', 40 ACTIVITYFORM : 'span.instancemaxmarkcontainer form', 41 ACTIVITYICON : 'img.activityicon', 42 ACTIVITYINSTANCE : '.' + CSS.ACTIVITYINSTANCE, 43 ACTIVITYLINK: '.' + CSS.ACTIVITYINSTANCE + ' > a', 44 ACTIVITYLI : 'li.activity', 45 ACTIVITYMAXMARK : 'input[name=maxmark]', 46 COMMANDSPAN : '.commands', 47 CONTENTAFTERLINK : 'div.contentafterlink', 48 CONTENTWITHOUTLINK : 'div.contentwithoutlink', 49 EDITMAXMARK: 'a.editing_maxmark', 50 HIDE : 'a.editing_hide', 51 HIGHLIGHT : 'a.editing_highlight', 52 INSTANCENAME : 'span.instancename', 53 INSTANCEMAXMARK : 'span.instancemaxmark', 54 MODINDENTDIV : '.mod-indent', 55 MODINDENTOUTER : '.mod-indent-outer', 56 NUMQUESTIONS : '.numberofquestions', 57 PAGECONTENT : 'div#page-content', 58 PAGELI : 'li.page', 59 SECTIONUL : 'ul.section', 60 SHOW : 'a.' + CSS.SHOW, 61 SHOWHIDE : 'a.editing_showhide', 62 SLOTLI : 'li.slot', 63 SUMMARKS : '.mod_quiz_summarks' 64 }, 65 BODY = Y.one(document.body); 66 67 // Setup the basic namespace. 68 M.mod_quiz = M.mod_quiz || {}; 69 70 /** 71 * The toolbox class is a generic class which should never be directly 72 * instantiated. Please extend it instead. 73 * 74 * @class toolbox 75 * @constructor 76 * @protected 77 * @extends Base 78 */ 79 var TOOLBOX = function() { 80 TOOLBOX.superclass.constructor.apply(this, arguments); 81 }; 82 83 Y.extend(TOOLBOX, Y.Base, { 84 /** 85 * Send a request using the REST API 86 * 87 * @method send_request 88 * @param {Object} data The data to submit with the AJAX request 89 * @param {Node} [statusspinner] A statusspinner which may contain a section loader 90 * @param {Function} success_callback The callback to use on success 91 * @param {Object} [optionalconfig] Any additional configuration to submit 92 * @chainable 93 */ 94 send_request: function(data, statusspinner, success_callback, optionalconfig) { 95 // Default data structure 96 if (!data) { 97 data = {}; 98 } 99 // Handle any variables which we must pass back through to 100 var pageparams = this.get('config').pageparams, 101 varname; 102 for (varname in pageparams) { 103 data[varname] = pageparams[varname]; 104 } 105 106 data.sesskey = M.cfg.sesskey; 107 data.courseid = this.get('courseid'); 108 data.quizid = this.get('quizid'); 109 110 var uri = M.cfg.wwwroot + this.get('ajaxurl'); 111 112 // Define the configuration to send with the request 113 var responsetext = []; 114 var config = { 115 method: 'POST', 116 data: data, 117 on: { 118 success: function(tid, response) { 119 try { 120 responsetext = Y.JSON.parse(response.responseText); 121 if (responsetext.error) { 122 new M.core.ajaxException(responsetext); 123 } 124 } catch (e) {} 125 126 // Run the callback if we have one. 127 if (responsetext.hasOwnProperty('newsummarks')) { 128 Y.one(SELECTOR.SUMMARKS).setHTML(responsetext.newsummarks); 129 } 130 if (responsetext.hasOwnProperty('newnumquestions')) { 131 Y.one(SELECTOR.NUMQUESTIONS).setHTML(M.util.get_string('numquestionsx', 'quiz', responsetext.newnumquestions)); 132 } 133 if (success_callback) { 134 Y.bind(success_callback, this, responsetext)(); 135 } 136 137 if (statusspinner) { 138 window.setTimeout(function() { 139 statusspinner.hide(); 140 }, 400); 141 } 142 }, 143 failure: function(tid, response) { 144 if (statusspinner) { 145 statusspinner.hide(); 146 } 147 new M.core.ajaxException(response); 148 } 149 }, 150 context: this 151 }; 152 153 // Apply optional config 154 if (optionalconfig) { 155 for (varname in optionalconfig) { 156 config[varname] = optionalconfig[varname]; 157 } 158 } 159 160 if (statusspinner) { 161 statusspinner.show(); 162 } 163 164 // Send the request 165 Y.io(uri, config); 166 return this; 167 } 168 }, 169 { 170 NAME: 'mod_quiz-toolbox', 171 ATTRS: { 172 /** 173 * The ID of the Moodle Course being edited. 174 * 175 * @attribute courseid 176 * @default 0 177 * @type Number 178 */ 179 courseid: { 180 'value': 0 181 }, 182 183 /** 184 * The Moodle course format. 185 * 186 * @attribute format 187 * @default 'topics' 188 * @type String 189 */ 190 quizid: { 191 'value': 0 192 }, 193 /** 194 * The URL to use when submitting requests. 195 * @attribute ajaxurl 196 * @default null 197 * @type String 198 */ 199 ajaxurl: { 200 'value': null 201 }, 202 /** 203 * Any additional configuration passed when creating the instance. 204 * 205 * @attribute config 206 * @default {} 207 * @type Object 208 */ 209 config: { 210 'value': {} 211 } 212 } 213 } 214 ); 215 /** 216 * Resource and activity toolbox class. 217 * 218 * This class is responsible for managing AJAX interactions with activities and resources 219 * when viewing a quiz in editing mode. 220 * 221 * @module mod_quiz-resource-toolbox 222 * @namespace M.mod_quiz.resource_toolbox 223 */ 224 225 /** 226 * Resource and activity toolbox class. 227 * 228 * This is a class extending TOOLBOX containing code specific to resources 229 * 230 * This class is responsible for managing AJAX interactions with activities and resources 231 * when viewing a quiz in editing mode. 232 * 233 * @class resources 234 * @constructor 235 * @extends M.course.toolboxes.toolbox 236 */ 237 var RESOURCETOOLBOX = function() { 238 RESOURCETOOLBOX.superclass.constructor.apply(this, arguments); 239 }; 240 241 Y.extend(RESOURCETOOLBOX, TOOLBOX, { 242 /** 243 * An Array of events added when editing a max mark field. 244 * These should all be detached when editing is complete. 245 * 246 * @property editmaxmarkevents 247 * @protected 248 * @type Array 249 * @protected 250 */ 251 editmaxmarkevents: [], 252 253 /** 254 * 255 */ 256 NODE_PAGE: 1, 257 NODE_SLOT: 2, 258 NODE_JOIN: 3, 259 260 /** 261 * Initialize the resource toolbox 262 * 263 * For each activity the commands are updated and a reference to the activity is attached. 264 * This way it doesn't matter where the commands are going to called from they have a reference to the 265 * activity that they relate to. 266 * This is essential as some of the actions are displayed in an actionmenu which removes them from the 267 * page flow. 268 * 269 * This function also creates a single event delegate to manage all AJAX actions for all activities on 270 * the page. 271 * 272 * @method initializer 273 * @protected 274 */ 275 initializer: function() { 276 M.mod_quiz.quizbase.register_module(this); 277 BODY.delegate('key', this.handle_data_action, 'down:enter', SELECTOR.ACTIVITYACTION, this); 278 Y.delegate('click', this.handle_data_action, BODY, SELECTOR.ACTIVITYACTION, this); 279 }, 280 281 /** 282 * Handles the delegation event. When this is fired someone has triggered an action. 283 * 284 * Note not all actions will result in an AJAX enhancement. 285 * 286 * @protected 287 * @method handle_data_action 288 * @param {EventFacade} ev The event that was triggered. 289 * @returns {boolean} 290 */ 291 handle_data_action: function(ev) { 292 // We need to get the anchor element that triggered this event. 293 var node = ev.target; 294 if (!node.test('a')) { 295 node = node.ancestor(SELECTOR.ACTIVITYACTION); 296 } 297 298 // From the anchor we can get both the activity (added during initialisation) and the action being 299 // performed (added by the UI as a data attribute). 300 var action = node.getData('action'), 301 activity = node.ancestor(SELECTOR.ACTIVITYLI); 302 303 if (!node.test('a') || !action || !activity) { 304 // It wasn't a valid action node. 305 return; 306 } 307 308 // Switch based upon the action and do the desired thing. 309 switch (action) { 310 case 'editmaxmark': 311 // The user wishes to edit the maxmark of the resource. 312 this.edit_maxmark(ev, node, activity, action); 313 break; 314 case 'delete': 315 // The user is deleting the activity. 316 this.delete_with_confirmation(ev, node, activity, action); 317 break; 318 case 'addpagebreak': 319 case 'removepagebreak': 320 // The user is adding or removing a page break. 321 this.update_page_break(ev, node, activity, action); 322 break; 323 default: 324 // Nothing to do here! 325 break; 326 } 327 }, 328 329 /** 330 * Add a loading icon to the specified activity. 331 * 332 * The icon is added within the action area. 333 * 334 * @method add_spinner 335 * @param {Node} activity The activity to add a loading icon to 336 * @return {Node|null} The newly created icon, or null if the action area was not found. 337 */ 338 add_spinner: function(activity) { 339 var actionarea = activity.one(SELECTOR.ACTIONAREA); 340 if (actionarea) { 341 return M.util.add_spinner(Y, actionarea); 342 } 343 return null; 344 }, 345 346 /** 347 * Deletes the given activity or resource after confirmation. 348 * 349 * @protected 350 * @method delete_with_confirmation 351 * @param {EventFacade} ev The event that was fired. 352 * @param {Node} button The button that triggered this action. 353 * @param {Node} activity The activity node that this action will be performed on. 354 * @chainable 355 */ 356 delete_with_confirmation: function(ev, button, activity) { 357 // Prevent the default button action. 358 ev.preventDefault(); 359 360 // Get the element we're working on. 361 var element = activity, 362 // Create confirm string (different if element has or does not have name) 363 confirmstring = '', 364 qtypename = M.util.get_string('pluginname', 365 'qtype_' + element.getAttribute('class').match(/qtype_([^\s]*)/)[1]); 366 confirmstring = M.util.get_string('confirmremovequestion', 'quiz', qtypename); 367 368 // Create the confirmation dialogue. 369 var confirm = new M.core.confirm({ 370 question: confirmstring, 371 modal: true 372 }); 373 374 // If it is confirmed. 375 confirm.on('complete-yes', function() { 376 377 var spinner = this.add_spinner(element); 378 var data = { 379 'class': 'resource', 380 'action': 'DELETE', 381 'id': Y.Moodle.mod_quiz.util.slot.getId(element) 382 }; 383 this.send_request(data, spinner, function(response) { 384 if (response.deleted) { 385 // Actually remove the element. 386 Y.Moodle.mod_quiz.util.slot.remove(element); 387 this.reorganise_edit_page(); 388 if (M.core.actionmenu && M.core.actionmenu.instance) { 389 M.core.actionmenu.instance.hideMenu(); 390 } 391 } else { 392 window.location.reload(true); 393 } 394 }); 395 396 }, this); 397 398 return this; 399 }, 400 401 402 /** 403 * Edit the maxmark for the resource 404 * 405 * @protected 406 * @method edit_maxmark 407 * @param {EventFacade} ev The event that was fired. 408 * @param {Node} button The button that triggered this action. 409 * @param {Node} activity The activity node that this action will be performed on. 410 * @param {String} action The action that has been requested. 411 * @return Boolean 412 */ 413 edit_maxmark : function(ev, button, activity) { 414 // Get the element we're working on 415 var activityid = Y.Moodle.mod_quiz.util.slot.getId(activity), 416 instancemaxmark = activity.one(SELECTOR.INSTANCEMAXMARK), 417 instance = activity.one(SELECTOR.ACTIVITYINSTANCE), 418 currentmaxmark = instancemaxmark.get('firstChild'), 419 oldmaxmark = currentmaxmark.get('data'), 420 maxmarktext = oldmaxmark, 421 thisevent, 422 anchor = instancemaxmark,// Grab the anchor so that we can swap it with the edit form. 423 data = { 424 'class' : 'resource', 425 'field' : 'getmaxmark', 426 'id' : activityid 427 }; 428 429 // Prevent the default actions. 430 ev.preventDefault(); 431 432 this.send_request(data, null, function(response) { 433 if (M.core.actionmenu && M.core.actionmenu.instance) { 434 M.core.actionmenu.instance.hideMenu(); 435 } 436 437 // Try to retrieve the existing string from the server. 438 if (response.instancemaxmark) { 439 maxmarktext = response.instancemaxmark; 440 } 441 442 // Create the editor and submit button. 443 var editform = Y.Node.create('<form action="#" />'); 444 var editinstructions = Y.Node.create('<span class="' + CSS.EDITINSTRUCTIONS + '" id="id_editinstructions" />') 445 .set('innerHTML', M.util.get_string('edittitleinstructions', 'moodle')); 446 var editor = Y.Node.create('<input name="maxmark" type="text" class="' + CSS.TITLEEDITOR + '" />').setAttrs({ 447 'value' : maxmarktext, 448 'autocomplete' : 'off', 449 'aria-describedby' : 'id_editinstructions', 450 'maxLength' : '12', 451 'size' : parseInt(this.get('config').questiondecimalpoints, 10) + 2 452 }); 453 454 // Clear the existing content and put the editor in. 455 editform.appendChild(editor); 456 editform.setData('anchor', anchor); 457 instance.insert(editinstructions, 'before'); 458 anchor.replace(editform); 459 460 // Force the editing instruction to match the mod-indent position. 461 var padside = 'left'; 462 if (right_to_left()) { 463 padside = 'right'; 464 } 465 466 // We hide various components whilst editing: 467 activity.addClass(CSS.EDITINGMAXMARK); 468 469 // Focus and select the editor text. 470 editor.focus().select(); 471 472 // Cancel the edit if we lose focus or the escape key is pressed. 473 thisevent = editor.on('blur', this.edit_maxmark_cancel, this, activity, false); 474 this.editmaxmarkevents.push(thisevent); 475 thisevent = editor.on('key', this.edit_maxmark_cancel, 'esc', this, activity, true); 476 this.editmaxmarkevents.push(thisevent); 477 478 // Handle form submission. 479 thisevent = editform.on('submit', this.edit_maxmark_submit, this, activity, oldmaxmark); 480 this.editmaxmarkevents.push(thisevent); 481 }); 482 }, 483 484 /** 485 * Handles the submit event when editing the activity or resources maxmark. 486 * 487 * @protected 488 * @method edit_maxmark_submit 489 * @param {EventFacade} ev The event that triggered this. 490 * @param {Node} activity The activity whose maxmark we are altering. 491 * @param {String} originalmaxmark The original maxmark the activity or resource had. 492 */ 493 edit_maxmark_submit : function(ev, activity, originalmaxmark) { 494 // We don't actually want to submit anything. 495 ev.preventDefault(); 496 var newmaxmark = Y.Lang.trim(activity.one(SELECTOR.ACTIVITYFORM + ' ' + SELECTOR.ACTIVITYMAXMARK).get('value')); 497 var spinner = this.add_spinner(activity); 498 this.edit_maxmark_clear(activity); 499 activity.one(SELECTOR.INSTANCEMAXMARK).setContent(newmaxmark); 500 if (newmaxmark !== null && newmaxmark !== "" && newmaxmark !== originalmaxmark) { 501 var data = { 502 'class' : 'resource', 503 'field' : 'updatemaxmark', 504 'maxmark' : newmaxmark, 505 'id' : Y.Moodle.mod_quiz.util.slot.getId(activity) 506 }; 507 this.send_request(data, spinner, function(response) { 508 if (response.instancemaxmark) { 509 activity.one(SELECTOR.INSTANCEMAXMARK).setContent(response.instancemaxmark); 510 } 511 }); 512 } 513 }, 514 515 /** 516 * Handles the cancel event when editing the activity or resources maxmark. 517 * 518 * @protected 519 * @method edit_maxmark_cancel 520 * @param {EventFacade} ev The event that triggered this. 521 * @param {Node} activity The activity whose maxmark we are altering. 522 * @param {Boolean} preventdefault If true we should prevent the default action from occuring. 523 */ 524 edit_maxmark_cancel : function(ev, activity, preventdefault) { 525 if (preventdefault) { 526 ev.preventDefault(); 527 } 528 this.edit_maxmark_clear(activity); 529 }, 530 531 /** 532 * Handles clearing the editing UI and returning things to the original state they were in. 533 * 534 * @protected 535 * @method edit_maxmark_clear 536 * @param {Node} activity The activity whose maxmark we were altering. 537 */ 538 edit_maxmark_clear : function(activity) { 539 // Detach all listen events to prevent duplicate triggers 540 new Y.EventHandle(this.editmaxmarkevents).detach(); 541 542 var editform = activity.one(SELECTOR.ACTIVITYFORM), 543 instructions = activity.one('#id_editinstructions'); 544 if (editform) { 545 editform.replace(editform.getData('anchor')); 546 } 547 if (instructions) { 548 instructions.remove(); 549 } 550 551 // Remove the editing class again to revert the display. 552 activity.removeClass(CSS.EDITINGMAXMARK); 553 554 // Refocus the link which was clicked originally so the user can continue using keyboard nav. 555 Y.later(100, this, function() { 556 activity.one(SELECTOR.EDITMAXMARK).focus(); 557 }); 558 559 // This hack is to keep Behat happy until they release a version of 560 // MinkSelenium2Driver that fixes 561 // https://github.com/Behat/MinkSelenium2Driver/issues/80. 562 if (!Y.one('input[name=maxmark')) { 563 Y.one('body').append('<input type="text" name="maxmark" style="display: none">'); 564 } 565 }, 566 567 /** 568 * Joins or separates the given slot with the page of the previous slot. Reorders the pages of 569 * the other slots 570 * 571 * @protected 572 * @method update_page_break 573 * @param {EventFacade} ev The event that was fired. 574 * @param {Node} button The button that triggered this action. 575 * @param {Node} activity The activity node that this action will be performed on. 576 * @chainable 577 */ 578 update_page_break: function(ev, button, activity, action) { 579 // Prevent the default button action 580 ev.preventDefault(); 581 582 nextactivity = activity.next('li.activity.slot'); 583 var spinner = this.add_spinner(nextactivity), 584 slotid = 0; 585 var value = action === 'removepagebreak' ? 1 : 2; 586 587 var data = { 588 'class': 'resource', 589 'field': 'updatepagebreak', 590 'id': slotid, 591 'value': value 592 }; 593 594 slotid = Y.Moodle.mod_quiz.util.slot.getId(nextactivity); 595 if (slotid) { 596 data.id = Number(slotid); 597 } 598 this.send_request(data, spinner, function(response) { 599 if (response.slots) { 600 if (action === 'addpagebreak') { 601 Y.Moodle.mod_quiz.util.page.add(activity); 602 } else { 603 var page = activity.next(Y.Moodle.mod_quiz.util.page.SELECTORS.PAGE); 604 Y.Moodle.mod_quiz.util.page.remove(page, true); 605 } 606 this.reorganise_edit_page(); 607 } else { 608 window.location.reload(true); 609 } 610 }); 611 612 return this; 613 }, 614 615 /** 616 * Reorganise the UI after every edit action. 617 * 618 * @protected 619 * @method reorganise_edit_page 620 */ 621 reorganise_edit_page: function() { 622 Y.Moodle.mod_quiz.util.slot.reorderSlots(); 623 Y.Moodle.mod_quiz.util.slot.reorderPageBreaks(); 624 Y.Moodle.mod_quiz.util.page.reorderPages(); 625 }, 626 627 NAME : 'mod_quiz-resource-toolbox', 628 ATTRS : { 629 courseid : { 630 'value' : 0 631 }, 632 quizid : { 633 'value' : 0 634 } 635 } 636 }); 637 638 M.mod_quiz.resource_toolbox = null; 639 M.mod_quiz.init_resource_toolbox = function(config) { 640 M.mod_quiz.resource_toolbox = new RESOURCETOOLBOX(config); 641 return M.mod_quiz.resource_toolbox; 642 }; 643 /** 644 * Resource and activity toolbox class. 645 * 646 * This class is responsible for managing AJAX interactions with activities and resources 647 * when viewing a course in editing mode. 648 * 649 * @module moodle-mod_quiz-toolboxes 650 * @namespace M.mod_quiz.toolboxes 651 */ 652 653 /** 654 * Section toolbox class. 655 * 656 * This class is responsible for managing AJAX interactions with sections 657 * when viewing a course in editing mode. 658 * 659 * @class section 660 * @constructor 661 * @extends M.mod_quiz.toolboxes.toolbox 662 */ 663 var SECTIONTOOLBOX = function() { 664 SECTIONTOOLBOX.superclass.constructor.apply(this, arguments); 665 }; 666 667 Y.extend(SECTIONTOOLBOX, TOOLBOX, { 668 /** 669 * Initialize the section toolboxes module. 670 * 671 * Updates all span.commands with relevant handlers and other required changes. 672 * 673 * @method initializer 674 * @protected 675 */ 676 initializer : function() { 677 M.mod_quiz.quizbase.register_module(this); 678 679 // Section Highlighting. 680 Y.delegate('click', this.toggle_highlight, SELECTOR.PAGECONTENT, SELECTOR.SECTIONLI + ' ' + SELECTOR.HIGHLIGHT, this); 681 682 // Section Visibility. 683 Y.delegate('click', this.toggle_hide_section, SELECTOR.PAGECONTENT, SELECTOR.SECTIONLI + ' ' + SELECTOR.SHOWHIDE, this); 684 }, 685 686 toggle_hide_section : function(e) { 687 // Prevent the default button action. 688 e.preventDefault(); 689 690 // Get the section we're working on. 691 var section = e.target.ancestor(M.mod_quiz.format.get_section_selector(Y)), 692 button = e.target.ancestor('a', true), 693 hideicon = button.one('img'), 694 695 // The value to submit 696 value, 697 698 // The text for strings and images. Also determines the icon to display. 699 action, 700 nextaction; 701 702 if (!section.hasClass(CSS.SECTIONHIDDENCLASS)) { 703 section.addClass(CSS.SECTIONHIDDENCLASS); 704 value = 0; 705 action = 'hide'; 706 nextaction = 'show'; 707 } else { 708 section.removeClass(CSS.SECTIONHIDDENCLASS); 709 value = 1; 710 action = 'show'; 711 nextaction = 'hide'; 712 } 713 714 var newstring = M.util.get_string(nextaction + 'fromothers', 'format_' + this.get('format')); 715 hideicon.setAttrs({ 716 'alt' : newstring, 717 'src' : M.util.image_url('i/' + nextaction) 718 }); 719 button.set('title', newstring); 720 721 // Change the highlight status 722 var data = { 723 'class' : 'section', 724 'field' : 'visible', 725 'id' : Y.Moodle.core_course.util.section.getId(section.ancestor(M.mod_quiz.edit.get_section_wrapper(Y), true)), 726 'value' : value 727 }; 728 729 var lightbox = M.util.add_lightbox(Y, section); 730 lightbox.show(); 731 732 this.send_request(data, lightbox, function(response) { 733 var activities = section.all(SELECTOR.ACTIVITYLI); 734 activities.each(function(node) { 735 var button; 736 if (node.one(SELECTOR.SHOW)) { 737 button = node.one(SELECTOR.SHOW); 738 } else { 739 button = node.one(SELECTOR.HIDE); 740 } 741 var activityid = Y.Moodle.mod_quiz.util.slot.getId(node); 742 743 // NOTE: resourcestotoggle is returned as a string instead 744 // of a Number so we must cast our activityid to a String. 745 if (Y.Array.indexOf(response.resourcestotoggle, "" + activityid) !== -1) { 746 M.mod_quiz.resource_toolbox.handle_resource_dim(button, node, action); 747 } 748 }, this); 749 }); 750 }, 751 752 /** 753 * Toggle highlighting the current section. 754 * 755 * @method toggle_highlight 756 * @param {EventFacade} e 757 */ 758 toggle_highlight : function(e) { 759 // Prevent the default button action. 760 e.preventDefault(); 761 762 // Get the section we're working on. 763 var section = e.target.ancestor(M.mod_quiz.edit.get_section_selector(Y)); 764 var button = e.target.ancestor('a', true); 765 var buttonicon = button.one('img'); 766 767 // Determine whether the marker is currently set. 768 var togglestatus = section.hasClass('current'); 769 var value = 0; 770 771 // Set the current highlighted item text. 772 var old_string = M.util.get_string('markthistopic', 'moodle'); 773 Y.one(SELECTOR.PAGECONTENT) 774 .all(M.mod_quiz.edit.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT) 775 .set('title', old_string); 776 Y.one(SELECTOR.PAGECONTENT) 777 .all(M.mod_quiz.edit.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT + ' img') 778 .set('alt', old_string) 779 .set('src', M.util.image_url('i/marker')); 780 781 // Remove the highlighting from all sections. 782 Y.one(SELECTOR.PAGECONTENT).all(M.mod_quiz.edit.get_section_selector(Y)) 783 .removeClass('current'); 784 785 // Then add it if required to the selected section. 786 if (!togglestatus) { 787 section.addClass('current'); 788 value = Y.Moodle.core_course.util.section.getId(section.ancestor(M.mod_quiz.edit.get_section_wrapper(Y), true)); 789 var new_string = M.util.get_string('markedthistopic', 'moodle'); 790 button 791 .set('title', new_string); 792 buttonicon 793 .set('alt', new_string) 794 .set('src', M.util.image_url('i/marked')); 795 } 796 797 // Change the highlight status. 798 var data = { 799 'class' : 'course', 800 'field' : 'marker', 801 'value' : value 802 }; 803 var lightbox = M.util.add_lightbox(Y, section); 804 lightbox.show(); 805 this.send_request(data, lightbox); 806 } 807 }, { 808 NAME : 'mod_quiz-section-toolbox', 809 ATTRS : { 810 courseid : { 811 'value' : 0 812 }, 813 quizid : { 814 'value' : 0 815 }, 816 format : { 817 'value' : 'topics' 818 } 819 } 820 }); 821 822 M.mod_quiz.init_section_toolbox = function(config) { 823 return new SECTIONTOOLBOX(config); 824 }; 825 826 827 }, '@VERSION@', { 828 "requires": [ 829 "base", 830 "node", 831 "event", 832 "event-key", 833 "io", 834 "moodle-mod_quiz-quizbase", 835 "moodle-mod_quiz-util-slot", 836 "moodle-core-notification-ajaxexception" 837 ] 838 });
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |