From 6d5af995d9c6294a164e0b0056950731be948866 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Sat, 9 Aug 2014 09:20:44 -0400 Subject: Add pagination. * js/guix-packages.js: (guix.chunk): New function. (guix.paginate): New function. (guix.controller.pages, guix.controller.currentPageIndex, guix.controller.pageSize): New variables. (guix.controller.currentPage, guix.controller.isFirstPage, guix.controller.isLastPage, guix.controller.isCurrentPage, guix.controller.packageCount): New functions. (guix.controller.doSearch): Paginate. (guix.view): Render pagination UI. --- js/guix-packages.js | 102 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 95 insertions(+), 7 deletions(-) diff --git a/js/guix-packages.js b/js/guix-packages.js index d4e975a..7ab30a0 100644 --- a/js/guix-packages.js +++ b/js/guix-packages.js @@ -17,25 +17,71 @@ var guix = {}; +guix.chunk = function(array, size) { + return array.reduce(function(memo, value, i) { + var currentSlice = _(memo).last(); + + if(i / size < memo.length) { + currentSlice.push(value); + } else { + memo.push([value]); + } + + return memo; + }, []); +}; + +guix.paginate = function(array, pageSize) { + return guix.chunk(array, pageSize); +}; + guix.Packages = function() { return m.request({ method: "GET", url: "packages.json" }); }; guix.controller = function() { + var self = this; + this.packages = guix.Packages(); - this.visiblePackages = m.prop([]); + this.pages = m.prop([]); + this.currentPageIndex = 0; + this.pageSize = 20; this.searchTerm = m.prop(""); // All packages are visible initially - this.packages.then(this.visiblePackages); + this.packages.then(function(packages) { + self.pages(guix.paginate(packages, self.pageSize)); + }); + + this.currentPage = function() { + return self.pages()[self.currentPageIndex] || []; + }; + + this.isFirstPage = function() { + return self.currentPageIndex === 0; + }; + + this.isLastPage = function() { + return self.currentPageIndex === self.pages().length - 1; + }; + + this.isCurrentPage = function(i) { + return self.currentPageIndex === i; + }; + + this.packageCount = function() { + return self.pages().reduce(function(memo, page) { + return memo + page.length; + }, 0); + }; this.doSearch = function() { var regexp = new RegExp(this.searchTerm(), "i"); - this.visiblePackages(this.packages().filter(function(package) { + this.pages(guix.paginate(this.packages().filter(function(package) { return regexp.test(package.name) || regexp.test(package.synopsis); - })); + }), self.pageSize)); }; }; @@ -70,10 +116,51 @@ guix.view = function(ctrl) { } } + function renderPagination() { + function renderPage(text, opts) { + return m("li", { + class: opts.class || "", + onclick: opts.onclick + }, m("a", { href: "#" }, text)); + } + + return m("ul.pagination", [ + // Back page + renderPage("«", { + class: ctrl.isFirstPage() ? "disabled" : "", + onclick: function() { + ctrl.currentPageIndex--; + + return false; + } + }) + ].concat(ctrl.pages().map(function(page, i) { + // Jump to page + return renderPage(i + 1, { + class: ctrl.isCurrentPage(i) ? "active" : "", + onclick: function() { + ctrl.currentPageIndex = i; + + return false; + } + }); + })).concat([ + // Forward page + renderPage("»", { + class: ctrl.isLastPage() ? "disabled" : "", + onclick: function() { + ctrl.currentPageIndex++; + + return false; + } + }) + ])); + } + return [ m("h2", [ "Packages", - m("span.badge", ctrl.visiblePackages().length) + m("span.badge", ctrl.packageCount()) ]), m("input.form-control", { type: "text", @@ -97,7 +184,7 @@ guix.view = function(ctrl) { ]) ]), m("tbody", [ - ctrl.visiblePackages().map(function(package) { + ctrl.currentPage().map(function(package) { return m("tr", [ m("td", renderName(package)), m("td", package.version), @@ -107,7 +194,8 @@ guix.view = function(ctrl) { ]); }) ]) - ]) + ]), + renderPagination() ]; }; -- cgit v1.2.3