1

通过 Javascript 正确显示分页菜单的数学运算让我发疯了。希望比我更了解这一点的人可以帮助我。

我只需要了解如何使用 javascript 在客户端正确显示分页菜单。

假设我总共有10 个项目

我想一次显示的最大值是1

菜单应该显示5 个数字,如果我们不在最后一组数字上,最后一个数字应该是带有 ... 的最后一页。

所以例如< 1 2 3 4 ... 10 >

用户点击 2 - 起始编号应为 1,最后 4 < 1 2 3 4 ... 10 >

用户点击 4 - 起始编号应为 2,最后 5 < 2 3 4 5 ... 10 >

用户点击 5 - 开始应该是 3,最后 6 < 3 4 5 6 ... 10 >

用户点击 7 - 我们在最后一组,所以 < 6 7 8 9 10 >

到目前为止,我所拥有的是:

var pages = Math.ceil(count / amount);
var maxIterations = 5;
var iterations = Math.min(pages, maxIterations);
var offset = Math.max(0, page-Math.round(maxIterations/2));
for(var i=0; i<iterations; i++) {
    var label = page + i;
    if(i == maxIterations-1) label = pages; //Last page number
    paginatorObjects.push({label: label}); //This create the menu button
}

基本上,我需要数字在用户点击它们时上下迭代(谷歌是如何做到的),而不必使用箭头按钮。我知道 jQuery 为这类事情提供了一个不错的插件,但这必须在 vanilla javascript 中完成。

4

2 回答 2

4

这个问题也让我摸不着头脑,我最近不得不为 AngularJS 应用程序实现它,但分页逻辑是纯 javascript。

在http://codepen.io/cornflourblue/pen/KVeaQL上有一个关于 CodePen 的工作演示

我还写了这篇博文,提供了更多细节

这是分页逻辑

function GetPager(totalItems, currentPage, pageSize) {
    // default to first page
    currentPage = currentPage || 1;

    // default page size is 10
    pageSize = pageSize || 10;

    // calculate total pages
    var totalPages = Math.ceil(totalItems / pageSize);

    var startPage, endPage;
    if (totalPages <= 10) {
        // less than 10 total pages so show all
        startPage = 1;
        endPage = totalPages;
    } else {
        // more than 10 total pages so calculate start and end pages
        if (currentPage <= 6) {
            startPage = 1;
            endPage = 10;
        } else if (currentPage + 4 >= totalPages) {
            startPage = totalPages - 9;
            endPage = totalPages;
        } else {
            startPage = currentPage - 5;
            endPage = currentPage + 4;
        }
    }

    // calculate start and end item indexes
    var startIndex = (currentPage - 1) * pageSize;
    var endIndex = startIndex + pageSize;

    // create an array of pages to ng-repeat in the pager control
    var pages = _.range(startPage, endPage + 1);

    // return object with all pager properties required by the view
    return {
        totalItems: totalItems,
        currentPage: currentPage,
        pageSize: pageSize,
        totalPages: totalPages,
        startPage: startPage,
        endPage: endPage,
        startIndex: startIndex,
        endIndex: endIndex,
        pages: pages
    };
}
于 2016-01-31T01:14:30.600 回答
2

What I ended up doing is this. This is directly from my source code, so there is some templating logic that doesn't make sense, but anyone who might be reading this in the future should be able to adjust according to their needs.

function paginate() {
    var paginator = sb.find('#' + moduleName + 'Pagination')[0];
    var container = paginator.getElementsByClass('container')[0];
    sb.dom.clearAll(container);
    if(count && count > 0) {
        sb.dom.removeClass(paginator, 'hidden');
        var pages = Math.ceil(count / amount);
        var maxIterations = 5;
        var iterations = Math.min(pages, maxIterations);
        var paginatorObjects = [];
        var center = Math.round(maxIterations/2);
        var offset = page-center;
        if(page < center) offset = 0; //Don't go lower than first page.
        if(offset + iterations > pages) offset -= (offset + iterations) - pages; //Don't go higher than total pages.
        for(var i=0; i<iterations; i++) {
            var label = (i+1) + offset;
            paginatorObjects.push({label: label});
        }
        sb.template.loadFrom(templateUrl, 'paginator').toHTML(paginatorObjects).appendTo(container, function(template) {
            var pageNumber = template.obj.label;

            if(pageNumber != page) {
                sb.addEvent(template, 'click', function() {                     
                    getAppointments(pageNumber);
                });
            } else {
                sb.dom.addClass(template, 'highlight');
            }               
        });

        if(offset + iterations < pages) {
            var dots = document.createTextNode(' ... ');
            container.appendChild(dots);
            sb.template.loadFrom(templateUrl, 'paginator').toHTML({label: pages}).appendTo(container, function(template) {
                sb.addEvent(template, 'click', function() {
                    getAppointments(pages);
                });
            });
        }

        var backBtn = paginator.getElementsByClass('icon back')[0];
        var forwardBtn = paginator.getElementsByClass('icon forward')[0];


        sb.removeEvent(backBtn, 'click');
        sb.removeEvent(forwardBtn, 'click');

        if(page - 1 > 0) {              
            sb.dom.removeClass(backBtn, 'hidden');
            sb.addEvent(backBtn, 'click', function() {
                getAppointments(page-1);                    
            });
        } else {
            sb.dom.addClass(backBtn, 'hidden');
        }

        if(page + 1 <= pages) {
            sb.dom.removeClass(forwardBtn, 'hidden');               
            sb.addEvent(forwardBtn, 'click', function() {
                getAppointments(page+1);                    
            });
        } else {
            sb.dom.addClass(forwardBtn, 'hidden');
        }

    } else {            
        sb.dom.addClass(paginator, 'hidden');
    }
}

When getAppointments() is called from the buttons, I use AJAX to get the next pages results, then this pagination() function is called again from that function so everything gets reset. The variables that determine the amount to show per page and the current page number are global (to the container function) and are not shown in this code sample.

The logic behind this is fairly simple. The center is determined (in my case the max it shows at once is 5, so the center is 3) and then an offset is calculated based on the page number. Clicking 4 will adjust the start number +1, and 2 would adjust it -1.

于 2012-08-21T04:31:59.233 回答