From 8ced57e86f518cecea4fa5c6499ad33459823b77 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Thu, 16 Oct 2014 22:20:04 -0400 Subject: js: Extract pagination model. * js/utils.js (guix.clamp): New function. * js/controller/packages.js (guix.packages.controller): Remove 'pages', 'currentPageIndex', and 'pageSize' properties. Add 'pager' prop. Delete 'paginate', 'currentPage', 'isFirstPage', 'isLastPage', and 'isCurrentPage' methods. * js/model/packages.js (guix.packages.Pager): New function. * js/view/packages.js (guix.packages.view): Use new Pager API. --- js/controller/packages.js | 47 +++++++++++++---------------------------- js/model/packages.js | 54 ++++++++++++++++++++++++++++++++++++++++++++--- js/utils.js | 4 ++++ js/view/packages.js | 26 +++++++++++------------ 4 files changed, 82 insertions(+), 49 deletions(-) (limited to 'js') diff --git a/js/controller/packages.js b/js/controller/packages.js index db94d72..89f01e9 100644 --- a/js/controller/packages.js +++ b/js/controller/packages.js @@ -15,14 +15,19 @@ // License along with this program. If not, see // . -(function(packages) { +(function() { + var packages = guix.packages; + packages.controller = (function() { + var PAGE_SIZE = 20; + + function Pager(items) { + return new packages.Pager(items, PAGE_SIZE); + } + function controller() { var self = this; - this.pages = m.prop([]); - this.currentPageIndex = 0; - this.pageSize = 20; this.searchTerm = m.prop(""); this.columns = [ { header: "Name", sortField: "name" }, @@ -43,40 +48,20 @@ } ]; this.sorter = m.prop(new packages.Sorter("name")); + this.pager = m.prop(Pager([])); this.phase = m.prop(packages.PHASE_NONE); this.selectedPackage = m.prop(null); this.packages = packages.Packages() .then(function(packages) { // All packages are visible initially - self.pages(self.paginate(packages, self.pageSize)); + self.pager(Pager(packages)); }) .then(m.redraw); }; - - controller.prototype.paginate = function(array, pageSize) { - return guix.chunk(this.sorter().sort(array), pageSize); - }; - - controller.prototype.currentPage = function() { - return this.pages()[this.currentPageIndex] || []; - }; - - controller.prototype.isFirstPage = function() { - return this.currentPageIndex === 0; - }; - - controller.prototype.isLastPage = function() { - return this.currentPageIndex === this.pages().length - 1; - }; - - controller.prototype.isCurrentPage = function(i) { - return this.currentPageIndex === i; - }; - controller.prototype.packageCount = function() { - return this.pages().reduce(function(memo, page) { + return this.pager().pages.reduce(function(memo, page) { return memo + page.length; }, 0); }; @@ -84,12 +69,10 @@ controller.prototype.doSearch = function() { var regexp = new RegExp(this.searchTerm(), "i"); - this.pages(this.paginate(this.packages().filter(function(package) { + this.pager(Pager(this.packages().filter(function(package) { return regexp.test(package.name) || regexp.test(package.synopsis); - }), this.pageSize)); - // Reset pagination - this.currentPageIndex = 0; + }))); }; controller.prototype.sortBy = function(field) { @@ -122,4 +105,4 @@ return controller; })(); -})(guix.packages); +})(); diff --git a/js/model/packages.js b/js/model/packages.js index 652d11a..1c61d25 100644 --- a/js/model/packages.js +++ b/js/model/packages.js @@ -15,9 +15,11 @@ // License along with this program. If not, see // . -guix.packages = {}; -(function(packages) { + +(function() { + var packages = guix.packages = {}; + packages.Packages = function() { return m.request({ method: "GET", @@ -45,9 +47,55 @@ guix.packages = {}; return Sorter; })(); + packages.Pager = (function() { + function Pager(items, pageSize) { + this.pageSize= pageSize; + this.pageIndex = 0; + this.pages = guix.chunk(items, pageSize); + } + + Pager.prototype.currentPage = function() { + return this.pages[this.pageIndex]; + }; + + Pager.prototype.pageCount = function() { + return this.pages.length; + }; + + Pager.prototype.isEmpty = function() { + return this.pageCount() === 0; + }; + + Pager.prototype.isFirstPage = function() { + return this.pageIndex === 0; + }; + + Pager.prototype.isLastPage = function() { + return this.pageIndex === this.pages.length - 1; + }; + + Pager.prototype.isCurrentPage = function(i) { + return this.pageIndex === i; + }; + + Pager.prototype.nextPage = function() { + this.pageIndex = Math.min(this.pageCount() - 1, this.pageIndex + 1); + }; + + Pager.prototype.previousPage = function() { + this.pageIndex = Math.max(0, this.pageIndex - 1); + }; + + Pager.prototype.gotoPage = function(page) { + this.pageIndex = guix.clamp(page, 0, this.pageCount() -1); + }; + + return Pager; + })(); + packages.PHASE_NONE = 0; packages.PHASE_PROMPT = 1; packages.PHASE_DERIVATION = 2; packages.PHASE_SUCCESS = 3; packages.PHASE_ERROR = 4; -})(guix.packages); +})(); diff --git a/js/utils.js b/js/utils.js index b3e4768..c44ee23 100644 --- a/js/utils.js +++ b/js/utils.js @@ -17,6 +17,10 @@ var guix = {}; +guix.clamp = function(n, min, max) { + return Math.max(Math.min(n, max), min); +}; + guix.chunk = function(array, size) { return array.reduce(function(memo, value, i) { var currentSlice = _(memo).last(); diff --git a/js/view/packages.js b/js/view/packages.js index e202471..7c55486 100644 --- a/js/view/packages.js +++ b/js/view/packages.js @@ -15,7 +15,8 @@ // License along with this program. If not, see // . -(function(packages) { +(function() { + var packages = guix.packages; var spinner = m(".spinner-container", m(".spinner")); packages.view = function(ctrl) { @@ -75,7 +76,7 @@ ]) ]), m("tbody", [ - ctrl.currentPage().map(function(package) { + ctrl.pager().currentPage().map(function(package) { return m("tr", [ m("td", renderName(package)), m("td", package.version), @@ -100,30 +101,27 @@ return m("div", m("ul.pagination", [ // Back page renderPage("«", { - class: ctrl.isFirstPage() ? "disabled" : "", + class: ctrl.pager().isFirstPage() ? "disabled" : "", onclick: function() { - ctrl.currentPageIndex--; - + ctrl.pager().previousPage(); return false; } }) - ].concat(ctrl.pages().map(function(page, i) { + ].concat(ctrl.pager().pages.map(function(page, i) { // Jump to page return renderPage(i + 1, { - class: ctrl.isCurrentPage(i) ? "active" : "", + class: ctrl.pager().isCurrentPage(i) ? "active" : "", onclick: function() { - ctrl.currentPageIndex = i; - + ctrl.pager().gotoPage(i); return false; } }); })).concat([ // Forward page renderPage("»", { - class: ctrl.isLastPage() ? "disabled" : "", + class: ctrl.pager().isLastPage() ? "disabled" : "", onclick: function() { - ctrl.currentPageIndex++; - + ctrl.pager().nextPage(); return false; } }) @@ -239,7 +237,7 @@ return null; } - return guix.withLayout(_.isEmpty(ctrl.pages()) ? spinner : [ + return guix.withLayout(ctrl.pager().isEmpty() ? spinner : [ m("h2", [ "Packages", m("span.badge", ctrl.packageCount()) @@ -250,4 +248,4 @@ renderPagination() ]); }; -})(guix.packages); +})(); -- cgit v1.2.3