summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2010-11-27 13:30:55 +0100
committerYorhel <git@yorhel.nl>2010-11-27 13:30:55 +0100
commit5f9aea8e9877b71b4372a8fde569367db6bb44e1 (patch)
tree98d12e246f36ad069a5478bcf0de7e559de563b7
parent156a362991ac6922f33e61a08f39f31048310183 (diff)
Replaced old VN advanced options with the new filter selection system
Had to fix some bugs here and there and add some new functionality to the abstractions at some places, but it appears to be working now. There are still a few TODOs left, I'll get to those in a bit.
-rw-r--r--ChangeLog2
-rw-r--r--data/lang.txt67
-rw-r--r--data/script.js94
-rw-r--r--data/style.css25
-rw-r--r--lib/VNDB/DB/VN.pm10
-rw-r--r--lib/VNDB/Func.pm2
-rw-r--r--lib/VNDB/Handler/Releases.pm2
-rw-r--r--lib/VNDB/Handler/VNBrowse.pm112
8 files changed, 131 insertions, 183 deletions
diff --git a/ChangeLog b/ChangeLog
index a03ac50f..fd2d8109 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,5 @@
2.14 - ?
- - Improved release filter selection interface
+ - Improved filter selection interface for the release and VN browser
- New release filters: voiced and animation
- Added Atom feeds for the recent announcements, changes and posts
(located in /www/feeds and updated every 15 min. by Multi::Feed)
diff --git a/data/lang.txt b/data/lang.txt
index 4a37e999..f5fec672 100644
--- a/data/lang.txt
+++ b/data/lang.txt
@@ -5656,19 +5656,19 @@ cs : nenalezeny takové tagy
hu : nem található ilyen címke
nl : tag niet gevonden
-:_vnbrowse_advsearch
-en : advanced search
-ru : расширенный поиск
-cs : pokročilé hledání
-hu : bővített keresés
-nl : geavanceerd zoeken
+:_vnbrowse_fil_title
+en : Visual Novel Filters
+ru*:
+cs*:
+hu*:
+nl :
:_vnbrowse_tags
-en : Tag filters
-ru : Фильтры тегов
-cs : Filtry tagů
-hu : címke szűrők
-nl : Tagfilters
+en : Tags
+ru*:
+cs*:
+hu*:
+nl :
:_vnbrowse_booland
en : boolean and, selecting more gives less results
@@ -5712,40 +5712,19 @@ cs : Ukázat všechny spoilery
hu : Nagyobb spoilerek megjelenítése
nl : Toon alle spoilers
-:_vnbrowse_lang
-en : Languages
-ru : Языки
-cs : Jazyky
-hu : Nyelvek
-nl : Talen
-
-:_vnbrowse_boolor
-en : boolean or, selecting more gives more results
-ru : логическое 'или', чем больше выбрано, тем больше даёт результатов
-cs : boolean nebo, výběr více dá více výsledků
-hu : Boole féle értékhalmaz(igaz/hamis), ha többet választasz ki akkor több találatot ad ki
-nl : booleaanse 'of', meerdere selecties geven meer resultaten
-
-:_vnbrowse_plat
-en : Platforms
-ru : Платформы
-cs : Platformy
-hu : Platformok
-nl : Platformen
+:_vnbrowse_language
+en : Language
+ru*: Языки
+cs*: Jazyky
+hu*: Nyelvek
+nl : Taal
-:_vnbrowse_apply
-en : Apply
-ru : Применить
-cs : Použít
-hu : Alkalmazás
-nl : Toepassen
-
-:_vnbrowse_clear
-en : Clear
-ru : Очистить
-cs : Začít znovu
-hu : Törlés
-nl : Wissen
+:_vnbrowse_platform
+en : Platform
+ru*: Платформы
+cs*: Platformy
+hu*: Platformok
+nl :
# VN add/edit form (/v+/edit)
diff --git a/data/script.js b/data/script.js
index 8cf49e97..2c2e0f6a 100644
--- a/data/script.js
+++ b/data/script.js
@@ -632,7 +632,7 @@ function dsKeyDown(ev) {
if(obj.ds_selectedId != 0)
obj.value = obj.ds_serFunc(byId('ds_box_'+obj.ds_selectedId).ds_itemData, obj);
if(obj.ds_returnFunc)
- obj.ds_returnFunc();
+ obj.ds_returnFunc(obj);
setClass(byId('ds_box'), 'hidden', true);
setContent(byId('ds_box'), tag('b', mt('_js_loading')));
@@ -1728,8 +1728,8 @@ if(byId('prodrelations'))
* Where:
* <title> human-readable title of the filter box
* <category_name> human-readable name of the category. ignored if there's only one category
- * <fieldcode> code of this field, refers to the <field> in the filter format
- * <fieldname> human-readanle name of the field. Empty to not display a label
+ * <fieldcode> code of this field, refers to the <field> in the filter format. Empty string for just a <tr>
+ * <fieldname> human-readanle name of the field. Empty to not display a label. Space for always-enabled items (without checkbox)
* <fieldcontents> tag() object, or an array of tag() objects
* <fieldreadfunc> function reference. argument: <fieldcontents>; must return data to be used in the filter format
* <fieldwritefunc> function reference, argument: <fieldcontents>, data from filter format; must update the contents with the passed data
@@ -1749,7 +1749,7 @@ if(byId('prodrelations'))
var fil_cats; // [ <object with field->tr mapping>, <category-link1>, .. ]
var fil_escape = "_ !\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~".split('');
function filLoad() {
- var l = filReleases();
+ var l = byId('filselect').href.match(/#r$/) ? filReleases() : filVN();
fil_cats = [ new Object ];
var p = tag('p', {'class':'browseopts'});
@@ -1768,13 +1768,14 @@ function filLoad() {
var fd = l[i][j];
var lab = typeof fd[1] == 'object' ? fd[1][0] : fd[1];
var f = tag('tr', {'class':'newfield', fil_code: fd[0], fil_contents: fd[2], fil_readfunc: fd[3], fil_writefunc: fd[4]},
- tag('td', {'class':'check'}, tag('input', {type:'checkbox', id:'fil_check_'+fd[0], name:'fil_check_'+fd[0], onclick: filSelectField })),
+ fd[0] ? tag('td', {'class':'check'}, tag('input', {type:'checkbox', id:'fil_check_'+fd[0], 'class':fd[1]==' '?'hidden':'', name:'fil_check_'+fd[0], onclick: filSelectField })) : tag('td', null),
fd[1] ? tag('td', {'class':'label'},
tag('label', {'for':'fil_check_'+fd[0]}, lab),
typeof fd[1] == 'object' ? tag('b', fd[1][1]) : null
) : null,
tag('td', {'class':'cont' }, fd[2]));
- fil_cats[0][fd[0]] = f;
+ if(fd[0])
+ fil_cats[0][fd[0]] = f;
t.appendChild(f);
}
c.appendChild(t);
@@ -1782,6 +1783,7 @@ function filLoad() {
fil_cats[i] = a;
}
+ // TODO: _rbrowse_ -> generalize (this isn't specific to the release browser)
addBody(tag('div', { id: 'fil_div', 'class':'hidden' },
tag('a', {href:'#', onclick:filShow, 'class':'close'}, mt('_rbrowse_close')),
tag('h3', l[0]),
@@ -1820,6 +1822,8 @@ function filSelectField(obj) {
var c = byId('fil_check_'+o.fil_code);
if(c != t)
c.checked = true;
+ if(hasClass(c, 'hidden'))
+ c.checked = true;
setClass(byName(o, 'label')[0], 'active', c.checked);
// update category link
@@ -1828,7 +1832,7 @@ function filSelectField(obj) {
var l = byName(o, 'input');
var n=0;
for(var i=0; i<l.length; i++)
- if(l[i].type == 'checkbox' && l[i].id.substr(0, 10) == 'fil_check_' && l[i].checked)
+ if(l[i].type == 'checkbox' && l[i].id.substr(0, 10) == 'fil_check_' && !hasClass(l[i], 'hidden') && l[i].checked)
n++;
setClass(fil_cats[o.fil_num], 'active', n>0);
@@ -1839,9 +1843,12 @@ function filSelectField(obj) {
function filSerialize() {
var l = [];
+ var num = 0;
for(var f in fil_cats[0]) {
if(!byId('fil_check_'+f).checked)
continue;
+ if(!hasClass(byId('fil_check_'+f), 'hidden'))
+ num++;
var v = fil_cats[0][f].fil_readfunc(fil_cats[0][f].fil_contents);
var r = [];
for(var h=0; h<v.length; h++) {
@@ -1859,8 +1866,7 @@ function filSerialize() {
l.push(fil_cats[0][f].fil_code+'-'+r.join('~'));
}
byId('fil').value = l.join('.');
- var cnt = byName(byId('filselect'), 'i')[1];
- setText(cnt, l.length > 0 ? ' ('+l.length+')' : '');
+ setText(byName(byId('filselect'), 'i')[1], num > 0 ? ' ('+num+')' : '');
}
function filDeSerialize() {
@@ -1880,7 +1886,7 @@ function filDeSerialize() {
c.checked = f[fn] == '' ? false : true;
var v = f[fn].split('~');
for(var i=0; i<v.length; i++)
- v[i] = v[i].replace(/_([0-9]{2})/g, function (a, e) { return fil_escape[e] });
+ v[i] = v[i].replace(/_([0-9]{2})/g, function (a, e) { return fil_escape[Math.floor(e)] });
fil_cats[0][fn].fil_writefunc(fil_cats[0][fn].fil_contents, v);
// not very efficient: filSelectField() does a lot of things that can be
// batched after all fields have been updated, and in some cases the
@@ -1985,6 +1991,50 @@ function filReleases() {
];
}
+function filVN() {
+ var lang = languages;
+ for(var i=0; i<lang.length; i++) // l10n /_lang_.+/
+ lang[i] = [ lang[i], mt('_lang_'+lang[i]) ];
+ var plat = platforms;
+ for(var i=0; i<plat.length; i++) // l10n /_plat_.+/
+ plat[i] = [ plat[i], mt('_plat_'+plat[i]) ];
+
+ // tag include/exclude dropdown search
+ var taginc = tag('input', {type:'text', 'class':'text', style:'width:350px', onfocus:filSelectField});
+ var tagexc = tag('input', {type:'text', 'class':'text', style:'width:350px', onfocus:filSelectField});
+ var trfunc = function(item, tr) {
+ tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40),
+ item.getAttribute('meta') == 'yes' ? tag('b', {'class': 'grayedout'}, ' '+mt('_js_ds_tag_meta')) : null,
+ item.getAttribute('state') == 0 ? tag('b', {'class': 'grayedout'}, ' '+mt('_js_ds_tag_mod')) : null
+ ));
+ };
+ var serfunc = function(item, obj) {
+ var tags = obj.value.split(/ *, */);
+ tags[tags.length-1] = item.firstChild.nodeValue;
+ filSelectField(obj);
+ return tags.join(', ');
+ };
+ var retfunc = function(o) { filSelectField(o); false };
+ var parfunc = function(val) { return (val.split(/, */))[val.split(/, */).length-1]; };
+ var readfunc = function(c) { return c.value.split(/, */) };
+ var writefunc = function(c,v) { c.value = v.join(', ') };
+ dsInit(taginc, '/xml/tags.xml?q=', trfunc, serfunc, retfunc, parfunc);
+ dsInit(tagexc, '/xml/tags.xml?q=', trfunc, serfunc, retfunc, parfunc);
+
+ return [
+ mt('_vnbrowse_fil_title'),
+ [ mt('_vnbrowse_tags'),
+ [ '', ' ', tag('('+mt('_vnbrowse_booland')+')') ],
+ [ 'taginc', mt('_vnbrowse_taginc'), taginc, readfunc, writefunc ],
+ [ 'tagexc', mt('_vnbrowse_tagexc'), tagexc, readfunc, writefunc ],
+ // TODO: get/set cookie
+ filFSelect('tagspoil', ' ', 1, [[0, mt('_vnbrowse_spoil0')],[1, mt('_vnbrowse_spoil1')],[2, mt('_vnbrowse_spoil2')]])
+ ],
+ [ mt('_vnbrowse_language'), filFSelect('lang', mt('_vnbrowse_language'), 20, lang) ],
+ [ mt('_vnbrowse_platform'), filFSelect('plat', mt('_vnbrowse_platform'), 20, plat) ]
+ ];
+}
+
if(byId('filselect'))
filLoad();
@@ -2035,13 +2085,14 @@ if(byId('advselect')) {
}
// Spoiler filters -> cookie (/v/*)
+/* TODO: unused
if(byId('sp_0')) {
byId('sp_0').onclick = function() { setCookie('tagspoil', 0) };
byId('sp_1').onclick = function() { setCookie('tagspoil', 1) };
byId('sp_2').onclick = function() { setCookie('tagspoil', 2) };
var spoil = getCookie('tagspoil');
byId('sp_'+(spoil == null ? 0 : spoil)).checked = true;
-}
+}*/
// NSFW VN image toggle (/v+)
if(byId('nsfw_show')) {
@@ -2212,27 +2263,6 @@ if(byId('expandprodrel')) {
};
}
-// auto-complete tag search (/v/*)
-if(byId('advselect') && byId('ti')) {
- var trfunc = function(item, tr) {
- tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40),
- item.getAttribute('meta') == 'yes' ? tag('b', {'class': 'grayedout'}, ' '+mt('_js_ds_tag_meta')) : null,
- item.getAttribute('state') == 0 ? tag('b', {'class': 'grayedout'}, ' '+mt('_js_ds_tag_mod')) : null
- ));
- };
- var serfunc = function(item, obj) {
- var tags = obj.value.split(/ *, */);
- tags[tags.length-1] = item.firstChild.nodeValue;
- return tags.join(', ');
- };
- var retfunc = function() { false; };
- var parfunc = function(val) {
- return (val.split(/, */))[val.split(/, */).length-1];
- };
- dsInit(byId('ti'), '/xml/tags.xml?q=', trfunc, serfunc, retfunc, parfunc);
- dsInit(byId('te'), '/xml/tags.xml?q=', trfunc, serfunc, retfunc, parfunc);
-}
-
// Language selector
if(byId('lang_select')) {
var d = byId('lang_select');
diff --git a/data/style.css b/data/style.css
index 243e15e5..b4f3a9ad 100644
--- a/data/style.css
+++ b/data/style.css
@@ -751,6 +751,7 @@ a.addnew {
border-top: none;
background-color: $secbg$;
cursor: pointer;
+ z-index: 2
}
#ds_box b {
padding: 2px 0 0 10px;
@@ -789,35 +790,13 @@ div.scr_uploader { visibility: hidden; overflow: hidden; width: 1px; height: 1px
.vnbrowse .tc3 { padding: 0; }
.vnbrowse .tc5 { text-align: right; padding-right: 10px }
.vnbrowse .tc6 { width: 80px }
-#advselect, #filselect {
+#filselect {
text-align: center;
display: block;
margin: 10px auto 3px auto;
border: none;
outline: none;
}
-#advoptions {
- width: 90%;
- padding: 0 30px 5px 30px;
- margin: 0 auto;
- border-top: 1px solid $border$;
-}
-#advoptions h2 {
- clear: left;
- padding-top: 10px;
- margin-left: -20px;
- margin-top: 0;
- margin-bottom: 3px;
-}
-#advoptions span {
- display: block;
- float: left;
- width: 170px;
-}
-#advoptions span input {
- margin-right: 3px;
-}
-
diff --git a/lib/VNDB/DB/VN.pm b/lib/VNDB/DB/VN.pm
index 6d99ba8a..11b7c29a 100644
--- a/lib/VNDB/DB/VN.pm
+++ b/lib/VNDB/DB/VN.pm
@@ -10,7 +10,7 @@ use Encode 'decode_utf8';
our @EXPORT = qw|dbVNGet dbVNRevisionInsert dbVNImageId dbScreenshotAdd dbScreenshotGet dbScreenshotRandom|;
-# Options: id, rev, char, search, lang, platform, tags_include, tags_exclude, results, page, what, sort, reverse
+# Options: id, rev, char, search, lang, plat, tags_include, tags_exclude, results, page, what, sort, reverse
# What: extended anime relations screenshots relgraph rating ranking changes
# Sort: id rel pop rating title tagscore rand
sub dbVNGet {
@@ -29,10 +29,10 @@ sub dbVNGet {
'LOWER(SUBSTR(vr.title, 1, 1)) = ?' => $o{char} ) : (),
defined $o{char} && !$o{char} ? (
'(ASCII(vr.title) < 97 OR ASCII(vr.title) > 122) AND (ASCII(vr.title) < 65 OR ASCII(vr.title) > 90)' => 1 ) : (),
- $o{lang} && @{$o{lang}} ? (
- 'v.c_languages && ARRAY[!l]::language[]' => [ $o{lang} ]) : (),
- $o{platform} && @{$o{platform}} ? (
- '('.join(' OR ', map "v.c_platforms ILIKE '%%$_%%'", @{$o{platform}}).')' => 1 ) : (),
+ $o{lang} ? (
+ 'v.c_languages && ARRAY[!l]::language[]' => [ ref $o{lang} ? $o{lang} : [$o{lang}] ]) : (),
+ $o{plat} ? (
+ '('.join(' OR ', map "v.c_platforms ILIKE '%%$_%%'", ref $o{plat} ? @{$o{plat}} : $o{plat}).')' => 1 ) : (),
$o{tags_include} && @{$o{tags_include}} ? (
'v.id IN(SELECT vid FROM tags_vn_inherit WHERE tag IN(!l) AND spoiler <= ? GROUP BY vid HAVING COUNT(tag) = ?)',
[ $o{tags_include}[1], $o{tags_include}[0], $#{$o{tags_include}[1]}+1 ]
diff --git a/lib/VNDB/Func.pm b/lib/VNDB/Func.pm
index 11d442f4..65b66f9e 100644
--- a/lib/VNDB/Func.pm
+++ b/lib/VNDB/Func.pm
@@ -13,7 +13,7 @@ our @EXPORT = (@VNDBUtil::EXPORT, qw| liststat clearfloat cssicon tagscore mt mi
# three ways to represent the same information
our $fil_escape = '_ !"#$%&\'()*+,-./:;<=>?@[\]^`{}~';
our @fil_escape = split //, $fil_escape;
-our %fil_escape = map +($fil_escape[$_], $_), 0..$#fil_escape;
+our %fil_escape = map +($fil_escape[$_], sprintf '%02d', $_), 0..$#fil_escape;
# Argument: hashref with rstat and vstat
diff --git a/lib/VNDB/Handler/Releases.pm b/lib/VNDB/Handler/Releases.pm
index 497c96de..cd3ea73c 100644
--- a/lib/VNDB/Handler/Releases.pm
+++ b/lib/VNDB/Handler/Releases.pm
@@ -511,7 +511,7 @@ sub browse {
div class => 'mainbox';
h1 mt '_rbrowse_title';
$self->htmlSearchBox('r', $f->{q});
- a id => 'filselect', href => '#';
+ a id => 'filselect', href => '#r';
lit '<i>&#9656;</i> '.mt('_rbrowse_filters').'<i></i>';
end;
input type => 'hidden', class => 'hidden', name => 'fil', id => 'fil', value => $f->{fil};
diff --git a/lib/VNDB/Handler/VNBrowse.pm b/lib/VNDB/Handler/VNBrowse.pm
index f3193b57..3a8ae7d5 100644
--- a/lib/VNDB/Handler/VNBrowse.pm
+++ b/lib/VNDB/Handler/VNBrowse.pm
@@ -21,14 +21,12 @@ sub list {
{ name => 'p', required => 0, default => 1, template => 'int' },
{ name => 'q', required => 0, default => '' },
{ name => 'sq', required => 0, default => '' },
- { name => 'ln', required => 0, multi => 1, enum => $self->{languages}, default => '' },
- { name => 'pl', required => 0, multi => 1, enum => $self->{platforms}, default => '' },
- { name => 'ti', required => 0, default => '', maxlength => 200 },
- { name => 'te', required => 0, default => '', maxlength => 200 },
- { name => 'sp', required => 0, default => $self->reqCookie($self->{cookie_prefix}.'tagspoil') =~ /^([0-2])$/ ? $1 : 0, enum => [0..2] },
+ { name => 'fil',required => 0, default => '' },
);
return 404 if $f->{_err};
$f->{q} ||= $f->{sq};
+ my $fil = fil_parse $f->{fil}, qw|taginc tagexc tagspoil lang plat|;
+ _fil_compat($self, $fil);
if($f->{q}) {
return $self->resRedirect('/'.$1.$2.(!$3 ? '' : $1 eq 'd' ? '#'.$3 : '.'.$3), 'temp')
@@ -37,9 +35,11 @@ sub list {
# for URL compatibilty with older versions (ugly hack to get English strings)
my @lang;
$f->{q} =~ s/\s*$VNDB::L10N::en::Lexicon{"_lang_$_"}\s*//&&push @lang, $_ for (@{$self->{languages}});
- $f->{ln} = $f->{ln}[0] ? [ @{$f->{ln}}, @lang ] : \@lang;
+ $fil->{lang} = $fil->{lang} ? [ ref($fil->{lang}) ? @{$fil->{lang}} : $fil->{lang}, @lang ] : \@lang;
}
+ $f->{fil} = fil_serialize $fil;
+ # TODO: this should be moved to dbVNGet() in order for savable VN filters to be useful
my @ignored;
my $tagfind = sub {
return map {
@@ -47,10 +47,10 @@ sub list {
push @ignored, [$_, 0] if !$i;
push @ignored, [$_, 1] if $i && $i->{meta};
$i && !$i->{meta} ? $i->{id} : ();
- } grep $_, split /\s*,\s*/, $_[0];
+ } grep $_, ref $_[0] ? @{$_[0]} : ($_[0]||'')
};
- my @ti = $tagfind->($f->{ti});
- my @te = $tagfind->($f->{te});
+ my @ti = $tagfind->(delete $fil->{taginc});
+ my @te = $tagfind->(delete $fil->{tagexc});
$f->{s} = 'title' if !@ti && $f->{s} eq 'tagscore';
$f->{o} = $f->{s} eq 'tagscore' ? 'd' : 'a' if !$f->{o};
@@ -62,28 +62,15 @@ sub list {
results => 50,
page => $f->{p},
sort => $f->{s}, reverse => $f->{o} eq 'd',
- $f->{pl}[0] ? ( platform => $f->{pl} ) : (),
- $f->{ln}[0] ? ( lang => $f->{ln} ) : (),
- @ti ? (tags_include => [ $f->{sp}, \@ti ]) : (),
+ @ti ? (tags_include => [ delete $fil->{tagspoil}, \@ti ]) : (),
@te ? (tags_exclude => \@te) : (),
+ %$fil
);
$self->resRedirect('/v'.$list->[0]{id}, 'temp')
if $f->{q} && @$list == 1 && $f->{p} == 1;
$self->htmlHeader(title => mt('_vnbrowse_title'), search => $f->{q});
- _filters($self, $f, $char, \@ignored);
-
- my $url = "/v/$char?q=$f->{q};ti=$f->{ti};te=$f->{te}";
- $_ and $url .= ";pl=$_" for @{$f->{pl}};
- $_ and $url .= ";ln=$_" for @{$f->{ln}};
- $self->htmlBrowseVN($list, $f, $np, $url, scalar @ti);
- $self->htmlFooter;
-}
-
-
-sub _filters {
- my($self, $f, $char, $ign) = @_;
form action => '/v/all', 'accept-charset' => 'UTF-8', method => 'get';
div class => 'mainbox';
@@ -95,68 +82,41 @@ sub _filters {
}
end;
- if(@$ign) {
+ if(@ignored) {
div class => 'warning';
h2 mt '_vnbrowse_tagign_title';
ul;
- li $_->[0].' ('.mt('_vnbrowse_tagign_'.($_->[1]?'meta':'notfound')).')' for @$ign;
+ li $_->[0].' ('.mt('_vnbrowse_tagign_'.($_->[1]?'meta':'notfound')).')' for @ignored;
end;
end;
}
- a id => 'advselect', href => '#';
- lit '<i>&#9656;</i> '.mt('_vnbrowse_advsearch');
+ a id => 'filselect', href => '#v';
+ lit '<i>&#9656;</i> '.mt('_rbrowse_filters').'<i></i>'; # TODO: it's not *r*browse
end;
- div id => 'advoptions', class => 'hidden vnoptions';
-
- h2;
- txt mt '_vnbrowse_tags';
- b ' ('.mt('_vnbrowse_booland').')';
- end;
- table class => 'formtable', style => 'margin-left: 0';
- $self->htmlFormPart($f, [ input => short => 'ti', name => mt('_vnbrowse_taginc'), width => 350 ]);
- $self->htmlFormPart($f, [ radio => short => 'sp', name => '', options => [map [$_, mt '_vnbrowse_spoil'.$_], 0..2]]);
- $self->htmlFormPart($f, [ input => short => 'te', name => mt('_vnbrowse_tagexc'), width => 350 ]);
- end;
-
- h2;
- txt mt '_vnbrowse_lang';
- b ' ('.mt('_vnbrowse_boolor').')';
- end;
- for my $i (@{$self->{languages}}) {
- span;
- input type => 'checkbox', name => 'ln', value => $i, id => "lang_$i",
- (scalar grep $_ eq $i, @{$f->{ln}}) ? (checked => 'checked') : ();
- label for => "lang_$i";
- cssicon "lang $i", mt "_lang_$i";
- txt mt "_lang_$i";
- end;
- end;
- }
+ input type => 'hidden', class => 'hidden', name => 'fil', id => 'fil', value => $f->{fil};
+ end;
+ end; # /form
- h2;
- txt mt '_vnbrowse_plat';
- b ' ('.mt('_vnbrowse_boolor').')';
- end;
- for my $i (sort @{$self->{platforms}}) {
- next if $i eq 'oth';
- span;
- input type => 'checkbox', id => "plat_$i", name => 'pl', value => $i,
- (scalar grep $_ eq $i, @{$f->{pl}}) ? (checked => 'checked') : ();
- label for => "plat_$i";
- cssicon $i, mt "_plat_$i";
- txt mt "_plat_$i";
- end;
- end;
- }
+ $self->htmlBrowseVN($list, $f, $np, "/v/$char?q=$f->{q};fil=$f->{fil}", scalar @ti);
+ $self->htmlFooter;
+}
- div style => 'text-align: center; clear: left;';
- input type => 'submit', value => mt('_vnbrowse_apply'), class => 'submit';
- input type => 'reset', value => mt('_vnbrowse_clear'), class => 'submit', onclick => 'location.href="/v/all"';
- end;
- end;
- end;
- end;
+
+sub _fil_compat {
+ my($self, $fil) = @_;
+ my $f = $self->formValidate(
+ { name => 'ln', required => 0, multi => 1, enum => $self->{languages}, default => '' },
+ { name => 'pl', required => 0, multi => 1, enum => $self->{platforms}, default => '' },
+ { name => 'ti', required => 0, default => '', maxlength => 200 },
+ { name => 'te', required => 0, default => '', maxlength => 200 },
+ { name => 'sp', required => 0, default => $self->reqCookie($self->{cookie_prefix}.'tagspoil') =~ /^([0-2])$/ ? $1 : 0, enum => [0..2] },
+ );
+ $fil->{lang} //= $f->{ln} if $f->{ln}[0];
+ $fil->{plat} //= $f->{pl} if $f->{pl}[0];
+ $fil->{taginc} //= $f->{ti} if $f->{ti};
+ $fil->{tagexc} //= $f->{te} if $f->{te};
+ $fil->{tagspoil} //= $f->{sp};
}