/* Filter box definition:
* [
,
* [ ,
* [ , , , , , ], ..
* ], ..
* ]
* Where:
* human-readable title of the filter box
* human-readable name of the category. ignored if there's only one category
* code of this field, refers to the in the filter format. Empty string for just a
* human-readanle name of the field. Empty to not display a label. Space for always-enabled items (without checkbox)
* tag() object, or an array of tag() objects
* function reference. argument: ; must return data to be used in the filter format
* function reference, argument: , data from filter format; must update the contents with the passed data
* function reference, argument: , called when the field is displayed
*
* Filter string format:
* -~.-.-~
* Where:
* = [a-z0-9]+
* = [a-zA-Z0-9_]+ and any UTF-8 characters not in the ASCII range
* Escaping of the :
* "_"
* Where is the decimal index to the following array:
* _ ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ ` { | } ~
* For boolean fields, the is either 0 or 1.
*/
var fil_escape = "_ !\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~".split('');
var fil_objs = [];
function getObj(obj) {
while(!obj.fil_fields)
obj = obj.parentNode;
return obj;
}
function filLoad(lnk, serobj) {
var type = lnk.href.match(/#r$/) ? 'r' : lnk.href.match(/#c$/) ? 'c' : lnk.href.match(/#s$/) ? 's' : 'v';
var l = {r: filReleases, c: filChars, s: filStaff, v: filVN}[type]();
var fields = {};
var cats = [];
var p = tag('p', {'class':'browseopts'});
var c = tag('div', null);
var idx = 0;
for(var i=1; i0);
// serialize
serialize(getObj(o));
return true;
}
function escapeVal(val) {
var r = [];
for(var h=0; h 0 ? ' ('+num+')' : '');
}
function deSerialize(obj) {
var d = obj.fil_serobj.value;
var fs = d.split('.');
var f = {};
for(var i=0; iw) x = w;
s.fil_val = min + Math.floor(x*(max-min)/w);
s.childNodes[1].innerHTML = s.fil_val+' '+unit;
s.childNodes[0].childNodes[0].style.left = x+'px';
return false;
}
b.onmousedown = p.onmousedown = function (e) {
curSlider = this.s;
if(!curSlider.oldmousemove) curSlider.oldmousemove = document.onmousemove;
if(!curSlider.oldmouseup) curSlider.oldmouseup = document.onmouseup;
document.onmouseup = function () {
document.onmousemove = curSlider.oldmousemove;
curSlider.oldmousemove = null;
document.onmouseup = curSlider.oldmouseup;
curSlider.oldmouseup = null;
selectField(curSlider);
return false;
}
document.onmousemove = set;
return set(e);
}
return [c, n, s, function (c) { return [ c.fil_val ]; }, set ];
}
function filFSelect(c, n, lines, opts) {
var s = tag('select', {onfocus: selectField, onchange: serialize, multiple: lines > 1, size: lines});
for(var i=0; i 1 ? [ n, 'Boolean or, selecting more gives more results' ] : n, s,
function (c) {
var l = [];
for(var i=0; i li -> ul -> div
var ul = this.parentNode.parentNode;
ul.removeChild(this.parentNode);
selectField(ul.parentNode);
return false
}
}, 'remove'), ')'
));
}
var fetch = function(c) {
var v = c.fil_val;
var ul = byName(c, 'ul')[0];
var txt = byName(c, 'input')[0];
if(v == null)
return;
if(!v[0]) {
setText(ul, '');
txt.disabled = false;
txt.value = '';
return;
}
if(!visible)
setText(ul, '');
var q = [];
for(var i=0; i characters).') ],
] : [ 'Traits',
[ '', ' ', tag('Boolean and, selecting more gives less results') ],
filFTagInput('trait_inc', 'Traits to include', 'trait'),
filFTagInput('trait_exc', 'Traits to exclude', 'trait'),
filFOptions('tagspoil', ' ', [[0, 'Hide spoilers'],[1, 'Show minor spoilers'],[2, 'Spoil me!']]),
],
[ 'Roles', filFSelect('role', 'Roles', 4, VARS.char_roles) ]
];
}
function filReleases() {
var plat = VARS.platforms;
plat.splice(0, 0, [ 'unk', 'Unknown' ]);
var med = VARS.media;
med.splice(0, 0, [ 'unk', 'Unknown' ]);
return [
'Release filters',
[ 'General',
filFOptions('type', 'Release type', VARS.release_types),
filFOptions('patch', 'Patch status', [ [1, 'Patch'], [0, 'Standalone'] ]),
filFOptions('freeware', 'Freeware', [ [1, 'Only freeware'], [0, 'Only non-free releases'] ]),
filFOptions('doujin', 'Doujin', [ [1, 'Only doujin releases'], [0, 'Only commercial releases'] ]),
[ 'date_after', 'Released after', dateLoad(null, selectField), function (c) { return [c.date_val] }, function(o,v) { o.dateSet(v) } ],
[ 'date_before', 'Released before', dateLoad(null, selectField), function (c) { return [c.date_val] }, function(o,v) { o.dateSet(v) } ],
filFOptions('released', 'Release date', [ [1, 'Past (already released)'], [0, 'Future (to be released)'] ])
],
[ 'Age rating', filFSelect('minage', 'Age rating', 15, VARS.age_ratings) ],
[ 'Language', filFSelect('lang', 'Language', 20, VARS.languages) ],
byId('rfilselect') ? null :
[ 'Original language', filFSelect('olang', 'Original language', 20, VARS.languages) ],
[ 'Screen resolution', filFSelect('resolution', 'Screen resolution', 15, VARS.resolutions) ],
[ 'Platform', filFSelect('plat', 'Platform', 20, plat) ],
[ 'Misc',
filFSelect('med', 'Medium', 10, med),
filFSelect('voiced', 'Voiced', 5, VARS.voiced),
filFSelect('ani_story', 'Story animation', 5, VARS.animated),
filFSelect('ani_ero', 'Ero animation', 5, VARS.animated)
]
];
}
function filVN() {
var ontagpage = location.pathname.indexOf('/v/') < 0;
return [
'Visual Novel Filters',
[ 'General',
filFSelect( 'length', 'Length', 6, VARS.vn_lengths),
filFOptions('hasani', 'Anime', [[1, 'Has anime'], [0, 'Does not have anime']]),
filFOptions('hasshot','Screenshots', [[1, 'Has screenshot'],[0, 'Does not have a screenshot']])
],
ontagpage ? [ 'Tags',
[ '', ' ', tag('Additional tag filters are not available on this page. Use the visual novel browser instead (available from the main menu -> visual novels).') ],
] : [ 'Tags',
[ '', ' ', tag('Boolean and, selecting more gives less results') ],
[ '', ' ', byId('pref_code') ? tag('These filters are ignored on tag pages (when set as default).') : null ],
filFTagInput('tag_inc', 'Tags to include', 'tag'),
filFTagInput('tag_exc', 'Tags to exclude', 'tag'),
filFOptions('tagspoil', ' ', [[0, 'Hide spoilers'],[1, 'Show minor spoilers'],[2, 'Spoil me!']])
],
[ 'Language', filFSelect('lang', 'Language', 20, VARS.languages) ],
[ 'Original language', filFSelect('olang','Original language', 20, VARS.languages) ],
[ 'Platform', filFSelect('plat', 'Platform', 20, VARS.platforms) ],
!byId('pref_code') ? null : [
'My lists',
filFOptions('ul_notblack', 'Blacklist', [[1, 'Exclude VNs on my blacklist']]),
filFOptions('ul_onwish', 'Wishlist', [[0, 'Not on my wishlist'],[1, 'On my wishlist']]),
filFOptions('ul_voted', 'Voted', [[0, 'Not voted on'], [1, 'Voted on' ]]),
filFOptions('ul_onlist', 'VN list', [[0, 'Not on my VN list'],[1, 'On my VN list']])
],
];
}
function filStaff() {
var gend = VARS.genders.slice(0, 3);
// Insert seiyuu into the list of roles, before the "staff" role.
var roles = VARS.staff_roles;
roles.splice(-1, 0, ['seiyuu', 'Voice actor']);
return [
'Staff filters',
[ 'General',
filFOptions('truename', 'Names', [[1, 'Primary names only'],[0, 'Include aliases']]),
filFSelect('role', 'Roles', roles.length, roles),
'',
filFSelect('gender', 'Gender', gend.length, gend),
],
[ 'Language', filFSelect('lang', 'Language', 20, VARS.languages) ],
];
}
if(byId('filselect'))
filLoad(byId('filselect'), byId('fil'));
if(byId('rfilselect'))
filLoad(byId('rfilselect'), byId('rfil'));