| 1 | efrain | 1 | /**
 | 
        
           |  |  | 2 |  * Section toolbox class.
 | 
        
           |  |  | 3 |  *
 | 
        
           |  |  | 4 |  * This class is responsible for managing AJAX interactions with sections
 | 
        
           |  |  | 5 |  * when adding, editing, removing section headings.
 | 
        
           |  |  | 6 |  *
 | 
        
           |  |  | 7 |  * @module moodle-mod_quiz-toolboxes
 | 
        
           |  |  | 8 |  * @namespace M.mod_quiz.toolboxes
 | 
        
           |  |  | 9 |  */
 | 
        
           |  |  | 10 |   | 
        
           |  |  | 11 | /**
 | 
        
           |  |  | 12 |  * Section toolbox class.
 | 
        
           |  |  | 13 |  *
 | 
        
           |  |  | 14 |  * This class is responsible for managing AJAX interactions with sections
 | 
        
           |  |  | 15 |  * when adding, editing, removing section headings when editing a quiz.
 | 
        
           |  |  | 16 |  *
 | 
        
           |  |  | 17 |  * @class section
 | 
        
           |  |  | 18 |  * @constructor
 | 
        
           |  |  | 19 |  * @extends M.mod_quiz.toolboxes.toolbox
 | 
        
           |  |  | 20 |  */
 | 
        
           |  |  | 21 | var SECTIONTOOLBOX = function() {
 | 
        
           |  |  | 22 |     SECTIONTOOLBOX.superclass.constructor.apply(this, arguments);
 | 
        
           |  |  | 23 | };
 | 
        
           |  |  | 24 |   | 
        
           |  |  | 25 | Y.extend(SECTIONTOOLBOX, TOOLBOX, {
 | 
        
           |  |  | 26 |     /**
 | 
        
           |  |  | 27 |      * An Array of events added when editing a max mark field.
 | 
        
           |  |  | 28 |      * These should all be detached when editing is complete.
 | 
        
           |  |  | 29 |      *
 | 
        
           |  |  | 30 |      * @property editsectionevents
 | 
        
           |  |  | 31 |      * @protected
 | 
        
           |  |  | 32 |      * @type Array
 | 
        
           |  |  | 33 |      * @protected
 | 
        
           |  |  | 34 |      */
 | 
        
           |  |  | 35 |     editsectionevents: [],
 | 
        
           |  |  | 36 |   | 
        
           |  |  | 37 |     /**
 | 
        
           |  |  | 38 |      * Initialize the section toolboxes module.
 | 
        
           |  |  | 39 |      *
 | 
        
           |  |  | 40 |      * Updates all span.commands with relevant handlers and other required changes.
 | 
        
           |  |  | 41 |      *
 | 
        
           |  |  | 42 |      * @method initializer
 | 
        
           |  |  | 43 |      * @protected
 | 
        
           |  |  | 44 |      */
 | 
        
           |  |  | 45 |     initializer: function() {
 | 
        
           |  |  | 46 |         M.mod_quiz.quizbase.register_module(this);
 | 
        
           |  |  | 47 |   | 
        
           |  |  | 48 |         BODY.delegate('key', this.handle_data_action, 'down:enter', SELECTOR.ACTIVITYACTION, this);
 | 
        
           |  |  | 49 |         Y.delegate('click', this.handle_data_action, BODY, SELECTOR.ACTIVITYACTION, this);
 | 
        
           |  |  | 50 |         Y.delegate('change', this.handle_data_action, BODY, SELECTOR.EDITSHUFFLEQUESTIONSACTION, this);
 | 
        
           |  |  | 51 |     },
 | 
        
           |  |  | 52 |   | 
        
           |  |  | 53 |     /**
 | 
        
           |  |  | 54 |      * Handles the delegation event. When this is fired someone has triggered an action.
 | 
        
           |  |  | 55 |      *
 | 
        
           |  |  | 56 |      * Note not all actions will result in an AJAX enhancement.
 | 
        
           |  |  | 57 |      *
 | 
        
           |  |  | 58 |      * @protected
 | 
        
           |  |  | 59 |      * @method handle_data_action
 | 
        
           |  |  | 60 |      * @param {EventFacade} ev The event that was triggered.
 | 
        
           |  |  | 61 |      * @returns {boolean}
 | 
        
           |  |  | 62 |      */
 | 
        
           |  |  | 63 |     handle_data_action: function(ev) {
 | 
        
           |  |  | 64 |         // We need to get the anchor element that triggered this event.
 | 
        
           |  |  | 65 |         var node = ev.target;
 | 
        
           |  |  | 66 |         if (!node.test('a') && !node.test('input[data-action]')) {
 | 
        
           |  |  | 67 |             node = node.ancestor(SELECTOR.ACTIVITYACTION);
 | 
        
           |  |  | 68 |         }
 | 
        
           |  |  | 69 |   | 
        
           |  |  | 70 |         // From the anchor we can get both the activity (added during initialisation) and the action being
 | 
        
           |  |  | 71 |         // performed (added by the UI as a data attribute).
 | 
        
           |  |  | 72 |         var action = node.getData('action'),
 | 
        
           |  |  | 73 |             activity = node.ancestor(SELECTOR.ACTIVITYLI);
 | 
        
           |  |  | 74 |   | 
        
           |  |  | 75 |         if ((!node.test('a') && !node.test('input[data-action]')) || !action || !activity) {
 | 
        
           |  |  | 76 |             // It wasn't a valid action node.
 | 
        
           |  |  | 77 |             return;
 | 
        
           |  |  | 78 |         }
 | 
        
           |  |  | 79 |   | 
        
           |  |  | 80 |         // Switch based upon the action and do the desired thing.
 | 
        
           |  |  | 81 |         switch (action) {
 | 
        
           |  |  | 82 |             case 'edit_section_title':
 | 
        
           |  |  | 83 |                 // The user wishes to edit the section headings.
 | 
        
           |  |  | 84 |                 this.edit_section_title(ev, node, activity, action);
 | 
        
           |  |  | 85 |                 break;
 | 
        
           |  |  | 86 |             case 'shuffle_questions':
 | 
        
           |  |  | 87 |                 // The user wishes to edit the shuffle questions of the section (resource).
 | 
        
           |  |  | 88 |                 this.edit_shuffle_questions(ev, node, activity, action);
 | 
        
           |  |  | 89 |                 break;
 | 
        
           |  |  | 90 |             case 'deletesection':
 | 
        
           |  |  | 91 |                 // The user is deleting the activity.
 | 
        
           |  |  | 92 |                 this.delete_section_with_confirmation(ev, node, activity, action);
 | 
        
           |  |  | 93 |                 break;
 | 
        
           |  |  | 94 |             default:
 | 
        
           |  |  | 95 |                 // Nothing to do here!
 | 
        
           |  |  | 96 |                 break;
 | 
        
           |  |  | 97 |         }
 | 
        
           |  |  | 98 |     },
 | 
        
           |  |  | 99 |   | 
        
           |  |  | 100 |     /**
 | 
        
           |  |  | 101 |      * Deletes the given section heading after confirmation.
 | 
        
           |  |  | 102 |      *
 | 
        
           |  |  | 103 |      * @protected
 | 
        
           |  |  | 104 |      * @method delete_section_with_confirmation
 | 
        
           |  |  | 105 |      * @param {EventFacade} ev The event that was fired.
 | 
        
           |  |  | 106 |      * @param {Node} button The button that triggered this action.
 | 
        
           |  |  | 107 |      * @param {Node} activity The activity node that this action will be performed on.
 | 
        
           |  |  | 108 |      * @chainable
 | 
        
           |  |  | 109 |      */
 | 
        
           |  |  | 110 |     delete_section_with_confirmation: function(ev, button, activity) {
 | 
        
           |  |  | 111 |         ev.preventDefault();
 | 
        
           |  |  | 112 |         require(['core/notification'], function(Notification) {
 | 
        
           |  |  | 113 |             Notification.saveCancelPromise(
 | 
        
           |  |  | 114 |                 M.util.get_string('confirm', 'moodle'),
 | 
        
           |  |  | 115 |                 M.util.get_string('confirmremovesectionheading', 'quiz', activity.getData('sectionname')),
 | 
        
           |  |  | 116 |                 M.util.get_string('yes', 'moodle')
 | 
        
           |  |  | 117 |             ).then(function() {
 | 
        
           |  |  | 118 |                 var spinner = M.util.add_spinner(Y, activity.one(SELECTOR.ACTIONAREA));
 | 
        
           |  |  | 119 |                 var data = {
 | 
        
           |  |  | 120 |                     'class': 'section',
 | 
        
           |  |  | 121 |                     'action': 'DELETE',
 | 
        
           |  |  | 122 |                     'id': activity.get('id').replace('section-', '')
 | 
        
           |  |  | 123 |                 };
 | 
        
           |  |  | 124 |                 this.send_request(data, spinner, function(response) {
 | 
        
           |  |  | 125 |                     if (response.deleted) {
 | 
        
           |  |  | 126 |                         window.location.reload(true);
 | 
        
           |  |  | 127 |                     }
 | 
        
           |  |  | 128 |                 });
 | 
        
           |  |  | 129 |   | 
        
           |  |  | 130 |                 return;
 | 
        
           |  |  | 131 |             }.bind(this)).catch(function() {
 | 
        
           |  |  | 132 |                 // User cancelled.
 | 
        
           |  |  | 133 |             });
 | 
        
           |  |  | 134 |         }.bind(this));
 | 
        
           |  |  | 135 |     },
 | 
        
           |  |  | 136 |   | 
        
           |  |  | 137 |     /**
 | 
        
           |  |  | 138 |      * Edit the edit section title for the section
 | 
        
           |  |  | 139 |      *
 | 
        
           |  |  | 140 |      * @protected
 | 
        
           |  |  | 141 |      * @method edit_section_title
 | 
        
           |  |  | 142 |      * @param {EventFacade} ev The event that was fired.
 | 
        
           |  |  | 143 |      * @param {Node} button The button that triggered this action.
 | 
        
           |  |  | 144 |      * @param {Node} activity The activity node that this action will be performed on.
 | 
        
           |  |  | 145 |      * @param {String} action The action that has been requested.
 | 
        
           |  |  | 146 |      * @return Boolean
 | 
        
           |  |  | 147 |      */
 | 
        
           |  |  | 148 |     edit_section_title: function(ev, button, activity) {
 | 
        
           |  |  | 149 |         // Get the element we're working on
 | 
        
           |  |  | 150 |         var activityid = activity.get('id').replace('section-', ''),
 | 
        
           |  |  | 151 |             instancesection = activity.one(SELECTOR.INSTANCESECTION),
 | 
        
           |  |  | 152 |             thisevent,
 | 
        
           |  |  | 153 |             anchor = instancesection, // Grab the anchor so that we can swap it with the edit form.
 | 
        
           |  |  | 154 |             data = {
 | 
        
           |  |  | 155 |                 'class': 'section',
 | 
        
           |  |  | 156 |                 'field': 'getsectiontitle',
 | 
        
           |  |  | 157 |                 'id':    activityid
 | 
        
           |  |  | 158 |             };
 | 
        
           |  |  | 159 |   | 
        
           |  |  | 160 |         // Prevent the default actions.
 | 
        
           |  |  | 161 |         ev.preventDefault();
 | 
        
           |  |  | 162 |   | 
        
           |  |  | 163 |         this.send_request(data, null, function(response) {
 | 
        
           |  |  | 164 |             // Try to retrieve the existing string from the server.
 | 
        
           |  |  | 165 |             var oldtext = response.instancesection;
 | 
        
           |  |  | 166 |   | 
        
           |  |  | 167 |             // Create the editor and submit button.
 | 
        
           |  |  | 168 |             var editform = Y.Node.create('<form action="#" />');
 | 
        
           |  |  | 169 |             var editinstructions = Y.Node.create('<span class="' + CSS.EDITINSTRUCTIONS + '" id="id_editinstructions" />')
 | 
        
           |  |  | 170 |                 .set('innerHTML', M.util.get_string('edittitleinstructions', 'moodle'));
 | 
        
           |  |  | 171 |             var editor = Y.Node.create('<input name="section" type="text" />').setAttrs({
 | 
        
           |  |  | 172 |                 'value': oldtext,
 | 
        
           |  |  | 173 |                 'autocomplete': 'off',
 | 
        
           |  |  | 174 |                 'aria-describedby': 'id_editinstructions',
 | 
        
           |  |  | 175 |                 'maxLength': '255' // This is the maxlength in DB.
 | 
        
           |  |  | 176 |             });
 | 
        
           |  |  | 177 |   | 
        
           |  |  | 178 |             // Clear the existing content and put the editor in.
 | 
        
           |  |  | 179 |             editform.appendChild(editor);
 | 
        
           |  |  | 180 |             editform.setData('anchor', anchor);
 | 
        
           |  |  | 181 |             instancesection.insert(editinstructions, 'before');
 | 
        
           |  |  | 182 |             anchor.replace(editform);
 | 
        
           |  |  | 183 |   | 
        
           |  |  | 184 |             // Focus and select the editor text.
 | 
        
           |  |  | 185 |             editor.focus().select();
 | 
        
           |  |  | 186 |             // Cancel the edit if we lose focus or the escape key is pressed.
 | 
        
           |  |  | 187 |             thisevent = editor.on('blur', this.edit_section_title_cancel, this, activity, false);
 | 
        
           |  |  | 188 |             this.editsectionevents.push(thisevent);
 | 
        
           |  |  | 189 |             thisevent = editor.on('key', this.edit_section_title_cancel, 'esc', this, activity, true);
 | 
        
           |  |  | 190 |             this.editsectionevents.push(thisevent);
 | 
        
           |  |  | 191 |             // Handle form submission.
 | 
        
           |  |  | 192 |             thisevent = editform.on('submit', this.edit_section_title_submit, this, activity, oldtext);
 | 
        
           |  |  | 193 |             this.editsectionevents.push(thisevent);
 | 
        
           |  |  | 194 |         });
 | 
        
           |  |  | 195 |     },
 | 
        
           |  |  | 196 |   | 
        
           |  |  | 197 |     /**
 | 
        
           |  |  | 198 |      * Handles the submit event when editing section heading.
 | 
        
           |  |  | 199 |      *
 | 
        
           |  |  | 200 |      * @protected
 | 
        
           |  |  | 201 |      * @method edit_section_title_submiy
 | 
        
           |  |  | 202 |      * @param {EventFacade} ev The event that triggered this.
 | 
        
           |  |  | 203 |      * @param {Node} activity The activity whose maxmark we are altering.
 | 
        
           |  |  | 204 |      * @param {String} oldtext The original maxmark the activity or resource had.
 | 
        
           |  |  | 205 |      */
 | 
        
           |  |  | 206 |     edit_section_title_submit: function(ev, activity, oldtext) {
 | 
        
           |  |  | 207 |          // We don't actually want to submit anything.
 | 
        
           |  |  | 208 |         ev.preventDefault();
 | 
        
           |  |  | 209 |         var newtext = Y.Lang.trim(activity.one(SELECTOR.SECTIONFORM + ' ' + SELECTOR.SECTIONINPUT).get('value'));
 | 
        
           |  |  | 210 |         var spinner = M.util.add_spinner(Y, activity.one(SELECTOR.INSTANCESECTIONAREA));
 | 
        
           |  |  | 211 |         this.edit_section_title_clear(activity);
 | 
        
           |  |  | 212 |         if (newtext !== null && newtext !== oldtext) {
 | 
        
           |  |  | 213 |             var instancesection = activity.one(SELECTOR.INSTANCESECTION);
 | 
        
           |  |  | 214 |             var instancesectiontext = newtext;
 | 
        
           |  |  | 215 |             if (newtext.trim() === '') {
 | 
        
           | 1441 | ariadna | 216 |                 // Add a visually-hidden default section heading text to make sure we don't end up with an empty section heading.
 | 
        
           | 1 | efrain | 217 |                 instancesectiontext = M.util.get_string('sectionnoname', 'quiz');
 | 
        
           | 1441 | ariadna | 218 |                 instancesection.addClass('visually-hidden');
 | 
        
           | 1 | efrain | 219 |             } else {
 | 
        
           |  |  | 220 |                 // Show the section heading when a non-empty value is set.
 | 
        
           | 1441 | ariadna | 221 |                 instancesection.removeClass('visually-hidden');
 | 
        
           | 1 | efrain | 222 |             }
 | 
        
           |  |  | 223 |             instancesection.setContent(instancesectiontext);
 | 
        
           |  |  | 224 |   | 
        
           |  |  | 225 |             var data = {
 | 
        
           |  |  | 226 |                 'class':      'section',
 | 
        
           |  |  | 227 |                 'field':      'updatesectiontitle',
 | 
        
           |  |  | 228 |                 'newheading': newtext,
 | 
        
           |  |  | 229 |                 'id':         activity.get('id').replace('section-', '')
 | 
        
           |  |  | 230 |             };
 | 
        
           |  |  | 231 |             this.send_request(data, spinner, function(response) {
 | 
        
           |  |  | 232 |                 if (response) {
 | 
        
           |  |  | 233 |                     // Set the content of the section heading if for some reason the response is different from the new text.
 | 
        
           |  |  | 234 |                     // e.g. filters were applied, the update failed, etc.
 | 
        
           |  |  | 235 |                     if (newtext !== response.instancesection) {
 | 
        
           |  |  | 236 |                         if (response.instancesection.trim() === '') {
 | 
        
           | 1441 | ariadna | 237 |                             // Add a visually-hidden default section heading text.
 | 
        
           | 1 | efrain | 238 |                             instancesectiontext = M.util.get_string('sectionnoname', 'quiz');
 | 
        
           | 1441 | ariadna | 239 |                             instancesection.addClass('visually-hidden');
 | 
        
           | 1 | efrain | 240 |                         } else {
 | 
        
           |  |  | 241 |                             instancesectiontext = response.instancesection;
 | 
        
           |  |  | 242 |                             // Show the section heading when a non-empty value is set.
 | 
        
           | 1441 | ariadna | 243 |                             instancesection.removeClass('visually-hidden');
 | 
        
           | 1 | efrain | 244 |                         }
 | 
        
           |  |  | 245 |                         instancesection.setContent(instancesectiontext);
 | 
        
           |  |  | 246 |                     }
 | 
        
           |  |  | 247 |   | 
        
           |  |  | 248 |                     activity.one(SELECTOR.EDITSECTIONICON).set('title',
 | 
        
           |  |  | 249 |                             M.util.get_string('sectionheadingedit', 'quiz', response.instancesection));
 | 
        
           |  |  | 250 |                     activity.one(SELECTOR.EDITSECTIONICON).set('alt',
 | 
        
           |  |  | 251 |                             M.util.get_string('sectionheadingedit', 'quiz', response.instancesection));
 | 
        
           |  |  | 252 |                     var deleteicon = activity.one(SELECTOR.DELETESECTIONICON);
 | 
        
           |  |  | 253 |                     if (deleteicon) {
 | 
        
           |  |  | 254 |                         deleteicon.set('title', M.util.get_string('sectionheadingremove', 'quiz', response.instancesection));
 | 
        
           |  |  | 255 |                         deleteicon.set('alt', M.util.get_string('sectionheadingremove', 'quiz', response.instancesection));
 | 
        
           |  |  | 256 |                     }
 | 
        
           |  |  | 257 |                 }
 | 
        
           |  |  | 258 |             });
 | 
        
           |  |  | 259 |         }
 | 
        
           |  |  | 260 |     },
 | 
        
           |  |  | 261 |   | 
        
           |  |  | 262 |     /**
 | 
        
           |  |  | 263 |      * Handles the cancel event when editing the activity or resources maxmark.
 | 
        
           |  |  | 264 |      *
 | 
        
           |  |  | 265 |      * @protected
 | 
        
           |  |  | 266 |      * @method edit_maxmark_cancel
 | 
        
           |  |  | 267 |      * @param {EventFacade} ev The event that triggered this.
 | 
        
           |  |  | 268 |      * @param {Node} activity The activity whose maxmark we are altering.
 | 
        
           |  |  | 269 |      * @param {Boolean} preventdefault If true we should prevent the default action from occuring.
 | 
        
           |  |  | 270 |      */
 | 
        
           |  |  | 271 |     edit_section_title_cancel: function(ev, activity, preventdefault) {
 | 
        
           |  |  | 272 |         if (preventdefault) {
 | 
        
           |  |  | 273 |             ev.preventDefault();
 | 
        
           |  |  | 274 |         }
 | 
        
           |  |  | 275 |         this.edit_section_title_clear(activity);
 | 
        
           |  |  | 276 |     },
 | 
        
           |  |  | 277 |   | 
        
           |  |  | 278 |     /**
 | 
        
           |  |  | 279 |      * Handles clearing the editing UI and returning things to the original state they were in.
 | 
        
           |  |  | 280 |      *
 | 
        
           |  |  | 281 |      * @protected
 | 
        
           |  |  | 282 |      * @method edit_maxmark_clear
 | 
        
           |  |  | 283 |      * @param {Node} activity  The activity whose maxmark we were altering.
 | 
        
           |  |  | 284 |      */
 | 
        
           |  |  | 285 |     edit_section_title_clear: function(activity) {
 | 
        
           |  |  | 286 |         // Detach all listen events to prevent duplicate triggers
 | 
        
           |  |  | 287 |         new Y.EventHandle(this.editsectionevents).detach();
 | 
        
           |  |  | 288 |   | 
        
           |  |  | 289 |         var editform = activity.one(SELECTOR.SECTIONFORM),
 | 
        
           |  |  | 290 |             instructions = activity.one('#id_editinstructions');
 | 
        
           |  |  | 291 |         if (editform) {
 | 
        
           |  |  | 292 |             editform.replace(editform.getData('anchor'));
 | 
        
           |  |  | 293 |         }
 | 
        
           |  |  | 294 |         if (instructions) {
 | 
        
           |  |  | 295 |             instructions.remove();
 | 
        
           |  |  | 296 |         }
 | 
        
           |  |  | 297 |   | 
        
           |  |  | 298 |         // Refocus the link which was clicked originally so the user can continue using keyboard nav.
 | 
        
           |  |  | 299 |         Y.later(100, this, function() {
 | 
        
           |  |  | 300 |             activity.one(SELECTOR.EDITSECTION).focus();
 | 
        
           |  |  | 301 |         });
 | 
        
           |  |  | 302 |   | 
        
           |  |  | 303 |         // This hack is to keep Behat happy until they release a version of
 | 
        
           |  |  | 304 |         // MinkSelenium2Driver that fixes
 | 
        
           |  |  | 305 |         // https://github.com/Behat/MinkSelenium2Driver/issues/80.
 | 
        
           |  |  | 306 |         if (!Y.one('input[name=section]')) {
 | 
        
           |  |  | 307 |             Y.one('body').append('<input type="text" name="section" style="display: none">');
 | 
        
           |  |  | 308 |         }
 | 
        
           |  |  | 309 |     },
 | 
        
           |  |  | 310 |   | 
        
           |  |  | 311 |     /**
 | 
        
           |  |  | 312 |      * Edit the edit shuffle questions for the section
 | 
        
           |  |  | 313 |      *
 | 
        
           |  |  | 314 |      * @protected
 | 
        
           |  |  | 315 |      * @method edit_shuffle_questions
 | 
        
           |  |  | 316 |      * @param {EventFacade} ev The event that was fired.
 | 
        
           |  |  | 317 |      * @param {Node} button The button that triggered this action.
 | 
        
           |  |  | 318 |      * @param {Node} activity The activity node that this action will be performed on.
 | 
        
           |  |  | 319 |      * @return Boolean
 | 
        
           |  |  | 320 |      */
 | 
        
           |  |  | 321 |     edit_shuffle_questions: function(ev, button, activity) {
 | 
        
           |  |  | 322 |         var newvalue;
 | 
        
           |  |  | 323 |         if (activity.one(SELECTOR.EDITSHUFFLEQUESTIONSACTION).get('checked')) {
 | 
        
           |  |  | 324 |             newvalue = 1;
 | 
        
           |  |  | 325 |             activity.addClass('shuffled');
 | 
        
           |  |  | 326 |         } else {
 | 
        
           |  |  | 327 |             newvalue = 0;
 | 
        
           |  |  | 328 |             activity.removeClass('shuffled');
 | 
        
           |  |  | 329 |         }
 | 
        
           |  |  | 330 |   | 
        
           |  |  | 331 |         // Prevent the default actions.
 | 
        
           |  |  | 332 |         ev.preventDefault();
 | 
        
           |  |  | 333 |   | 
        
           |  |  | 334 |         // Get the element we're working on
 | 
        
           |  |  | 335 |         var data = {
 | 
        
           |  |  | 336 |             'class': 'section',
 | 
        
           |  |  | 337 |             'field': 'updateshufflequestions',
 | 
        
           |  |  | 338 |             'id': activity.get('id').replace('section-', ''),
 | 
        
           |  |  | 339 |             'newshuffle': newvalue
 | 
        
           |  |  | 340 |         };
 | 
        
           |  |  | 341 |   | 
        
           |  |  | 342 |         // Send request.
 | 
        
           |  |  | 343 |         var spinner = M.util.add_spinner(Y, activity.one(SELECTOR.EDITSHUFFLEAREA));
 | 
        
           |  |  | 344 |         this.send_request(data, spinner);
 | 
        
           |  |  | 345 |     }
 | 
        
           |  |  | 346 |   | 
        
           |  |  | 347 | }, {
 | 
        
           |  |  | 348 |     NAME: 'mod_quiz-section-toolbox',
 | 
        
           |  |  | 349 |     ATTRS: {
 | 
        
           |  |  | 350 |         courseid: {
 | 
        
           |  |  | 351 |             'value': 0
 | 
        
           |  |  | 352 |         },
 | 
        
           |  |  | 353 |         quizid: {
 | 
        
           |  |  | 354 |             'value': 0
 | 
        
           |  |  | 355 |         }
 | 
        
           |  |  | 356 |     }
 | 
        
           |  |  | 357 | });
 | 
        
           |  |  | 358 |   | 
        
           |  |  | 359 | M.mod_quiz.init_section_toolbox = function(config) {
 | 
        
           |  |  | 360 |     return new SECTIONTOOLBOX(config);
 | 
        
           |  |  | 361 | };
 |