1 |
efrain |
1 |
// This file is part of Moodle - http://moodle.org/
|
|
|
2 |
//
|
|
|
3 |
// Moodle is free software: you can redistribute it and/or modify
|
|
|
4 |
// it under the terms of the GNU General Public License as published by
|
|
|
5 |
// the Free Software Foundation, either version 3 of the License, or
|
|
|
6 |
// (at your option) any later version.
|
|
|
7 |
//
|
|
|
8 |
// Moodle is distributed in the hope that it will be useful,
|
|
|
9 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
10 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
11 |
// GNU General Public License for more details.
|
|
|
12 |
//
|
|
|
13 |
// You should have received a copy of the GNU General Public License
|
|
|
14 |
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
|
|
15 |
|
|
|
16 |
/**
|
|
|
17 |
* Javascript to enhance the paged content paging bar.
|
|
|
18 |
*
|
|
|
19 |
* @module core/paged_content_paging_bar
|
|
|
20 |
* @copyright 2018 Ryan Wyllie <ryan@moodle.com>
|
|
|
21 |
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
|
22 |
*/
|
|
|
23 |
define([
|
|
|
24 |
'jquery',
|
|
|
25 |
'core/custom_interaction_events',
|
|
|
26 |
'core/paged_content_events',
|
|
|
27 |
'core/str',
|
|
|
28 |
'core/pubsub',
|
|
|
29 |
'core/pending',
|
|
|
30 |
],
|
|
|
31 |
function(
|
|
|
32 |
$,
|
|
|
33 |
CustomEvents,
|
|
|
34 |
PagedContentEvents,
|
|
|
35 |
Str,
|
|
|
36 |
PubSub,
|
|
|
37 |
Pending
|
|
|
38 |
) {
|
|
|
39 |
|
|
|
40 |
var SELECTORS = {
|
|
|
41 |
ROOT: '[data-region="paging-bar"]',
|
|
|
42 |
PAGE: '[data-page]',
|
|
|
43 |
PAGE_ITEM: '[data-region="page-item"]',
|
|
|
44 |
PAGE_LINK: '[data-region="page-link"]',
|
|
|
45 |
FIRST_BUTTON: '[data-control="first"]',
|
|
|
46 |
LAST_BUTTON: '[data-control="last"]',
|
|
|
47 |
NEXT_BUTTON: '[data-control="next"]',
|
|
|
48 |
PREVIOUS_BUTTON: '[data-control="previous"]',
|
|
|
49 |
DOTS_BUTTONS: '[data-dots]',
|
|
|
50 |
BEGINNING_DOTS_BUTTON: '[data-dots="beginning"]',
|
|
|
51 |
ENDING_DOTS_BUTTON: '[data-dots="ending"]',
|
|
|
52 |
};
|
|
|
53 |
|
|
|
54 |
/**
|
|
|
55 |
* Get the page element by number.
|
|
|
56 |
*
|
|
|
57 |
* @param {object} root The root element.
|
|
|
58 |
* @param {Number} pageNumber The page number.
|
|
|
59 |
* @return {jQuery}
|
|
|
60 |
*/
|
|
|
61 |
var getPageByNumber = function(root, pageNumber) {
|
|
|
62 |
return root.find(SELECTORS.PAGE_ITEM + '[data-page-number="' + pageNumber + '"]');
|
|
|
63 |
};
|
|
|
64 |
|
|
|
65 |
/**
|
|
|
66 |
* Get the next button element.
|
|
|
67 |
*
|
|
|
68 |
* @param {object} root The root element.
|
|
|
69 |
* @return {jQuery}
|
|
|
70 |
*/
|
|
|
71 |
var getNextButton = function(root) {
|
|
|
72 |
return root.find(SELECTORS.NEXT_BUTTON);
|
|
|
73 |
};
|
|
|
74 |
|
|
|
75 |
/**
|
|
|
76 |
* Set the last page number after which no more pages
|
|
|
77 |
* should be loaded.
|
|
|
78 |
*
|
|
|
79 |
* @param {object} root The root element.
|
|
|
80 |
* @param {Number} number Page number.
|
|
|
81 |
*/
|
|
|
82 |
var setLastPageNumber = function(root, number) {
|
|
|
83 |
root.attr('data-last-page-number', number);
|
|
|
84 |
};
|
|
|
85 |
|
|
|
86 |
/**
|
|
|
87 |
* Get the last page number.
|
|
|
88 |
*
|
|
|
89 |
* @param {object} root The root element.
|
|
|
90 |
* @return {Number}
|
|
|
91 |
*/
|
|
|
92 |
var getLastPageNumber = function(root) {
|
|
|
93 |
return parseInt(root.attr('data-last-page-number'), 10);
|
|
|
94 |
};
|
|
|
95 |
|
|
|
96 |
/**
|
|
|
97 |
* Get the active page number.
|
|
|
98 |
*
|
|
|
99 |
* @param {object} root The root element.
|
|
|
100 |
* @returns {Number} The page number
|
|
|
101 |
*/
|
|
|
102 |
var getActivePageNumber = function(root) {
|
|
|
103 |
return parseInt(root.attr('data-active-page-number'), 10);
|
|
|
104 |
};
|
|
|
105 |
|
|
|
106 |
/**
|
|
|
107 |
* Set the active page number.
|
|
|
108 |
*
|
|
|
109 |
* @param {object} root The root element.
|
|
|
110 |
* @param {Number} number Page number.
|
|
|
111 |
*/
|
|
|
112 |
var setActivePageNumber = function(root, number) {
|
|
|
113 |
root.attr('data-active-page-number', number);
|
|
|
114 |
};
|
|
|
115 |
|
|
|
116 |
/**
|
|
|
117 |
* Check if there is an active page number.
|
|
|
118 |
*
|
|
|
119 |
* @param {object} root The root element.
|
|
|
120 |
* @returns {bool}
|
|
|
121 |
*/
|
|
|
122 |
var hasActivePageNumber = function(root) {
|
|
|
123 |
var number = getActivePageNumber(root);
|
|
|
124 |
return !isNaN(number) && number != 0;
|
|
|
125 |
};
|
|
|
126 |
|
|
|
127 |
/**
|
|
|
128 |
* Get the page number for a given page.
|
|
|
129 |
*
|
|
|
130 |
* @param {object} root The root element.
|
|
|
131 |
* @param {object} page The page element.
|
|
|
132 |
* @returns {Number} The page number
|
|
|
133 |
*/
|
|
|
134 |
var getPageNumber = function(root, page) {
|
|
|
135 |
if (page.attr('data-page') != undefined) {
|
|
|
136 |
// If it's an actual page then we can just use the page number
|
|
|
137 |
// attribute.
|
|
|
138 |
return parseInt(page.attr('data-page-number'), 10);
|
|
|
139 |
}
|
|
|
140 |
|
|
|
141 |
var pageNumber = 1;
|
|
|
142 |
var activePageNumber = null;
|
|
|
143 |
|
|
|
144 |
switch (page.attr('data-control')) {
|
|
|
145 |
case 'first':
|
|
|
146 |
pageNumber = 1;
|
|
|
147 |
break;
|
|
|
148 |
|
|
|
149 |
case 'last':
|
|
|
150 |
pageNumber = getLastPageNumber(root);
|
|
|
151 |
break;
|
|
|
152 |
|
|
|
153 |
case 'next':
|
|
|
154 |
activePageNumber = getActivePageNumber(root);
|
|
|
155 |
var lastPage = getLastPageNumber(root);
|
|
|
156 |
if (!lastPage) {
|
|
|
157 |
pageNumber = activePageNumber + 1;
|
|
|
158 |
} else if (activePageNumber && activePageNumber < lastPage) {
|
|
|
159 |
pageNumber = activePageNumber + 1;
|
|
|
160 |
} else {
|
|
|
161 |
pageNumber = lastPage;
|
|
|
162 |
}
|
|
|
163 |
break;
|
|
|
164 |
|
|
|
165 |
case 'previous':
|
|
|
166 |
activePageNumber = getActivePageNumber(root);
|
|
|
167 |
if (activePageNumber && activePageNumber > 1) {
|
|
|
168 |
pageNumber = activePageNumber - 1;
|
|
|
169 |
} else {
|
|
|
170 |
pageNumber = 1;
|
|
|
171 |
}
|
|
|
172 |
break;
|
|
|
173 |
|
|
|
174 |
default:
|
|
|
175 |
pageNumber = 1;
|
|
|
176 |
break;
|
|
|
177 |
}
|
|
|
178 |
|
|
|
179 |
// Make sure we return an int not a string.
|
|
|
180 |
return parseInt(pageNumber, 10);
|
|
|
181 |
};
|
|
|
182 |
|
|
|
183 |
/**
|
|
|
184 |
* Get the limit of items for each page.
|
|
|
185 |
*
|
|
|
186 |
* @param {object} root The root element.
|
|
|
187 |
* @returns {Number}
|
|
|
188 |
*/
|
|
|
189 |
var getLimit = function(root) {
|
|
|
190 |
return parseInt(root.attr('data-items-per-page'), 10);
|
|
|
191 |
};
|
|
|
192 |
|
|
|
193 |
/**
|
|
|
194 |
* Set the limit of items for each page.
|
|
|
195 |
*
|
|
|
196 |
* @param {object} root The root element.
|
|
|
197 |
* @param {Number} limit Items per page limit.
|
|
|
198 |
*/
|
|
|
199 |
var setLimit = function(root, limit) {
|
|
|
200 |
root.attr('data-items-per-page', limit);
|
|
|
201 |
};
|
|
|
202 |
|
|
|
203 |
/**
|
|
|
204 |
* Show the paging bar.
|
|
|
205 |
*
|
|
|
206 |
* @param {object} root The root element.
|
|
|
207 |
*/
|
|
|
208 |
var show = function(root) {
|
|
|
209 |
root.removeClass('hidden');
|
|
|
210 |
};
|
|
|
211 |
|
|
|
212 |
/**
|
|
|
213 |
* Hide the paging bar.
|
|
|
214 |
*
|
|
|
215 |
* @param {object} root The root element.
|
|
|
216 |
*/
|
|
|
217 |
var hide = function(root) {
|
|
|
218 |
root.addClass('hidden');
|
|
|
219 |
};
|
|
|
220 |
|
|
|
221 |
/**
|
|
|
222 |
* Disable the next and last buttons in the paging bar.
|
|
|
223 |
*
|
|
|
224 |
* @param {object} root The root element.
|
|
|
225 |
*/
|
|
|
226 |
var disableNextControlButtons = function(root) {
|
|
|
227 |
var nextButton = root.find(SELECTORS.NEXT_BUTTON);
|
|
|
228 |
var lastButton = root.find(SELECTORS.LAST_BUTTON);
|
|
|
229 |
|
|
|
230 |
nextButton.addClass('disabled');
|
|
|
231 |
nextButton.attr('aria-disabled', true);
|
|
|
232 |
lastButton.addClass('disabled');
|
|
|
233 |
lastButton.attr('aria-disabled', true);
|
|
|
234 |
};
|
|
|
235 |
|
|
|
236 |
/**
|
|
|
237 |
* Enable the next and last buttons in the paging bar.
|
|
|
238 |
*
|
|
|
239 |
* @param {object} root The root element.
|
|
|
240 |
*/
|
|
|
241 |
var enableNextControlButtons = function(root) {
|
|
|
242 |
var nextButton = root.find(SELECTORS.NEXT_BUTTON);
|
|
|
243 |
var lastButton = root.find(SELECTORS.LAST_BUTTON);
|
|
|
244 |
|
|
|
245 |
nextButton.removeClass('disabled');
|
|
|
246 |
nextButton.removeAttr('aria-disabled');
|
|
|
247 |
lastButton.removeClass('disabled');
|
|
|
248 |
lastButton.removeAttr('aria-disabled');
|
|
|
249 |
};
|
|
|
250 |
|
|
|
251 |
/**
|
|
|
252 |
* Disable the previous and first buttons in the paging bar.
|
|
|
253 |
*
|
|
|
254 |
* @param {object} root The root element.
|
|
|
255 |
*/
|
|
|
256 |
var disablePreviousControlButtons = function(root) {
|
|
|
257 |
var previousButton = root.find(SELECTORS.PREVIOUS_BUTTON);
|
|
|
258 |
var firstButton = root.find(SELECTORS.FIRST_BUTTON);
|
|
|
259 |
|
|
|
260 |
previousButton.addClass('disabled');
|
|
|
261 |
previousButton.attr('aria-disabled', true);
|
|
|
262 |
firstButton.addClass('disabled');
|
|
|
263 |
firstButton.attr('aria-disabled', true);
|
|
|
264 |
};
|
|
|
265 |
|
|
|
266 |
/**
|
|
|
267 |
* Adjusts the size of the paging bar and hides unnecessary pages.
|
|
|
268 |
*
|
|
|
269 |
* @param {object} root The root element.
|
|
|
270 |
*/
|
|
|
271 |
var adjustPagingBarSize = function(root) {
|
|
|
272 |
var activePageNumber = getActivePageNumber(root);
|
|
|
273 |
var lastPageNumber = getLastPageNumber(root);
|
|
|
274 |
|
|
|
275 |
var dotsButtons = root.find(SELECTORS.DOTS_BUTTONS);
|
|
|
276 |
var beginningDotsButton = root.find(SELECTORS.BEGINNING_DOTS_BUTTON);
|
|
|
277 |
var endingDotsButton = root.find(SELECTORS.ENDING_DOTS_BUTTON);
|
|
|
278 |
|
|
|
279 |
var pages = root.find(SELECTORS.PAGE);
|
|
|
280 |
var barSize = parseInt(root.attr('data-bar-size'), 10);
|
|
|
281 |
|
|
|
282 |
if (barSize && lastPageNumber > barSize) {
|
|
|
283 |
|
|
|
284 |
var minpage = Math.max(activePageNumber - Math.round(barSize / 2), 1);
|
|
|
285 |
var maxpage = minpage + barSize - 1;
|
|
|
286 |
|
|
|
287 |
if (maxpage >= lastPageNumber) {
|
|
|
288 |
maxpage = lastPageNumber;
|
|
|
289 |
minpage = maxpage - barSize + 1;
|
|
|
290 |
}
|
|
|
291 |
|
|
|
292 |
if (minpage > 1) {
|
|
|
293 |
show(beginningDotsButton);
|
|
|
294 |
minpage++;
|
|
|
295 |
} else {
|
|
|
296 |
hide(beginningDotsButton);
|
|
|
297 |
}
|
|
|
298 |
if (maxpage < lastPageNumber) {
|
|
|
299 |
show(endingDotsButton);
|
|
|
300 |
maxpage--;
|
|
|
301 |
} else {
|
|
|
302 |
hide(endingDotsButton);
|
|
|
303 |
}
|
|
|
304 |
dotsButtons.addClass('disabled');
|
|
|
305 |
dotsButtons.attr('aria-disabled', true);
|
|
|
306 |
|
|
|
307 |
hide(pages);
|
|
|
308 |
|
|
|
309 |
pages.each(function(index, page) {
|
|
|
310 |
page = $(page);
|
|
|
311 |
if ((index + 1) >= minpage && (index + 1) <= maxpage) {
|
|
|
312 |
show(page);
|
|
|
313 |
}
|
|
|
314 |
});
|
|
|
315 |
|
|
|
316 |
} else {
|
|
|
317 |
hide(dotsButtons);
|
|
|
318 |
}
|
|
|
319 |
};
|
|
|
320 |
|
|
|
321 |
/**
|
|
|
322 |
* Enable the previous and first buttons in the paging bar.
|
|
|
323 |
*
|
|
|
324 |
* @param {object} root The root element.
|
|
|
325 |
*/
|
|
|
326 |
var enablePreviousControlButtons = function(root) {
|
|
|
327 |
var previousButton = root.find(SELECTORS.PREVIOUS_BUTTON);
|
|
|
328 |
var firstButton = root.find(SELECTORS.FIRST_BUTTON);
|
|
|
329 |
|
|
|
330 |
previousButton.removeClass('disabled');
|
|
|
331 |
previousButton.removeAttr('aria-disabled');
|
|
|
332 |
firstButton.removeClass('disabled');
|
|
|
333 |
firstButton.removeAttr('aria-disabled');
|
|
|
334 |
};
|
|
|
335 |
|
|
|
336 |
/**
|
|
|
337 |
* Get the components for a get_string request for the aria-label
|
|
|
338 |
* on a page. The value is a comma separated string of key and
|
|
|
339 |
* component.
|
|
|
340 |
*
|
|
|
341 |
* @param {object} root The root element.
|
|
|
342 |
* @return {array} First element is the key, second is the component.
|
|
|
343 |
*/
|
|
|
344 |
var getPageAriaLabelComponents = function(root) {
|
|
|
345 |
var componentString = root.attr('data-aria-label-components-pagination-item');
|
|
|
346 |
var components = componentString.split(',').map(function(component) {
|
|
|
347 |
return component.trim();
|
|
|
348 |
});
|
|
|
349 |
return components;
|
|
|
350 |
};
|
|
|
351 |
|
|
|
352 |
/**
|
|
|
353 |
* Get the components for a get_string request for the aria-label
|
|
|
354 |
* on an active page. The value is a comma separated string of key and
|
|
|
355 |
* component.
|
|
|
356 |
*
|
|
|
357 |
* @param {object} root The root element.
|
|
|
358 |
* @return {array} First element is the key, second is the component.
|
|
|
359 |
*/
|
|
|
360 |
var getActivePageAriaLabelComponents = function(root) {
|
|
|
361 |
var componentString = root.attr('data-aria-label-components-pagination-active-item');
|
|
|
362 |
var components = componentString.split(',').map(function(component) {
|
|
|
363 |
return component.trim();
|
|
|
364 |
});
|
|
|
365 |
return components;
|
|
|
366 |
};
|
|
|
367 |
|
|
|
368 |
/**
|
|
|
369 |
* Set page numbers on each of the given items. Page numbers are set
|
|
|
370 |
* from 1..n (where n is the number of items).
|
|
|
371 |
*
|
|
|
372 |
* Sets the active page number to be the last page found with
|
|
|
373 |
* an "active" class (if any).
|
|
|
374 |
*
|
|
|
375 |
* Sets the last page number.
|
|
|
376 |
*
|
|
|
377 |
* @param {object} root The root element.
|
|
|
378 |
* @param {jQuery} items A jQuery list of items.
|
|
|
379 |
*/
|
|
|
380 |
var generatePageNumbers = function(root, items) {
|
|
|
381 |
var lastPageNumber = 0;
|
|
|
382 |
setActivePageNumber(root, 0);
|
|
|
383 |
|
|
|
384 |
items.each(function(index, item) {
|
|
|
385 |
var pageNumber = index + 1;
|
|
|
386 |
item = $(item);
|
|
|
387 |
item.attr('data-page-number', pageNumber);
|
|
|
388 |
lastPageNumber++;
|
|
|
389 |
|
|
|
390 |
if (item.hasClass('active')) {
|
|
|
391 |
setActivePageNumber(root, pageNumber);
|
|
|
392 |
}
|
|
|
393 |
});
|
|
|
394 |
|
|
|
395 |
setLastPageNumber(root, lastPageNumber);
|
|
|
396 |
};
|
|
|
397 |
|
|
|
398 |
/**
|
|
|
399 |
* Set the aria-labels on each of the page items in the paging bar.
|
|
|
400 |
* This includes the next, previous, first, and last items.
|
|
|
401 |
*
|
|
|
402 |
* @param {object} root The root element.
|
|
|
403 |
*/
|
|
|
404 |
var generateAriaLabels = function(root) {
|
|
|
405 |
var pageAriaLabelComponents = getPageAriaLabelComponents(root);
|
|
|
406 |
var activePageAriaLabelComponents = getActivePageAriaLabelComponents(root);
|
|
|
407 |
var activePageNumber = getActivePageNumber(root);
|
|
|
408 |
var pageItems = root.find(SELECTORS.PAGE_ITEM);
|
|
|
409 |
// We want to request all of the strings at once rather than
|
|
|
410 |
// one at a time.
|
|
|
411 |
var stringRequests = pageItems.toArray().map(function(index, page) {
|
|
|
412 |
page = $(page);
|
|
|
413 |
var pageNumber = getPageNumber(root, page);
|
|
|
414 |
|
|
|
415 |
if (pageNumber === activePageNumber) {
|
|
|
416 |
return {
|
|
|
417 |
key: activePageAriaLabelComponents[0],
|
|
|
418 |
component: activePageAriaLabelComponents[1],
|
|
|
419 |
param: pageNumber
|
|
|
420 |
};
|
|
|
421 |
} else {
|
|
|
422 |
return {
|
|
|
423 |
key: pageAriaLabelComponents[0],
|
|
|
424 |
component: pageAriaLabelComponents[1],
|
|
|
425 |
param: pageNumber
|
|
|
426 |
};
|
|
|
427 |
}
|
|
|
428 |
});
|
|
|
429 |
|
|
|
430 |
Str.get_strings(stringRequests).then(function(strings) {
|
|
|
431 |
pageItems.each(function(index, page) {
|
|
|
432 |
page = $(page);
|
|
|
433 |
var string = strings[index];
|
|
|
434 |
page.attr('aria-label', string);
|
|
|
435 |
page.find(SELECTORS.PAGE_LINK).attr('aria-label', string);
|
|
|
436 |
});
|
|
|
437 |
|
|
|
438 |
return strings;
|
|
|
439 |
})
|
|
|
440 |
.catch(function() {
|
|
|
441 |
// No need to interrupt the page if we can't load the aria lang strings.
|
|
|
442 |
return;
|
|
|
443 |
});
|
|
|
444 |
};
|
|
|
445 |
|
|
|
446 |
/**
|
|
|
447 |
* Make the paging bar item for the given page number visible and fire
|
|
|
448 |
* the SHOW_PAGES paged content event to tell any listening content to
|
|
|
449 |
* update.
|
|
|
450 |
*
|
|
|
451 |
* @param {object} root The root element.
|
|
|
452 |
* @param {Number} pageNumber The number for the page to show.
|
|
|
453 |
* @param {string} id A uniqie id for this instance.
|
|
|
454 |
*/
|
|
|
455 |
var showPage = function(root, pageNumber, id) {
|
|
|
456 |
var pendingPromise = new Pending('core/paged_content_paging_bar:showPage');
|
|
|
457 |
var lastPageNumber = getLastPageNumber(root);
|
|
|
458 |
var isSamePage = pageNumber == getActivePageNumber(root);
|
|
|
459 |
var limit = getLimit(root);
|
|
|
460 |
var offset = (pageNumber - 1) * limit;
|
|
|
461 |
|
|
|
462 |
if (!isSamePage) {
|
|
|
463 |
// We only need to toggle the active class if the user didn't click
|
|
|
464 |
// on the already active page.
|
|
|
465 |
root.find(SELECTORS.PAGE_ITEM).removeClass('active').removeAttr('aria-current');
|
|
|
466 |
var page = getPageByNumber(root, pageNumber);
|
|
|
467 |
page.addClass('active');
|
|
|
468 |
page.attr('aria-current', true);
|
|
|
469 |
setActivePageNumber(root, pageNumber);
|
|
|
470 |
|
|
|
471 |
adjustPagingBarSize(root);
|
|
|
472 |
}
|
|
|
473 |
|
|
|
474 |
// Make sure the control buttons are disabled as the user navigates
|
|
|
475 |
// to either end of the limits.
|
|
|
476 |
if (lastPageNumber && pageNumber >= lastPageNumber) {
|
|
|
477 |
disableNextControlButtons(root);
|
|
|
478 |
} else {
|
|
|
479 |
enableNextControlButtons(root);
|
|
|
480 |
}
|
|
|
481 |
|
|
|
482 |
if (pageNumber > 1) {
|
|
|
483 |
enablePreviousControlButtons(root);
|
|
|
484 |
} else {
|
|
|
485 |
disablePreviousControlButtons(root);
|
|
|
486 |
}
|
|
|
487 |
|
|
|
488 |
generateAriaLabels(root);
|
|
|
489 |
|
|
|
490 |
// This event requires a payload that contains a list of all pages that
|
|
|
491 |
// were activated. In the case of the paging bar we only show one page at
|
|
|
492 |
// a time.
|
|
|
493 |
PubSub.publish(id + PagedContentEvents.SHOW_PAGES, [{
|
|
|
494 |
pageNumber: pageNumber,
|
|
|
495 |
limit: limit,
|
|
|
496 |
offset: offset
|
|
|
497 |
}]);
|
|
|
498 |
|
|
|
499 |
pendingPromise.resolve();
|
|
|
500 |
};
|
|
|
501 |
|
|
|
502 |
/**
|
|
|
503 |
* Add event listeners for interactions with the paging bar as well as listening
|
|
|
504 |
* for custom paged content events.
|
|
|
505 |
*
|
|
|
506 |
* Each event will trigger different logic to update parts of the paging bar's
|
|
|
507 |
* display.
|
|
|
508 |
*
|
|
|
509 |
* @param {object} root The root element.
|
|
|
510 |
* @param {string} id A uniqie id for this instance.
|
|
|
511 |
*/
|
|
|
512 |
var registerEventListeners = function(root, id) {
|
|
|
513 |
var ignoreControlWhileLoading = root.attr('data-ignore-control-while-loading');
|
|
|
514 |
var loading = false;
|
|
|
515 |
|
|
|
516 |
if (ignoreControlWhileLoading == "") {
|
|
|
517 |
// Default to ignoring control while loading if not specified.
|
|
|
518 |
ignoreControlWhileLoading = true;
|
|
|
519 |
}
|
|
|
520 |
|
|
|
521 |
CustomEvents.define(root, [
|
|
|
522 |
CustomEvents.events.activate
|
|
|
523 |
]);
|
|
|
524 |
|
|
|
525 |
root.on(CustomEvents.events.activate, SELECTORS.PAGE_ITEM, function(e, data) {
|
|
|
526 |
data.originalEvent.preventDefault();
|
|
|
527 |
data.originalEvent.stopPropagation();
|
|
|
528 |
|
|
|
529 |
if (ignoreControlWhileLoading && loading) {
|
|
|
530 |
// Do nothing if configured to ignore control while loading.
|
|
|
531 |
return;
|
|
|
532 |
}
|
|
|
533 |
|
|
|
534 |
var page = $(e.target).closest(SELECTORS.PAGE_ITEM);
|
|
|
535 |
|
|
|
536 |
if (!page.hasClass('disabled')) {
|
|
|
537 |
var pageNumber = getPageNumber(root, page);
|
|
|
538 |
showPage(root, pageNumber, id);
|
|
|
539 |
loading = true;
|
|
|
540 |
}
|
|
|
541 |
});
|
|
|
542 |
|
|
|
543 |
// This event is fired when all of the items have been loaded. Typically used
|
|
|
544 |
// in an "infinite" pages context when we don't know the exact number of pages
|
|
|
545 |
// ahead of time.
|
|
|
546 |
PubSub.subscribe(id + PagedContentEvents.ALL_ITEMS_LOADED, function(pageNumber) {
|
|
|
547 |
loading = false;
|
|
|
548 |
var currentLastPage = getLastPageNumber(root);
|
|
|
549 |
|
|
|
550 |
if (!currentLastPage || pageNumber < currentLastPage) {
|
|
|
551 |
// Somehow the value we've got saved is higher than the new
|
|
|
552 |
// value we just received. Perhaps events came out of order.
|
|
|
553 |
// In any case, save the lowest value.
|
|
|
554 |
setLastPageNumber(root, pageNumber);
|
|
|
555 |
}
|
|
|
556 |
|
|
|
557 |
if (pageNumber === 1 && root.attr('data-hide-control-on-single-page')) {
|
|
|
558 |
// If all items were loaded on the first page then we can hide
|
|
|
559 |
// the paging bar because there are no other pages to load.
|
|
|
560 |
hide(root);
|
|
|
561 |
disableNextControlButtons(root);
|
|
|
562 |
disablePreviousControlButtons(root);
|
|
|
563 |
} else {
|
|
|
564 |
show(root);
|
|
|
565 |
disableNextControlButtons(root);
|
|
|
566 |
}
|
|
|
567 |
});
|
|
|
568 |
|
|
|
569 |
// This event is fired after all of the requested pages have been rendered.
|
|
|
570 |
PubSub.subscribe(id + PagedContentEvents.PAGES_SHOWN, function() {
|
|
|
571 |
// All pages have been shown so turn off the loading flag.
|
|
|
572 |
loading = false;
|
|
|
573 |
});
|
|
|
574 |
|
|
|
575 |
// This is triggered when the paging limit is modified.
|
|
|
576 |
PubSub.subscribe(id + PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT, function(limit) {
|
|
|
577 |
// Update the limit.
|
|
|
578 |
setLimit(root, limit);
|
|
|
579 |
setLastPageNumber(root, 0);
|
|
|
580 |
setActivePageNumber(root, 0);
|
|
|
581 |
show(root);
|
|
|
582 |
// Reload the data from page 1 again.
|
|
|
583 |
showPage(root, 1, id);
|
|
|
584 |
});
|
|
|
585 |
};
|
|
|
586 |
|
|
|
587 |
/**
|
|
|
588 |
* Initialise the paging bar.
|
|
|
589 |
* @param {object} root The root element.
|
|
|
590 |
* @param {string} id A uniqie id for this instance.
|
|
|
591 |
*/
|
|
|
592 |
var init = function(root, id) {
|
|
|
593 |
root = $(root);
|
|
|
594 |
var pages = root.find(SELECTORS.PAGE);
|
|
|
595 |
generatePageNumbers(root, pages);
|
|
|
596 |
registerEventListeners(root, id);
|
|
|
597 |
|
|
|
598 |
if (hasActivePageNumber(root)) {
|
|
|
599 |
var activePageNumber = getActivePageNumber(root);
|
|
|
600 |
// If the the paging bar was rendered with an active page selected
|
|
|
601 |
// then make sure we fired off the event to tell the content page to
|
|
|
602 |
// show.
|
|
|
603 |
getPageByNumber(root, activePageNumber).click();
|
|
|
604 |
if (activePageNumber == 1) {
|
|
|
605 |
// If the first page is active then disable the previous buttons.
|
|
|
606 |
disablePreviousControlButtons(root);
|
|
|
607 |
}
|
|
|
608 |
} else {
|
|
|
609 |
// There was no active page number so load the first page using
|
|
|
610 |
// the next button. This allows the infinite pagination to work.
|
|
|
611 |
getNextButton(root).click();
|
|
|
612 |
}
|
|
|
613 |
|
|
|
614 |
adjustPagingBarSize(root);
|
|
|
615 |
};
|
|
|
616 |
|
|
|
617 |
return {
|
|
|
618 |
init: init,
|
|
|
619 |
disableNextControlButtons: disableNextControlButtons,
|
|
|
620 |
enableNextControlButtons: enableNextControlButtons,
|
|
|
621 |
disablePreviousControlButtons: disablePreviousControlButtons,
|
|
|
622 |
enablePreviousControlButtons: enablePreviousControlButtons,
|
|
|
623 |
showPage: showPage,
|
|
|
624 |
rootSelector: SELECTORS.ROOT,
|
|
|
625 |
};
|
|
|
626 |
});
|