最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Javascript Google Style Pagination Menu - Stack Overflow

programmeradmin4浏览0评论

The math to correctly display a pagination menu via Javascript is driving me insane. Hopefully someone who understands this a little better than me can help me out.

All I need is to understand how to properly display a pagination menu on the client side with javascript.

Lets say I have 10 total items.

The max I want show at once is 1.

The menu should display 5 numbers and the last number should be the last page with a ... if we aren't on the last set of numbers.

So for instance < 1 2 3 4 ... 10 >

User clicks 2 - Start number should be 1, last 4 < 1 2 3 4 ... 10 >

User clicks 4 - start number should 2, last 5 < 2 3 4 5 ... 10 >

User clicks 5 - start should be 3, last 6 < 3 4 5 6 ... 10 >

User clicks 7 - we are on the last set so < 6 7 8 9 10 >

So far all I have is:

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
}

Basically the point is that I need the numbers to iterate up and down as the user clicks through them (how google does it) without having to use the arrow buttons. I understand jQuery has a nice plugin for this sort of thing, but this has to be done in vanilla javascript.

The math to correctly display a pagination menu via Javascript is driving me insane. Hopefully someone who understands this a little better than me can help me out.

All I need is to understand how to properly display a pagination menu on the client side with javascript.

Lets say I have 10 total items.

The max I want show at once is 1.

The menu should display 5 numbers and the last number should be the last page with a ... if we aren't on the last set of numbers.

So for instance < 1 2 3 4 ... 10 >

User clicks 2 - Start number should be 1, last 4 < 1 2 3 4 ... 10 >

User clicks 4 - start number should 2, last 5 < 2 3 4 5 ... 10 >

User clicks 5 - start should be 3, last 6 < 3 4 5 6 ... 10 >

User clicks 7 - we are on the last set so < 6 7 8 9 10 >

So far all I have is:

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
}

Basically the point is that I need the numbers to iterate up and down as the user clicks through them (how google does it) without having to use the arrow buttons. I understand jQuery has a nice plugin for this sort of thing, but this has to be done in vanilla javascript.

Share Improve this question asked Aug 20, 2012 at 14:36 ryandlfryandlf 28.6k37 gold badges111 silver badges164 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

This problem had me scratching my head for a while too, I recently had to implement it for an AngularJS application, but the pagination logic is pure javascript.

There's a working demo on CodePen at http://codepen.io/cornflourblue/pen/KVeaQL

I also wrote this blog post with further details

Here's the pagination logic

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
    };
}

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.

发布评论

评论列表(0)

  1. 暂无评论