From 4ab09853f4f77c956abc7b78e45f08003f172024 Mon Sep 17 00:00:00 2001 From: Ryan Wyllie Date: Wed, 21 Mar 2018 15:15:11 +0800 Subject: [PATCH] MDL-61138 javascript: add paged content widget --- lib/amd/build/paged_content_events.min.js | 1 + lib/amd/build/paged_content_factory.min.js | 1 + lib/amd/build/paged_content_pages.min.js | 1 + lib/amd/build/paged_content_paging_bar.min.js | 1 + lib/amd/build/paged_content_paging_dropdown.min.js | 1 + lib/amd/src/paged_content_events.js | 27 ++ lib/amd/src/paged_content_factory.js | 280 ++++++++++++++++++++ lib/amd/src/paged_content_pages.js | 283 +++++++++++++++++++++ lib/amd/src/paged_content_paging_bar.js | 228 +++++++++++++++++ lib/amd/src/paged_content_paging_dropdown.js | 237 +++++++++++++++++ lib/templates/paged_content.mustache | 81 ++++++ lib/templates/paged_content_page.mustache | 36 +++ lib/templates/paged_content_pages.mustache | 44 ++++ lib/templates/paged_content_paging_bar.mustache | 97 +++++++ .../paged_content_paging_bar_item.mustache | 41 +++ .../paged_content_paging_dropdown.mustache | 75 ++++++ .../paged_content_paging_dropdown_item.mustache | 35 +++ .../core/paged_content_paging_bar.mustache | 98 +++++++ .../core/paged_content_paging_dropdown.mustache | 76 ++++++ .../paged_content_paging_dropdown_item.mustache | 34 +++ 20 files changed, 1677 insertions(+) create mode 100644 lib/amd/build/paged_content_events.min.js create mode 100644 lib/amd/build/paged_content_factory.min.js create mode 100644 lib/amd/build/paged_content_pages.min.js create mode 100644 lib/amd/build/paged_content_paging_bar.min.js create mode 100644 lib/amd/build/paged_content_paging_dropdown.min.js create mode 100644 lib/amd/src/paged_content_events.js create mode 100644 lib/amd/src/paged_content_factory.js create mode 100644 lib/amd/src/paged_content_pages.js create mode 100644 lib/amd/src/paged_content_paging_bar.js create mode 100644 lib/amd/src/paged_content_paging_dropdown.js create mode 100644 lib/templates/paged_content.mustache create mode 100644 lib/templates/paged_content_page.mustache create mode 100644 lib/templates/paged_content_pages.mustache create mode 100644 lib/templates/paged_content_paging_bar.mustache create mode 100644 lib/templates/paged_content_paging_bar_item.mustache create mode 100644 lib/templates/paged_content_paging_dropdown.mustache create mode 100644 lib/templates/paged_content_paging_dropdown_item.mustache create mode 100644 theme/bootstrapbase/templates/core/paged_content_paging_bar.mustache create mode 100644 theme/bootstrapbase/templates/core/paged_content_paging_dropdown.mustache create mode 100644 theme/bootstrapbase/templates/core/paged_content_paging_dropdown_item.mustache diff --git a/lib/amd/build/paged_content_events.min.js b/lib/amd/build/paged_content_events.min.js new file mode 100644 index 00000000000..27e1fa81414 --- /dev/null +++ b/lib/amd/build/paged_content_events.min.js @@ -0,0 +1 @@ +define([],function(){return{SHOW_PAGES:"core-paged-content-show-pages"}}); \ No newline at end of file diff --git a/lib/amd/build/paged_content_factory.min.js b/lib/amd/build/paged_content_factory.min.js new file mode 100644 index 00000000000..c0fd46e8fbc --- /dev/null +++ b/lib/amd/build/paged_content_factory.min.js @@ -0,0 +1 @@ +define(["jquery","core/templates","core/notification","core/paged_content_pages"],function(a,b,c,d){var e={PAGED_CONTENT:"core/paged_content"},f=function(a,b){for(var c={itemsperpage:b,previous:{},next:{},pages:[]},d=1;d<=a;d++){var e={number:d,page:""+d};1===d&&(e.active=!0),c.pages.push(e)}return c},g=function(a,b,c){var d={options:[]},e=0,f=0,g=a;c.hasOwnProperty("maxPages")&&(g=c.maxPages);for(var h=1;h<=g;h++){var i=0;h<=2?(i=b,f=b):(f=2*f,i=f),e+=i;var j={itemcount:i,content:e};1===h&&(j.active=!0),d.options.push(j)}return d},h=function(a,b,c){var d={pagingbar:!1,pagingdropdown:!1,skipjs:!0};return c.hasOwnProperty("dropdown")&&c.dropdown?d.pagingdropdown=g(a,b,c):d.pagingbar=f(a,b),d},i=function(a,b){var c=1;if(a>0){var d=a%b;d?(a-=d,c=a/b+1):c=a/b}return c},j=function(f,g,j,k){"undefined"==typeof k&&(k={});var l=a.Deferred(),m=i(f,g),n=h(m,g,k);return b.render(e.PAGED_CONTENT,n).then(function(b,c){b=a(b);var e=b,f=b.find(d.rootSelector);d.init(f,e,j),l.resolve(b,c)}).fail(function(a){l.reject(a)}).fail(c.exception),l},k=function(a,b,c,d){"undefined"==typeof d&&(d={});var e=a.length;return j(e,b,function(b){var d=[];return b.forEach(function(b){var c=b.offset,f=b.limit?c+b.limit:e,g=a.slice(c,f);d.push(g)}),c(d)},d)};return{createFromAjax:j,createFromStaticList:k}}); \ No newline at end of file diff --git a/lib/amd/build/paged_content_pages.min.js b/lib/amd/build/paged_content_pages.min.js new file mode 100644 index 00000000000..b59f52d4601 --- /dev/null +++ b/lib/amd/build/paged_content_pages.min.js @@ -0,0 +1 @@ +define(["jquery","core/templates","core/notification","core/paged_content_events"],function(a,b,c,d){var e={ROOT:'[data-region="page-container"]',PAGE_REGION:'[data-region="paged-content-page"]',ACTIVE_PAGE_REGION:'[data-region="paged-content-page"].active'},f={PAGING_CONTENT_ITEM:"core/paged_content_page",LOADING:"core/overlay_loading"},g=function(a,b){return a.find('[data-page="'+b+'"]')},h=function(d){var e=a.Deferred();return b.render(f.LOADING,{visible:!0}).then(function(b){var c=a(b),f=setTimeout(function(){d.css("position","relative"),c.appendTo(d)},100);e.always(function(){clearTimeout(f),c.remove(),d.css("position","")})}).fail(c.exception),e},i=function(d,e,h){var i=a.Deferred();return e.then(function(a,e){b.render(f.PAGING_CONTENT_ITEM,{page:h,content:a}).then(function(a){b.appendNodeContents(d,a,e);var c=g(d,h);i.resolve(c)}).fail(function(a){i.reject(a)}).fail(c.exception)}).fail(function(a){i.reject(a)}).fail(c.exception),i},j=function(b,d,f){var j=[],k=[],l=a.Deferred();if(d.forEach(function(a){var c=a.pageNumber,d=g(b,c);d.length?j.push(d):k.push(a)}),k.length&&"function"==typeof f){var m=f(k),n=m.map(function(a,c){return i(b,a,k[c].pageNumber)});a.when.apply(a,n).then(function(){var a=Array.prototype.slice.call(arguments);l.resolve(a)}).fail(function(a){l.reject(a)}).fail(c.exception)}else l.resolve([]);var o=h(b);l.then(function(a){var c=j.concat(a);b.find(e.PAGE_REGION).addClass("hidden"),c.forEach(function(a){a.removeClass("hidden")})}).fail(c.exception).always(function(){o.resolve()})},k=function(b,c,e){b=a(b),c=a(c),c.on(d.SHOW_PAGES,function(a,c){j(b,c,e)})};return{init:k,rootSelector:e.ROOT}}); \ No newline at end of file diff --git a/lib/amd/build/paged_content_paging_bar.min.js b/lib/amd/build/paged_content_paging_bar.min.js new file mode 100644 index 00000000000..fcf975938cc --- /dev/null +++ b/lib/amd/build/paged_content_paging_bar.min.js @@ -0,0 +1 @@ +define(["jquery","core/custom_interaction_events","core/paged_content_events"],function(a,b,c){var d={ROOT:'[data-region="paging-bar"]',PAGE:"[data-page]",PAGE_ITEM:'[data-region="page-item"]',ACTIVE_PAGE_ITEM:'[data-region="page-item"].active'},e=function(a,b){return a.find(d.PAGE_ITEM+'[data-page-number="'+b+'"]')},f=function(a){var b=a.find(d.PAGE).last();return b?parseInt(b.attr("data-page-number"),10):null},g=function(a){var b=a.find(d.ACTIVE_PAGE_ITEM);return b.length?h(a,b):null},h=function(a,b){if(void 0!=b.attr("data-page"))return parseInt(b.attr("data-page-number"),10);var c=1,d=null;switch(b.attr("data-control")){case"first":c=1;break;case"last":c=f(a);break;case"next":d=g(a);var e=f(a);c=d&&d1?d-1:1;break;default:c=1}return parseInt(c,10)},i=function(a){return parseInt(a.attr("data-items-per-page"),10)},j=function(b){b.each(function(b,c){c=a(c),c.attr("data-page-number",b+1)})},k=function(a,b){var f=b==g(a),h=i(a),j=(b-1)*h;if(!f){a.find(d.PAGE_ITEM).removeClass("active");var k=e(a,b);k.addClass("active")}a.trigger(c.SHOW_PAGES,[[{pageNumber:b,limit:h,offset:j}]])},l=function(c){c=a(c);var e=c.find(d.PAGE);j(e);var f=g(c);f&&k(c,f),b.define(c,[b.events.activate]),c.on(b.events.activate,d.PAGE_ITEM,function(b,e){var f=a(b.target).closest(d.PAGE_ITEM),g=h(c,f);k(c,g),e.originalEvent.preventDefault(),e.originalEvent.stopPropagation()})};return{init:l,rootSelector:d.ROOT}}); \ No newline at end of file diff --git a/lib/amd/build/paged_content_paging_dropdown.min.js b/lib/amd/build/paged_content_paging_dropdown.min.js new file mode 100644 index 00000000000..381853b3283 --- /dev/null +++ b/lib/amd/build/paged_content_paging_dropdown.min.js @@ -0,0 +1 @@ +define(["jquery","core/custom_interaction_events","core/paged_content_events"],function(a,b,c){var d={ROOT:'[data-region="paging-dropdown-container"]',DROPDOWN_ITEM:'[data-region="dropdown-item"]',DROPDOWN_TOGGLE:'[data-region="dropdown-toggle"]',ACTIVE_DROPDOWN_ITEM:'[data-region="dropdown-item"].active',CARET:'[data-region="caret"]'},e=function(a){return parseInt(a.attr("data-page-number"),10)},f=function(a){return a.find(d.DROPDOWN_ITEM)},g=function(b,c){var d=e(c);return f(b).filter(function(b,c){return e(a(c)). + +/** + * Javascript to load and render the paging bar. + * + * @module core/paging_bar + * @copyright 2018 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define([], function() { + return { + SHOW_PAGES: 'core-paged-content-show-pages', + }; +}); diff --git a/lib/amd/src/paged_content_factory.js b/lib/amd/src/paged_content_factory.js new file mode 100644 index 00000000000..709dd8ebaa1 --- /dev/null +++ b/lib/amd/src/paged_content_factory.js @@ -0,0 +1,280 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Factory to create a paged content widget. + * + * @module core/paged_content_factory + * @copyright 2018 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define( +[ + 'jquery', + 'core/templates', + 'core/notification', + 'core/paged_content_pages' +], +function( + $, + Templates, + Notification, + PagedContent +) { + var TEMPLATES = { + PAGED_CONTENT: 'core/paged_content' + }; + + /** + * Build the context to render the paging bar template with based on the number + * of pages to show. + * + * @param {int} numberOfPages How many pages to have in the paging bar. + * @param {int} itemsPerPage How many items will be shown per page. + * @return {object} The template context. + */ + var buildPagingBarTemplateContext = function(numberOfPages, itemsPerPage) { + var context = { + "itemsperpage": itemsPerPage, + "previous": {}, + "next": {}, + "pages": [] + }; + + for (var i = 1; i <= numberOfPages; i++) { + var page = { + number: i, + page: "" + i, + }; + + // Make the first page active by default. + if (i === 1) { + page.active = true; + } + + context.pages.push(page); + } + + return context; + }; + + /** + * Build the context to render the paging dropdown template with based on the number + * of pages to show and items per page. + * + * This control is rendered with a gradual increase of the items per page to + * limit the number of pages in the dropdown. Each page will show twice as much + * as the previous page (except for the first two pages). + * + * For example: + * Number of pages = 3 + * Items per page = 25 + * Would render a dropdown will 4 options: + * 25 + * 50 + * 100 + * All + * + * @param {int} numberOfPages How many options to have in the dropdown. + * @param {int} itemsPerPage How many items will be shown per page. + * @param {object} config Configuration options provided by the client. + * @return {object} The template context. + */ + var buildPagingDropdownTemplateContext = function(numberOfPages, itemsPerPage, config) { + var context = { + options: [] + }; + + var totalItems = 0; + var lastIncrease = 0; + var maxPages = numberOfPages; + + if (config.hasOwnProperty('maxPages')) { + maxPages = config.maxPages; + } + + for (var i = 1; i <= maxPages; i++) { + var itemCount = 0; + + if (i <= 2) { + itemCount = itemsPerPage; + lastIncrease = itemsPerPage; + } else { + lastIncrease = lastIncrease * 2; + itemCount = lastIncrease; + } + + totalItems += itemCount; + var option = { + itemcount: itemCount, + content: totalItems + }; + + // Make the first option active by default. + if (i === 1) { + option.active = true; + } + + context.options.push(option); + } + + return context; + }; + + /** + * Build the context to render the paged content template with based on the number + * of pages to show, items per page, and configuration option. + * + * By default the code will render a paging bar for the paging controls unless + * otherwise specified in the provided config. + * + * @param {int} numberOfPages How many pages to have. + * @param {int} itemsPerPage How many items will be shown per page. + * @param {object} config Configuration options provided by the client. + * @return {object} The template context. + */ + var buildTemplateContext = function(numberOfPages, itemsPerPage, config) { + var context = { + pagingbar: false, + pagingdropdown: false, + skipjs: true + }; + + if (config.hasOwnProperty('dropdown') && config.dropdown) { + context.pagingdropdown = buildPagingDropdownTemplateContext(numberOfPages, itemsPerPage, config); + } else { + context.pagingbar = buildPagingBarTemplateContext(numberOfPages, itemsPerPage); + } + + return context; + }; + + /** + * Calculate the number of pages required for the given number of items and + * how many of each item should appear on a page. + * + * @param {int} numberOfItems How many items in total. + * @param {int} itemsPerPage How many items will be shown per page. + * @return {int} The number of pages required. + */ + var calculateNumberOfPages = function(numberOfItems, itemsPerPage) { + var numberOfPages = 1; + + if (numberOfItems > 0) { + var partial = numberOfItems % itemsPerPage; + + if (partial) { + numberOfItems -= partial; + numberOfPages = (numberOfItems / itemsPerPage) + 1; + } else { + numberOfPages = numberOfItems / itemsPerPage; + } + } + + return numberOfPages; + }; + + /** + * Create a paged content widget where the complete list of items is not loaded + * up front but will instead be loaded by an ajax request (or similar). + * + * The client code must provide a callback function which loads and renders the + * items for each page. See PagedContent.init for more details. + * + * The function will return a deferred that is resolved with a jQuery object + * for the HTML content and a string for the JavaScript. + * + * The current list of configuration options available are: + * dropdown {bool} True to render the page control as a dropdown (paging bar is default). + * + * @param {int} numberOfItems How many items are there in total. + * @param {int} itemsPerPage How many items will be shown per page. + * @param {function} renderPagesContentCallback Callback for loading and rendering the items. + * @param {object} config Configuration options provided by the client. + * @return {promise} Resolved with jQuery HTML and string JS. + */ + var createFromAjax = function(numberOfItems, itemsPerPage, renderPagesContentCallback, config) { + if (typeof config == 'undefined') { + config = {}; + } + + var deferred = $.Deferred(); + var numberOfPages = calculateNumberOfPages(numberOfItems, itemsPerPage); + var templateContext = buildTemplateContext(numberOfPages, itemsPerPage, config); + + Templates.render(TEMPLATES.PAGED_CONTENT, templateContext) + .then(function(html, js) { + html = $(html); + + var container = html; + var pagedContent = html.find(PagedContent.rootSelector); + + PagedContent.init(pagedContent, container, renderPagesContentCallback); + + deferred.resolve(html, js); + return; + }) + .fail(function(exception) { + deferred.reject(exception); + }) + .fail(Notification.exception); + + return deferred; + }; + + /** + * Create a paged content widget where the complete list of items is loaded + * up front. + * + * The client code must provide a callback function which renders the + * items for each page. The callback will be provided with an array where each + * value in the array is a the list of items to render for the page. + * + * The function will return a deferred that is resolved with a jQuery object + * for the HTML content and a string for the JavaScript. + * + * The current list of configuration options available are: + * dropdown {bool} True to render the page control as a dropdown (paging bar is default). + * + * @param {array} contentItems The list of items to paginate. + * @param {int} itemsPerPage How many items will be shown per page. + * @param {function} renderContentCallback Callback for rendering the items for the page. + * @param {object} config Configuration options provided by the client. + * @return {promise} Resolved with jQuery HTML and string JS. + */ + var createFromStaticList = function(contentItems, itemsPerPage, renderContentCallback, config) { + if (typeof config == 'undefined') { + config = {}; + } + + var numberOfItems = contentItems.length; + return createFromAjax(numberOfItems, itemsPerPage, function(pagesData) { + var contentToRender = []; + pagesData.forEach(function(pageData) { + var begin = pageData.offset; + var end = pageData.limit ? begin + pageData.limit : numberOfItems; + var items = contentItems.slice(begin, end); + contentToRender.push(items); + }); + + return renderContentCallback(contentToRender); + }, config); + }; + + return { + createFromAjax: createFromAjax, + createFromStaticList: createFromStaticList + }; +}); diff --git a/lib/amd/src/paged_content_pages.js b/lib/amd/src/paged_content_pages.js new file mode 100644 index 00000000000..4fbbb104622 --- /dev/null +++ b/lib/amd/src/paged_content_pages.js @@ -0,0 +1,283 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Javascript for showing/hiding pages of content. + * + * @module core/paged_content_pages + * @copyright 2018 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define( + [ + 'jquery', + 'core/templates', + 'core/notification', + 'core/paged_content_events' + ], + function( + $, + Templates, + Notification, + PagedContentEvents + ) { + + var SELECTORS = { + ROOT: '[data-region="page-container"]', + PAGE_REGION: '[data-region="paged-content-page"]', + ACTIVE_PAGE_REGION: '[data-region="paged-content-page"].active' + }; + + var TEMPLATES = { + PAGING_CONTENT_ITEM: 'core/paged_content_page', + LOADING: 'core/overlay_loading' + }; + + /** + * Find a page by the number. + * + * @param {object} root The root element. + * @param {Number} pageNumber The number of the page to be found. + * @returns {jQuery} The page. + */ + var findPage = function(root, pageNumber) { + return root.find('[data-page="' + pageNumber + '"]'); + }; + + /** + * Show the loading spinner until the returned deferred is resolved by the + * calling code. + * + * @param {object} root The root element. + * @returns {promise} The page. + */ + var startLoading = function(root) { + var deferred = $.Deferred(); + + Templates.render(TEMPLATES.LOADING, {visible: true}) + .then(function(html) { + var loadingSpinner = $(html); + // Put this in a timer to give the calling code 100 milliseconds + // to render the content before we show the loading spinner. This + // helps prevent a loading icon flicker on close to instant + // rendering. + var timerId = setTimeout(function() { + root.css('position', 'relative'); + loadingSpinner.appendTo(root); + }, 100); + + deferred.always(function() { + clearTimeout(timerId); + // Remove the loading spinner when our deferred is resolved + // by the calling code. + loadingSpinner.remove(); + root.css('position', ''); + return; + }); + + return; + }) + .fail(Notification.exception); + + return deferred; + }; + + /** + * Render the result of the page promise in a paged content page. + * + * This function returns a promise that is resolved with the new paged content + * page. + * + * @param {object} root The root element. + * @param {promise} pagePromise The promise resolved with HTML and JS to render in the page. + * @param {int} pageNumber The page number. + * @returns {promise} The page. + */ + var renderPagePromise = function(root, pagePromise, pageNumber) { + var deferred = $.Deferred(); + pagePromise.then(function(html, pageJS) { + // When we get the contents to be rendered we can pass it in as the + // content for a new page. + Templates.render(TEMPLATES.PAGING_CONTENT_ITEM, { + page: pageNumber, + content: html + }) + .then(function(html) { + // Make sure the JS we got from the page promise is being added + // to the page when we render the page. + Templates.appendNodeContents(root, html, pageJS); + var page = findPage(root, pageNumber); + deferred.resolve(page); + return; + }) + .fail(function(exception) { + deferred.reject(exception); + }) + .fail(Notification.exception); + + return; + }) + .fail(function(exception) { + deferred.reject(exception); + return; + }) + .fail(Notification.exception); + + return deferred; + }; + + /** + * Make one or more pages visible based on the SHOW_PAGES event. The show + * pages event provides data containing which pages should be shown as well + * as the limit and offset values for loading the items for each of those pages. + * + * The renderPagesContentCallback is provided this list of data to know which + * pages to load. E.g. the data to load 2 pages might look like: + * [ + * { + * pageNumber: 1, + * limit: 5, + * offset: 0 + * }, + * { + * pageNumber: 2, + * limit: 5, + * offset: 5 + * } + * ] + * + * The renderPagesContentCallback should return an array of promises, one for + * each page in the pages data, that is resolved with the HTML and JS for that page. + * + * If the renderPagesContentCallback is not provided then it is assumed that + * all pages have been rendered prior to initialising this module. + * + * @param {object} root The root element. + * @param {Number} pagesData The data for which pages need to be visible. + * @param {function} renderPagesContentCallback Render pages content. + */ + var showPages = function(root, pagesData, renderPagesContentCallback) { + var existingPages = []; + var newPageData = []; + var newPagesPromise = $.Deferred(); + + // Check which of the pages being requests have previously been rendered + // so that we only ask for new pages to be rendered by the callback. + pagesData.forEach(function(pageData) { + var pageNumber = pageData.pageNumber; + var existingPage = findPage(root, pageNumber); + if (existingPage.length) { + existingPages.push(existingPage); + } else { + newPageData.push(pageData); + } + }); + + if (newPageData.length && typeof renderPagesContentCallback === 'function') { + // If we have pages we haven't previously seen then ask the client code + // to render them for us by calling the callback. + var promises = renderPagesContentCallback(newPageData); + // After the client has finished rendering each of the pages being asked + // for then begin our rendering process to put that content into paged + // content pages. + var renderPagePromises = promises.map(function(promise, index) { + // Create our promise for when our rendering will be completed. + return renderPagePromise(root, promise, newPageData[index].pageNumber); + }); + // After each of our rendering promises have been completed then we can + // give all of the new pages to the next bit of code for handling. + $.when.apply($, renderPagePromises) + .then(function() { + var newPages = Array.prototype.slice.call(arguments); + // Resolve the promise with the list of newly rendered pages. + newPagesPromise.resolve(newPages); + return; + }) + .fail(function(exception) { + newPagesPromise.reject(exception); + return; + }) + .fail(Notification.exception); + } else { + // If there aren't any pages to load then immediately resolve the promise. + newPagesPromise.resolve([]); + } + + var loadingPromise = startLoading(root); + newPagesPromise.then(function(newPages) { + // Once all of the new pages have been created then add them to any + // existing pages we have. + var pagesToShow = existingPages.concat(newPages); + // Hide all existing pages. + root.find(SELECTORS.PAGE_REGION).addClass('hidden'); + // Show each of the pages that were requested. + pagesToShow.forEach(function(page) { + page.removeClass('hidden'); + }); + + return; + }) + .fail(Notification.exception) + .always(function() { + loadingPromise.resolve(); + }); + }; + + /** + * Initialise the module to listen for SHOW_PAGES events and render the + * appropriate pages using the provided renderPagesContentCallback function. + * + * The renderPagesContentCallback is provided a list of data to know which + * pages to load. + * E.g. the data to load 2 pages might look like: + * [ + * { + * pageNumber: 1, + * limit: 5, + * offset: 0 + * }, + * { + * pageNumber: 2, + * limit: 5, + * offset: 5 + * } + * ] + * + * The renderPagesContentCallback should return an array of promises, one for + * each page in the pages data, that is resolved with the HTML and JS for that page. + * + * If the renderPagesContentCallback is not provided then it is assumed that + * all pages have been rendered prior to initialising this module. + * + * The event element is the element to listen for the paged content events on. + * + * @param {object} root The root element. + * @param {object} eventElement The element to listen for events on. + * @param {function} renderPagesContentCallback Render pages content. + */ + var init = function(root, eventElement, renderPagesContentCallback) { + root = $(root); + eventElement = $(eventElement); + + eventElement.on(PagedContentEvents.SHOW_PAGES, function(e, pagesData) { + showPages(root, pagesData, renderPagesContentCallback); + }); + }; + + return { + init: init, + rootSelector: SELECTORS.ROOT, + }; +}); diff --git a/lib/amd/src/paged_content_paging_bar.js b/lib/amd/src/paged_content_paging_bar.js new file mode 100644 index 00000000000..c1d26b4993c --- /dev/null +++ b/lib/amd/src/paged_content_paging_bar.js @@ -0,0 +1,228 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Javascript to enhance the paged content paging bar. + * + * @module core/paging_bar + * @copyright 2018 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define( + [ + 'jquery', + 'core/custom_interaction_events', + 'core/paged_content_events' + ], + function( + $, + CustomEvents, + PagedContentEvents + ) { + + var SELECTORS = { + ROOT: '[data-region="paging-bar"]', + PAGE: '[data-page]', + PAGE_ITEM: '[data-region="page-item"]', + ACTIVE_PAGE_ITEM: '[data-region="page-item"].active' + }; + + /** + * Get the page element by number. + * + * @param {object} root The root element. + * @param {Number} pageNumber The page number. + * @return {jQuery} + */ + var getPageByNumber = function(root, pageNumber) { + return root.find(SELECTORS.PAGE_ITEM + '[data-page-number="' + pageNumber + '"]'); + }; + + /** + * Get the last page number. + * + * @param {object} root The root element. + * @return {int} + */ + var getLastPageNumber = function(root) { + var lastPage = root.find(SELECTORS.PAGE).last(); + if (lastPage) { + return parseInt(lastPage.attr('data-page-number'), 10); + } else { + return null; + } + }; + + /** + * Get the active page number. + * + * @param {object} root The root element. + * @returns {int} The page number + */ + var getActivePageNumber = function(root) { + var activePage = root.find(SELECTORS.ACTIVE_PAGE_ITEM); + + if (activePage.length) { + return getPageNumber(root, activePage); + } else { + return null; + } + }; + + /** + * Get the page number. + * + * @param {object} root The root element. + * @param {object} page The page. + * @returns {int} The page number + */ + var getPageNumber = function(root, page) { + if (page.attr('data-page') != undefined) { + // If it's an actual page then we can just use the page number + // attribute. + return parseInt(page.attr('data-page-number'), 10); + } + + var pageNumber = 1; + var activePageNumber = null; + + switch (page.attr('data-control')) { + case 'first': + pageNumber = 1; + break; + + case 'last': + pageNumber = getLastPageNumber(root); + break; + + case 'next': + activePageNumber = getActivePageNumber(root); + var lastPage = getLastPageNumber(root); + if (activePageNumber && activePageNumber < lastPage) { + pageNumber = activePageNumber + 1; + } else { + pageNumber = lastPage; + } + break; + + case 'previous': + activePageNumber = getActivePageNumber(root); + if (activePageNumber && activePageNumber > 1) { + pageNumber = activePageNumber - 1; + } else { + pageNumber = 1; + } + break; + + default: + pageNumber = 1; + break; + } + + // Make sure we return an int not a string. + return parseInt(pageNumber, 10); + }; + + /** + * Get the limit of items for each page. + * + * @param {object} root The root element. + * @returns {int} + */ + var getLimit = function(root) { + return parseInt(root.attr('data-items-per-page'), 10); + }; + + /** + * Set page numbers on each of the given items. Page numbers are set + * from 1..n (where n is the number of items). + * + * @param {jQuery} items A jQuery list of items. + */ + var generatePageNumbers = function(items) { + items.each(function(index, item) { + item = $(item); + item.attr('data-page-number', index + 1); + }); + }; + + /** + * Make the paging bar item for the given page number visible and fire + * the SHOW_PAGES paged content event to tell any listening content to + * update. + * + * @param {object} root The root element. + * @param {int} pageNumber The number for the page to show. + * @param {object} page The page. + */ + var showPage = function(root, pageNumber) { + var isSamePage = pageNumber == getActivePageNumber(root); + var limit = getLimit(root); + var offset = (pageNumber - 1) * limit; + + if (!isSamePage) { + // We only need to toggle the active class if the user didn't click + // on the already active page. + root.find(SELECTORS.PAGE_ITEM).removeClass('active'); + var page = getPageByNumber(root, pageNumber); + page.addClass('active'); + } + + // This event requires a payload that contains a list of all pages that + // were activated. In the case of the paging bar we only show one page at + // a time. + root.trigger(PagedContentEvents.SHOW_PAGES, [[{ + pageNumber: pageNumber, + limit: limit, + offset: offset + }]]); + }; + + /** + * Initialise the paging bar. + * @param {object} root The root element. + */ + var init = function(root) { + root = $(root); + var pages = root.find(SELECTORS.PAGE); + generatePageNumbers(pages); + + var activePageNumber = getActivePageNumber(root); + if (activePageNumber) { + // If the the paging bar was rendered with an active page selected + // then make sure we fired off the event to tell the content page to + // show. + showPage(root, activePageNumber); + } + + CustomEvents.define(root, [ + CustomEvents.events.activate + ]); + + root.on(CustomEvents.events.activate, SELECTORS.PAGE_ITEM, function(e, data) { + var page = $(e.target).closest(SELECTORS.PAGE_ITEM); + var pageNumber = getPageNumber(root, page); + showPage(root, pageNumber); + + data.originalEvent.preventDefault(); + data.originalEvent.stopPropagation(); + }); + }; + + return { + init: init, + rootSelector: SELECTORS.ROOT, + }; +}); diff --git a/lib/amd/src/paged_content_paging_dropdown.js b/lib/amd/src/paged_content_paging_dropdown.js new file mode 100644 index 00000000000..59d75b59cb1 --- /dev/null +++ b/lib/amd/src/paged_content_paging_dropdown.js @@ -0,0 +1,237 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Javascript to manage the paging dropdown control. + * + * @module core/paged_content_paging_dropdown + * @copyright 2018 Ryan Wyllie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define( + [ + 'jquery', + 'core/custom_interaction_events', + 'core/paged_content_events' + ], + function( + $, + CustomEvents, + PagedContentEvents + ) { + + var SELECTORS = { + ROOT: '[data-region="paging-dropdown-container"]', + DROPDOWN_ITEM: '[data-region="dropdown-item"]', + DROPDOWN_TOGGLE: '[data-region="dropdown-toggle"]', + ACTIVE_DROPDOWN_ITEM: '[data-region="dropdown-item"].active', + CARET: '[data-region="caret"]' + }; + + /** + * Get the page number. + * + * @param {jquery} item The dropdown item. + * @returns {int} + */ + var getPageNumber = function(item) { + return parseInt(item.attr('data-page-number'), 10); + }; + + /** + * Get all paging dropdown items. + * + * @param {jquery} root The root element. + * @returns {jquery} A jquery object with all items. + */ + var getAllItems = function(root) { + return root.find(SELECTORS.DROPDOWN_ITEM); + }; + + /** + * Get all paging dropdown items with lower page numbers than the given + * dropdown item. + * + * @param {jquery} root The root element. + * @param {jquery} item The dropdown item. + * @returns {jquery} A jquery object with all items. + */ + var getPreviousItems = function(root, item) { + var pageNumber = getPageNumber(item); + return getAllItems(root).filter(function(index, element) { + return getPageNumber($(element)) < pageNumber; + }); + }; + + /** + * Get the number of items to be loaded for the dropdown item. + * + * @param {jquery} item The dropdown item. + * @returns {int} + */ + var getLimit = function(item) { + return parseInt(item.attr('data-item-count'), 10); + }; + + /** + * Get the offset of items from the start of the itemset for the given + * dropdown item. + * + * @param {jquery} root The root element. + * @param {jquery} item The dropdown item. + * @returns {int} + */ + var getOffset = function(root, item) { + if (item.attr('data-offset') != undefined) { + return parseInt(item.attr('data-offset'), 10); + } + + var offset = 0; + + getPreviousItems(root, item).each(function(index, prevItem) { + prevItem = $(prevItem); + offset += getLimit(prevItem); + }); + + item.attr('data-offset', offset); + return offset; + }; + + /** + * Get the active dropdown item. + * + * @param {jquery} root The root element. + * @returns {jquery} The active dropdown item. + */ + var getActiveItem = function(root) { + return root.find(SELECTORS.ACTIVE_DROPDOWN_ITEM); + }; + + /** + * Create the event payload for the list of dropdown items. The event payload + * is an array of objects with one object per dropdown item. + * + * Each payload object contains the page number, limit, and offset for the + * corresponding dropdown item. + * + * For example: If we had 3 dropdown items with incrementing page numbers loading + * 25 items per page then the generated payload would look like: + * [ + * { + * pageNumber: 1, + * limit: 25, + * offset: 0 + * }, + * { + * pageNumber: 2, + * limit: 25, + * offset: 25 + * }, + * { + * pageNumber: 3, + * limit: 25, + * offset: 50 + * } + * ] + * + * @param {jquery} root The root element. + * @param {jquery} items The dropdown items. + * @returns {object[]} The payload for the event. + */ + var generateEventPayload = function(root, items) { + return items.map(function(index, item) { + item = $(item); + return { + pageNumber: getPageNumber(item), + limit: getLimit(item), + offset: getOffset(root, item), + }; + }).get(); + }; + + /** + * Add page number attributes to each of the given items. The page numbers + * start at 1 and increment by 1 for each item, e.g. 1, 2, 3 etc. + * + * @param {jquery} items The dropdown items. + */ + var generatePageNumbers = function(items) { + items.each(function(index, item) { + item = $(item); + item.attr('data-page-number', index + 1); + }); + }; + + /** + * Make the given item active by setting the active class on it and firing + * the SHOW_PAGES event for the paged content to show the appropriate + * pages. + * + * @param {jquery} root The root element. + * @param {jquery} item The dropdown item. + */ + var setActiveItem = function(root, item) { + var prevItems = getPreviousItems(root, item); + var allItems = prevItems.add(item); + var eventPayload = generateEventPayload(root, allItems); + var toggle = root.find(SELECTORS.DROPDOWN_TOGGLE); + var caret = toggle.find(SELECTORS.CARET); + + getActiveItem(root).removeClass('active'); + item.addClass('active'); + + // Update the dropdown toggle to show which item is selected. + toggle.html(item.text()); + // Bootstrap 2 compatibility. + toggle.append(caret); + // Fire the event to tell the content to update. + root.trigger(PagedContentEvents.SHOW_PAGES, [eventPayload]); + }; + + /** + * Initialise the module by firing the SHOW_PAGES event for an existing + * active page found and setting up the event listener for the user to select + * new pages. + * + * @param {object} root The root element. + */ + var init = function(root) { + root = $(root); + var items = getAllItems(root); + generatePageNumbers(items); + + var activeItem = getActiveItem(root); + if (activeItem.length) { + // Fire the first event for the content to make sure it's visible. + setActiveItem(root, activeItem); + } + + CustomEvents.define(root, [ + CustomEvents.events.activate + ]); + + root.on(CustomEvents.events.activate, SELECTORS.DROPDOWN_ITEM, function(e, data) { + var item = $(e.target).closest(SELECTORS.DROPDOWN_ITEM); + setActiveItem(root, item); + + data.originalEvent.preventDefault(); + }); + }; + + return { + init: init, + rootSelector: SELECTORS.ROOT, + }; +}); diff --git a/lib/templates/paged_content.mustache b/lib/templates/paged_content.mustache new file mode 100644 index 00000000000..47b5fbb4f5a --- /dev/null +++ b/lib/templates/paged_content.mustache @@ -0,0 +1,81 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template core/paged_content + + This template renders each of the content regions for a paginated + content section. + + Example context (json): + { + "pagingbar": { + "itemsperpage": 1, + "previous": true, + "next": true, + "first": true, + "last": true, + "pages": [ + { + "page": "1", + "active": true + }, + { + "url": "#", + "page": "2" + } + ] + }, + "pages": [ + { + "active": true, + "page": 1, + "content": "

Some page 1 content

" + }, + { + "page": 2, + "content": "

Some page 2 content

" + } + ] + } +}} +
+ {{#pagingbar}} + {{> core/paged_content_paging_bar }} + {{/pagingbar}} + {{#pagingdropdown}} + {{> core/paged_content_paging_dropdown }} + {{/pagingdropdown}} + {{> core/paged_content_pages }} +
+{{^skipjs}} +{{#js}} +require( +[ + 'jquery', + 'core/paged_content_pages' +], +function( + $, + PagedContent +) { + var container = $("#paged-content-container-{{uniqid}}"); + var pagingContent = container.find(PagedContent.rootSelector); + + PagedContent.init(pagingContent, container); +}); +{{/js}} +{{/skipjs}} diff --git a/lib/templates/paged_content_page.mustache b/lib/templates/paged_content_page.mustache new file mode 100644 index 00000000000..f912290a692 --- /dev/null +++ b/lib/templates/paged_content_page.mustache @@ -0,0 +1,36 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template core/paged_content_page + + This template renders the content of a page. It is to be used with + the paging bar or paging dropdown to toggle visibility of the content items. + + Example context (json): + { + "active": true, + "page": 1, + "content": "

Some page content

" + } +}} +
+ {{$content}} + {{{content}}} + {{/content}} +
diff --git a/lib/templates/paged_content_pages.mustache b/lib/templates/paged_content_pages.mustache new file mode 100644 index 00000000000..a93b33757b0 --- /dev/null +++ b/lib/templates/paged_content_pages.mustache @@ -0,0 +1,44 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template core/paged_content_pages + + This template renders each of the content regions for a paginated + content section. + + Example context (json): + { + "pages": [ + { + "active": true, + "page": 1, + "content": "

Some page content

" + }, + { + "page": 2, + "content": "

Some page content

" + } + ] + } +}} +
+ {{#pages}} + {{$paged-content-page}} + {{> core/paged_content_page }} + {{/paged-content-page}} + {{/pages}} +
diff --git a/lib/templates/paged_content_paging_bar.mustache b/lib/templates/paged_content_paging_bar.mustache new file mode 100644 index 00000000000..1147f6b691f --- /dev/null +++ b/lib/templates/paged_content_paging_bar.mustache @@ -0,0 +1,97 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template core/paged_content_paging_bar + + This template renders the bootstrap style paging bar to control a paged + content section. + + Example context (json): + { + "itemsperpage": 2, + "previous": true, + "next": true, + "first": true, + "last": true, + "pages": [ + { + "url": "#", + "page": "1", + "active": true + }, + { + "url": "#", + "page": "2" + } + ] + } +}} + +{{#js}} +require(['jquery', 'core/paged_content_paging_bar'], function($, PagingControl) { + var root = $('#{{$pagingbarid}}paging-bar-{{uniqid}}{{/pagingbarid}}'); + PagingControl.init(root); +}); +{{/js}} diff --git a/lib/templates/paged_content_paging_bar_item.mustache b/lib/templates/paged_content_paging_bar_item.mustache new file mode 100644 index 00000000000..e3ef1a2f07b --- /dev/null +++ b/lib/templates/paged_content_paging_bar_item.mustache @@ -0,0 +1,41 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template core/paged_content_paging_bar_item + + This template renders a single item in the paging bar. + + Example context (json): + { + "url": "#", + "number": 1, + "page": "1", + "active": true + } +}} +
  • + + + {{$item-content}} + {{{page}}} + {{/item-content}} + +
  • diff --git a/lib/templates/paged_content_paging_dropdown.mustache b/lib/templates/paged_content_paging_dropdown.mustache new file mode 100644 index 00000000000..d065d39745e --- /dev/null +++ b/lib/templates/paged_content_paging_dropdown.mustache @@ -0,0 +1,75 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template core/paged_content_paging_dropdown + + This template renders the bootstrap style dropdown menu to control + paged content. + + Example context (json): + { + "options": [ + { + "itemcount": 25, + "content": "25", + "active": true + }, + { + "itemcount": 25, + "content": "50" + }, + { + "itemcount": 50, + "content": "100" + } + ] + } +}} + +{{#js}} +require(['jquery', 'core/paged_content_paging_dropdown'], function($, PagingControl) { + var root = $('#paging-dropdown-{{uniqid}}'); + PagingControl.init(root); +}); +{{/js}} diff --git a/lib/templates/paged_content_paging_dropdown_item.mustache b/lib/templates/paged_content_paging_dropdown_item.mustache new file mode 100644 index 00000000000..7d4d5c9c3a0 --- /dev/null +++ b/lib/templates/paged_content_paging_dropdown_item.mustache @@ -0,0 +1,35 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template core/paged_content_paging_dropdown_item + + This template renders a single item in the paging dropdown menu. + + Example context (json): + { + "itemcount": 25, + "content": "25", + "active": true + } +}} + + + {{$content}}{{{content}}}{{/content}} + diff --git a/theme/bootstrapbase/templates/core/paged_content_paging_bar.mustache b/theme/bootstrapbase/templates/core/paged_content_paging_bar.mustache new file mode 100644 index 00000000000..b4bfd4fac81 --- /dev/null +++ b/theme/bootstrapbase/templates/core/paged_content_paging_bar.mustache @@ -0,0 +1,98 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template core/paged_content_paging_bar + + This template renders the bootstrap style paging bar to control a paged + content section. + + Example context (json): + { + "itemsperpage": 2, + "previous": true, + "next": true, + "first": true, + "last": true, + "pages": [ + { + "url": "#", + "page": "1", + "active": true + }, + { + "url": "#", + "page": "2" + } + ] + } +}} + +{{#js}} +require(['jquery', 'core/paged_content_paging_bar'], function($, PagingControl) { + var root = $('#{{$pagingbarid}}paging-bar-{{uniqid}}{{/pagingbarid}}'); + PagingControl.init(root); +}); +{{/js}} diff --git a/theme/bootstrapbase/templates/core/paged_content_paging_dropdown.mustache b/theme/bootstrapbase/templates/core/paged_content_paging_dropdown.mustache new file mode 100644 index 00000000000..de8517b248d --- /dev/null +++ b/theme/bootstrapbase/templates/core/paged_content_paging_dropdown.mustache @@ -0,0 +1,76 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template core/paged_content_paging_dropdown + + This template renders the bootstrap style dropdown menu to control + paged content. + + Example context (json): + { + "options": [ + { + "itemcount": 25, + "content": "25", + "active": true + }, + { + "itemcount": 25, + "content": "50" + }, + { + "itemcount": 50, + "content": "100" + } + ] + } +}} +
    + + + +
    +{{#js}} +require(['jquery', 'core/paged_content_paging_dropdown'], function($, PagingControl) { + var root = $('#paging-dropdown-{{uniqid}}'); + PagingControl.init(root); +}); +{{/js}} diff --git a/theme/bootstrapbase/templates/core/paged_content_paging_dropdown_item.mustache b/theme/bootstrapbase/templates/core/paged_content_paging_dropdown_item.mustache new file mode 100644 index 00000000000..974f345b30a --- /dev/null +++ b/theme/bootstrapbase/templates/core/paged_content_paging_dropdown_item.mustache @@ -0,0 +1,34 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template core/paged_content_paging_dropdown_item + + This template renders a single item in the paging dropdown menu. + + Example context (json): + { + "itemcount": 25, + "content": "25", + "active": true + } +}} + -- 2.11.4.GIT