Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Objective: Get images to print 20 per page in a specific order.

Success: The first page prints in order I specify nicely (it prints the 20 newest images stored into the database).

Failure: When you reach over 20 images and you use the url_param, the images on this new page aren't in the right order.

Example: If I have 23 images, I'd type in script.pl?page=2 and it SHOULD print the first three images (but it doesn't).

Can someone check the math to see if I'm going about it correctly?

my $page = url_param('page'); my $top = -($page * 20); my $bottom = $top + 19; if ($page ne "") { for ( grep defined($_), ( reverse keys %upload )[ $top .. $bottom ] ) +{

Replies are listed 'Best First'.
Re: math mistake?
by sulfericacid (Deacon) on Jul 27, 2003 at 07:57 UTC
    I think you might be the first person I ever get to help! I just encountered a similar problem to this..

    If you want page 2, 3.. to print the FIRST images, then you shouldn't be using -($page * 20). This will give you a negative number, right? If you reverse the keys, you're already using -19 .. -1. You need to use a positive equation. Try

    my $top = $page * 19; my $bottom = $top - 19;
    It's 3AM, hopefully this works.

    "Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

    sulfericacid

Re: math mistake?
by blokhead (Monsignor) on Jul 27, 2003 at 08:17 UTC
    sulfericacid is right, there's no reason to use negative indices to do this; you start counting page numbers from the beginning of the array anyway, and it's not too tough to calculate the start and end indices of the range. Here's some pagination code I use in my photo album software, which correctly handles all edge cases I could think of at the time I wrote it:
    use POSIX 'ceil'; my @things = 1 .. 42; my $per_page = 20; my $num_pages = ceil( @things / $per_page ); my $page = param('page') || 1; ## verify page num is within range $page = 1 if $page < 1; $page = $num_pages if $page > $num_pages; my $first = ($page-1) * $per_page; my $last = $first + $per_page - 1; $last = $#things if $last > $#things; print @things[ $first .. $last ];
    I also at least 2 odd things about this line:
    for ( grep defined($_), ( reverse keys %upload )[ $top .. $bottom ] ) +{
    1: You're using the keys of a hash to paginate. This is a very bad idea. When you add something to the hash, the ordering of keys %upload can change. To make things worse, in the newest (and all future) versions of Perl, the ordering of keys will completely change between program instances, even if the data hasn't changed. This would make your pagination useless, as you would basically get a random page of 20 things each time, no matter what page number you give to your CGI script. Use an array of things, or else sort the hash keys to make the ordering consistent between datasets and program instances.

    2: Why do you have grep defined($_) ?? Are you expecting an undef hash key? Did you really mean grep exists $upload{$_} instead?

    HTH

    blokhead

Re: math mistake?
by vbrtrmn (Pilgrim) on Jul 27, 2003 at 08:53 UTC

    I use this for a guestbook, the data is sent via get with a simple link.

    # number of rows in db, this is actually pulled from the # database, i'll just do 1000 here. my $termNUM = 1000; my $numberset = param('value'); # if no value is passed or if someone passes 0 # this sets it to 1 if ($numberset eq "") { $numberset = 1; } elsif ($numberset eq 0) { $numberset = 1; } $origNUM = $termNUM - 25; # 25 is the entries i want to view per page $termNUM = $rowNUM - (($numberset - 1) * 26); # 26 is the entries plus 1, i guess i could have set a variable, but i +'m lazy

    to generate the links, i use a subroutine:

    sub Test25 { if ($termNUM < $rowNUM) { print "<div style=\"text-align: left; float: left;\"><a href=\"?va +lue=".($numberset - 1)."\">View Previous 25 Entries</a></div>\n"; } if ($origNUM > 1) { print "<div style=\"text-align: right; float: right;\"><a href=\"? +value=".($numberset + 1)."\">View Next 25 Entries</a></div><BR>\n"; } }

    you'll have to modify this a bit for your own use.

    --
    paul

      my $numberset = param('value'); if ($numberset eq "") { $numberset = 1; } elsif ($numberset eq 0) { $numberset = 1; }

      Rather than testing for string emptiness and numerical zero, you could change the above snippet to one simple line. It will catch undefined, empty string, or number zero:

      my $numberset = param('value') || 1;


      If the above content is missing any vital points or you feel that any of the information is misleading, incorrect or irrelevant, please feel free to downvote the post. At the same time, please reply to this node or /msg me to inform me as to what is wrong with the post, so that I may update the node to the best of my ability.