You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by be...@apache.org on 2015/11/27 20:18:14 UTC

fauxton commit: updated refs/heads/master to 5ee9903

Repository: couchdb-fauxton
Updated Branches:
  refs/heads/master b2195ac7d -> 5ee99031f


Pagination component update

This refactors the <Pagination /> element to make it a bit more
generic. Namely:
- max visible pages that appear in pagination is now configurable
- can add a callback function to be called when the user clicks
a pagination link, instead of just outputting an href on the <a>
tags


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/5ee99031
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/5ee99031
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/5ee99031

Branch: refs/heads/master
Commit: 5ee99031f04c70b79719a0c958927f7cec3c3702
Parents: b2195ac
Author: Ben Keen <be...@gmail.com>
Authored: Wed Nov 25 15:11:23 2015 -0800
Committer: Ben Keen <be...@gmail.com>
Committed: Fri Nov 27 10:53:18 2015 -0800

----------------------------------------------------------------------
 app/addons/fauxton/components.react.jsx         | 67 ++++++++++++--------
 .../fauxton/tests/componentsSpec.react.jsx      | 44 +++++++++++++
 2 files changed, 85 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ee99031/app/addons/fauxton/components.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/components.react.jsx b/app/addons/fauxton/components.react.jsx
index b8bad67..784c514 100644
--- a/app/addons/fauxton/components.react.jsx
+++ b/app/addons/fauxton/components.react.jsx
@@ -234,34 +234,36 @@ function (app, FauxtonAPI, React, ZeroClipboard) {
     }
   });
 
-  var Pagination = React.createClass({
 
-    getInitialState: function () {
-      return {};
-    },
+  var Pagination = React.createClass({
 
     getDefaultProps: function () {
       return {
         perPage: FauxtonAPI.constants.MISC.DEFAULT_PAGE_SIZE,
+        onClick: null,
         page: 1,
-        total: 0
+        total: 0,
+        urlPrefix: '',
+        urlSuffix: '',
+        maxNavPages: 10
       };
     },
 
     getVisiblePages: function (page, totalPages) {
       var from, to;
-      if (totalPages < 10) {
+      if (totalPages < this.props.maxNavPages) {
         from = 1;
         to = totalPages + 1;
       } else {
-        from = page - 5;
-        to = page + 5;
+        var halfMaxNavPages = Math.floor(this.props.maxNavPages / 2);
+        from = page - halfMaxNavPages;
+        to = page + halfMaxNavPages;
         if (from <= 1) {
           from = 1;
-          to = 11;
+          to = this.props.maxNavPages + 1;
         }
         if (to > totalPages + 1) {
-          from =  totalPages - 9;
+          from = totalPages - (this.props.maxNavPages - 1);
           to = totalPages + 1;
         }
       }
@@ -271,33 +273,46 @@ function (app, FauxtonAPI, React, ZeroClipboard) {
       };
     },
 
-    createItemsForPage: function (visiblePages, page, prefix, suffix) {
+    createItemsForPage: function (visiblePages) {
       return _.range(visiblePages.from, visiblePages.to).map(function (i) {
         return (
-          <li key={i} className={(page === i ? "active" : null)}>
-            <a href={prefix + i + suffix}>{i}</a>
+          <li key={i} className={(this.props.page === i ? 'active' : null)}>
+            {this.getLink(i, i)}
           </li>
         );
-      });
+      }.bind(this));
+    },
+
+    getLink: function (i, label) {
+      if (this.props.onClick) {
+        return (
+          <a onClick={this.props.onClick.bind(null, i)} dangerouslySetInnerHTML={{__html: label}}></a>
+        );
+      }
+      return (
+        <a href={this.props.urlPrefix + i + this.props.urlSuffix} dangerouslySetInnerHTML={{__html: label}}></a>
+      );
+    },
+
+    getTotalPages: function () {
+      return this.props.total === 0 ? 1 : Math.ceil(this.props.total / this.props.perPage);
     },
 
     render: function () {
-      var page = this.state.page || this.props.page;
-      var total = this.state.total || this.props.total;
-      var perPage = this.props.perPage;
-      var prefix = this.props.urlPrefix || "";
-      var suffix = this.props.urlSuffix || "";
-      var totalPages = total === 0 ? 1 : Math.ceil(total / perPage);
-      var visiblePages = this.getVisiblePages(page, totalPages);
-      var rangeItems = this.createItemsForPage(visiblePages, page, prefix, suffix);
+      var totalPages = this.getTotalPages();
+      var visiblePages = this.getVisiblePages(this.props.page, totalPages);
+      var rangeItems = this.createItemsForPage(visiblePages);
+      var prevPage = Math.max(this.props.page - 1, 1);
+      var nextPage = Math.min(this.props.page + 1, totalPages);
+
       return (
         <ul className="pagination">
-          <li className={(page === 1 ? "disabled" : null)}>
-            <a href={prefix + Math.max(page - 1, 1) + suffix}>&laquo;</a>
+          <li className={(this.props.page === 1 ? "disabled" : null)}>
+            {this.getLink(prevPage, '&laquo;')}
           </li>
           {rangeItems}
-          <li className={(page < totalPages ? null : "disabled")}>
-            <a href={prefix + Math.min(page + 1, totalPages) + suffix}>&raquo;</a>
+          <li className={(this.props.page < totalPages ? null : "disabled")}>
+            {this.getLink(nextPage, '&raquo;')}
           </li>
         </ul>
       );

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ee99031/app/addons/fauxton/tests/componentsSpec.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/tests/componentsSpec.react.jsx b/app/addons/fauxton/tests/componentsSpec.react.jsx
index c478c78..fd53843 100644
--- a/app/addons/fauxton/tests/componentsSpec.react.jsx
+++ b/app/addons/fauxton/tests/componentsSpec.react.jsx
@@ -202,6 +202,50 @@ define([
       assert.equal("30", lis[10].innerText);
     });
 
+    it('limits the number of total pages when customized', function () {
+      var maxNavPages = 15;
+      var pageEl = TestUtils.renderIntoDocument(
+        <Views.Pagination page={1} total={1000} maxNavPages={maxNavPages} />,
+        container
+      );
+      var lis = pageEl.getDOMNode().getElementsByTagName("li");
+      assert.equal(1 + maxNavPages + 1, lis.length);
+    });
+
+    it('calls callback method when supplied', function () {
+      var spy = sinon.spy();
+      var pageEl = TestUtils.renderIntoDocument(
+        <Views.Pagination page={1} total={100} onClick={spy} />,
+        container
+      );
+      var links = React.findDOMNode(pageEl).getElementsByTagName("a");
+
+      TestUtils.Simulate.click(links[3]);
+
+      // confirm it gets called
+      assert.ok(spy.calledOnce);
+
+      // confirm it's called with the pagination number (3)
+      assert.ok(spy.calledWith(3));
+    });
+
+    it('calls callback method with correct values for prev and next', function () {
+      var spy = sinon.spy();
+
+      var currentPage = 5;
+      var pageEl = TestUtils.renderIntoDocument(
+        <Views.Pagination page={currentPage} total={200} onClick={spy} />,
+        container
+      );
+      var links = React.findDOMNode(pageEl).getElementsByTagName("a");
+
+      TestUtils.Simulate.click(links[0]);
+      assert.ok(spy.calledWith(currentPage - 1));
+
+      TestUtils.Simulate.click(links[11]); // last index
+      assert.ok(spy.calledWith(currentPage + 1));
+    });
+
   });