From 17b4f1210392e6104aa34547b9fae642278501a9 Mon Sep 17 00:00:00 2001
From: Justin Richer <jricher@mit.edu>
Date: Wed, 19 Mar 2014 17:39:40 -0400
Subject: [PATCH] added pagination to client display, closes #439

---
 .../src/main/webapp/WEB-INF/tags/footer.tag   |   3 +-
 .../src/main/webapp/resources/js/client.js    |  53 ++++++--
 .../main/webapp/resources/js/lib/bootpag.js   | 128 ++++++++++++++++++
 .../webapp/resources/template/client.html     |   3 +-
 4 files changed, 174 insertions(+), 13 deletions(-)
 create mode 100644 openid-connect-server-webapp/src/main/webapp/resources/js/lib/bootpag.js

diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/footer.tag b/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/footer.tag
index 30daa33de..6946aa6a9 100644
--- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/footer.tag
+++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/footer.tag
@@ -21,8 +21,8 @@
 <script type="text/javascript" src="resources/js/lib/purl.js"></script>
 <script type="text/javascript" src="resources/js/lib/bootstrapx-clickover.js"></script>
 <script type="text/javascript" src="resources/js/lib/moment.js"></script>
-<script type="text/javascript" src="resources/js/lib/retina.js"></script>
 <script type="text/javascript" src="resources/js/lib/bootstrap-sheet.js"></script>
+<script type="text/javascript" src="resources/js/lib/bootpag.js"></script>
 <c:if test="${js != null && js != ''}">
 	<script type="text/javascript" src="resources/js/client.js"></script>
 	<script type="text/javascript" src="resources/js/grant.js"></script>
@@ -32,5 +32,6 @@
 	<script type="text/javascript" src="resources/js/token.js"></script>
 	<script type="text/javascript" src="resources/js/admin.js"></script>
 </c:if>
+<script type="text/javascript" src="resources/js/lib/retina.js"></script>
 </body>
 </html>
diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js
index 17bf8dcf3..d1d17c3b0 100644
--- a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js
+++ b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js
@@ -303,7 +303,8 @@ var ClientListView = Backbone.View.extend({
         "click .new-client":"newClient",
         "click .refresh-table":"refreshTable",
         'keyup .search-query':'searchTable',
-        'click .form-search button':'clearSearch'
+        'click .form-search button':'clearSearch',
+        'page #paginator':'changePage'
     },
 
     newClient:function (e) {
@@ -323,18 +324,36 @@ var ClientListView = Backbone.View.extend({
     },
     
     renderInner:function(eventName) {
-    	
-    	_.each(this.filteredModel.models, function (client) {
-            $("#client-table",this.el).append(
-            		new ClientView({
-            				model:client, 
-            				count:this.options.stats.get(client.get('id')),
-            				systemScopeList: this.options.systemScopeList,
-            				whiteList: this.options.whiteListList.getByClientId(client.get('clientId'))
-            			}).render().el);
+
+        // set up pagination
+        var numPages = Math.ceil(this.filteredModel.length / 10);
+        if (numPages > 1) {
+        	$('#paginator').show();
+        	$('#paginator', this.el).bootpag({
+        		total: numPages,
+        		page: 1
+        	});        	
+        } else {
+        	$('#paginator', this.el).hide();
+        }
+
+        // render the rows
+    	_.each(this.filteredModel.models, function (client, index) {
+    		var element = new ClientView({
+				model:client, 
+				count:this.options.stats.get(client.get('id')),
+				systemScopeList: this.options.systemScopeList,
+				whiteList: this.options.whiteListList.getByClientId(client.get('clientId'))
+			}).render().el;
+            $("#client-table",this.el).append(element);
+            if (Math.ceil((index + 1) / 10) != 1) {
+            	$(element).hide();
+            }
         }, this);
 
-        this.togglePlaceholder();        
+        this.togglePlaceholder();
+
+        
     },
     
 	togglePlaceholder:function() {
@@ -357,6 +376,18 @@ var ClientListView = Backbone.View.extend({
 		}
 	},
 	
+	changePage:function(event, num) {
+		this.page = num;
+		$('#client-table tbody tr', this.el).each(function(index, element) {
+			console.log([num, index]);
+			if (Math.ceil((index + 1) / 10) != num) {
+            	$(element).hide();
+            } else {
+            	$(element).show();
+            }
+		});
+	},
+	
     refreshTable:function(e) {
     	e.preventDefault();
     	$('#loadingbox').sheet('show');
diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/lib/bootpag.js b/openid-connect-server-webapp/src/main/webapp/resources/js/lib/bootpag.js
new file mode 100644
index 000000000..b0330fce6
--- /dev/null
+++ b/openid-connect-server-webapp/src/main/webapp/resources/js/lib/bootpag.js
@@ -0,0 +1,128 @@
+/**
+ * @preserve 
+ * bootpag - jQuery plugin for dynamic pagination
+ *
+ * Copyright (c) 2013 botmonster@7items.com
+ *
+ * Licensed under the MIT license:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *
+ * Project home:
+ *   http://botmonster.com/jquery-bootpag/
+ *
+ * Version:  1.0.5
+ *
+ */
+(function($, window) {
+
+    $.fn.bootpag = function(options){
+
+        var $owner = this, 
+            settings = $.extend({
+                total: 0,
+                page: 1,
+                maxVisible: null,
+                leaps: true,
+                href: 'javascript:void(0);',
+                hrefVariable: '{{number}}',
+                next: '&raquo;',
+                prev: '&laquo;'
+            }, 
+            $owner.data('settings') || {}, 
+            options || {});
+
+        if(settings.total <= 0)
+            return this;
+
+          if(!$.isNumeric(settings.maxVisible) && !settings.maxVisible){
+            settings.maxVisible = settings.total;
+        }
+
+        $owner.data('settings', settings);
+
+        function renderPage($bootpag, page){
+        
+            var lp, 
+                maxV = settings.maxVisible == 0 ? 1 : settings.maxVisible,
+                step = settings.maxVisible == 1 ? 0 : 1,
+                vis = Math.floor((page - 1) / maxV) * maxV,
+                $page = $bootpag.find('li');
+            settings.page = page = page < 0 ? 0 : page > settings.total ? settings.total : page;
+            $page.removeClass('disabled');
+            lp = page - 1 < 1 ? 1 : 
+                    settings.leaps && page - 1 >= settings.maxVisible ? 
+                        Math.floor((page - 1) / maxV) * maxV : page - 1;
+            $page
+                .first()
+                .toggleClass('disabled', page === 1)
+                .attr('data-lp', lp)
+                .find('a').attr('href', href(lp));
+            
+            var step = settings.maxVisible == 1 ? 0 : 1;
+            
+            lp = page + 1 > settings.total ? settings.total : 
+                    settings.leaps && page + 1 < settings.total - settings.maxVisible ? 
+                        vis + settings.maxVisible + step: page + 1;
+       
+            $page
+                .last()
+                .toggleClass('disabled', page === settings.total)
+                .attr('data-lp', lp)
+                .find('a').attr('href', href(lp));;
+
+            var $currPage = $page.filter('[data-lp='+page+']');
+            if(!$currPage.not('.next,.prev').length){
+                var d = page <= vis ? -settings.maxVisible : 0;
+                $page.not('.next,.prev').each(function(index){
+                    lp = index + 1 + vis + d;
+                    $(this)
+                        .attr('data-lp', lp)
+                        .toggle(lp <= settings.total)
+                        .find('a').html(lp).attr('href', href(lp));
+                });
+                $currPage = $page.filter('[data-lp='+page+']');
+            }
+            $currPage.addClass('disabled');
+            $owner.data('settings', settings);
+        }
+
+        function href(c){
+
+            return settings.href.replace(settings.hrefVariable, c);
+        }
+
+        return this.each(function(){
+            
+            var $bootpag, lp, me = $(this),
+                p = ['<ul class="pagination bootpag">'];
+
+            if(settings.prev){
+                p.push('<li data-lp="1" class="prev"><a href="'+href(1)+'">'+settings.prev+'</a></li>');
+            }
+            for(var c = 1; c <= Math.min(settings.total, settings.maxVisible); c++){
+                p.push('<li data-lp="'+c+'"><a href="'+href(c)+'">'+c+'</a></li>');
+            }
+            if(settings.next){
+                lp = settings.leaps && settings.total > settings.maxVisible
+                    ? Math.min(settings.maxVisible + 1, settings.total) : 2;
+                p.push('<li data-lp="'+lp+'" class="next"><a href="'+href(lp)+'">'+settings.next+'</a></li>');
+            }
+            p.push('</ul>');
+            me.find('ul.bootpag').remove();
+            me.append(p.join(''));
+            $bootpag = me.find('ul.bootpag');
+            me.find('li').click(function paginationClick(){
+            
+                var me = $(this);
+                if(me.hasClass('disabled')){
+                    return;
+                }
+                var page = parseInt(me.attr('data-lp'), 10);
+                renderPage($bootpag, page);
+                $owner.trigger('page', page);
+            });
+            renderPage($bootpag, settings.page);
+        });
+    }
+
+})(jQuery, window);
diff --git a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html
index e6f0a5a8e..264be37b8 100644
--- a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html
+++ b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html
@@ -114,6 +114,8 @@
         </tbody>
     </table>
 
+	<div id="paginator" class="pagination"> </div>
+
     <div class="well well-small">
 		<button class="btn btn-small refresh-table"><i class="icon-refresh"></i> Refresh</button> &nbsp; 
         <button class="btn btn-small btn-primary new-client"><i class="icon-plus icon-white"></i> New Client</button>
@@ -708,4 +710,3 @@
 	<% } %>
 
 </script>
-