【AngularJS】独自のページネーションサービスを実装する。

してみた。

下記URLのソースを参考に作成。

https://github.com/svileng/ng-simplePagination/blob/master/simplePagination.js
https://github.com/cakephp/cakephp/blob/master/lib/Cake/View/Helper/PaginatorHelper.php

これはかなり使いやすい。

"use strict";

var paginationModule = angular.module('ngPagination', []);

/**
 * usage
 * 
 * - main module
 * 
 * var app = angular.module('app', [
 *     'ngPagination'
 * ]);
 * 
 * 
 * - controller
 * 
 * @recipe     ng-resource object
 * @Pagination Pagination object
 * 
 * app.controller('exampleCtrl'. function($scope, recipe, Pagination) {
 *     $scope.pagination = Pagination.getNew(10, 6); // (parPage, modules)
 *     $scope.lists = recipe.query(function() {
 *         $scope.pagination.numPages = Math.ceil($scope.lists.length / $scope.pagination.perPage);
 *     });
 * });
 * 
 * 
 * - view (template)
 * 
 * - pagination element
 *  
 * <ul>
 *     <li><a href="" ng-click="pagination.firstPage()" ng-hide="pagination.page == 0">??</a></li>
 *     <li><a href="" ng-click="pagination.prevPage()" ng-hide="pagination.page == 0">?</a></li>
 *     <li><a href="" ng-show="pagination.beforeEllipsis">...</a></li>
 *     <li ng-repeat="n in [] | range: pagination" ng-class="{active: n == pagination.page}"><a href="" ng-click="pagination.toPageId(n)">{{n + 1}}</a></li>
 *     <li><a href="" ng-show="pagination.afterEllipsis">...</a></li>
 *     <li><a href="" ng-click="pagination.nextPage()" ng-hide="pagination.page + 1 >= pagination.numPages">?</a></li>
 *     <li><a href="" ng-click="pagination.lastPage()" ng-hide="pagination.page + 1 >= pagination.numPages">??</a></li>
 * </ul>
 * 
 * - angular repeater
 * 
 * <ANY
 *     ng-repeat="data in lists | startFrom: pagination.page * pagination.perPage | limitTo: pagination.perPage"
 * >
 * ...
 * </ANY>
 * 
 */
paginationModule.factory('$pagination', function() {

    var pagination = {};
  
    pagination.getNew = function(perPage, modules) {

        perPage = perPage === undefined ? 5 : perPage;
        modules = modules === undefined ? 4 : modules;
    
        var paginator = {
            numPages: 1,
            perPage: perPage,
            page: 0,
            modules: modules,
            beforeEllipsis: false,
            afterEllipsis: false
        };
    
        paginator.prevPage = function() {
            if (paginator.page > 0) {
                paginator.page -= 1;
            }
        };
    
        paginator.nextPage = function() {
            if (paginator.page < paginator.numPages - 1) {
                paginator.page += 1;
            }
        };
        
        paginator.firstPage = function() {
            if (paginator.page > 0) {
                paginator.page = 0;
            }
        };
        
        paginator.lastPage = function() {
            if (paginator.page < paginator.numPages - 1) {
                paginator.page = paginator.numPages - 1;
            }
        };
    
        paginator.toPageId = function(id) {
            if (id >= 0 && id <= paginator.numPages - 1) {
                paginator.page = id;
            }
        };
    
        return paginator;
    };

    return pagination;
});

paginationModule.filter('startFrom', function() {
    return function(input, start) {
        if (input === undefined) {
            return input;
        } else {
            return input.slice(+start);
        }
    };
});

/**
 * @input      ng-repeat elements
 * @pagination pagination object
 */
paginationModule.filter('range', function() {
    return function(input, pagination) {
        
        var pageCount = pagination.numPages,
            page = pagination.page,
            modules = pagination.modules
        ;
        
        pageCount = parseInt(pageCount);
        
        if (modules && pageCount > modules) {
            
            page += 1;
            
            if (Math.ceil(modules / 2) + 1 < page) {
                pagination.beforeEllipsis = true;
            } else {
                pagination.beforeEllipsis = false;
            }
            
            if (pageCount - Math.floor(modules / 2) - 1 < page) {
                pagination.afterEllipsis = false;
            } else {
                pagination.afterEllipsis = true;
            }
            
            var half = parseInt(modules / 2, 10);
            var end = page + half;
            
            if (end > pageCount) {
                end = pageCount;
            }
            
            var start = page - (modules - (end - page));
            if (start <= 1) {
                start = 1;
                end = page + (modules - page) + 1;
            }
            
            for (var i = start; i < page; i++) {
                input.push(i - 1);
            }
            
            input.push(page - 1);
            
            start = page + 1;
            for (var i = start; i < end; i++) {
                input.push(i - 1);
            }
            
            if (end != page) {
                input.push(i - 1);
            }
            
        } else {

            pagination.beforeEllipsis = false;
            pagination.afterEllipsis = false;
            
            for (var i = 0; i < pageCount; i++) {
                input.push(i);
            }
            
        }
        
        return input;
    };
});