package MasterWebInterface::Util::BrowseHTML; use strict; use warnings; use utf8; use TUWF ':html', 'xml_escape'; use Exporter 'import'; use POSIX 'ceil'; our @EXPORT = qw| htmlSearchBox htmlBrowse htmlBrowseNavigate |; # generates a search box, arguments: # title => games/ (game) servers # action => form action # sel => g or s selected # fq => form query string sub htmlSearchBox { my($self, %opt) = @_; div class => 'mainbox'; div class => "header"; h1 "Browse $opt{title}"; p class => "alttitle", "An overview of games titles and servers that are currently online."; end; # search box form action => $opt{action}, 'accept-charset' => 'UTF-8', method => 'get'; fieldset class => 'search'; a href => '/g', $opt{sel} eq 'g' ? (class => 'sel') : (), 'Games'; a href => '/s', $opt{sel} eq 's' ? (class => 'sel') : (), 'Servers'; input type => 'text', name => 'q', id => 'q', class => 'text', value => $opt{fq} || 'search...'; input type => 'submit', class => 'submit', value => 'submit'; end 'fieldset'; div class => "dropdown"; a href => "#", onclick => "toggleAdvanced()"; txt "advanced search "; lit "\x{25BE}"; end; end; fieldset id => 'advancedsearch'; #input type => 'text', name => 'aq', class => 'text', value => ''; #input type => 'submit', class => 'submit', value => 'submit'; txt "Patience, young one. With time, advanced search options will become available to you."; end; end; end 'div'; # mainbox } # generates a browse box, arguments: # items => arrayref with the list items # options => hashref containing at least the keys s (sort key), o (order) and p (page) # nextpage => whether there's a next page or not # sorturl => base URL to append the sort options to (if there are any sortable columns) # pageurl => base URL to append the page option to # class => classname of the mainbox # header => # can be either an arrayref or subroutine reference, # in the case of a subroutine, it will be called when the header should be written, # in the case of an arrayref, the array should contain the header items. Each item # can again be either an arrayref or subroutine ref. The arrayref would consist of # two elements: the name of the header, and the name of the sorting column if it can # be sorted # row => subroutine ref, which is called for each item in $list, arguments will be # $self, $item_number (starting from 0), $item_value # footer => subroutine ref, called after all rows have been processed # Mostly written by Yorhel --> https://g.blicky.net/vndb.git/tree/COPYING sub htmlBrowse { my($self, %opt) = @_; # get options $opt{sorturl} .= $opt{sorturl} =~ /\?/ ? ';' : '?' if $opt{sorturl}; # top navigation $self->htmlBrowseNavigate($opt{pageurl}, $opt{options}{p}, $opt{nextpage}, 't') if $opt{pageurl}; div class => 'mainbox browse'.($opt{class} ? ' '.$opt{class} : ''); table class => 'stripe'; # header thead; Tr; if(ref $opt{header} eq 'CODE') { $opt{header}->($self); } else { for(0..$#{$opt{header}}) { if(ref $opt{header}[$_] eq 'CODE') { $opt{header}[$_]->($self, $_+1); } elsif ($opt{simple}) { td class => $opt{header}[$_][3]||'tc'.($_+1), $opt{header}[$_][2] ? (colspan => $opt{header}[$_][2]) : (); if($opt{header}[$_][1]) { lit qq|$opt{header}[$_][0]|; } else { txt $opt{header}[$_][0]; } end; } else { td class => $opt{header}[$_][3]||'tc'.($_+1), $opt{header}[$_][2] ? (colspan => $opt{header}[$_][2]) : (); if ( $opt{options}{s} eq $opt{header}[$_][1] ) { # active sort if ( $opt{options}{o} eq 'a' ) { a href => "$opt{sorturl}o=d;s=$opt{header}[$_][1]"; lit $opt{header}[$_][0]; lit " \x{25B4}"; end; } else { # eq 'd' a href => "$opt{sorturl}o=a;s=$opt{header}[$_][1]"; lit $opt{header}[$_][0]; lit " \x{25BE}"; end; } } else { # passive sort options a href => "$opt{sorturl}o=d;s=$opt{header}[$_][1]"; lit $opt{header}[$_][0]; end; } end; } } } end; end 'thead'; # footer if($opt{footer}) { tfoot; $opt{footer}->($self); end; } # rows $opt{row}->($self, $_+1, $opt{items}[$_]) for 0..$#{$opt{items}}; end 'table'; end 'div'; # bottom navigation $self->htmlBrowseNavigate($opt{pageurl}, $opt{options}{p}, $opt{nextpage}, 'b') if $opt{pageurl}; } # creates next/previous buttons (tabs), if needed # Arguments: page url, current page (1..n), nextpage (0/1 or [$total, $perpage]), alignment (t/b), noappend (0/1) # Mostly written by Yorhel --> https://g.blicky.net/vndb.git/tree/COPYING sub htmlBrowseNavigate { my($self, $url, $p, $np, $al, $na) = @_; my($cnt, $pp) = ref($np) ? @$np : ($p+$np, 1); return if $p == 1 && $cnt <= $pp; $url .= $url =~ /\?/ ? ';p=' : '?p=' unless $na; my $tab = sub { my($left, $page, $label) = @_; li $left ? (class => 'left') : (); a href => $url.$page; lit $label; end; end; }; my $ell = sub { li class => 'ellipsis'.(shift() ? ' left' : ''); b '⋯'; end; }; my $nc = 5; # max. number of buttons on each side ul class => 'maintabs browsetabs ' . ($al eq 't' ? 'notfirst' : 'bottom'); $p > $nc and ref $np and $tab->(1, 1, '« first'); $p > $nc and ref $np and $ell->(1); $p > $_ and ref $np and $tab->(1, $p-$_, $p-$_) for (reverse 1..($nc>$p-1?$p-1:$nc-1)); $p > 1 and $tab->(1, $p-1, '‹ previous'); my $l = ceil($cnt/$pp)-$p+1; $l > $nc and $tab->(0, $l+$p-1, ('last').' »'); $l > $nc and $ell->(0); $l > $_ and $tab->(0, $p+$_, $p+$_) for (reverse 1..($nc>$l-1?$l-1:$nc-1)); $l > 1 and $tab->(0, $p+1, ('next').' ›'); end 'ul'; } 1;