2 * A collection of utility classes for use with pages.
4 * @module moodle-mod_quiz-util
5 * @submodule moodle-mod_quiz-util-page
8 Y.namespace('Moodle.mod_quiz.util.page');
11 * A collection of utility classes for use with pages.
13 * @class Moodle.mod_quiz.util.page
16 Y.Moodle.mod_quiz.util.page = {
21 ACTIONMENUIDPREFIX: 'action-menu-',
22 ACTIONMENUBARIDSUFFIX: '-menubar',
23 ACTIONMENUMENUIDSUFFIX: '-menu',
24 PAGEIDPREFIX: 'page-',
25 PAGENUMBERPREFIX: M.util.get_string('page', 'moodle') + ' '
28 ACTIONMENU: 'div.moodle-actionmenu',
29 ACTIONMENUBAR: 'ul.menubar',
30 ACTIONMENUMENU: 'ul.menu',
32 INSTANCENAME: '.instancename',
37 * Retrieve the page item from one of it's child Nodes.
39 * @method getPageFromComponent
40 * @param pagecomponent {Node} The component Node.
41 * @return {Node|null} The Page Node.
43 getPageFromComponent: function(pagecomponent) {
44 return Y.one(pagecomponent).ancestor(this.SELECTORS.PAGE, true);
48 * Retrieve the page item from one of it's previous siblings.
50 * @method getPageFromSlot
51 * @param pagecomponent {Node} The component Node.
52 * @return {Node|null} The Page Node.
54 getPageFromSlot: function(slot) {
55 return Y.one(slot).previous(this.SELECTORS.PAGE);
59 * Returns the page ID for the provided page.
62 * @param page {Node} The page to find an ID for.
63 * @return {Number|false} The ID of the page in question or false if no ID was found.
65 getId: function(page) {
66 // We perform a simple substitution operation to get the ID.
67 var id = page.get('id').replace(
68 this.CONSTANTS.PAGEIDPREFIX, '');
70 // Attempt to validate the ID.
71 id = parseInt(id, 10);
72 if (typeof id === 'number' && isFinite(id)) {
79 * Updates the page id for the provided page.
82 * @param page {Node} The page to update the number for.
83 * @param id int The id value.
86 setId: function(page, id) {
87 page.set('id', this.CONSTANTS.PAGEIDPREFIX + id);
91 * Determines the page name for the provided page.
94 * @param page {Node} The page to find a name for.
95 * @return {string|false} The name of the page in question or false if no ID was found.
97 getName: function(page) {
98 var instance = page.one(this.SELECTORS.INSTANCENAME);
100 return instance.get('firstChild').get('data');
106 * Determines the page number for the provided page.
109 * @param page {Node} The page to find a number for.
110 * @return {Number|false} The number of the page in question or false if no number was found.
112 getNumber: function(page) {
113 // We perform a simple substitution operation to get the number.
114 var number = page.one(this.SELECTORS.NUMBER).get('text').replace(
115 this.CONSTANTS.PAGENUMBERPREFIX, '');
117 // Attempt to validate the ID.
118 number = parseInt(number, 10);
119 if (typeof number === 'number' && isFinite(number)) {
126 * Updates the page number for the provided page.
129 * @param page {Node} The page to update the number for.
132 setNumber: function(page, number) {
133 page.one(this.SELECTORS.NUMBER).set('text', this.CONSTANTS.PAGENUMBERPREFIX + number);
137 * Returns a list of all page elements.
140 * @return {node[]} An array containing page nodes.
142 getPages: function() {
143 return Y.all(Y.Moodle.mod_quiz.util.slot.SELECTORS.PAGECONTENT + ' ' +
144 Y.Moodle.mod_quiz.util.slot.SELECTORS.SECTIONUL + ' ' +
145 this.SELECTORS.PAGE);
149 * Is the given element a page element?
152 * @param page Page node
155 isPage: function(page) {
159 return page.hasClass(this.CSS.PAGE);
163 * Does the page have atleast one slot?
166 * @param page Page node
169 isEmpty: function(page) {
170 var activity = page.next('li.activity');
174 return !activity.hasClass('slot');
178 * Add a page and related elements to the list of slots.
181 * @param beforenode Int | Node | HTMLElement | String to add
182 * @return page Page node
184 add: function(beforenode) {
185 var pagenumber = this.getNumber(this.getPageFromSlot(beforenode)) + 1;
186 var pagehtml = M.mod_quiz.resource_toolbox.get('config').pagehtml;
188 // Normalise the page number.
189 pagehtml = pagehtml.replace(/%%PAGENUMBER%%/g, pagenumber);
191 // Create the page node.
192 var page = Y.Node.create(pagehtml);
194 // Assign is as a drop target.
195 YUI().use('dd-drop', function(Y) {
196 var drop = new Y.DD.Drop({
198 groups: M.mod_quiz.dragres.groups
203 // Insert in the correct place.
204 beforenode.insert(page, 'after');
206 // Enhance the add menu to make if fully visible and clickable.
207 M.core.actionmenu.newDOMNode(page);
212 * Remove a page and related elements from the list of slots.
215 * @param page Page node
218 remove: function(page, keeppagebreak) {
219 // Remove page break from previous slot.
220 var previousslot = page.previous(Y.Moodle.mod_quiz.util.slot.SELECTORS.SLOT);
221 if (!keeppagebreak && previousslot) {
222 Y.Moodle.mod_quiz.util.slot.removePageBreak(previousslot);
228 * Reset the order of the numbers given to each page.
230 * @method reorderPages
233 reorderPages: function() {
234 // Get list of page nodes.
235 var pages = this.getPages(), currentpagenumber = 0;
236 // Loop through pages incrementing the number each time.
237 pages.each(function(page) {
238 // Is the page empty?
239 if (this.isEmpty(page)) {
240 var keeppagebreak = page.next('li.slot') ? true : false;
241 this.remove(page, keeppagebreak);
247 this.setNumber(page, currentpagenumber);
248 this.setId(page, currentpagenumber);
251 // Reorder action menus
252 this.reorderActionMenus();
256 * Reset the order of the numbers given to each action menu.
258 * @method reorderActionMenus
261 reorderActionMenus: function() {
262 // Get list of action menu nodes.
263 var actionmenus = this.getActionMenus();
264 // Loop through pages incrementing the number each time.
265 actionmenus.each(function(actionmenu, key) {
266 var previousActionMenu = actionmenus.item(key - 1),
267 previousActionMenunumber = 0;
268 if (previousActionMenu) {
269 previousActionMenunumber = this.getActionMenuId(previousActionMenu);
271 var id = previousActionMenunumber + 1;
274 this.setActionMenuId(actionmenu, id);
276 // Update action-menu-1-menubar
277 var menubar = actionmenu.one(this.SELECTORS.ACTIONMENUBAR);
278 menubar.set('id', this.CONSTANTS.ACTIONMENUIDPREFIX + id + this.CONSTANTS.ACTIONMENUBARIDSUFFIX);
280 // Update action-menu-1-menu
281 var menumenu = actionmenu.one(this.SELECTORS.ACTIONMENUMENU);
282 menumenu.set('id', this.CONSTANTS.ACTIONMENUIDPREFIX + id + this.CONSTANTS.ACTIONMENUMENUIDSUFFIX);
284 // Update the URL of the add-section action.
285 menumenu.one('a.addasection').set('href',
286 menumenu.one('a.addasection').get('href').replace(/\baddsectionatpage=\d/, 'addsectionatpage=' + id));
292 * Returns a list of all page elements.
294 * @method getActionMenus
295 * @return {node[]} An array containing page nodes.
297 getActionMenus: function() {
298 return Y.all(Y.Moodle.mod_quiz.util.slot.SELECTORS.PAGECONTENT + ' ' +
299 Y.Moodle.mod_quiz.util.slot.SELECTORS.SECTIONUL + ' ' +
300 this.SELECTORS.ACTIONMENU);
304 * Returns the ID for the provided action menu.
307 * @param actionmenu {Node} The actionmenu to find an ID for.
308 * @return {Number|false} The ID of the actionmenu in question or false if no ID was found.
310 getActionMenuId: function(actionmenu) {
311 // We perform a simple substitution operation to get the ID.
312 var id = actionmenu.get('id').replace(
313 this.CONSTANTS.ACTIONMENUIDPREFIX, '');
315 // Attempt to validate the ID.
316 id = parseInt(id, 10);
317 if (typeof id === 'number' && isFinite(id)) {
324 * Updates the page id for the provided page.
327 * @param page {Node} The page to update the number for.
328 * @param id int The id value.
331 setActionMenuId: function(actionmenu, id) {
332 actionmenu.set('id', this.CONSTANTS.ACTIONMENUIDPREFIX + id);