Domanda

I am trying to create some pagination on the latest news section of my site. I've managed to actually get the page navigation working so that each page is output at the bottom of the screen along with next and previous buttons however, I also want to try and reduce the size of the pagination field when we have a large number of pages overall. With this in mind I want to try and mimic the following behaviour:

When the total number of pages is less than 7, output the pagination as:

    <Previous> 1 2 3 4 5 6 7 <Next>

However, if the total number of pages is not less than 7, output only the first 2
pages, the last 2 pages and the 2 pages either side of the current page as well
as the link for the current page. In place of the missing page, there should be
a single ...

I've managed to get some way towards this behavour using the following code:

@if (totalPages > 1){
  <ul class="pager">
    @if (page > 1){
      <li><a href="?page=@(page-1)">Previous</a></li>
    }
    @for (int p = 1; p < totalPages + 1; p++){
      var linkClass = (p == page) ? "disabled" : "active";
      if ((p >= page - 2 && p <= page + 2 || p <= 2 || p >= totalPages -2) 
          || totalPages <= 7){
            <li class="@Html.Raw(linkClass)">
              <a href="?page=@p">@p</a>
            </li>
      }          
    }

    @if (page < totalPages){
        <li><a href="?page=@(page+1)">Next</a></li>
    }
  </ul>
}

However, the main part I am now struggling with is how to output a single ... in the place of the pages that do not match the criteria. I can easily output multiple ... using an else criteria on the if condition but this is not the behaviour I am looking for.

Any help would be greatly appreciated.

È stato utile?

Soluzione

With a slight rephrase, the rules you mentioned become easier to understand.

The following ruleset is equivalent:

Any page number that is either the 
    first, 
    second, 
    second before current, 
    first before current, 
    current, 
    first after current, 
    second after current, 
    second to last, 
    or last page  
should be displayed. Any other page should be an ellipsis.

Worked out in code, this becomes:

//Note: I'm addressing the pages as a 1-based index. 
//If 0-based is needed, just add -1 to all index values

bool previousPageIsEllipsis = false;

for(int i = 1; i <= totalpages; i++)
{
    if(i == currentpage) {
        //Print current page number

        previousPageIsEllipsis = false;
    }
    else
    {
        if( i == 1
            || i == 2
            || i == currentpage - 2
            || i == currentpage - 1
            || i == currentpage + 1
            || i == currentpage + 2
            || i == totalpages - 1
            || i == totalpages)
        {
            //Print a visible link button

            previousPageIsEllipsis = false;
        }
        else
        {
            if(previousPageIsEllipsis)
            {
                //an ellipsis was already added. Do not add it again. Do nothing.
                continue;
            }
            else
            {
                //Print an ellipsis
                previousPageIsEllipsis = true;
            }
        }
    }
}

I did not add the actual code, because you have that already. But here, you see there are three options: either show the page, show an ellipsis, or show nothing new if the previous element is already an ellipsis.

Just insert the needed HTML output on the //comment lines and you should be good to go :)

Note: I made a 4th option (for the current page), because you generally want to render that as a non-clickable item.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top