diff --git a/blocks/myoverview/tests/behat/block_myoverview_pagination.feature b/blocks/myoverview/tests/behat/block_myoverview_pagination.feature index 97922524079..b3a6b514f47 100644 --- a/blocks/myoverview/tests/behat/block_myoverview_pagination.feature +++ b/blocks/myoverview/tests/behat/block_myoverview_pagination.feature @@ -147,7 +147,6 @@ Feature: My overview block pagination | student1 | C13 | student | When I log in as "student1" And I click on "[data-control='next']" "css_element" in the "Course overview" "block" - And I wait until ".block_myoverview [data-control='next']" "css_element" exists Then the "class" attribute of ".block_myoverview [data-control='next']" "css_element" should contain "disabled" And I log out @@ -181,7 +180,6 @@ Feature: My overview block pagination | student1 | C25 | student | When I log in as "student1" And I click on "[data-control='next']" "css_element" in the "Course overview" "block" - And I wait until ".block_myoverview [data-control='next']" "css_element" exists Then the "class" attribute of ".block_myoverview [data-control='next']" "css_element" should not contain "disabled" And the "class" attribute of ".block_myoverview [data-control='previous']" "css_element" should not contain "disabled" And I should see "Course 13" in the "Course overview" "block" diff --git a/lib/amd/build/paged_content_pages.min.js b/lib/amd/build/paged_content_pages.min.js index d792ca049d4..5aa19715b14 100644 --- a/lib/amd/build/paged_content_pages.min.js +++ b/lib/amd/build/paged_content_pages.min.js @@ -1,2 +1,2 @@ -define ("core/paged_content_pages",["jquery","core/templates","core/notification","core/pubsub","core/paged_content_events"],function(a,b,c,d,e){var f={ROOT:"[data-region=\"page-container\"]",PAGE_REGION:"[data-region=\"paged-content-page\"]",ACTIVE_PAGE_REGION:"[data-region=\"paged-content-page\"].active"},g={PAGING_CONTENT_ITEM:"core/paged_content_page",LOADING:"core/overlay_loading"},h=function(a,b){return a.find("[data-page=\""+b+"\"]")},i=function(d){var e=a.Deferred();d.attr("aria-busy",!0);b.render(g.LOADING,{visible:!0}).then(function(b){var c=a(b),f=setTimeout(function(){d.css("position","relative");c.appendTo(d)},300);e.always(function(){clearTimeout(f);c.remove();d.css("position","");d.removeAttr("aria-busy")})}).fail(c.exception);return e},j=function(d,e,f){var i=a.Deferred();e.then(function(a,e){e=e||"";b.render(g.PAGING_CONTENT_ITEM,{page:f,content:a}).then(function(a){b.appendNodeContents(d,a,e);var c=h(d,f);i.resolve(c)}).fail(function(a){i.reject(a)}).fail(c.exception)}).fail(function(a){i.reject(a)}).fail(c.exception);return i.promise()},k=function(b,g,k,l){var m=[],n=[],o=a.Deferred();g.forEach(function(a){var c=a.pageNumber,d=h(b,c);if(d.length){m.push(d)}else{n.push(a)}});if(n.length&&"function"==typeof l){var p=l(n,{allItemsLoaded:function allItemsLoaded(a){d.publish(k+e.ALL_ITEMS_LOADED,a)}}),q=p.map(function(a,c){return j(b,a,n[c].pageNumber)});a.when.apply(a,q).then(function(){var a=Array.prototype.slice.call(arguments);o.resolve(a)}).fail(function(a){o.reject(a)}).fail(c.exception)}else{o.resolve([])}var r=i(b);o.then(function(a){var c=m.concat(a);b.find(f.PAGE_REGION).addClass("hidden");c.forEach(function(a){if(!0){a.removeClass("hidden")}})}).then(function(){d.publish(k+e.PAGES_SHOWN,g)}).fail(c.exception).always(function(){r.resolve()})};return{init:function init(b,c,f){b=a(b);d.subscribe(c+e.SHOW_PAGES,function(a){k(b,a,c,f)});d.subscribe(c+e.SET_ITEMS_PER_PAGE_LIMIT,function(){b.empty()})},rootSelector:f.ROOT}}); +define ("core/paged_content_pages",["jquery","core/templates","core/notification","core/pubsub","core/paged_content_events","core/pending"],function(a,b,c,d,e,f){var g={ROOT:"[data-region=\"page-container\"]",PAGE_REGION:"[data-region=\"paged-content-page\"]",ACTIVE_PAGE_REGION:"[data-region=\"paged-content-page\"].active"},h={PAGING_CONTENT_ITEM:"core/paged_content_page",LOADING:"core/overlay_loading"},i=function(a,b){return a.find("[data-page=\""+b+"\"]")},j=function(d){var e=a.Deferred();d.attr("aria-busy",!0);var g=new f("core/paged_content_pages:startLoading");b.render(h.LOADING,{visible:!0}).then(function(b){var c=a(b),f=setTimeout(function(){d.css("position","relative");c.appendTo(d)},300);e.always(function(){clearTimeout(f);c.remove();d.css("position","");d.removeAttr("aria-busy");g.resolve()})}).fail(c.exception);return e},k=function(d,e,f){var g=a.Deferred();e.then(function(a,e){e=e||"";b.render(h.PAGING_CONTENT_ITEM,{page:f,content:a}).then(function(a){b.appendNodeContents(d,a,e);var c=i(d,f);g.resolve(c)}).fail(function(a){g.reject(a)}).fail(c.exception)}).fail(function(a){g.reject(a)}).fail(c.exception);return g.promise()},l=function(b,h,l,m){var n=new f("core/paged_content_pages:showPages"),o=[],p=[],q=a.Deferred();h.forEach(function(a){var c=a.pageNumber,d=i(b,c);if(d.length){o.push(d)}else{p.push(a)}});if(p.length&&"function"==typeof m){var r=m(p,{allItemsLoaded:function allItemsLoaded(a){d.publish(l+e.ALL_ITEMS_LOADED,a)}}),s=r.map(function(a,c){return k(b,a,p[c].pageNumber)});a.when.apply(a,s).then(function(){var a=Array.prototype.slice.call(arguments);q.resolve(a)}).fail(function(a){q.reject(a)}).fail(c.exception)}else{q.resolve([])}var t=j(b);q.then(function(a){var c=o.concat(a);b.find(g.PAGE_REGION).addClass("hidden");c.forEach(function(a){if(!0){a.removeClass("hidden")}})}).then(function(){d.publish(l+e.PAGES_SHOWN,h)}).fail(c.exception).always(function(){t.resolve();n.resolve()}).catch()};return{init:function init(b,c,f){b=a(b);d.subscribe(c+e.SHOW_PAGES,function(a){l(b,a,c,f)});d.subscribe(c+e.SET_ITEMS_PER_PAGE_LIMIT,function(){b.empty()})},rootSelector:g.ROOT}}); //# sourceMappingURL=paged_content_pages.min.js.map diff --git a/lib/amd/build/paged_content_pages.min.js.map b/lib/amd/build/paged_content_pages.min.js.map index a6dc9eb22b4..949523e2be7 100644 --- a/lib/amd/build/paged_content_pages.min.js.map +++ b/lib/amd/build/paged_content_pages.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/paged_content_pages.js"],"names":["define","$","Templates","Notification","PubSub","PagedContentEvents","SELECTORS","ROOT","PAGE_REGION","ACTIVE_PAGE_REGION","TEMPLATES","PAGING_CONTENT_ITEM","LOADING","findPage","root","pageNumber","find","startLoading","deferred","Deferred","attr","render","visible","then","html","loadingSpinner","timerId","setTimeout","css","appendTo","always","clearTimeout","remove","removeAttr","fail","exception","renderPagePromise","pagePromise","pageJS","page","content","appendNodeContents","resolve","reject","promise","showPages","pagesData","id","renderPagesContentCallback","existingPages","newPageData","newPagesPromise","forEach","pageData","existingPage","length","push","promises","allItemsLoaded","lastPageNumber","publish","ALL_ITEMS_LOADED","renderPagePromises","map","index","when","apply","newPages","Array","prototype","slice","call","arguments","loadingPromise","pagesToShow","concat","addClass","removeClass","PAGES_SHOWN","init","subscribe","SHOW_PAGES","SET_ITEMS_PER_PAGE_LIMIT","empty","rootSelector"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Javascript for showing/hiding pages of content.\n *\n * @module core/paged_content_pages\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n [\n 'jquery',\n 'core/templates',\n 'core/notification',\n 'core/pubsub',\n 'core/paged_content_events'\n ],\n function(\n $,\n Templates,\n Notification,\n PubSub,\n PagedContentEvents\n ) {\n\n var SELECTORS = {\n ROOT: '[data-region=\"page-container\"]',\n PAGE_REGION: '[data-region=\"paged-content-page\"]',\n ACTIVE_PAGE_REGION: '[data-region=\"paged-content-page\"].active'\n };\n\n var TEMPLATES = {\n PAGING_CONTENT_ITEM: 'core/paged_content_page',\n LOADING: 'core/overlay_loading'\n };\n\n var PRELOADING_GRACE_PERIOD = 300;\n\n /**\n * Find a page by the number.\n *\n * @param {object} root The root element.\n * @param {Number} pageNumber The number of the page to be found.\n * @returns {jQuery} The page.\n */\n var findPage = function(root, pageNumber) {\n return root.find('[data-page=\"' + pageNumber + '\"]');\n };\n\n /**\n * Show the loading spinner until the returned deferred is resolved by the\n * calling code.\n *\n * The loading spinner is only rendered after a short grace period to avoid\n * having it flash up briefly in the interface.\n *\n * @param {object} root The root element.\n * @returns {promise} The page.\n */\n var startLoading = function(root) {\n var deferred = $.Deferred();\n root.attr('aria-busy', true);\n\n Templates.render(TEMPLATES.LOADING, {visible: true})\n .then(function(html) {\n var loadingSpinner = $(html);\n // Put this in a timer to give the calling code 300 milliseconds\n // to render the content before we show the loading spinner. This\n // helps prevent a loading icon flicker on close to instant\n // rendering.\n var timerId = setTimeout(function() {\n root.css('position', 'relative');\n loadingSpinner.appendTo(root);\n }, PRELOADING_GRACE_PERIOD);\n\n deferred.always(function() {\n clearTimeout(timerId);\n // Remove the loading spinner when our deferred is resolved\n // by the calling code.\n loadingSpinner.remove();\n root.css('position', '');\n root.removeAttr('aria-busy');\n return;\n });\n\n return;\n })\n .fail(Notification.exception);\n\n return deferred;\n };\n\n /**\n * Render the result of the page promise in a paged content page.\n *\n * This function returns a promise that is resolved with the new paged content\n * page.\n *\n * @param {object} root The root element.\n * @param {promise} pagePromise The promise resolved with HTML and JS to render in the page.\n * @param {Number} pageNumber The page number.\n * @returns {promise} The page.\n */\n var renderPagePromise = function(root, pagePromise, pageNumber) {\n var deferred = $.Deferred();\n pagePromise.then(function(html, pageJS) {\n pageJS = pageJS || '';\n // When we get the contents to be rendered we can pass it in as the\n // content for a new page.\n Templates.render(TEMPLATES.PAGING_CONTENT_ITEM, {\n page: pageNumber,\n content: html\n })\n .then(function(html) {\n // Make sure the JS we got from the page promise is being added\n // to the page when we render the page.\n Templates.appendNodeContents(root, html, pageJS);\n var page = findPage(root, pageNumber);\n deferred.resolve(page);\n return;\n })\n .fail(function(exception) {\n deferred.reject(exception);\n })\n .fail(Notification.exception);\n\n return;\n })\n .fail(function(exception) {\n deferred.reject(exception);\n return;\n })\n .fail(Notification.exception);\n\n return deferred.promise();\n };\n\n /**\n * Make one or more pages visible based on the SHOW_PAGES event. The show\n * pages event provides data containing which pages should be shown as well\n * as the limit and offset values for loading the items for each of those pages.\n *\n * The renderPagesContentCallback is provided this list of data to know which\n * pages to load. E.g. the data to load 2 pages might look like:\n * [\n * {\n * pageNumber: 1,\n * limit: 5,\n * offset: 0\n * },\n * {\n * pageNumber: 2,\n * limit: 5,\n * offset: 5\n * }\n * ]\n *\n * The renderPagesContentCallback should return an array of promises, one for\n * each page in the pages data, that is resolved with the HTML and JS for that page.\n *\n * If the renderPagesContentCallback is not provided then it is assumed that\n * all pages have been rendered prior to initialising this module.\n *\n * This function triggers the PAGES_SHOWN event after the pages have been rendered.\n *\n * @param {object} root The root element.\n * @param {Number} pagesData The data for which pages need to be visible.\n * @param {string} id A unique id for this instance.\n * @param {function} renderPagesContentCallback Render pages content.\n */\n var showPages = function(root, pagesData, id, renderPagesContentCallback) {\n var existingPages = [];\n var newPageData = [];\n var newPagesPromise = $.Deferred();\n var shownewpage = true;\n // Check which of the pages being requests have previously been rendered\n // so that we only ask for new pages to be rendered by the callback.\n pagesData.forEach(function(pageData) {\n var pageNumber = pageData.pageNumber;\n var existingPage = findPage(root, pageNumber);\n if (existingPage.length) {\n existingPages.push(existingPage);\n } else {\n newPageData.push(pageData);\n }\n });\n\n if (newPageData.length && typeof renderPagesContentCallback === 'function') {\n // If we have pages we haven't previously seen then ask the client code\n // to render them for us by calling the callback.\n var promises = renderPagesContentCallback(newPageData, {\n allItemsLoaded: function(lastPageNumber) {\n PubSub.publish(id + PagedContentEvents.ALL_ITEMS_LOADED, lastPageNumber);\n }\n });\n // After the client has finished rendering each of the pages being asked\n // for then begin our rendering process to put that content into paged\n // content pages.\n var renderPagePromises = promises.map(function(promise, index) {\n // Create our promise for when our rendering will be completed.\n return renderPagePromise(root, promise, newPageData[index].pageNumber);\n });\n // After each of our rendering promises have been completed then we can\n // give all of the new pages to the next bit of code for handling.\n $.when.apply($, renderPagePromises)\n .then(function() {\n var newPages = Array.prototype.slice.call(arguments);\n // Resolve the promise with the list of newly rendered pages.\n newPagesPromise.resolve(newPages);\n return;\n })\n .fail(function(exception) {\n newPagesPromise.reject(exception);\n return;\n })\n .fail(Notification.exception);\n } else {\n // If there aren't any pages to load then immediately resolve the promise.\n newPagesPromise.resolve([]);\n }\n\n var loadingPromise = startLoading(root);\n newPagesPromise.then(function(newPages) {\n // Once all of the new pages have been created then add them to any\n // existing pages we have.\n var pagesToShow = existingPages.concat(newPages);\n // Hide all existing pages.\n root.find(SELECTORS.PAGE_REGION).addClass('hidden');\n // Show each of the pages that were requested.;\n pagesToShow.forEach(function(page) {\n if (shownewpage) {\n page.removeClass('hidden');\n }\n });\n\n return;\n })\n .then(function() {\n // Let everything else know we've displayed the pages.\n PubSub.publish(id + PagedContentEvents.PAGES_SHOWN, pagesData);\n return;\n })\n .fail(Notification.exception)\n .always(function() {\n loadingPromise.resolve();\n });\n };\n\n /**\n * Initialise the module to listen for SHOW_PAGES events and render the\n * appropriate pages using the provided renderPagesContentCallback function.\n *\n * The renderPagesContentCallback is provided a list of data to know which\n * pages to load.\n * E.g. the data to load 2 pages might look like:\n * [\n * {\n * pageNumber: 1,\n * limit: 5,\n * offset: 0\n * },\n * {\n * pageNumber: 2,\n * limit: 5,\n * offset: 5\n * }\n * ]\n *\n * The renderPagesContentCallback should return an array of promises, one for\n * each page in the pages data, that is resolved with the HTML and JS for that page.\n *\n * If the renderPagesContentCallback is not provided then it is assumed that\n * all pages have been rendered prior to initialising this module.\n *\n * The event element is the element to listen for the paged content events on.\n *\n * @param {object} root The root element.\n * @param {string} id A unique id for this instance.\n * @param {function} renderPagesContentCallback Render pages content.\n */\n var init = function(root, id, renderPagesContentCallback) {\n root = $(root);\n\n PubSub.subscribe(id + PagedContentEvents.SHOW_PAGES, function(pagesData) {\n showPages(root, pagesData, id, renderPagesContentCallback);\n });\n\n PubSub.subscribe(id + PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT, function() {\n // If the items per page limit was changed then we need to clear our content\n // the load new values based on the new limit.\n root.empty();\n });\n };\n\n return {\n init: init,\n rootSelector: SELECTORS.ROOT,\n };\n});\n"],"file":"paged_content_pages.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/paged_content_pages.js"],"names":["define","$","Templates","Notification","PubSub","PagedContentEvents","Pending","SELECTORS","ROOT","PAGE_REGION","ACTIVE_PAGE_REGION","TEMPLATES","PAGING_CONTENT_ITEM","LOADING","findPage","root","pageNumber","find","startLoading","deferred","Deferred","attr","pendingPromise","render","visible","then","html","loadingSpinner","timerId","setTimeout","css","appendTo","always","clearTimeout","remove","removeAttr","resolve","fail","exception","renderPagePromise","pagePromise","pageJS","page","content","appendNodeContents","reject","promise","showPages","pagesData","id","renderPagesContentCallback","existingPages","newPageData","newPagesPromise","forEach","pageData","existingPage","length","push","promises","allItemsLoaded","lastPageNumber","publish","ALL_ITEMS_LOADED","renderPagePromises","map","index","when","apply","newPages","Array","prototype","slice","call","arguments","loadingPromise","pagesToShow","concat","addClass","removeClass","PAGES_SHOWN","catch","init","subscribe","SHOW_PAGES","SET_ITEMS_PER_PAGE_LIMIT","empty","rootSelector"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Javascript for showing/hiding pages of content.\n *\n * @module core/paged_content_pages\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n [\n 'jquery',\n 'core/templates',\n 'core/notification',\n 'core/pubsub',\n 'core/paged_content_events',\n 'core/pending',\n ],\n function(\n $,\n Templates,\n Notification,\n PubSub,\n PagedContentEvents,\n Pending\n ) {\n\n var SELECTORS = {\n ROOT: '[data-region=\"page-container\"]',\n PAGE_REGION: '[data-region=\"paged-content-page\"]',\n ACTIVE_PAGE_REGION: '[data-region=\"paged-content-page\"].active'\n };\n\n var TEMPLATES = {\n PAGING_CONTENT_ITEM: 'core/paged_content_page',\n LOADING: 'core/overlay_loading'\n };\n\n var PRELOADING_GRACE_PERIOD = 300;\n\n /**\n * Find a page by the number.\n *\n * @param {object} root The root element.\n * @param {Number} pageNumber The number of the page to be found.\n * @returns {jQuery} The page.\n */\n var findPage = function(root, pageNumber) {\n return root.find('[data-page=\"' + pageNumber + '\"]');\n };\n\n /**\n * Show the loading spinner until the returned deferred is resolved by the\n * calling code.\n *\n * The loading spinner is only rendered after a short grace period to avoid\n * having it flash up briefly in the interface.\n *\n * @param {object} root The root element.\n * @returns {promise} The page.\n */\n var startLoading = function(root) {\n var deferred = $.Deferred();\n root.attr('aria-busy', true);\n\n var pendingPromise = new Pending('core/paged_content_pages:startLoading');\n\n Templates.render(TEMPLATES.LOADING, {visible: true})\n .then(function(html) {\n var loadingSpinner = $(html);\n // Put this in a timer to give the calling code 300 milliseconds\n // to render the content before we show the loading spinner. This\n // helps prevent a loading icon flicker on close to instant\n // rendering.\n var timerId = setTimeout(function() {\n root.css('position', 'relative');\n loadingSpinner.appendTo(root);\n }, PRELOADING_GRACE_PERIOD);\n\n deferred.always(function() {\n clearTimeout(timerId);\n // Remove the loading spinner when our deferred is resolved\n // by the calling code.\n loadingSpinner.remove();\n root.css('position', '');\n root.removeAttr('aria-busy');\n\n pendingPromise.resolve();\n return;\n });\n\n return;\n })\n .fail(Notification.exception);\n\n return deferred;\n };\n\n /**\n * Render the result of the page promise in a paged content page.\n *\n * This function returns a promise that is resolved with the new paged content\n * page.\n *\n * @param {object} root The root element.\n * @param {promise} pagePromise The promise resolved with HTML and JS to render in the page.\n * @param {Number} pageNumber The page number.\n * @returns {promise} The page.\n */\n var renderPagePromise = function(root, pagePromise, pageNumber) {\n var deferred = $.Deferred();\n pagePromise.then(function(html, pageJS) {\n pageJS = pageJS || '';\n // When we get the contents to be rendered we can pass it in as the\n // content for a new page.\n Templates.render(TEMPLATES.PAGING_CONTENT_ITEM, {\n page: pageNumber,\n content: html\n })\n .then(function(html) {\n // Make sure the JS we got from the page promise is being added\n // to the page when we render the page.\n Templates.appendNodeContents(root, html, pageJS);\n var page = findPage(root, pageNumber);\n deferred.resolve(page);\n return;\n })\n .fail(function(exception) {\n deferred.reject(exception);\n })\n .fail(Notification.exception);\n\n return;\n })\n .fail(function(exception) {\n deferred.reject(exception);\n return;\n })\n .fail(Notification.exception);\n\n return deferred.promise();\n };\n\n /**\n * Make one or more pages visible based on the SHOW_PAGES event. The show\n * pages event provides data containing which pages should be shown as well\n * as the limit and offset values for loading the items for each of those pages.\n *\n * The renderPagesContentCallback is provided this list of data to know which\n * pages to load. E.g. the data to load 2 pages might look like:\n * [\n * {\n * pageNumber: 1,\n * limit: 5,\n * offset: 0\n * },\n * {\n * pageNumber: 2,\n * limit: 5,\n * offset: 5\n * }\n * ]\n *\n * The renderPagesContentCallback should return an array of promises, one for\n * each page in the pages data, that is resolved with the HTML and JS for that page.\n *\n * If the renderPagesContentCallback is not provided then it is assumed that\n * all pages have been rendered prior to initialising this module.\n *\n * This function triggers the PAGES_SHOWN event after the pages have been rendered.\n *\n * @param {object} root The root element.\n * @param {Number} pagesData The data for which pages need to be visible.\n * @param {string} id A unique id for this instance.\n * @param {function} renderPagesContentCallback Render pages content.\n */\n var showPages = function(root, pagesData, id, renderPagesContentCallback) {\n var pendingPromise = new Pending('core/paged_content_pages:showPages');\n var existingPages = [];\n var newPageData = [];\n var newPagesPromise = $.Deferred();\n var shownewpage = true;\n // Check which of the pages being requests have previously been rendered\n // so that we only ask for new pages to be rendered by the callback.\n pagesData.forEach(function(pageData) {\n var pageNumber = pageData.pageNumber;\n var existingPage = findPage(root, pageNumber);\n if (existingPage.length) {\n existingPages.push(existingPage);\n } else {\n newPageData.push(pageData);\n }\n });\n\n if (newPageData.length && typeof renderPagesContentCallback === 'function') {\n // If we have pages we haven't previously seen then ask the client code\n // to render them for us by calling the callback.\n var promises = renderPagesContentCallback(newPageData, {\n allItemsLoaded: function(lastPageNumber) {\n PubSub.publish(id + PagedContentEvents.ALL_ITEMS_LOADED, lastPageNumber);\n }\n });\n // After the client has finished rendering each of the pages being asked\n // for then begin our rendering process to put that content into paged\n // content pages.\n var renderPagePromises = promises.map(function(promise, index) {\n // Create our promise for when our rendering will be completed.\n return renderPagePromise(root, promise, newPageData[index].pageNumber);\n });\n // After each of our rendering promises have been completed then we can\n // give all of the new pages to the next bit of code for handling.\n $.when.apply($, renderPagePromises)\n .then(function() {\n var newPages = Array.prototype.slice.call(arguments);\n // Resolve the promise with the list of newly rendered pages.\n newPagesPromise.resolve(newPages);\n return;\n })\n .fail(function(exception) {\n newPagesPromise.reject(exception);\n return;\n })\n .fail(Notification.exception);\n } else {\n // If there aren't any pages to load then immediately resolve the promise.\n newPagesPromise.resolve([]);\n }\n\n var loadingPromise = startLoading(root);\n newPagesPromise.then(function(newPages) {\n // Once all of the new pages have been created then add them to any\n // existing pages we have.\n var pagesToShow = existingPages.concat(newPages);\n // Hide all existing pages.\n root.find(SELECTORS.PAGE_REGION).addClass('hidden');\n // Show each of the pages that were requested.;\n pagesToShow.forEach(function(page) {\n if (shownewpage) {\n page.removeClass('hidden');\n }\n });\n\n return;\n })\n .then(function() {\n // Let everything else know we've displayed the pages.\n PubSub.publish(id + PagedContentEvents.PAGES_SHOWN, pagesData);\n return;\n })\n .fail(Notification.exception)\n .always(function() {\n loadingPromise.resolve();\n pendingPromise.resolve();\n })\n .catch();\n };\n\n /**\n * Initialise the module to listen for SHOW_PAGES events and render the\n * appropriate pages using the provided renderPagesContentCallback function.\n *\n * The renderPagesContentCallback is provided a list of data to know which\n * pages to load.\n * E.g. the data to load 2 pages might look like:\n * [\n * {\n * pageNumber: 1,\n * limit: 5,\n * offset: 0\n * },\n * {\n * pageNumber: 2,\n * limit: 5,\n * offset: 5\n * }\n * ]\n *\n * The renderPagesContentCallback should return an array of promises, one for\n * each page in the pages data, that is resolved with the HTML and JS for that page.\n *\n * If the renderPagesContentCallback is not provided then it is assumed that\n * all pages have been rendered prior to initialising this module.\n *\n * The event element is the element to listen for the paged content events on.\n *\n * @param {object} root The root element.\n * @param {string} id A unique id for this instance.\n * @param {function} renderPagesContentCallback Render pages content.\n */\n var init = function(root, id, renderPagesContentCallback) {\n root = $(root);\n\n PubSub.subscribe(id + PagedContentEvents.SHOW_PAGES, function(pagesData) {\n showPages(root, pagesData, id, renderPagesContentCallback);\n });\n\n PubSub.subscribe(id + PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT, function() {\n // If the items per page limit was changed then we need to clear our content\n // the load new values based on the new limit.\n root.empty();\n });\n };\n\n return {\n init: init,\n rootSelector: SELECTORS.ROOT,\n };\n});\n"],"file":"paged_content_pages.min.js"} \ 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 index ef384a4c157..e93df0e9582 100644 --- a/lib/amd/build/paged_content_paging_bar.min.js +++ b/lib/amd/build/paged_content_paging_bar.min.js @@ -1,2 +1,2 @@ -define ("core/paged_content_paging_bar",["jquery","core/custom_interaction_events","core/paged_content_events","core/str","core/pubsub"],function(a,b,c,d,e){var f={ROOT:"[data-region=\"paging-bar\"]",PAGE:"[data-page]",PAGE_ITEM:"[data-region=\"page-item\"]",PAGE_LINK:"[data-region=\"page-link\"]",FIRST_BUTTON:"[data-control=\"first\"]",LAST_BUTTON:"[data-control=\"last\"]",NEXT_BUTTON:"[data-control=\"next\"]",PREVIOUS_BUTTON:"[data-control=\"previous\"]",DOTS_BUTTONS:"[data-dots]",BEGINNING_DOTS_BUTTON:"[data-dots=\"beginning\"]",ENDING_DOTS_BUTTON:"[data-dots=\"ending\"]"},g=function(a,b){return a.find(f.PAGE_ITEM+"[data-page-number=\""+b+"\"]")},h=function(a){return a.find(f.NEXT_BUTTON)},i=function(a,b){a.attr("data-last-page-number",b)},j=function(a){return parseInt(a.attr("data-last-page-number"),10)},k=function(a){return parseInt(a.attr("data-active-page-number"),10)},l=function(a,b){a.attr("data-active-page-number",b)},m=function(a){var b=k(a);return!isNaN(b)&&0!=b},n=function(a,b){if(b.attr("data-page")!=void 0){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=j(a);break;case"next":d=k(a);var e=j(a);if(!e){c=d+1}else if(d&&dl){var m=Math.max(c-Math.round(l/2),1),n=m+l-1;if(n>=d){n=d;m=n-l+1}if(1=m&&b+1<=n){q(c)}})}else{r(e)}},w=function(a){var b=a.find(f.PREVIOUS_BUTTON),c=a.find(f.FIRST_BUTTON);b.removeClass("disabled");b.removeAttr("aria-disabled");c.removeClass("disabled");c.removeAttr("aria-disabled")},x=function(a){var b=a.attr("data-aria-label-components-pagination-item"),c=b.split(",").map(function(a){return a.trim()});return c},y=function(a){var b=a.attr("data-aria-label-components-pagination-active-item"),c=b.split(",").map(function(a){return a.trim()});return c},z=function(b,c){var d=0;l(b,0);c.each(function(c,e){var f=c+1;e=a(e);e.attr("data-page-number",f);d++;if(e.hasClass("active")){l(b,f)}});i(b,d)},A=function(b){var c=x(b),e=y(b),g=k(b),h=b.find(f.PAGE_ITEM),i=h.map(function(d,f){f=a(f);var h=n(b,f);if(h===g){return{key:e[0],component:e[1],param:h}}else{return{key:c[0],component:c[1],param:h}}});d.get_strings(i).then(function(b){h.each(function(c,d){d=a(d);var e=b[c];d.attr("aria-label",e);d.find(f.PAGE_LINK).attr("aria-label",e)});return b}).catch(function(){})},B=function(a,b,d){var h=j(a),i=b==k(a),m=o(a);if(!i){a.find(f.PAGE_ITEM).removeClass("active").removeAttr("aria-current");var n=g(a,b);n.addClass("active");n.attr("aria-current",!0);l(a,b);v(a)}if(h&&b>=h){s(a)}else{t(a)}if(1j){var m=Math.max(c-Math.round(j/2),1),n=m+j-1;if(n>=d){n=d;m=n-j+1}if(1=m&&b+1<=n){r(c)}})}else{s(e)}},x=function(a){var b=a.find(g.PREVIOUS_BUTTON),c=a.find(g.FIRST_BUTTON);b.removeClass("disabled");b.removeAttr("aria-disabled");c.removeClass("disabled");c.removeAttr("aria-disabled")},y=function(a){var b=a.attr("data-aria-label-components-pagination-item"),c=b.split(",").map(function(a){return a.trim()});return c},z=function(a){var b=a.attr("data-aria-label-components-pagination-active-item"),c=b.split(",").map(function(a){return a.trim()});return c},A=function(b,c){var d=0;m(b,0);c.each(function(c,e){var f=c+1;e=a(e);e.attr("data-page-number",f);d++;if(e.hasClass("active")){m(b,f)}});j(b,d)},B=function(b){var c=y(b),e=z(b),f=l(b),h=b.find(g.PAGE_ITEM),i=h.map(function(d,g){g=a(g);var h=o(b,g);if(h===f){return{key:e[0],component:e[1],param:h}}else{return{key:c[0],component:c[1],param:h}}});d.get_strings(i).then(function(b){h.each(function(c,d){d=a(d);var e=b[c];d.attr("aria-label",e);d.find(g.PAGE_LINK).attr("aria-label",e)});return b}).catch(function(){})},C=function(a,b,d){var i=new f("core/paged_content_paging_bar:showPage"),j=k(a),n=b==l(a),o=p(a);if(!n){a.find(g.PAGE_ITEM).removeClass("active").removeAttr("aria-current");var q=h(a,b);q.addClass("active");q.attr("aria-current",!0);m(a,b);w(a)}if(j&&b>=j){t(a)}else{u(a)}if(1.\n\n/**\n * Javascript to enhance the paged content paging bar.\n *\n * @module core/paging_bar\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/custom_interaction_events',\n 'core/paged_content_events',\n 'core/str',\n 'core/pubsub'\n],\nfunction(\n $,\n CustomEvents,\n PagedContentEvents,\n Str,\n PubSub\n) {\n\n var SELECTORS = {\n ROOT: '[data-region=\"paging-bar\"]',\n PAGE: '[data-page]',\n PAGE_ITEM: '[data-region=\"page-item\"]',\n PAGE_LINK: '[data-region=\"page-link\"]',\n FIRST_BUTTON: '[data-control=\"first\"]',\n LAST_BUTTON: '[data-control=\"last\"]',\n NEXT_BUTTON: '[data-control=\"next\"]',\n PREVIOUS_BUTTON: '[data-control=\"previous\"]',\n DOTS_BUTTONS: '[data-dots]',\n BEGINNING_DOTS_BUTTON: '[data-dots=\"beginning\"]',\n ENDING_DOTS_BUTTON: '[data-dots=\"ending\"]',\n };\n\n /**\n * Get the page element by number.\n *\n * @param {object} root The root element.\n * @param {Number} pageNumber The page number.\n * @return {jQuery}\n */\n var getPageByNumber = function(root, pageNumber) {\n return root.find(SELECTORS.PAGE_ITEM + '[data-page-number=\"' + pageNumber + '\"]');\n };\n\n /**\n * Get the next button element.\n *\n * @param {object} root The root element.\n * @return {jQuery}\n */\n var getNextButton = function(root) {\n return root.find(SELECTORS.NEXT_BUTTON);\n };\n\n /**\n * Set the last page number after which no more pages\n * should be loaded.\n *\n * @param {object} root The root element.\n * @param {Number} number Page number.\n */\n var setLastPageNumber = function(root, number) {\n root.attr('data-last-page-number', number);\n };\n\n /**\n * Get the last page number.\n *\n * @param {object} root The root element.\n * @return {Number}\n */\n var getLastPageNumber = function(root) {\n return parseInt(root.attr('data-last-page-number'), 10);\n };\n\n /**\n * Get the active page number.\n *\n * @param {object} root The root element.\n * @returns {Number} The page number\n */\n var getActivePageNumber = function(root) {\n return parseInt(root.attr('data-active-page-number'), 10);\n };\n\n /**\n * Set the active page number.\n *\n * @param {object} root The root element.\n * @param {Number} number Page number.\n */\n var setActivePageNumber = function(root, number) {\n root.attr('data-active-page-number', number);\n };\n\n /**\n * Check if there is an active page number.\n *\n * @param {object} root The root element.\n * @returns {bool}\n */\n var hasActivePageNumber = function(root) {\n var number = getActivePageNumber(root);\n return !isNaN(number) && number != 0;\n };\n\n /**\n * Get the page number for a given page.\n *\n * @param {object} root The root element.\n * @param {object} page The page element.\n * @returns {Number} The page number\n */\n var getPageNumber = function(root, page) {\n if (page.attr('data-page') != undefined) {\n // If it's an actual page then we can just use the page number\n // attribute.\n return parseInt(page.attr('data-page-number'), 10);\n }\n\n var pageNumber = 1;\n var activePageNumber = null;\n\n switch (page.attr('data-control')) {\n case 'first':\n pageNumber = 1;\n break;\n\n case 'last':\n pageNumber = getLastPageNumber(root);\n break;\n\n case 'next':\n activePageNumber = getActivePageNumber(root);\n var lastPage = getLastPageNumber(root);\n if (!lastPage) {\n pageNumber = activePageNumber + 1;\n } else if (activePageNumber && activePageNumber < lastPage) {\n pageNumber = activePageNumber + 1;\n } else {\n pageNumber = lastPage;\n }\n break;\n\n case 'previous':\n activePageNumber = getActivePageNumber(root);\n if (activePageNumber && activePageNumber > 1) {\n pageNumber = activePageNumber - 1;\n } else {\n pageNumber = 1;\n }\n break;\n\n default:\n pageNumber = 1;\n break;\n }\n\n // Make sure we return an int not a string.\n return parseInt(pageNumber, 10);\n };\n\n /**\n * Get the limit of items for each page.\n *\n * @param {object} root The root element.\n * @returns {Number}\n */\n var getLimit = function(root) {\n return parseInt(root.attr('data-items-per-page'), 10);\n };\n\n /**\n * Set the limit of items for each page.\n *\n * @param {object} root The root element.\n * @param {Number} limit Items per page limit.\n */\n var setLimit = function(root, limit) {\n root.attr('data-items-per-page', limit);\n };\n\n /**\n * Show the paging bar.\n *\n * @param {object} root The root element.\n */\n var show = function(root) {\n root.removeClass('hidden');\n };\n\n /**\n * Hide the paging bar.\n *\n * @param {object} root The root element.\n */\n var hide = function(root) {\n root.addClass('hidden');\n };\n\n /**\n * Disable the next and last buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var disableNextControlButtons = function(root) {\n var nextButton = root.find(SELECTORS.NEXT_BUTTON);\n var lastButton = root.find(SELECTORS.LAST_BUTTON);\n\n nextButton.addClass('disabled');\n nextButton.attr('aria-disabled', true);\n lastButton.addClass('disabled');\n lastButton.attr('aria-disabled', true);\n };\n\n /**\n * Enable the next and last buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var enableNextControlButtons = function(root) {\n var nextButton = root.find(SELECTORS.NEXT_BUTTON);\n var lastButton = root.find(SELECTORS.LAST_BUTTON);\n\n nextButton.removeClass('disabled');\n nextButton.removeAttr('aria-disabled');\n lastButton.removeClass('disabled');\n lastButton.removeAttr('aria-disabled');\n };\n\n /**\n * Disable the previous and first buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var disablePreviousControlButtons = function(root) {\n var previousButton = root.find(SELECTORS.PREVIOUS_BUTTON);\n var firstButton = root.find(SELECTORS.FIRST_BUTTON);\n\n previousButton.addClass('disabled');\n previousButton.attr('aria-disabled', true);\n firstButton.addClass('disabled');\n firstButton.attr('aria-disabled', true);\n };\n\n /**\n * Adjusts the size of the paging bar and hides unnecessary pages.\n *\n * @param {object} root The root element.\n */\n var adjustPagingBarSize = function(root) {\n var activePageNumber = getActivePageNumber(root);\n var lastPageNumber = getLastPageNumber(root);\n\n var dotsButtons = root.find(SELECTORS.DOTS_BUTTONS);\n var beginningDotsButton = root.find(SELECTORS.BEGINNING_DOTS_BUTTON);\n var endingDotsButton = root.find(SELECTORS.ENDING_DOTS_BUTTON);\n\n var pages = root.find(SELECTORS.PAGE);\n var barSize = parseInt(root.attr('data-bar-size'), 10);\n\n if (barSize && lastPageNumber > barSize) {\n\n var minpage = Math.max(activePageNumber - Math.round(barSize / 2), 1);\n var maxpage = minpage + barSize - 1;\n\n if (maxpage >= lastPageNumber) {\n maxpage = lastPageNumber;\n minpage = maxpage - barSize + 1;\n }\n\n if (minpage > 1) {\n show(beginningDotsButton);\n minpage++;\n } else {\n hide(beginningDotsButton);\n }\n if (maxpage < lastPageNumber) {\n show(endingDotsButton);\n maxpage--;\n } else {\n hide(endingDotsButton);\n }\n dotsButtons.addClass('disabled');\n dotsButtons.attr('aria-disabled', true);\n\n hide(pages);\n\n pages.each(function(index, page) {\n page = $(page);\n if ((index + 1) >= minpage && (index + 1) <= maxpage) {\n show(page);\n }\n });\n\n } else {\n hide(dotsButtons);\n }\n };\n\n /**\n * Enable the previous and first buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var enablePreviousControlButtons = function(root) {\n var previousButton = root.find(SELECTORS.PREVIOUS_BUTTON);\n var firstButton = root.find(SELECTORS.FIRST_BUTTON);\n\n previousButton.removeClass('disabled');\n previousButton.removeAttr('aria-disabled');\n firstButton.removeClass('disabled');\n firstButton.removeAttr('aria-disabled');\n };\n\n /**\n * Get the components for a get_string request for the aria-label\n * on a page. The value is a comma separated string of key and\n * component.\n *\n * @param {object} root The root element.\n * @return {array} First element is the key, second is the component.\n */\n var getPageAriaLabelComponents = function(root) {\n var componentString = root.attr('data-aria-label-components-pagination-item');\n var components = componentString.split(',').map(function(component) {\n return component.trim();\n });\n return components;\n };\n\n /**\n * Get the components for a get_string request for the aria-label\n * on an active page. The value is a comma separated string of key and\n * component.\n *\n * @param {object} root The root element.\n * @return {array} First element is the key, second is the component.\n */\n var getActivePageAriaLabelComponents = function(root) {\n var componentString = root.attr('data-aria-label-components-pagination-active-item');\n var components = componentString.split(',').map(function(component) {\n return component.trim();\n });\n return components;\n };\n\n /**\n * Set page numbers on each of the given items. Page numbers are set\n * from 1..n (where n is the number of items).\n *\n * Sets the active page number to be the last page found with\n * an \"active\" class (if any).\n *\n * Sets the last page number.\n *\n * @param {object} root The root element.\n * @param {jQuery} items A jQuery list of items.\n */\n var generatePageNumbers = function(root, items) {\n var lastPageNumber = 0;\n setActivePageNumber(root, 0);\n\n items.each(function(index, item) {\n var pageNumber = index + 1;\n item = $(item);\n item.attr('data-page-number', pageNumber);\n lastPageNumber++;\n\n if (item.hasClass('active')) {\n setActivePageNumber(root, pageNumber);\n }\n });\n\n setLastPageNumber(root, lastPageNumber);\n };\n\n /**\n * Set the aria-labels on each of the page items in the paging bar.\n * This includes the next, previous, first, and last items.\n *\n * @param {object} root The root element.\n */\n var generateAriaLabels = function(root) {\n var pageAriaLabelComponents = getPageAriaLabelComponents(root);\n var activePageAriaLabelComponents = getActivePageAriaLabelComponents(root);\n var activePageNumber = getActivePageNumber(root);\n var pageItems = root.find(SELECTORS.PAGE_ITEM);\n // We want to request all of the strings at once rather than\n // one at a time.\n var stringRequests = pageItems.map(function(index, page) {\n page = $(page);\n var pageNumber = getPageNumber(root, page);\n\n if (pageNumber === activePageNumber) {\n return {\n key: activePageAriaLabelComponents[0],\n component: activePageAriaLabelComponents[1],\n param: pageNumber\n };\n } else {\n return {\n key: pageAriaLabelComponents[0],\n component: pageAriaLabelComponents[1],\n param: pageNumber\n };\n }\n });\n\n Str.get_strings(stringRequests).then(function(strings) {\n pageItems.each(function(index, page) {\n page = $(page);\n var string = strings[index];\n page.attr('aria-label', string);\n page.find(SELECTORS.PAGE_LINK).attr('aria-label', string);\n });\n\n return strings;\n })\n .catch(function() {\n // No need to interrupt the page if we can't load the aria lang strings.\n return;\n });\n };\n\n /**\n * Make the paging bar item for the given page number visible and fire\n * the SHOW_PAGES paged content event to tell any listening content to\n * update.\n *\n * @param {object} root The root element.\n * @param {Number} pageNumber The number for the page to show.\n * @param {string} id A uniqie id for this instance.\n */\n var showPage = function(root, pageNumber, id) {\n var lastPageNumber = getLastPageNumber(root);\n var isSamePage = pageNumber == getActivePageNumber(root);\n var limit = getLimit(root);\n var offset = (pageNumber - 1) * limit;\n\n if (!isSamePage) {\n // We only need to toggle the active class if the user didn't click\n // on the already active page.\n root.find(SELECTORS.PAGE_ITEM).removeClass('active').removeAttr('aria-current');\n var page = getPageByNumber(root, pageNumber);\n page.addClass('active');\n page.attr('aria-current', true);\n setActivePageNumber(root, pageNumber);\n\n adjustPagingBarSize(root);\n }\n\n // Make sure the control buttons are disabled as the user navigates\n // to either end of the limits.\n if (lastPageNumber && pageNumber >= lastPageNumber) {\n disableNextControlButtons(root);\n } else {\n enableNextControlButtons(root);\n }\n\n if (pageNumber > 1) {\n enablePreviousControlButtons(root);\n } else {\n disablePreviousControlButtons(root);\n }\n\n generateAriaLabels(root);\n\n // This event requires a payload that contains a list of all pages that\n // were activated. In the case of the paging bar we only show one page at\n // a time.\n PubSub.publish(id + PagedContentEvents.SHOW_PAGES, [{\n pageNumber: pageNumber,\n limit: limit,\n offset: offset\n }]);\n };\n\n /**\n * Add event listeners for interactions with the paging bar as well as listening\n * for custom paged content events.\n *\n * Each event will trigger different logic to update parts of the paging bar's\n * display.\n *\n * @param {object} root The root element.\n * @param {string} id A uniqie id for this instance.\n */\n var registerEventListeners = function(root, id) {\n var ignoreControlWhileLoading = root.attr('data-ignore-control-while-loading');\n var loading = false;\n\n if (ignoreControlWhileLoading == \"\") {\n // Default to ignoring control while loading if not specified.\n ignoreControlWhileLoading = true;\n }\n\n CustomEvents.define(root, [\n CustomEvents.events.activate\n ]);\n\n root.on(CustomEvents.events.activate, SELECTORS.PAGE_ITEM, function(e, data) {\n data.originalEvent.preventDefault();\n data.originalEvent.stopPropagation();\n\n if (ignoreControlWhileLoading && loading) {\n // Do nothing if configured to ignore control while loading.\n return;\n }\n\n var page = $(e.target).closest(SELECTORS.PAGE_ITEM);\n\n if (!page.hasClass('disabled')) {\n var pageNumber = getPageNumber(root, page);\n showPage(root, pageNumber, id);\n loading = true;\n }\n });\n\n // This event is fired when all of the items have been loaded. Typically used\n // in an \"infinite\" pages context when we don't know the exact number of pages\n // ahead of time.\n PubSub.subscribe(id + PagedContentEvents.ALL_ITEMS_LOADED, function(pageNumber) {\n loading = false;\n var currentLastPage = getLastPageNumber(root);\n\n if (!currentLastPage || pageNumber < currentLastPage) {\n // Somehow the value we've got saved is higher than the new\n // value we just received. Perhaps events came out of order.\n // In any case, save the lowest value.\n setLastPageNumber(root, pageNumber);\n }\n\n if (pageNumber === 1 && root.attr('data-hide-control-on-single-page')) {\n // If all items were loaded on the first page then we can hide\n // the paging bar because there are no other pages to load.\n hide(root);\n disableNextControlButtons(root);\n disablePreviousControlButtons(root);\n } else {\n show(root);\n disableNextControlButtons(root);\n }\n });\n\n // This event is fired after all of the requested pages have been rendered.\n PubSub.subscribe(id + PagedContentEvents.PAGES_SHOWN, function() {\n // All pages have been shown so turn off the loading flag.\n loading = false;\n });\n\n // This is triggered when the paging limit is modified.\n PubSub.subscribe(id + PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT, function(limit) {\n // Update the limit.\n setLimit(root, limit);\n setLastPageNumber(root, 0);\n setActivePageNumber(root, 0);\n show(root);\n // Reload the data from page 1 again.\n showPage(root, 1, id);\n });\n };\n\n /**\n * Initialise the paging bar.\n * @param {object} root The root element.\n * @param {string} id A uniqie id for this instance.\n */\n var init = function(root, id) {\n root = $(root);\n var pages = root.find(SELECTORS.PAGE);\n generatePageNumbers(root, pages);\n registerEventListeners(root, id);\n\n if (hasActivePageNumber(root)) {\n var activePageNumber = getActivePageNumber(root);\n // If the the paging bar was rendered with an active page selected\n // then make sure we fired off the event to tell the content page to\n // show.\n getPageByNumber(root, activePageNumber).click();\n if (activePageNumber == 1) {\n // If the first page is active then disable the previous buttons.\n disablePreviousControlButtons(root);\n }\n } else {\n // There was no active page number so load the first page using\n // the next button. This allows the infinite pagination to work.\n getNextButton(root).click();\n }\n\n adjustPagingBarSize(root);\n };\n\n return {\n init: init,\n disableNextControlButtons: disableNextControlButtons,\n enableNextControlButtons: enableNextControlButtons,\n disablePreviousControlButtons: disablePreviousControlButtons,\n enablePreviousControlButtons: enablePreviousControlButtons,\n showPage: showPage,\n rootSelector: SELECTORS.ROOT,\n };\n});\n"],"file":"paged_content_paging_bar.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/paged_content_paging_bar.js"],"names":["define","$","CustomEvents","PagedContentEvents","Str","PubSub","Pending","SELECTORS","ROOT","PAGE","PAGE_ITEM","PAGE_LINK","FIRST_BUTTON","LAST_BUTTON","NEXT_BUTTON","PREVIOUS_BUTTON","DOTS_BUTTONS","BEGINNING_DOTS_BUTTON","ENDING_DOTS_BUTTON","getPageByNumber","root","pageNumber","find","getNextButton","setLastPageNumber","number","attr","getLastPageNumber","parseInt","getActivePageNumber","setActivePageNumber","hasActivePageNumber","isNaN","getPageNumber","page","activePageNumber","lastPage","getLimit","setLimit","limit","show","removeClass","hide","addClass","disableNextControlButtons","nextButton","lastButton","enableNextControlButtons","removeAttr","disablePreviousControlButtons","previousButton","firstButton","adjustPagingBarSize","lastPageNumber","dotsButtons","beginningDotsButton","endingDotsButton","pages","barSize","minpage","Math","max","round","maxpage","each","index","enablePreviousControlButtons","getPageAriaLabelComponents","componentString","components","split","map","component","trim","getActivePageAriaLabelComponents","generatePageNumbers","items","item","hasClass","generateAriaLabels","pageAriaLabelComponents","activePageAriaLabelComponents","pageItems","stringRequests","key","param","get_strings","then","strings","string","catch","showPage","id","pendingPromise","isSamePage","publish","SHOW_PAGES","offset","resolve","registerEventListeners","ignoreControlWhileLoading","loading","events","activate","on","e","data","originalEvent","preventDefault","stopPropagation","target","closest","subscribe","ALL_ITEMS_LOADED","currentLastPage","PAGES_SHOWN","SET_ITEMS_PER_PAGE_LIMIT","init","click","rootSelector"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Javascript to enhance the paged content paging bar.\n *\n * @module core/paging_bar\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/custom_interaction_events',\n 'core/paged_content_events',\n 'core/str',\n 'core/pubsub',\n 'core/pending',\n],\nfunction(\n $,\n CustomEvents,\n PagedContentEvents,\n Str,\n PubSub,\n Pending\n) {\n\n var SELECTORS = {\n ROOT: '[data-region=\"paging-bar\"]',\n PAGE: '[data-page]',\n PAGE_ITEM: '[data-region=\"page-item\"]',\n PAGE_LINK: '[data-region=\"page-link\"]',\n FIRST_BUTTON: '[data-control=\"first\"]',\n LAST_BUTTON: '[data-control=\"last\"]',\n NEXT_BUTTON: '[data-control=\"next\"]',\n PREVIOUS_BUTTON: '[data-control=\"previous\"]',\n DOTS_BUTTONS: '[data-dots]',\n BEGINNING_DOTS_BUTTON: '[data-dots=\"beginning\"]',\n ENDING_DOTS_BUTTON: '[data-dots=\"ending\"]',\n };\n\n /**\n * Get the page element by number.\n *\n * @param {object} root The root element.\n * @param {Number} pageNumber The page number.\n * @return {jQuery}\n */\n var getPageByNumber = function(root, pageNumber) {\n return root.find(SELECTORS.PAGE_ITEM + '[data-page-number=\"' + pageNumber + '\"]');\n };\n\n /**\n * Get the next button element.\n *\n * @param {object} root The root element.\n * @return {jQuery}\n */\n var getNextButton = function(root) {\n return root.find(SELECTORS.NEXT_BUTTON);\n };\n\n /**\n * Set the last page number after which no more pages\n * should be loaded.\n *\n * @param {object} root The root element.\n * @param {Number} number Page number.\n */\n var setLastPageNumber = function(root, number) {\n root.attr('data-last-page-number', number);\n };\n\n /**\n * Get the last page number.\n *\n * @param {object} root The root element.\n * @return {Number}\n */\n var getLastPageNumber = function(root) {\n return parseInt(root.attr('data-last-page-number'), 10);\n };\n\n /**\n * Get the active page number.\n *\n * @param {object} root The root element.\n * @returns {Number} The page number\n */\n var getActivePageNumber = function(root) {\n return parseInt(root.attr('data-active-page-number'), 10);\n };\n\n /**\n * Set the active page number.\n *\n * @param {object} root The root element.\n * @param {Number} number Page number.\n */\n var setActivePageNumber = function(root, number) {\n root.attr('data-active-page-number', number);\n };\n\n /**\n * Check if there is an active page number.\n *\n * @param {object} root The root element.\n * @returns {bool}\n */\n var hasActivePageNumber = function(root) {\n var number = getActivePageNumber(root);\n return !isNaN(number) && number != 0;\n };\n\n /**\n * Get the page number for a given page.\n *\n * @param {object} root The root element.\n * @param {object} page The page element.\n * @returns {Number} The page number\n */\n var getPageNumber = function(root, page) {\n if (page.attr('data-page') != undefined) {\n // If it's an actual page then we can just use the page number\n // attribute.\n return parseInt(page.attr('data-page-number'), 10);\n }\n\n var pageNumber = 1;\n var activePageNumber = null;\n\n switch (page.attr('data-control')) {\n case 'first':\n pageNumber = 1;\n break;\n\n case 'last':\n pageNumber = getLastPageNumber(root);\n break;\n\n case 'next':\n activePageNumber = getActivePageNumber(root);\n var lastPage = getLastPageNumber(root);\n if (!lastPage) {\n pageNumber = activePageNumber + 1;\n } else if (activePageNumber && activePageNumber < lastPage) {\n pageNumber = activePageNumber + 1;\n } else {\n pageNumber = lastPage;\n }\n break;\n\n case 'previous':\n activePageNumber = getActivePageNumber(root);\n if (activePageNumber && activePageNumber > 1) {\n pageNumber = activePageNumber - 1;\n } else {\n pageNumber = 1;\n }\n break;\n\n default:\n pageNumber = 1;\n break;\n }\n\n // Make sure we return an int not a string.\n return parseInt(pageNumber, 10);\n };\n\n /**\n * Get the limit of items for each page.\n *\n * @param {object} root The root element.\n * @returns {Number}\n */\n var getLimit = function(root) {\n return parseInt(root.attr('data-items-per-page'), 10);\n };\n\n /**\n * Set the limit of items for each page.\n *\n * @param {object} root The root element.\n * @param {Number} limit Items per page limit.\n */\n var setLimit = function(root, limit) {\n root.attr('data-items-per-page', limit);\n };\n\n /**\n * Show the paging bar.\n *\n * @param {object} root The root element.\n */\n var show = function(root) {\n root.removeClass('hidden');\n };\n\n /**\n * Hide the paging bar.\n *\n * @param {object} root The root element.\n */\n var hide = function(root) {\n root.addClass('hidden');\n };\n\n /**\n * Disable the next and last buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var disableNextControlButtons = function(root) {\n var nextButton = root.find(SELECTORS.NEXT_BUTTON);\n var lastButton = root.find(SELECTORS.LAST_BUTTON);\n\n nextButton.addClass('disabled');\n nextButton.attr('aria-disabled', true);\n lastButton.addClass('disabled');\n lastButton.attr('aria-disabled', true);\n };\n\n /**\n * Enable the next and last buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var enableNextControlButtons = function(root) {\n var nextButton = root.find(SELECTORS.NEXT_BUTTON);\n var lastButton = root.find(SELECTORS.LAST_BUTTON);\n\n nextButton.removeClass('disabled');\n nextButton.removeAttr('aria-disabled');\n lastButton.removeClass('disabled');\n lastButton.removeAttr('aria-disabled');\n };\n\n /**\n * Disable the previous and first buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var disablePreviousControlButtons = function(root) {\n var previousButton = root.find(SELECTORS.PREVIOUS_BUTTON);\n var firstButton = root.find(SELECTORS.FIRST_BUTTON);\n\n previousButton.addClass('disabled');\n previousButton.attr('aria-disabled', true);\n firstButton.addClass('disabled');\n firstButton.attr('aria-disabled', true);\n };\n\n /**\n * Adjusts the size of the paging bar and hides unnecessary pages.\n *\n * @param {object} root The root element.\n */\n var adjustPagingBarSize = function(root) {\n var activePageNumber = getActivePageNumber(root);\n var lastPageNumber = getLastPageNumber(root);\n\n var dotsButtons = root.find(SELECTORS.DOTS_BUTTONS);\n var beginningDotsButton = root.find(SELECTORS.BEGINNING_DOTS_BUTTON);\n var endingDotsButton = root.find(SELECTORS.ENDING_DOTS_BUTTON);\n\n var pages = root.find(SELECTORS.PAGE);\n var barSize = parseInt(root.attr('data-bar-size'), 10);\n\n if (barSize && lastPageNumber > barSize) {\n\n var minpage = Math.max(activePageNumber - Math.round(barSize / 2), 1);\n var maxpage = minpage + barSize - 1;\n\n if (maxpage >= lastPageNumber) {\n maxpage = lastPageNumber;\n minpage = maxpage - barSize + 1;\n }\n\n if (minpage > 1) {\n show(beginningDotsButton);\n minpage++;\n } else {\n hide(beginningDotsButton);\n }\n if (maxpage < lastPageNumber) {\n show(endingDotsButton);\n maxpage--;\n } else {\n hide(endingDotsButton);\n }\n dotsButtons.addClass('disabled');\n dotsButtons.attr('aria-disabled', true);\n\n hide(pages);\n\n pages.each(function(index, page) {\n page = $(page);\n if ((index + 1) >= minpage && (index + 1) <= maxpage) {\n show(page);\n }\n });\n\n } else {\n hide(dotsButtons);\n }\n };\n\n /**\n * Enable the previous and first buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var enablePreviousControlButtons = function(root) {\n var previousButton = root.find(SELECTORS.PREVIOUS_BUTTON);\n var firstButton = root.find(SELECTORS.FIRST_BUTTON);\n\n previousButton.removeClass('disabled');\n previousButton.removeAttr('aria-disabled');\n firstButton.removeClass('disabled');\n firstButton.removeAttr('aria-disabled');\n };\n\n /**\n * Get the components for a get_string request for the aria-label\n * on a page. The value is a comma separated string of key and\n * component.\n *\n * @param {object} root The root element.\n * @return {array} First element is the key, second is the component.\n */\n var getPageAriaLabelComponents = function(root) {\n var componentString = root.attr('data-aria-label-components-pagination-item');\n var components = componentString.split(',').map(function(component) {\n return component.trim();\n });\n return components;\n };\n\n /**\n * Get the components for a get_string request for the aria-label\n * on an active page. The value is a comma separated string of key and\n * component.\n *\n * @param {object} root The root element.\n * @return {array} First element is the key, second is the component.\n */\n var getActivePageAriaLabelComponents = function(root) {\n var componentString = root.attr('data-aria-label-components-pagination-active-item');\n var components = componentString.split(',').map(function(component) {\n return component.trim();\n });\n return components;\n };\n\n /**\n * Set page numbers on each of the given items. Page numbers are set\n * from 1..n (where n is the number of items).\n *\n * Sets the active page number to be the last page found with\n * an \"active\" class (if any).\n *\n * Sets the last page number.\n *\n * @param {object} root The root element.\n * @param {jQuery} items A jQuery list of items.\n */\n var generatePageNumbers = function(root, items) {\n var lastPageNumber = 0;\n setActivePageNumber(root, 0);\n\n items.each(function(index, item) {\n var pageNumber = index + 1;\n item = $(item);\n item.attr('data-page-number', pageNumber);\n lastPageNumber++;\n\n if (item.hasClass('active')) {\n setActivePageNumber(root, pageNumber);\n }\n });\n\n setLastPageNumber(root, lastPageNumber);\n };\n\n /**\n * Set the aria-labels on each of the page items in the paging bar.\n * This includes the next, previous, first, and last items.\n *\n * @param {object} root The root element.\n */\n var generateAriaLabels = function(root) {\n var pageAriaLabelComponents = getPageAriaLabelComponents(root);\n var activePageAriaLabelComponents = getActivePageAriaLabelComponents(root);\n var activePageNumber = getActivePageNumber(root);\n var pageItems = root.find(SELECTORS.PAGE_ITEM);\n // We want to request all of the strings at once rather than\n // one at a time.\n var stringRequests = pageItems.map(function(index, page) {\n page = $(page);\n var pageNumber = getPageNumber(root, page);\n\n if (pageNumber === activePageNumber) {\n return {\n key: activePageAriaLabelComponents[0],\n component: activePageAriaLabelComponents[1],\n param: pageNumber\n };\n } else {\n return {\n key: pageAriaLabelComponents[0],\n component: pageAriaLabelComponents[1],\n param: pageNumber\n };\n }\n });\n\n Str.get_strings(stringRequests).then(function(strings) {\n pageItems.each(function(index, page) {\n page = $(page);\n var string = strings[index];\n page.attr('aria-label', string);\n page.find(SELECTORS.PAGE_LINK).attr('aria-label', string);\n });\n\n return strings;\n })\n .catch(function() {\n // No need to interrupt the page if we can't load the aria lang strings.\n return;\n });\n };\n\n /**\n * Make the paging bar item for the given page number visible and fire\n * the SHOW_PAGES paged content event to tell any listening content to\n * update.\n *\n * @param {object} root The root element.\n * @param {Number} pageNumber The number for the page to show.\n * @param {string} id A uniqie id for this instance.\n */\n var showPage = function(root, pageNumber, id) {\n var pendingPromise = new Pending('core/paged_content_paging_bar:showPage');\n var lastPageNumber = getLastPageNumber(root);\n var isSamePage = pageNumber == getActivePageNumber(root);\n var limit = getLimit(root);\n var offset = (pageNumber - 1) * limit;\n\n if (!isSamePage) {\n // We only need to toggle the active class if the user didn't click\n // on the already active page.\n root.find(SELECTORS.PAGE_ITEM).removeClass('active').removeAttr('aria-current');\n var page = getPageByNumber(root, pageNumber);\n page.addClass('active');\n page.attr('aria-current', true);\n setActivePageNumber(root, pageNumber);\n\n adjustPagingBarSize(root);\n }\n\n // Make sure the control buttons are disabled as the user navigates\n // to either end of the limits.\n if (lastPageNumber && pageNumber >= lastPageNumber) {\n disableNextControlButtons(root);\n } else {\n enableNextControlButtons(root);\n }\n\n if (pageNumber > 1) {\n enablePreviousControlButtons(root);\n } else {\n disablePreviousControlButtons(root);\n }\n\n generateAriaLabels(root);\n\n // This event requires a payload that contains a list of all pages that\n // were activated. In the case of the paging bar we only show one page at\n // a time.\n PubSub.publish(id + PagedContentEvents.SHOW_PAGES, [{\n pageNumber: pageNumber,\n limit: limit,\n offset: offset\n }]);\n\n pendingPromise.resolve();\n };\n\n /**\n * Add event listeners for interactions with the paging bar as well as listening\n * for custom paged content events.\n *\n * Each event will trigger different logic to update parts of the paging bar's\n * display.\n *\n * @param {object} root The root element.\n * @param {string} id A uniqie id for this instance.\n */\n var registerEventListeners = function(root, id) {\n var ignoreControlWhileLoading = root.attr('data-ignore-control-while-loading');\n var loading = false;\n\n if (ignoreControlWhileLoading == \"\") {\n // Default to ignoring control while loading if not specified.\n ignoreControlWhileLoading = true;\n }\n\n CustomEvents.define(root, [\n CustomEvents.events.activate\n ]);\n\n root.on(CustomEvents.events.activate, SELECTORS.PAGE_ITEM, function(e, data) {\n data.originalEvent.preventDefault();\n data.originalEvent.stopPropagation();\n\n if (ignoreControlWhileLoading && loading) {\n // Do nothing if configured to ignore control while loading.\n return;\n }\n\n var page = $(e.target).closest(SELECTORS.PAGE_ITEM);\n\n if (!page.hasClass('disabled')) {\n var pageNumber = getPageNumber(root, page);\n showPage(root, pageNumber, id);\n loading = true;\n }\n });\n\n // This event is fired when all of the items have been loaded. Typically used\n // in an \"infinite\" pages context when we don't know the exact number of pages\n // ahead of time.\n PubSub.subscribe(id + PagedContentEvents.ALL_ITEMS_LOADED, function(pageNumber) {\n loading = false;\n var currentLastPage = getLastPageNumber(root);\n\n if (!currentLastPage || pageNumber < currentLastPage) {\n // Somehow the value we've got saved is higher than the new\n // value we just received. Perhaps events came out of order.\n // In any case, save the lowest value.\n setLastPageNumber(root, pageNumber);\n }\n\n if (pageNumber === 1 && root.attr('data-hide-control-on-single-page')) {\n // If all items were loaded on the first page then we can hide\n // the paging bar because there are no other pages to load.\n hide(root);\n disableNextControlButtons(root);\n disablePreviousControlButtons(root);\n } else {\n show(root);\n disableNextControlButtons(root);\n }\n });\n\n // This event is fired after all of the requested pages have been rendered.\n PubSub.subscribe(id + PagedContentEvents.PAGES_SHOWN, function() {\n // All pages have been shown so turn off the loading flag.\n loading = false;\n });\n\n // This is triggered when the paging limit is modified.\n PubSub.subscribe(id + PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT, function(limit) {\n // Update the limit.\n setLimit(root, limit);\n setLastPageNumber(root, 0);\n setActivePageNumber(root, 0);\n show(root);\n // Reload the data from page 1 again.\n showPage(root, 1, id);\n });\n };\n\n /**\n * Initialise the paging bar.\n * @param {object} root The root element.\n * @param {string} id A uniqie id for this instance.\n */\n var init = function(root, id) {\n root = $(root);\n var pages = root.find(SELECTORS.PAGE);\n generatePageNumbers(root, pages);\n registerEventListeners(root, id);\n\n if (hasActivePageNumber(root)) {\n var activePageNumber = getActivePageNumber(root);\n // If the the paging bar was rendered with an active page selected\n // then make sure we fired off the event to tell the content page to\n // show.\n getPageByNumber(root, activePageNumber).click();\n if (activePageNumber == 1) {\n // If the first page is active then disable the previous buttons.\n disablePreviousControlButtons(root);\n }\n } else {\n // There was no active page number so load the first page using\n // the next button. This allows the infinite pagination to work.\n getNextButton(root).click();\n }\n\n adjustPagingBarSize(root);\n };\n\n return {\n init: init,\n disableNextControlButtons: disableNextControlButtons,\n enableNextControlButtons: enableNextControlButtons,\n disablePreviousControlButtons: disablePreviousControlButtons,\n enablePreviousControlButtons: enablePreviousControlButtons,\n showPage: showPage,\n rootSelector: SELECTORS.ROOT,\n };\n});\n"],"file":"paged_content_paging_bar.min.js"} \ No newline at end of file diff --git a/lib/amd/src/paged_content_pages.js b/lib/amd/src/paged_content_pages.js index f7445c7cefd..57e49494c66 100644 --- a/lib/amd/src/paged_content_pages.js +++ b/lib/amd/src/paged_content_pages.js @@ -26,14 +26,16 @@ define( 'core/templates', 'core/notification', 'core/pubsub', - 'core/paged_content_events' + 'core/paged_content_events', + 'core/pending', ], function( $, Templates, Notification, PubSub, - PagedContentEvents + PagedContentEvents, + Pending ) { var SELECTORS = { @@ -74,6 +76,8 @@ define( var deferred = $.Deferred(); root.attr('aria-busy', true); + var pendingPromise = new Pending('core/paged_content_pages:startLoading'); + Templates.render(TEMPLATES.LOADING, {visible: true}) .then(function(html) { var loadingSpinner = $(html); @@ -93,6 +97,8 @@ define( loadingSpinner.remove(); root.css('position', ''); root.removeAttr('aria-busy'); + + pendingPromise.resolve(); return; }); @@ -182,6 +188,7 @@ define( * @param {function} renderPagesContentCallback Render pages content. */ var showPages = function(root, pagesData, id, renderPagesContentCallback) { + var pendingPromise = new Pending('core/paged_content_pages:showPages'); var existingPages = []; var newPageData = []; var newPagesPromise = $.Deferred(); @@ -256,7 +263,9 @@ define( .fail(Notification.exception) .always(function() { loadingPromise.resolve(); - }); + pendingPromise.resolve(); + }) + .catch(); }; /** diff --git a/lib/amd/src/paged_content_paging_bar.js b/lib/amd/src/paged_content_paging_bar.js index fed32da8f3d..46c8fd7c6df 100644 --- a/lib/amd/src/paged_content_paging_bar.js +++ b/lib/amd/src/paged_content_paging_bar.js @@ -25,14 +25,16 @@ define([ 'core/custom_interaction_events', 'core/paged_content_events', 'core/str', - 'core/pubsub' + 'core/pubsub', + 'core/pending', ], function( $, CustomEvents, PagedContentEvents, Str, - PubSub + PubSub, + Pending ) { var SELECTORS = { @@ -451,6 +453,7 @@ function( * @param {string} id A uniqie id for this instance. */ var showPage = function(root, pageNumber, id) { + var pendingPromise = new Pending('core/paged_content_paging_bar:showPage'); var lastPageNumber = getLastPageNumber(root); var isSamePage = pageNumber == getActivePageNumber(root); var limit = getLimit(root); @@ -492,6 +495,8 @@ function( limit: limit, offset: offset }]); + + pendingPromise.resolve(); }; /**