Permalänk
Medlem

Sidnumreringsutmaning

Jag har lite problem med att printa ut sidnumreringarna. Något som till synes borde vara enkelt har jag fått att bli svårt, speciellt om man vill göra det på ett snyggt sätt.

Syfte
Printa ut länkarna till första två sidorna, fem stycken som omger sidan man är på samt de två sista sidorna, enligt nedanstående:

9 är valda sidan.

1 2 ... 7 8 [9] 10 11 ... 56 67

So far, so easy.

Sen kommer specialfallen när man väljer t.ex. sida [3], då ska det fortfarande visas fem "mellanlänkar" som följande.

1 2 [3] 4 5 6 7 ... 56 57

Och samma sak åt andra hållet...

1 2 ... 51 52 53 54 [55] 56 57

Sen är det ännu ett specialfall.

När sidan bara har två sidor; ska den inte printa ut två första och två sista eftersom det då blir: 1 2 1 2.

Är det bara en sida, ska den förstås inte skriva ut de två första sidorna, utan bara en sida.

Det finns säkert någon som löst detta på ett elegant sätt tidigare, men jag hittar bara källkodsexempel på folk som löst det så att alla sidorna skrivs ut, men min hjärna står stilla just nu. Enda lösningen jag ser är en fullösning med ett gäng iffar.

Vad säger ni?

Visa signatur

Let me tell you something. You don't have to say anything, you know why? Cause you can pick up all your stuff, because you're mother-fucking fired! | Lemeno.se - En blogg om att Tjäna Pengar På Internet | Min blogg om styrketräning och kost

Permalänk
Hedersmedlem

Är det något fel på if-satser?

Permalänk
Medlem

Nej, absolut inte.

Men när jag skrev koden såg den betydligt otympligare ut än det kändes att den borde vara.

Visa signatur

Let me tell you something. You don't have to say anything, you know why? Cause you can pick up all your stuff, because you're mother-fucking fired! | Lemeno.se - En blogg om att Tjäna Pengar På Internet | Min blogg om styrketräning och kost

Permalänk
Medlem

Här kommer en lösning i C# kod, som är ganska dynamisk om du vill ändra antalet sidor runt om och i början/slutet du vill printa.

Om det är några frågor så hojta till bara.

int numbersOfPagesAroundCurrentPage = 5; int numbersOfPagesAtStartAndEnd = 2; int currentPage = 55; int maxPages = 57; //Printar dom första (2) sidorna for (int i = 1; i <= numbersOfPagesAtStartAndEnd && i != currentPage; i++) { Print(i); } //Printar de (5) sidorna innan den sidan du är på for (int i = currentPage - numbersOfPagesAroundCurrentPage; i < currentPage && i > numbersOfPagesAtStartAndEnd; i++) { Print(i); } //Printar den sidan du är på PrintCurrentPage(currentPage); //printar de (5) sidorna efter den sidan du är på for (int i = currentPage + 1; i < currentPage + numbersOfPagesAroundCurrentPage + 1 && i < maxPages - numbersOfPagesAtStartAndEnd; i++) { Print(i); } //printar de sista (2) sidorna for (int i = maxPages - numbersOfPagesAtStartAndEnd + 1; i <= maxPages; i++) { Print(i); }

Permalänk
Medlem

Tjao.

I ditt exempel:

Om det är 1 sida, kommer det printas ut två sidor.

De två looparna skulle kunna bytas ut mot

for (i=(currentPage-2); i!=(currentPage+2); i++)
{
if (currentPage==i)
print sida[i]

else
print sida i

Edit: Exemplet tar inte heller hänsyn till tidigare utskrivna rader. Om sidan är 3 t.ex. så kommer det skrivas ut

1 2 1 2 3 4 5 osv

Visa signatur

Let me tell you something. You don't have to say anything, you know why? Cause you can pick up all your stuff, because you're mother-fucking fired! | Lemeno.se - En blogg om att Tjäna Pengar På Internet | Min blogg om styrketräning och kost

Permalänk
Medlem

Xenarion nu skall det vara uppdaterat för det me

Litet lustigt problem, man vill ju lösa det snyggt och det skall vara lätt att ändra, sen finns det ju sjukt många undantag

Permalänk
Medlem

Kolla min post ovan

Utöver det, genom att titta på din kod känns det som att om man är på t.ex. sida 3 och NumbersAround är 5 så blir i's startvärde -2.

Visa signatur

Let me tell you something. You don't have to say anything, you know why? Cause you can pick up all your stuff, because you're mother-fucking fired! | Lemeno.se - En blogg om att Tjäna Pengar På Internet | Min blogg om styrketräning och kost

Permalänk
Medlem

i > numbersOfPagesAtStartAndEnd

Löser det

Btw din ger dock det problemet:
-2 -1 0 1 2 [3] 4 5 6 7

Permalänk
Medlem

Lustigt att du säger det, för när jag prövar med max pages 3 och current page 1 så får jag upp till -4

Visa signatur

Let me tell you something. You don't have to say anything, you know why? Cause you can pick up all your stuff, because you're mother-fucking fired! | Lemeno.se - En blogg om att Tjäna Pengar På Internet | Min blogg om styrketräning och kost

Permalänk
Medlem

Max pages 3 och current page 1 ger mig

[1] 2 3

med ovanstånde kod, btw du har sätt att den är uppdaterad va?

Permalänk

Här följer mitt försök, påminner en del om lösningen ovan antar jag men det var ett kul problem så jag ville prova att lösa det på egen hand.

Har inte testat lösningen ordentligt så det finns risk för buggar...

#include <iostream> #include <cassert> using namespace std; enum { LINK_DEFAULT, LINK_FIRST, LINK_LAST, LINK_NEXT, LINK_PREV, LINK_SELECTED }; void emitSeparator() { cout << " ... "; } void emitPageLink(int page, int type = LINK_DEFAULT) { cout << " "; switch(type) { case LINK_DEFAULT: cout << page; break; case LINK_FIRST: cout << "first"; break; case LINK_LAST: cout << "last"; break; case LINK_NEXT: cout << "| next"; break; case LINK_PREV: cout << "prev |"; break; case LINK_SELECTED: cout << "[" << page << "]"; break; default: assert(0); } cout << " "; } void makePageFooter(int firstPage, int currentPage, int lastPage, int numToWrap, int numAtEnds) { assert(firstPage > 0); assert(lastPage >= firstPage); assert(currentPage >= firstPage && currentPage <= lastPage); assert(numToWrap > 0); assert(numAtEnds > 0); if (currentPage > firstPage) { if ((currentPage - 1) != firstPage) emitPageLink(firstPage, LINK_FIRST); emitPageLink(currentPage - 1, LINK_PREV); } if( (firstPage + numAtEnds - 1) < (currentPage - numToWrap) ) { for ( int i = 0; i < numAtEnds; i++ ) emitPageLink(firstPage + i); emitSeparator(); } int wrapBegin = max(firstPage, currentPage - numToWrap); for(int i = wrapBegin; i < currentPage; i++) emitPageLink(i); emitPageLink(currentPage, LINK_SELECTED); int wrapEnd = min(lastPage, currentPage + numToWrap); for (int i = currentPage + 1; i <= wrapEnd; i++) emitPageLink(i); if ( (lastPage - numAtEnds + 1) > (currentPage + numToWrap) ) { emitSeparator(); for ( int i = numAtEnds; i > 0 ; i-- ) emitPageLink(lastPage - i + 1); } if (currentPage < lastPage) { emitPageLink(currentPage + 1, LINK_NEXT); if ((currentPage + 1) != lastPage ) emitPageLink(lastPage, LINK_LAST); } } int main(int argc, char* argv[]) { makePageFooter(1, 5, 10, 1, 2); return 0; }

Permalänk
Medlem

function paginate( $url_start, $url_end, $pages, $page, $padding_ends, $padding_middle ) { $str = '<div class="gbpager">'; $str .= ( $page > 1 ) ? '<a href="' . format_url( $url_start . ( $page - 1 ) . $url_end ) . '">←</a>' : '<span class="nolink">←</span>'; for( $i = 1; $i <= $pages; $i++ ) { if( $i <= $padding_ends || $i > $pages - $padding_ends || ( $i > $page - $padding_middle && $i < $page + $padding_middle ) ) { if( $i == $page ) $str .= '<span class="nolink">' . $i . '</span>'; else $str .= '<a href="' . format_url( $url_start . $i . $url_end ) . '">' . $i . '</a>'; } else { $str .= '.'; } } $str = preg_replace( '/(?<=\>)(\.+)((?=\<))/', '...', $str ); $str .= ( $page < $pages ) ? '<a href="' . format_url( $url_start . ( $page + 1 ) . $url_end ) . '">→</a>' : '<span class="nolink">→</span>'; $str .= '</div>'; return $str; }

I ditt fall skulle anropet se ut något i stil med:

paginate( 'index.php?page=', '', $total_amount_of_pages, $current_page, 2, 2 );

Permalänk

Här är min version. Det blev Python, men som den är skriven är det inga problem att porta till valfritt språk. Dessutom skriver den bara ut siffrorna, men det är ju inte heller några problem att fixa till.
Jag måste säga att det var ett roligt problem att lösa.

def pageNumbering(currPage, numPages): startPage = 1 endPage = numPages toShowInBeg = 2 toShowInEnd = 2 onEachSide = 2 outstr = '' leftSide = currPage-onEachSide rightSide = currPage+onEachSide rightSide +=max(0, startPage-leftSide) leftSide -= max(0, rightSide-endPage) rightSide = max(currPage, min(endPage, rightSide)) leftSide = max(startPage, min(currPage, leftSide)) lastOfBeg = min(toShowInBeg+1, leftSide) for i in range(1, lastOfBeg): #motsvarar for(i=1;i<lastOfBeg;i++) i C/C++/Java osv outstr += str(i) + ' ' if lastOfBeg < leftSide: outstr += '... ' for i in range(leftSide, currPage): outstr += str(i) + ' ' outstr+= '[' + str(currPage) + '] ' for i in range(currPage+1, rightSide+1): outstr += str(i) + ' ' if rightSide < numPages - toShowInEnd: outstr += '... ' firstOfEnd = max(numPages - toShowInEnd, rightSide) + 1 for i in range(firstOfEnd, numPages+1): outstr += str(i) + ' ' return outstr[:-1 ] #Ta bort det sista mellanslaget som alltid genererats.