[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 YUI.add('moodle-mod_quiz-util-slot', function (Y, NAME) { 2 3 /** 4 * A collection of utility classes for use with slots. 5 * 6 * @module moodle-mod_quiz-util 7 * @submodule moodle-mod_quiz-util-slot 8 */ 9 10 Y.namespace('Moodle.mod_quiz.util.slot'); 11 12 /** 13 * A collection of utility classes for use with slots. 14 * 15 * @class Moodle.mod_quiz.util.slot 16 * @static 17 */ 18 Y.Moodle.mod_quiz.util.slot = { 19 CSS: { 20 SLOT: 'slot', 21 QUESTIONTYPEDESCRIPTION: 'qtype_description', 22 CANNOT_DEPEND: 'question_dependency_cannot_depend' 23 }, 24 CONSTANTS: { 25 SLOTIDPREFIX: 'slot-', 26 QUESTION: M.util.get_string('question', 'moodle') 27 }, 28 SELECTORS: { 29 SLOT: 'li.slot', 30 INSTANCENAME: '.instancename', 31 NUMBER: 'span.slotnumber', 32 PAGECONTENT: 'div#page-content', 33 PAGEBREAK: 'span.page_split_join_wrapper', 34 ICON: 'img.smallicon', 35 QUESTIONTYPEDESCRIPTION: '.qtype_description', 36 SECTIONUL: 'ul.section', 37 DEPENDENCY_WRAPPER: '.question_dependency_wrapper', 38 DEPENDENCY_LINK: '.question_dependency_wrapper .cm-edit-action', 39 DEPENDENCY_ICON: '.question_dependency_wrapper img' 40 }, 41 42 /** 43 * Retrieve the slot item from one of it's child Nodes. 44 * 45 * @method getSlotFromComponent 46 * @param slotcomponent {Node} The component Node. 47 * @return {Node|null} The Slot Node. 48 */ 49 getSlotFromComponent: function(slotcomponent) { 50 return Y.one(slotcomponent).ancestor(this.SELECTORS.SLOT, true); 51 }, 52 53 /** 54 * Determines the slot ID for the provided slot. 55 * 56 * @method getId 57 * @param slot {Node} The slot to find an ID for. 58 * @return {Number|false} The ID of the slot in question or false if no ID was found. 59 */ 60 getId: function(slot) { 61 // We perform a simple substitution operation to get the ID. 62 var id = slot.get('id').replace( 63 this.CONSTANTS.SLOTIDPREFIX, ''); 64 65 // Attempt to validate the ID. 66 id = parseInt(id, 10); 67 if (typeof id === 'number' && isFinite(id)) { 68 return id; 69 } 70 return false; 71 }, 72 73 /** 74 * Determines the slot name for the provided slot. 75 * 76 * @method getName 77 * @param slot {Node} The slot to find a name for. 78 * @return {string|false} The name of the slot in question or false if no ID was found. 79 */ 80 getName: function(slot) { 81 var instance = slot.one(this.SELECTORS.INSTANCENAME); 82 if (instance) { 83 return instance.get('firstChild').get('data'); 84 } 85 return null; 86 }, 87 88 /** 89 * Determines the slot number for the provided slot. 90 * 91 * @method getNumber 92 * @param slot {Node} The slot to find the number for. 93 * @return {Number|false} The number of the slot in question or false if no number was found. 94 */ 95 getNumber: function(slot) { 96 if (!slot) { 97 return false; 98 } 99 // We perform a simple substitution operation to get the number. 100 var number = slot.one(this.SELECTORS.NUMBER).get('text').replace( 101 this.CONSTANTS.QUESTION, ''); 102 // Attempt to validate the ID. 103 number = parseInt(number, 10); 104 if (typeof number === 'number' && isFinite(number)) { 105 return number; 106 } 107 return false; 108 }, 109 110 /** 111 * Updates the slot number for the provided slot. 112 * 113 * @method setNumber 114 * @param slot {Node} The slot to update the number for. 115 * @return void 116 */ 117 setNumber: function(slot, number) { 118 var numbernode = slot.one(this.SELECTORS.NUMBER); 119 numbernode.setHTML('<span class="accesshide">' + this.CONSTANTS.QUESTION + '</span> ' + number); 120 }, 121 122 /** 123 * Returns a list of all slot elements on the page. 124 * 125 * @method getSlots 126 * @return {node[]} An array containing slot nodes. 127 */ 128 getSlots: function() { 129 return Y.all(this.SELECTORS.PAGECONTENT + ' ' + this.SELECTORS.SECTIONUL + ' ' + this.SELECTORS.SLOT); 130 }, 131 132 /** 133 * Returns a list of all slot elements on the page that have numbers. Excudes description questions. 134 * 135 * @method getSlots 136 * @return {node[]} An array containing slot nodes. 137 */ 138 getNumberedSlots: function() { 139 var selector = this.SELECTORS.PAGECONTENT + ' ' + this.SELECTORS.SECTIONUL; 140 selector += ' ' + this.SELECTORS.SLOT + ':not(' + this.SELECTORS.QUESTIONTYPEDESCRIPTION + ')'; 141 return Y.all(selector); 142 }, 143 144 /** 145 * Returns the previous slot to the given slot. 146 * 147 * @method getPrevious 148 * @param slot Slot node 149 * @return {node|false} The previous slot node or false. 150 */ 151 getPrevious: function(slot) { 152 return slot.previous(this.SELECTORS.SLOT); 153 }, 154 155 /** 156 * Returns the previous numbered slot to the given slot. 157 * 158 * Ignores slots containing description question types. 159 * 160 * @method getPrevious 161 * @param slot Slot node 162 * @return {node|false} The previous slot node or false. 163 */ 164 getPreviousNumbered: function(slot) { 165 var previous = slot.previous(this.SELECTORS.SLOT + ':not(' + this.SELECTORS.QUESTIONTYPEDESCRIPTION + ')'); 166 if (previous) { 167 return previous; 168 } 169 170 var section = slot.ancestor('li.section').previous('li.section'); 171 while (section) { 172 var questions = section.all(this.SELECTORS.SLOT + ':not(' + this.SELECTORS.QUESTIONTYPEDESCRIPTION + ')'); 173 if (questions.size() > 0) { 174 return questions.item(questions.size() - 1); 175 } 176 section = section.previous('li.section'); 177 } 178 return false; 179 }, 180 181 /** 182 * Reset the order of the numbers given to each slot. 183 * 184 * @method reorderSlots 185 * @return void 186 */ 187 reorderSlots: function() { 188 // Get list of slot nodes. 189 var slots = this.getSlots(); 190 // Loop through slots incrementing the number each time. 191 slots.each(function(slot) { 192 193 if (!Y.Moodle.mod_quiz.util.page.getPageFromSlot(slot)) { 194 // Move the next page to the front. 195 var nextpage = slot.next(Y.Moodle.mod_quiz.util.page.SELECTORS.PAGE); 196 slot.swap(nextpage); 197 } 198 199 var previousSlot = this.getPreviousNumbered(slot), 200 previousslotnumber = 0; 201 if (slot.hasClass(this.CSS.QUESTIONTYPEDESCRIPTION)) { 202 return; 203 } 204 205 if (previousSlot) { 206 previousslotnumber = this.getNumber(previousSlot); 207 } 208 209 // Set slot number. 210 this.setNumber(slot, previousslotnumber + 1); 211 }, this); 212 }, 213 214 /** 215 * Add class only-has-one-slot to those sections that need it. 216 * 217 * @method updateOneSlotSections 218 * @return void 219 */ 220 updateOneSlotSections: function() { 221 Y.all('.mod-quiz-edit-content ul.slots li.section').each(function(section) { 222 if (section.all(this.SELECTORS.SLOT).size() > 1) { 223 section.removeClass('only-has-one-slot'); 224 } else { 225 section.addClass('only-has-one-slot'); 226 } 227 }, this); 228 }, 229 230 /** 231 * Remove a slot and related elements from the list of slots. 232 * 233 * @method remove 234 * @param slot Slot node 235 * @return void 236 */ 237 remove: function(slot) { 238 var page = Y.Moodle.mod_quiz.util.page.getPageFromSlot(slot); 239 slot.remove(); 240 // Is the page empty. 241 if (!Y.Moodle.mod_quiz.util.page.isEmpty(page)) { 242 return; 243 } 244 // If so remove it. Including add menu and page break. 245 Y.Moodle.mod_quiz.util.page.remove(page); 246 }, 247 248 /** 249 * Returns a list of all page break elements on the page. 250 * 251 * @method getPageBreaks 252 * @return {node[]} An array containing page break nodes. 253 */ 254 getPageBreaks: function() { 255 var selector = this.SELECTORS.PAGECONTENT + ' ' + this.SELECTORS.SECTIONUL; 256 selector += ' ' + this.SELECTORS.SLOT + this.SELECTORS.PAGEBREAK; 257 return Y.all(selector); 258 }, 259 260 /** 261 * Retrieve the page break element item from the given slot. 262 * 263 * @method getPageBreak 264 * @param slot Slot node 265 * @return {Node|null} The Page Break Node. 266 */ 267 getPageBreak: function(slot) { 268 return Y.one(slot).one(this.SELECTORS.PAGEBREAK); 269 }, 270 271 /** 272 * Add a page break and related elements to the list of slots. 273 * 274 * @method addPageBreak 275 * @param beforenode Int | Node | HTMLElement | String to add 276 * @return pagebreak PageBreak node 277 */ 278 addPageBreak: function(slot) { 279 var nodetext = M.mod_quiz.resource_toolbox.get('config').addpageiconhtml; 280 nodetext = nodetext.replace('%%SLOT%%', this.getNumber(slot)); 281 var pagebreak = Y.Node.create(nodetext); 282 slot.one('div').insert(pagebreak, 'after'); 283 return pagebreak; 284 }, 285 286 /** 287 * Remove a pagebreak from the given slot. 288 * 289 * @method removePageBreak 290 * @param slot Slot node 291 * @return boolean 292 */ 293 removePageBreak: function(slot) { 294 var pagebreak = this.getPageBreak(slot); 295 if (!pagebreak) { 296 return false; 297 } 298 pagebreak.remove(); 299 return true; 300 }, 301 302 /** 303 * Reorder each pagebreak by iterating through each related slot. 304 * 305 * @method reorderPageBreaks 306 * @return void 307 */ 308 reorderPageBreaks: function() { 309 // Get list of slot nodes. 310 var slots = this.getSlots(); 311 var slotnumber = 0; 312 // Loop through slots incrementing the number each time. 313 slots.each(function(slot, key) { 314 slotnumber++; 315 var pagebreak = this.getPageBreak(slot); 316 var nextitem = slot.next('li.activity'); 317 if (!nextitem) { 318 // Last slot in a section. Should not have an icon. 319 return; 320 } 321 322 // No pagebreak and not last slot. Add one. 323 if (!pagebreak) { 324 pagebreak = this.addPageBreak(slot); 325 } 326 327 // Remove last page break if there is one. 328 if (pagebreak && key === slots.size() - 1) { 329 this.removePageBreak(slot); 330 } 331 332 // Get page break anchor element. 333 var pagebreaklink = pagebreak.get('childNodes').item(0); 334 335 // Get the correct title. 336 var action = ''; 337 var iconname = ''; 338 if (Y.Moodle.mod_quiz.util.page.isPage(nextitem)) { 339 action = 'removepagebreak'; 340 iconname = 'e/remove_page_break'; 341 } else { 342 action = 'addpagebreak'; 343 iconname = 'e/insert_page_break'; 344 } 345 346 // Update the link and image titles 347 pagebreaklink.set('title', M.util.get_string(action, 'quiz')); 348 pagebreaklink.setData('action', action); 349 // Update the image title. 350 var icon = pagebreaklink.one(this.SELECTORS.ICON); 351 icon.set('title', M.util.get_string(action, 'quiz')); 352 icon.set('alt', M.util.get_string(action, 'quiz')); 353 354 // Update the image src. 355 icon.set('src', M.util.image_url(iconname)); 356 357 // Get anchor url parameters as an associative array. 358 var params = Y.QueryString.parse(pagebreaklink.get('href')); 359 // Update slot number. 360 params.slot = slotnumber; 361 // Create the new url. 362 var newurl = ''; 363 for (var index in params) { 364 if (newurl.length) { 365 newurl += "&"; 366 } 367 newurl += index + "=" + params[index]; 368 } 369 // Update the anchor. 370 pagebreaklink.set('href', newurl); 371 }, this); 372 }, 373 374 /** 375 * Update the dependency icons. 376 * 377 * @method updateAllDependencyIcons 378 * @return void 379 */ 380 updateAllDependencyIcons: function() { 381 // Get list of slot nodes. 382 var slots = this.getSlots(), 383 slotnumber = 0, 384 previousslot = null; 385 // Loop through slots incrementing the number each time. 386 slots.each(function(slot) { 387 slotnumber++; 388 389 if (slotnumber == 1 || previousslot.getData('canfinish') === '0') { 390 slot.one(this.SELECTORS.DEPENDENCY_WRAPPER).addClass(this.CSS.CANNOT_DEPEND); 391 } else { 392 slot.one(this.SELECTORS.DEPENDENCY_WRAPPER).removeClass(this.CSS.CANNOT_DEPEND); 393 } 394 this.updateDependencyIcon(slot, null); 395 396 previousslot = slot; 397 }, this); 398 }, 399 400 /** 401 * Update the slot icon to indicate the new requiresprevious state. 402 * 403 * @method slot Slot node 404 * @method requiresprevious Whether this node now requires the previous one. 405 * @return void 406 */ 407 updateDependencyIcon: function(slot, requiresprevious) { 408 var link = slot.one(this.SELECTORS.DEPENDENCY_LINK); 409 var icon = slot.one(this.SELECTORS.DEPENDENCY_ICON); 410 var previousSlot = this.getPrevious(slot); 411 var a = {thisq: this.getNumber(slot)}; 412 if (previousSlot) { 413 a.previousq = this.getNumber(previousSlot); 414 } 415 416 if (requiresprevious === null) { 417 requiresprevious = link.getData('action') === 'removedependency'; 418 } 419 420 if (requiresprevious) { 421 link.set('title', M.util.get_string('questiondependencyremove', 'quiz', a)); 422 link.setData('action', 'removedependency'); 423 icon.set('alt', M.util.get_string('questiondependsonprevious', 'quiz')); 424 icon.set('src', M.util.image_url('t/locked', 'moodle')); 425 } else { 426 link.set('title', M.util.get_string('questiondependencyadd', 'quiz', a)); 427 link.setData('action', 'adddependency'); 428 icon.set('alt', M.util.get_string('questiondependencyfree', 'quiz')); 429 icon.set('src', M.util.image_url('t/unlocked', 'moodle')); 430 } 431 } 432 }; 433 434 435 }, '@VERSION@', {"requires": ["node", "moodle-mod_quiz-util-base"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |