tags:

views:

2821

answers:

7

I'm looking for an example algorithm of smart pagination. By smart, what I mean is that I only want to show, for example, 2 adjacent pages to the current page, so instead of ending up with a ridiculously long page list, I truncate it.

Here's a quick example to make it clearer... this is what I have now:

Pages: 1 2 3 4 [5] 6 7 8 9 10 11

This is what I want to end up with:

Pages: ... 3 4 [5] 6 7 ...

(In this example, I'm only showing 2 adjacent pages to the current page)

I'm implementing it in PHP/Mysql, and the "basic" pagination (no trucating) is already coded, I'm just looking for an example to optimize it... It can be an example in any language, as long as it gives me an idea as to how to implement it...

+10  A: 

I had the same need a while ago.

Here's the article I used to get it done (with PHP code): Digg-Style Pagination

It works pretty fast and has some additions to what you're trying to do, like:

[1] 2 3 4 5 6 ... 100
1 [2] 3 4 5 6 ... 100
...
1 ... 4 5 [6] 7 8 ... 100
changelog
+1  A: 

See my question on paging links

Geoff
A: 

I would use something simple on the page you are showing the paginator, like:

if (
  $page_number == 1 || $page_number == $last_page ||
  $page_number == $actual_page ||
  $page_number == $actual_page+1 || $page_number == $actual_page+2 ||
  $page_number == $actual_page-1 || $page_number == $actual_page-2
  ) echo $page_number;

You can adapt it to show each 10 or so pages with % operator ...

I think using switch() case would be better in this case, I just don't remember the syntax now

Keep it Simple :)

Fernando Barrocal
+2  A: 

Is this what you are looking for?

http://www.phpeasystep.com/phptu/29.html

Chris Lawlor
A: 

I use this in a personal project I'm building and its very fast. It basically produces a dataset that you can bind to a repeater.

public static DataSet GeneratePageNumbers(int PageSize, int TotalCount, int CurrentPageNumber, int CurrentPageListNumber, out int StartRecordNumber, out int EndRecordNumber)
        {
            //Author: Donny V.
            //Blog: http://donnyvblog.blogspot.com

            StartRecordNumber = 0;
            EndRecordNumber = 0;
            try
            {
                int NumberOfPages;                      //Total number of pages
                int PageCount;                          //Number of pages for that list
                int PageNumber = CurrentPageNumber;     //The current page number that has been clicked on or the first one.
                int PageListSize = 5;                   //How many page numbers are shown
                int PageListNumber = CurrentPageListNumber;
                int FirstPageListNumber;                //First number in a page list
                int LastPageListNumber;                 //Last number in a page list
                bool AddPrevDots = false;
                bool AddNextDots = false;
                bool AddNextText = false;
                bool AddPrevText = false;

                //Create page DataSet table
                DataSet ds = new DataSet();
                DataTable dt = ds.Tables.Add("PageNumbers");
                dt.Columns.Add("PageNumber", typeof(string));
                dt.Columns.Add("Cmd", typeof(string));
                dt.Columns.Add("IsCurrentPageNumber", typeof(bool));
                dt.Columns.Add("ButtonType", typeof(string));
                dt.Columns.Add("PageListNumber", typeof(int));


                //Convert to double
                double dTotalCount;
                double.TryParse(TotalCount.ToString(), out dTotalCount);
                double dPageSize;
                double.TryParse(PageSize.ToString(), out dPageSize);

                NumberOfPages = (int)Math.Ceiling(dTotalCount / dPageSize);


                //If CurrentPageListNumber = 0 than find what page list number PageNumber is on
                if (PageListNumber == 0)
                {
                    int NumberOfPageLists = (int)Math.Ceiling(((decimal)NumberOfPages) / ((decimal)PageListSize));
                    for (int i = 1; i <= NumberOfPageLists; i++)
                    {
                        int MaxPageListNumber = PageListSize * i;
                        if (PageNumber <= MaxPageListNumber)
                        {
                            PageListNumber = i;
                            break;
                        }
                    }
                }


                //Get first number in page list
                FirstPageListNumber = (PageListNumber * PageListSize) - (PageListSize - 1);

                //Get last number in pages list
                LastPageListNumber = FirstPageListNumber + (PageListSize - 1);

                //Check to see if its beyond the first page list and add Prev. dots if it is.
                //Also check to see of there are more pages ahead of the current page list and add Next dots if there is.
                if (LastPageListNumber > NumberOfPages)
                {
                    PageCount = NumberOfPages - FirstPageListNumber;

                    if (PageListNumber != 1)
                        AddPrevDots = true;
                }
                else
                {
                    PageCount = PageListSize - 1;

                    if (PageListNumber != 1)
                        AddPrevDots = true;

                    if (LastPageListNumber < NumberOfPages)
                        if (NumberOfPages > PageListSize)
                            AddNextDots = true;
                }

                //Check PageNumber to see if page list needs a Prev. or Next button.
                if (PageNumber > 1)
                    AddPrevText = true;
                if (PageNumber < NumberOfPages)
                    AddNextText = true;

                //Build table for current page list
                DataRow dr;

                //Add Prev. text
                if (AddPrevText)
                {
                    dr = dt.NewRow();
                    dr[0] = "&lt;&lt;Prev.";
                    dr[1] = ePager.GetPrevPage.ToString();
                    dr[2] = false;
                    dr[3] = "NavButton";
                    dr[4] = 0;
                    dt.Rows.Add(dr);
                }

                //Add Prev. dots
                if (AddPrevDots)
                {
                    dr = dt.NewRow();
                    dr[0] = "...";
                    dr[1] = ePager.GetPrevPageList.ToString();
                    dr[2] = false;
                    dr[4] = PageListNumber - 1;
                    dt.Rows.Add(dr);
                }

                int PageNumberLabel;
                for (int i = 0; i <= PageCount; i++)
                {
                    dr = dt.NewRow();
                    PageNumberLabel = FirstPageListNumber + i;
                    dr[0] = PageNumberLabel.ToString();
                    dr[1] = ePager.GetPageNumber.ToString();

                    if (PageNumberLabel == CurrentPageNumber)
                        dr[2] = true;
                    else
                        dr[2] = false;

                    dr[4] = PageListNumber;

                    dt.Rows.Add(dr);
                }

                //Add Next dots 
                if (AddNextDots)
                {
                    dr = dt.NewRow();
                    dr[0] = "...";
                    dr[1] = ePager.GetNextPageList.ToString();
                    dr[2] = false;
                    dr[4] = PageListNumber + 1;
                    dt.Rows.Add(dr);
                }

                //Add Prev. text
                if (AddNextText)
                {
                    dr = dt.NewRow();
                    dr[0] = "Next&gt;&gt;";
                    dr[1] = ePager.GetNextPage.ToString();
                    dr[2] = false;
                    dr[3] = "NavButton";
                    dr[4] = 0;
                    dt.Rows.Add(dr);
                }

                //Calculate record range
                if (TotalCount != 0)
                {
                    if (TotalCount != 1)
                    {
                        EndRecordNumber = PageNumber * PageSize;
                        StartRecordNumber = EndRecordNumber - (PageSize - 1);

                        if (EndRecordNumber > TotalCount)
                            EndRecordNumber = TotalCount;
                    }
                    else
                    {
                        EndRecordNumber = 1;
                        StartRecordNumber = 1;
                    }
                }

                return ds;

            }
            catch (Exception ex)
            {
                return null;
            }
        }

This is how its used in the page with a repeater.

<asp:Repeater ID="rpPages1" runat="server">
                    <HeaderTemplate>
                        <div class="PageNumbers">
                        <ul>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <li id='<%#((DataRowView)Container.DataItem)["ButtonType"]%>'>
                            <span id="Span1" visible='<%#((bool)((DataRowView)Container.DataItem)["IsCurrentPageNumber"]) == true%>'
runat="server"><%#(string)((DataRowView)Container.DataItem)["PageNumber"]%></span>
                            <asp:LinkButton ID="Pager" Text='<%#(string)((DataRowView)Container.DataItem)["PageNumber"]%>' CommandName='<%#(string)((DataRowView)Container.DataItem)["Cmd"]%>' CommandArgument='<%#(int)((DataRowView)Container.DataItem)["PageListNumber"]%>' Visible='<%#((bool)((DataRowView)Container.DataItem)["IsCurrentPageNumber"]) == false%>' runat="server" />
                        </li>
                    </ItemTemplate>
                    <FooterTemplate>
                        </ul>
                        </div>
                    </FooterTemplate>
                </asp:Repeater>
Donny V.
A: 

I made a pagination class and put in on Google Code a while ago. Check it out its pretty simple http://code.google.com/p/spaceshipcollaborative/wiki/PHPagination

$paging = new Pagination();
$paging->set('urlscheme','class.pagination.php?page=%page%');
$paging->set('perpage',10);
$paging->set('page',15);
$paging->set('total',3000);
$paging->set('nexttext','Next Page');
$paging->set('prevtext','Previous Page');
$paging->set('focusedclass','selected');
$paging->set('delimiter','');
$paging->set('numlinks',9);
$paging->display();
Jacob
A: 
List<int> pages = new List<int>();
int pn = 2; //example of actual pagenumber
int total = 8;

for(int i = pn - 9; i <= pn + 9; i++)
{
  if(i < 1) continue;
  if(i > total) break;
  pages.Add(i);
}

return pages;enter code here
lazaro