summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2020-04-24 16:00:28 +0200
committerYorhel <git@yorhel.nl>2020-04-24 16:00:34 +0200
commit493866f8114dc785433e401b4e3203516be9f71b (patch)
treee71aad73b32e0fa909d0866cdf374c574b19cb11
parent935d17e532e8d382e4db22f197a5f53a4cc94f98 (diff)
v2rw/VN::Page: Remove old and unused code
There's a lot of unused code in VNDB::DB::{VN,Release} still, but I'll not fiddle with that for now.
-rw-r--r--data/js/charops.js88
-rw-r--r--data/js/main.js3
-rw-r--r--data/js/misc.js223
-rw-r--r--data/js/polls.js21
-rw-r--r--data/js/vnreldropdown.js36
-rw-r--r--lib/VNDB/DB/ULists.pm77
-rw-r--r--lib/VNDB/Handler/Chars.pm28
-rw-r--r--lib/VNDB/Handler/ULists.pm51
-rw-r--r--lib/VNDB/Handler/VNPage.pm717
-rw-r--r--lib/VNDB/Util/CommonHTML.pm84
10 files changed, 3 insertions, 1325 deletions
diff --git a/data/js/charops.js b/data/js/charops.js
deleted file mode 100644
index 9478ca95..00000000
--- a/data/js/charops.js
+++ /dev/null
@@ -1,88 +0,0 @@
-var spoil, sexual, t;
-
-
-// Fixes the commas between trait names and the hidden status of the entire row
-function fixrow(c) {
- var l = byName(byName(c, 'td')[1], 'span');
- var first = 1;
- for(var i=0; i<l.length; i++)
- if(!hasClass(l[i], 'ishidden')) {
- first = 0;
- break;
- }
- setClass(c, 'hidden', first);
-}
-
-
-function restripe() {
- for(var i=0; i<t.length; i++) {
- var b = byName(t[i], 'tbody');
- if(!b.length)
- continue;
- setClass(t[i], 'stripe', false);
- var r = 1;
- var rows = byName(b[0], 'tr');
- for(var j=0; j<rows.length; j++) {
- if(hasClass(rows[j], 'traitrow'))
- fixrow(rows[j]);
- if(!hasClass(rows[j], 'nostripe') && !hasClass(rows[j], 'hidden'))
- setClass(rows[j], 'odd', r++&1);
- }
- }
-}
-
-
-function setall() {
- var k = byClass('charspoil');
- for(var i=0; i<k.length; i++)
- setClass(k[i], 'ishidden',
- !sexual && hasClass(k[i], 'sexual') ? true :
- hasClass(k[i], 'charspoil_0') ? false :
- hasClass(k[i], 'charspoil_-1') ? spoil > 1 :
- hasClass(k[i], 'charspoil_1') ? spoil < 1 : spoil < 2);
-
- if(k.length)
- restripe();
- return false;
-}
-
-
-function init() {
- var opsParent = byId('charops');
- if(!opsParent)
- return;
-
- t = byClass('table', 'stripe');
-
- // Spoiler level
- for(var i=0; i<3; i++) {
- var splChk = byClass(opsParent, 'radio_spoil' + i)[0];
- if(!splChk)
- continue;
-
- splChk.num = i;
- splChk.onchange = function() {
- spoil = this.num;
- return setall();
- };
- if(splChk.checked)
- spoil = i;
- };
-
- // Sexual toggle
- var sexChk = byClass(opsParent, 'sexual_check');
- if(sexChk.length) {
- sexChk = sexChk[0]
-
- sexChk.onchange = function() {
- sexual = !sexual;
- return setall();
- };
- sexual = sexChk.checked;
- }
- setall();
-}
-
-
-if(byId('charops'))
- init();
diff --git a/data/js/main.js b/data/js/main.js
index fdb6a813..042c18e8 100644
--- a/data/js/main.js
+++ b/data/js/main.js
@@ -27,11 +27,8 @@ VARS = /*VARS*/;
//include tabs.js
// Page/functionality-specific widgets
-//include vnreldropdown.js
-//include charops.js
//include filter.js
//include misc.js
-//include polls.js
// VN editing (/v+/edit)
//include vnrel.js
diff --git a/data/js/misc.js b/data/js/misc.js
index ccacd0ee..9c151eae 100644
--- a/data/js/misc.js
+++ b/data/js/misc.js
@@ -1,226 +1,3 @@
-function ulist_redirect(type, path, formcode, args) {
- var r = new RegExp('/('+type+'[0-9]+).*$');
- location.href = location.href.replace(r, '/$1')+path
- +'?formcode='+formcode
- +';ref='+encodeURIComponent(location.pathname+location.search)
- +';'+args;
-}
-
-
-function vote_validate(s) {
- if(s < 1)
- s = prompt('Please input your vote as a number between 1 and 10. One digit after the decimal is allowed, for example: 8.6 or 7.3.', '');
- if(!s)
- return 0;
- s = s.replace(',', '.');
- if(!s.match(/^([1-9]|10)([\.,][0-9])?$/) || s > 10 || s < 1) {
- alert('Invalid number.');
- return 0;
- }
- if(s == 1 && !confirm('You are about to give this visual novel a 1 out of 10.'+
- ' This is a rather extreme rating, meaning this game has absolutely nothing to offer, and that it\'s the worst game you have ever played.'+
- ' Are you really sure this visual novel matches that description?'))
- return 0;
- if(s == 10 && !confirm('You are about to give this visual novel a 10 out of 10.'+
- ' This is a rather extreme rating, meaning this is one of the best visual novels you\'ve ever played and it\'s unlikely that any other game could ever be better than this one.'+
- ' It is generally a bad idea to have more than three games in your vote list with this rating, choose carefully!'))
- return 0;
- return s;
-}
-
-
-// VN Voting (/v+)
-if(byId('votesel'))
- byId('votesel').onchange = function() {
- var s = this.options[this.selectedIndex].value;
- if(s == -3)
- return;
- if(s != -1)
- s = vote_validate(s);
- if(!s)
- this.selectedIndex = 0;
- else
- ulist_redirect('v', '/vote', this.name, 'v='+s);
- };
-
-
-// VN voting from list (/u+/votes)
-if(byId('batchvotes'))
- byId('batchvotes').onchange = function() {
- var s = this.options[this.selectedIndex].value;
- if(s == -2)
- return;
- if(s != -1)
- s = vote_validate(s);
- if(!s) {
- this.selectedIndex = 0;
- return;
- }
- this.options[this.selectedIndex].value = s;
- var frm = this;
- while(frm.nodeName.toLowerCase() != 'form')
- frm = frm.parentNode;
- frm.submit();
- };
-
-
-// VN Wishlist dropdown box (/v+)
-if(byId('wishsel'))
- byId('wishsel').onchange = function() {
- if(this.selectedIndex != 0)
- ulist_redirect('v', '/wish', this.name, ';s='+this.options[this.selectedIndex].value);
- };
-
-
-// 'more' / 'less' summarization of some boxes on VN pages
-(function(){
- function set(o, h) {
- var a = tag('a', {href:'#', summarizeOn:false}, '');
- var toggle = function() {
- a.summarizeOn = !a.summarizeOn;
- o.style.maxHeight = a.summarizeOn ? h+'px' : null;
- o.style.overflowY = a.summarizeOn ? 'hidden' : null;
- setText(a, a.summarizeOn ? '⇓ more ⇓' : '⇑ less ⇑');
- return false;
- };
- a.onclick = toggle;
- var t = tag('div', {'class':'summarize_more'}, a);
- l[i].parentNode.insertBefore(t, l[i].nextSibling);
- toggle();
- }
-
- var l = byClass(document, 'summarize');
-
- for(var i=0; i<l.length; i++) {
- var h = Math.floor(l[i].getAttribute('data-summarize-height') || 150);
- if(l[i].offsetHeight > h+100)
- set(l[i], h);
- }
-})();
-
-
-// make some fields readonly when patch flag is set and hide uncensored
-// checkbox when age rating isn't 18+ (/r+/edit)
-(function(){
- function sync() {
- byId('doujin').disabled =
- byId('resolution').disabled =
- byId('voiced').disabled =
- byId('ani_story').disabled =
- byId('ani_ero').disabled =
- byId('engine').disabled =
- byId('engine_oth').disabled =
- byId('patch').checked;
-
- setClass(
- byId('uncensored').parentNode.parentNode,
- 'hidden',
- byId('minage').options[byId('minage').selectedIndex].value != 18
- );
- };
- if(byId('jt_box_rel_geninfo')) {
- sync();
- byId('patch').onclick = byId('minage').onclick = sync;
- }
-})();
-
-
-// Release edit engine selection (/r+/edit)
-(function(){
- var en = byId('engine');
- var en_other = byId('engine_oth');
- if(en && en_other) {
- en.onchange = function() {
- setClass(en_other, 'hidden', en.options[en.selectedIndex].value != '_other_');
- return true;
- };
- }
-})();
-
-
-// Batch edit dropdown box (/u+/wish)
-if(byId('batchedit'))
- byId('batchedit').onchange = function() {
- if(this.selectedIndex == 0)
- return true;
- var frm = this;
- while(frm.nodeName.toLowerCase() != 'form')
- frm = frm.parentNode;
- frm.submit();
- };
-
-
-// collapse/expand row groups (/u+/list)
-(function(){
- var table = byId('expandall');
- if(!table)
- return;
- while(table.nodeName.toLowerCase() != 'table')
- table = table.parentNode;
- var heads = byClass(table, 'td', 'collapse_but');
- var allhid = false;
-
- function sethid(l, h, hid) {
- var i;
- for(i=0; i<l.length; i++) {
- setClass(l[i], 'hidden', hid);
- // Set the hidden class on the input checkbox, if it exists. This
- // prevents the "select all" functionality from selecting it if the row
- // is not visible.
- var sel = byName(l[i], 'input')[0];
- if(sel)
- setClass(sel, 'hidden', hid);
- }
- for(i=0; i<h.length; i++)
- setText(h[i], allhid ? collapsed_icon : expanded_icon);
- }
-
- function alltoggle() {
- allhid = !allhid;
- setText(byId('expandall'), allhid ? collapsed_icon : expanded_icon);
- sethid(byClass(table, 'tr', 'collapse'), heads, allhid);
- return false;
- }
-
- function singletoggle() {
- var l = byClass(table, 'tr', 'collapse_'+this.id);
- sethid(l, [this], !hasClass(l[0], 'hidden'));
- }
-
- byId('expandall').onclick = alltoggle;
- for(var i=0; i<heads.length; i++)
- heads[i].onclick = singletoggle;
- alltoggle();
-})();
-
-
-// external links dropdown for releases (/v+)
-(function(){
- var l = byClass('rllinks');
- for(var i=0; i<l.length; i++) {
- var o = byName(l[i].parentNode, 'ul')[0];
- if(o) {
- l[i].links_ul = l[i].parentNode.removeChild(o);
- setClass(l[i].links_ul, 'hidden', false);
- ddInit(l[i], 'left', function(acr) {
- return acr.links_ul;
- });
- if(l[i].href.match(/#$/)) {
- l[i].onclick = function() { return false; };
- }
- }
- }
-})();
-
-// set note input box (/u+/list)
-if(byId('not') && byId('vns'))
- byId('vns').onchange = function () {
- if(this.options[this.selectedIndex].value == 999)
- byId('not').value = prompt('Set notes (leave empty to remove note)', '');
- return true;
- };
-
-
// expand/collapse release listing (/p+)
(function(){
var lnk = byId('expandprodrel');
diff --git a/data/js/polls.js b/data/js/polls.js
deleted file mode 100644
index 94a0bba2..00000000
--- a/data/js/polls.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// Discussion board polls
-if(byId('jt_box_postedit') && byId('poll')) {
- var c = byId('poll');
- var parentNode = function(n, tag) {
- while(n && n.nodeName.toLowerCase() != tag)
- n = n.parentNode;
- return n;
- };
- var show = function(v) {
- setClass(parentNode(byId('poll_question'), 'tr'), 'hidden', !v);
- setClass(parentNode(byId('poll_options'), 'tr'), 'hidden', !v);
- setClass(parentNode(byId('poll_max_options'), 'tr'), 'hidden', !v);
- setClass(parentNode(byId('poll_preview'), 'tr'), 'hidden', !v);
- setClass(parentNode(byId('poll_recast'), 'tr'), 'hidden', !v);
- };
- c.onclick = function() {
- show(this.checked);
- return true;
- };
- show(c.checked);
-}
diff --git a/data/js/vnreldropdown.js b/data/js/vnreldropdown.js
deleted file mode 100644
index 16a1dbcd..00000000
--- a/data/js/vnreldropdown.js
+++ /dev/null
@@ -1,36 +0,0 @@
-function dropdown(lnk) {
- var relid = lnk.id.substr(6);
- var st = getText(lnk);
- if(st == 'Loading...')
- return null;
-
- var o = tag('ul', null);
- for(var i=0; i<VARS.rlist_status.length; i++) {
- var val = VARS.rlist_status[i];
- o.appendChild(tag('li', st == val[1]
- ? tag('i', val[1])
- : tag('a', {href:'#', rl_rid:relid, rl_act:val[0], onclick:change}, val[1])));
- }
- if(st != '--')
- o.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:-1, onclick:change}, 'Remove from list')));
-
- return tag('div', o);
-}
-
-function change() {
- var lnk = byId('rlsel_'+this.rl_rid);
- var code = getText(byId('vnrlist_code'));
- var act = this.rl_act;
- ddHide();
- setContent(lnk, tag('b', {'class': 'grayedout'}, 'Loading...'));
- ajax('/xml/rlist.xml?formcode='+code+';id='+this.rl_rid+';e='+act, function(hr) {
- setText(lnk, act == -1 ? '--' : VARS.rlist_status[act][1]);
- });
- return false;
-}
-
-if(byId('vnrlist_code')) {
- var l = byClass('a', 'vnrlsel');
- for(var i=0; i<l.length; i++)
- ddInit(l[i], 'left', dropdown);
-}
diff --git a/lib/VNDB/DB/ULists.pm b/lib/VNDB/DB/ULists.pm
deleted file mode 100644
index 4c1d10ae..00000000
--- a/lib/VNDB/DB/ULists.pm
+++ /dev/null
@@ -1,77 +0,0 @@
-
-package VNDB::DB::ULists;
-
-use strict;
-use warnings;
-use Exporter 'import';
-
-
-our @EXPORT = qw|
- dbRListGet dbRListAdd dbRListDel
- dbVoteStats
-|;
-
-
-# Options: uid rid
-sub dbRListGet {
- my($self, %o) = @_;
-
- my %where = (
- 'uid = ?' => $o{uid},
- $o{rid} ? ('rid IN(!l)' => [ ref $o{rid} ? $o{rid} : [$o{rid}] ]) : (),
- );
-
- return $self->dbAll(q|
- SELECT uid, rid, status
- FROM rlists
- !W|,
- \%where
- );
-}
-
-
-# Arguments: uid rid status
-# rid can be an arrayref only when the rows are already present, in which case an update is done
-sub dbRListAdd {
- my($self, $uid, $rid, $stat) = @_;
- $self->dbExec(
- 'UPDATE rlists SET status = ? WHERE uid = ? AND rid IN(!l)',
- $stat, $uid, ref($rid) ? $rid : [ $rid ]
- )
- ||
- $self->dbExec(
- 'INSERT INTO rlists (uid, rid, status) VALUES(?, ?, ?)',
- $uid, $rid, $stat
- );
-}
-
-
-# Arguments: uid, rid
-sub dbRListDel {
- my($self, $uid, $rid) = @_;
- $self->dbExec(
- 'DELETE FROM rlists WHERE uid = ? AND rid IN(!l)',
- $uid, ref($rid) ? $rid : [ $rid ]
- );
-}
-
-
-# Arguments: 'vid', id
-# Returns an arrayref with 10 elements containing the [ count(vote), sum(vote) ]
-# for votes in the range of ($index+0.5) .. ($index+1.4)
-sub dbVoteStats {
- my($self, $col, $id, $ign) = @_;
- my $r = [ map [0,0], 0..9 ];
- $r->[$_->{idx}] = [ $_->{votes}, $_->{total} ] for (@{$self->dbAll(q|
- SELECT (vote::numeric/10)::int-1 AS idx, COUNT(vote) as votes, SUM(vote) AS total
- FROM ulist_vns uv
- WHERE uv.vote IS NOT NULL AND NOT EXISTS(SELECT 1 FROM users u WHERE u.id = uv.uid AND u.ign_votes)
- AND uv.vid = ?
- GROUP BY (vote::numeric/10)::int|,
- $id
- )});
- return $r;
-}
-
-1;
-
diff --git a/lib/VNDB/Handler/Chars.pm b/lib/VNDB/Handler/Chars.pm
index 95430108..ee2452f9 100644
--- a/lib/VNDB/Handler/Chars.pm
+++ b/lib/VNDB/Handler/Chars.pm
@@ -7,9 +7,8 @@ use TUWF ':html', 'uri_escape';
use Exporter 'import';
use VNDB::Func;
use VNDB::Types;
-use List::Util 'min';
-our @EXPORT = ('charOps', 'charBrowseTable');
+our @EXPORT = ('charBrowseTable');
TUWF::register(
qr{c(?:([1-9]\d*)(?:\.([1-9]\d*))?/(edit|copy)|/new)}
@@ -18,31 +17,6 @@ TUWF::register(
);
-sub charOps {
- my($self, $sexual, $blockId) = @_;
- $blockId ||= 'charops_block';
- my $spoil = $self->authPref('spoilers')||0;
-
- if($sexual) {
- my $id_sex = $blockId.'_sex';
- input type => 'checkbox', class => 'visuallyhidden sexual_check', id => $id_sex, ($self->authPref('traits_sexual') ? (checked => 'checked') : ());
- label for => $id_sex, class => 'lst sec', 'Show sexual traits';
- }
-
- my $id_2 = $blockId.'_2';
- input type => 'radio', class => 'visuallyhidden radio_spoil2', name => $blockId, id => $id_2, $spoil == 2 ? (checked => 'checked') : ();
- label for => $id_2, $sexual ? () : (class => 'lst'), 'Spoil me!';
-
- my $id_1 = $blockId.'_1';
- input type => 'radio', class => 'visuallyhidden radio_spoil1', name => $blockId, id => $id_1, $spoil == 1 ? (checked => 'checked') : ();
- label for => $id_1, 'Show minor spoilers';
-
- my $id_0 = $blockId.'_0';
- input type => 'radio', class => 'visuallyhidden radio_spoil0', name => $blockId, id => $id_0, $spoil == 0 ? (checked => 'checked') : ();
- label for => $id_0, 'Hide spoilers';
-}
-
-
sub edit {
my($self, $id, $rev, $copy) = @_;
diff --git a/lib/VNDB/Handler/ULists.pm b/lib/VNDB/Handler/ULists.pm
deleted file mode 100644
index 03c079b1..00000000
--- a/lib/VNDB/Handler/ULists.pm
+++ /dev/null
@@ -1,51 +0,0 @@
-
-package VNDB::Handler::ULists;
-
-use strict;
-use warnings;
-use TUWF ':xml';
-use VNDB::Func;
-use VNDB::Types;
-
-
-TUWF::register(
- qr{r([1-9]\d*)/list}, \&rlist_e,
- qr{xml/rlist.xml}, \&rlist_e,
-);
-
-
-sub rlist_e {
- my($self, $id) = @_;
-
- my $rid = $id;
- if(!$rid) {
- my $f = $self->formValidate({ get => 'id', required => 1, template => 'id' });
- return $self->resNotFound if $f->{_err};
- $rid = $f->{id};
- }
-
- my $uid = $self->authInfo->{id};
- return $self->htmlDenied() if !$uid;
-
- return if !$self->authCheckCode;
- my $f = $self->formValidate(
- { get => 'e', required => 1, enum => [ -1, keys %RLIST_STATUS ] },
- { get => 'ref', required => 0, default => "/r$rid" }
- );
- return $self->resNotFound if $f->{_err};
-
- $self->dbRListDel($uid, $rid) if $f->{e} == -1;
- $self->dbRListAdd($uid, $rid, $f->{e}) if $f->{e} >= 0;
-
- if($id) {
- $self->resRedirect($f->{ref}, 'temp');
- } else {
- # doesn't really matter what we return, as long as it's XML
- $self->resHeader('Content-type' => 'text/xml');
- xml;
- tag 'done', '';
- }
-}
-
-1;
-
diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm
index 89ee33c9..cc0c7da4 100644
--- a/lib/VNDB/Handler/VNPage.pm
+++ b/lib/VNDB/Handler/VNPage.pm
@@ -3,19 +3,15 @@ package VNDB::Handler::VNPage;
use strict;
use warnings;
-use TUWF ':html', 'xml_escape';
+use TUWF ':html';
use VNDB::Func;
use VNDB::Types;
-use VNDB::ExtLinks;
-use List::Util 'min';
-use POSIX 'strftime';
TUWF::register(
qr{v/rand} => \&rand,
qr{v([1-9]\d*)/releases} => \&releases,
qr{v([1-9]\d*)/staff} => sub { $_[0]->resRedirect("/v$_[1]#staff") },
- qr{old/v([1-9]\d*)(?:\.([1-9]\d*))?} => \&page,
);
@@ -302,717 +298,6 @@ sub _releases_table {
}
-sub page {
- my($self, $vid, $rev) = @_;
-
- my $char = $rev && $rev eq 'chars'; # XXX: Not used anymore; implemented in VNWeb::VN::Page.
- $rev = undef if $char;
-
- my $method = $rev ? 'dbVNGetRev' : 'dbVNGet';
- my $v = $self->$method(
- id => $vid,
- what => 'extended anime relations screenshots rating ranking staff'.($rev ? ' seiyuu' : ''),
- $rev ? (rev => $rev) : (),
- )->[0];
- return $self->resNotFound if !$v->{id};
-
- my $r = $self->dbReleaseGet(vid => $vid, what => 'extended links vns producers platforms media', results => 200);
-
- enrich_extlinks v => $v;
- enrich_extlinks r => $r;
-
- my $metadata = {
- 'og:title' => $v->{title},
- 'og:description' => bb2text $v->{desc},
- };
-
- if($v->{image} && !$v->{img_nsfw}) {
- $metadata->{'og:image'} = imgurl(cv => $v->{image});
- } elsif(my ($ss) = grep !$_->{nsfw}, @{$v->{screenshots}}) {
- $metadata->{'og:image'} = imgurl(st => $ss->{id});
- }
-
- $self->htmlHeader(title => $v->{title}, noindex => $rev, metadata => $metadata);
- $self->htmlMainTabs('v', $v);
- return if $self->htmlHiddenMessage('v', $v);
-
- _revision($self, $v, $rev);
-
- div class => 'mainbox';
- $self->htmlItemMessage('v', $v);
- h1 $v->{title};
- h2 class => 'alttitle', lang_attr($v->{c_olang}), $v->{original} if $v->{original};
-
- div class => 'vndetails';
-
- # image
- div class => 'vnimg';
- if(!$v->{image}) {
- p 'No image uploaded yet';
- } else {
- if($v->{img_nsfw}) {
- p class => 'nsfw_pic';
- input id => 'nsfw_chk', type => 'checkbox', class => 'visuallyhidden', $self->authPref('show_nsfw') ? (checked => 'checked') : ();
- label for => 'nsfw_chk';
- span id => 'nsfw_show';
- txt 'This image has been flagged as Not Safe For Work.';
- br; br;
- span class => 'fake_link', 'Show me anyway';
- br; br;
- txt '(This warning can be disabled in your account)';
- end;
- span id => 'nsfw_hid';
- img src => imgurl(cv => $v->{image}), alt => $v->{title};
- i 'Flagged as NSFW';
- end;
- end;
- end;
- } else {
- img src => imgurl(cv => $v->{image}), alt => $v->{title};
- }
- }
- end 'div'; # /vnimg
-
- # general info
- table class => 'stripe';
- Tr;
- td class => 'key', 'Title';
- td $v->{title};
- end;
- if($v->{original}) {
- Tr;
- td 'Original title';
- td lang_attr($v->{c_olang}), $v->{original};
- end;
- }
- if($v->{alias}) {
- $v->{alias} =~ s/\n/, /g;
- Tr;
- td 'Aliases';
- td $v->{alias};
- end;
- }
- if($v->{length}) {
- Tr;
- td 'Length';
- td fmtvnlen $v->{length}, 1;
- end;
- }
-
- _producers($self, $r);
- _relations($self, $v) if @{$v->{relations}};
-
- if($v->{extlinks}->@*) {
- Tr;
- td 'Links';
- td;
- for($v->{extlinks}->@*) {
- a href => $_->[1], $_->[0];
- txt ', ' if $_ ne $v->{extlinks}[$#{$v->{extlinks}}];
- }
- end;
- end;
- }
- _affiliate_links($self, $r);
-
- _anime($self, $v) if @{$v->{anime}};
-
- _useroptions($self, $v, $r) if $self->authInfo->{id};
-
- Tr class => 'nostripe';
- td class => 'vndesc', colspan => 2;
- h2 'Description';
- p;
- lit $v->{desc} ? bb2html $v->{desc} : '-';
- end;
- end;
- end;
-
- end 'table';
- end 'div';
- div class => 'clearfloat', style => 'height: 5px', ''; # otherwise the tabs below aren't positioned correctly
-
- # tags
- my $t = $self->dbTagStats(vid => $v->{id}, sort => 'rating', reverse => 1, minrating => 0, results => 999, state => 2);
- if(@$t) {
- div id => 'tagops';
- for (keys %TAG_CATEGORY) {
- input id => "cat_$_", type => 'checkbox', class => 'visuallyhidden',
- ($self->authInfo->{id} ? $self->authPref("tags_$_") : $_ ne 'ero') ? (checked => 'checked') : ();
- label for => "cat_$_", lc $TAG_CATEGORY{$_};
- }
- my $spoiler = $self->authPref('spoilers') || 0;
- input id => 'tag_spoil_none', type => 'radio', class => 'visuallyhidden', name => 'tag_spoiler', $spoiler == 0 ? (checked => 'checked') : ();
- label for => 'tag_spoil_none', class => 'sec', lc 'Hide spoilers';
- input id => 'tag_spoil_some', type => 'radio', class => 'visuallyhidden', name => 'tag_spoiler', $spoiler == 1 ? (checked => 'checked') : ();
- label for => 'tag_spoil_some', lc 'Show minor spoilers';
- input id => 'tag_spoil_all', type => 'radio', class => 'visuallyhidden', name => 'tag_spoiler', $spoiler == 2 ? (checked => 'checked') : ();
- label for => 'tag_spoil_all', lc 'Spoil me!';
-
- input id => 'tag_toggle_summary', type => 'radio', class => 'visuallyhidden', name => 'tag_all', $self->authPref('tags_all') ? () : (checked => 'checked');
- label for => 'tag_toggle_summary', class => 'sec', lc 'summary';
- input id => 'tag_toggle_all', type => 'radio', class => 'visuallyhidden', name => 'tag_all', $self->authPref('tags_all') ? (checked => 'checked') : ();
- label for => 'tag_toggle_all', class => 'lst', lc 'all';
- div id => 'vntags';
- my %counts = ();
- for (@$t) {
- my $cnt0 = $counts{$_->{cat} . '0'} || 0;
- my $cnt1 = $counts{$_->{cat} . '1'} || 0;
- my $cnt2 = $counts{$_->{cat} . '2'} || 0;
- my $spoil = $_->{spoiler} > 1.3 ? 2 : $_->{spoiler} > 0.4 ? 1 : 0;
- SWITCH: {
- $counts{$_->{cat} . '2'} = ++$cnt2;
- if ($spoil == 2) { last SWITCH; }
- $counts{$_->{cat} . '1'} = ++$cnt1;
- if ($spoil == 1) { last SWITCH; }
- $counts{$_->{cat} . '0'} = ++$cnt0;
- }
- my $cut = $cnt0 > 15 ? ' cut cut2 cut1 cut0' : ($cnt1 > 15 ? ' cut cut2 cut1' : ($cnt2 > 15 ? ' cut cut2' : ''));
- span class => sprintf 'tagspl%d cat_%s%s', $spoil, $_->{cat}, $cut;
- a href => "/g$_->{id}", style => sprintf('font-size: %dpx', $_->{rating}*3.5+6), $_->{name};
- b class => 'grayedout', sprintf ' %.1f', $_->{rating};
- end;
- txt ' ';
- }
- end;
- end;
- }
- end 'div'; # /mainbox
-
- my $chars = $self->dbCharGet(vid => $v->{id}, what => "seiyuu vns($v->{id})".($char ? ' extended traits' : ''), results => 500);
- if(@$chars || $self->authCan('edit')) {
- clearfloat; # fix tabs placement when tags are hidden
- div class => 'maintabs';
- ul;
- if(@$chars) {
- li class => (!$char ? ' tabselected' : ''); a href => "/v$v->{id}#main", name => 'main', 'main'; end;
- li class => ($char ? ' tabselected' : ''); a href => "/v$v->{id}/chars#chars", name => 'chars', 'characters'; end;
- }
- end;
- ul;
- if($self->authCan('edit')) {
- li; a href => "/v$v->{id}/add", 'add release'; end;
- li; a href => "/c/new?vid=$v->{id}", 'add character'; end;
- }
- end;
- end;
- }
-
- if($char) {
- #_chars($self, $chars, $v);
- } else {
- _releases($self, $v, $r);
- _staff($self, $v);
- _charsum($self, $chars, $v);
- _stats($self, $v);
- _screenshots($self, $v, $r) if @{$v->{screenshots}};
- }
-
- $self->htmlFooter(v2rwjs => $self->authInfo->{id});
-}
-
-
-sub _revision {
- my($self, $v, $rev) = @_;
- return if !$rev;
-
- my $prev = $rev && $rev > 1 && $self->dbVNGetRev(
- id => $v->{id}, rev => $rev-1, what => 'extended anime relations screenshots staff seiyuu'
- )->[0];
-
- $self->htmlRevision('v', $prev, $v,
- [ title => 'Title (romaji)', diff => 1 ],
- [ original => 'Original title', diff => 1 ],
- [ alias => 'Alias', diff => qr/[ ,\n\.]/ ],
- [ desc => 'Description', diff => qr/[ ,\n\.]/ ],
- [ length => 'Length', serialize => sub { fmtvnlen $_[0] } ],
- [ l_wp => 'Wikipedia link', htmlize => sub {
- $_[0] ? sprintf '<a href="http://en.wikipedia.org/wiki/%s">%1$s</a>', xml_escape $_[0] : '[empty]'
- }],
- [ l_wikidata => 'Wikidata ID', htmlize => sub { $_[0] ? sprintf '<a href="https://www.wikidata.org/wiki/Q%d">Q%1$d</a>', $_[0] : '[empty]' } ],
- [ l_encubed => 'Encubed tag', htmlize => sub {
- $_[0] ? sprintf '<a href="http://novelnews.net/tag/%s/">%1$s</a>', xml_escape $_[0] : '[empty]'
- }],
- [ l_renai => 'Renai.us link', htmlize => sub {
- $_[0] ? sprintf '<a href="https://renai.us/game/%s">%1$s</a>', xml_escape $_[0] : '[empty]'
- }],
- [ credits => 'Credits', join => '<br />', split => sub {
- my @r = map sprintf('<a href="/s%d" title="%s">%s</a> [%s]%s', $_->{id},
- xml_escape($_->{original}||$_->{name}), xml_escape($_->{name}), xml_escape($CREDIT_TYPE{$_->{role}}),
- $_->{note} ? ' ['.xml_escape($_->{note}).']' : ''),
- sort { $a->{id} <=> $b->{id} || $a->{role} cmp $b->{role} } @{$_[0]};
- return @r ? @r : ('[empty]');
- }],
- [ seiyuu => 'Seiyuu', join => '<br />', split => sub {
- my @r = map sprintf('<a href="/s%d" title="%s">%s</a> as <a href="/c%d">%s</a>%s',
- $_->{id}, xml_escape($_->{original}||$_->{name}), xml_escape($_->{name}), $_->{cid}, xml_escape($_->{cname}),
- $_->{note} ? ' ['.xml_escape($_->{note}).']' : ''),
- sort { $a->{id} <=> $b->{id} || $a->{cid} <=> $b->{cid} || $a->{note} cmp $b->{note} } @{$_[0]};
- return @r ? @r : ('[empty]');
- }],
- [ relations => 'Relations', join => '<br />', split => sub {
- my @r = map sprintf('[%s] %s: <a href="/v%d" title="%s">%s</a>',
- $_->{official} ? 'official' : 'unofficial', $VN_RELATION{$_->{relation}}{txt},
- $_->{id}, xml_escape($_->{original}||$_->{title}), xml_escape shorten $_->{title}, 40
- ), sort { $a->{id} <=> $b->{id} } @{$_[0]};
- return @r ? @r : ('[empty]');
- }],
- [ anime => 'Anime', join => ', ', split => sub {
- my @r = map sprintf('<a href="http://anidb.net/a%d">a%1$d</a>', $_->{id}), sort { $a->{id} <=> $b->{id} } @{$_[0]};
- return @r ? @r : ('[empty]');
- }],
- [ screenshots => 'Screenshots', join => '<br />', split => sub {
- my @r = map sprintf('[%s] <a href="%s" data-iv="%dx%d">%d</a> (%s)',
- $_->{rid} ? qq|<a href="/r$_->{rid}">r$_->{rid}</a>| : 'no release',
- imgurl(sf => $_->{id}), $_->{width}, $_->{height}, $_->{id},
- $_->{nsfw} ? 'Not safe' : 'Safe'
- ), @{$_[0]};
- return @r ? @r : ('[empty]');
- }],
- [ image => 'Image', htmlize => sub {
- my $url = imgurl(cv => $_[0]);
- if($_[0]) {
- return $_[1]->{img_nsfw} && !$self->authPref('show_nsfw') ? "<a href=\"$url\">(NSFW)</a>" : "<img src=\"$url\" />";
- } else {
- return 'No image';
- }
- }],
- [ img_nsfw => 'Image NSFW', serialize => sub { $_[0] ? 'Not safe' : 'Safe' } ],
- );
-}
-
-
-sub _producers {
- my($self, $r) = @_;
-
- my %lang;
- my @lang = grep !$lang{$_}++, map @{$_->{languages}}, @$r;
-
- if(grep $_->{developer}, map @{$_->{producers}}, @$r) {
- my %dev = map $_->{developer} ? ($_->{id} => $_) : (), map @{$_->{producers}}, @$r;
- my @dev = sort { $a->{name} cmp $b->{name} } values %dev;
- Tr;
- td 'Developer';
- td;
- for (@dev) {
- a href => "/p$_->{id}", title => $_->{original}||$_->{name}, shorten $_->{name}, 30;
- txt ' & ' if $_ != $dev[$#dev];
- }
- end;
- end;
- }
-
- if(grep $_->{publisher}, map @{$_->{producers}}, @$r) {
- Tr;
- td 'Publishers';
- td;
- for my $l (@lang) {
- my %p = map $_->{publisher} ? ($_->{id} => $_) : (), map @{$_->{producers}}, grep grep($_ eq $l, @{$_->{languages}}), @$r;
- my @p = sort { $a->{name} cmp $b->{name} } values %p;
- next if !@p;
- cssicon "lang $l", $LANGUAGE{$l};
- for (@p) {
- a href => "/p$_->{id}", title => $_->{original}||$_->{name}, shorten $_->{name}, 30;
- txt ' & ' if $_ != $p[$#p];
- }
- br;
- }
- end;
- end 'tr';
- }
-}
-
-
-sub _relations {
- my($self, $v) = @_;
-
- my %rel;
- push @{$rel{$_->{relation}}}, $_
- for (sort { $a->{title} cmp $b->{title} } @{$v->{relations}});
-
-
- Tr;
- td 'Relations';
- td class => 'relations';
- dl;
- for(sort keys %rel) {
- dt $VN_RELATION{$_}{txt};
- dd;
- for (@{$rel{$_}}) {
- b class => 'grayedout', '[unofficial] ' if !$_->{official};
- a href => "/v$_->{id}", title => $_->{original}||$_->{title}, shorten $_->{title}, 40;
- br;
- }
- end;
- }
- end;
- end;
- end 'tr';
-}
-
-
-sub _anime {
- my($self, $v) = @_;
-
- Tr;
- td 'Related anime';
- td class => 'anime';
- for (sort { ($a->{year}||9999) <=> ($b->{year}||9999) } @{$v->{anime}}) {
- if(!$_->{lastfetch} || !$_->{year} || !$_->{title_romaji}) {
- b;
- lit sprintf '[no information available at this time: <a href="http://anidb.net/a%d">%1$d</a>]', $_->{id};
- end;
- } else {
- b;
- txt '[';
- a href => "http://anidb.net/a$_->{id}", title => 'AniDB', 'DB';
- # AnimeNFO links seem to be broken at the moment. TODO: Completely remove?
- #if($_->{nfo_id}) {
- # txt '-';
- # a href => "http://animenfo.com/animetitle,$_->{nfo_id},a.html", title => 'AnimeNFO', 'NFO';
- #}
- if($_->{ann_id}) {
- txt '-';
- a href => "http://www.animenewsnetwork.com/encyclopedia/anime.php?id=$_->{ann_id}", title => 'Anime News Network', 'ANN';
- }
- txt '] ';
- end;
- abbr title => $_->{title_kanji}||$_->{title_romaji}, shorten $_->{title_romaji}, 50;
- b ' ('.(defined $_->{type} ? $ANIME_TYPE{$_->{type}}{txt}.', ' : '').$_->{year}.')';
- br;
- }
- }
- end;
- end 'tr';
-}
-
-
-sub _useroptions {
- my($self, $v, $r) = @_;
-
- # Voting option is hidden if nothing has been released yet
- my $minreleased = min grep $_, map $_->{released}, @$r;
-
- my $labels = tuwf->dbAlli(
- 'SELECT l.id, l.label, l.private, uvl.vid IS NOT NULL as assigned
- FROM ulist_labels l
- LEFT JOIN ulist_vns_labels uvl ON uvl.uid = l.uid AND uvl.lbl = l.id AND uvl.vid =', \$v->{id}, '
- WHERE l.uid =', \$self->authInfo->{id}, '
- ORDER BY CASE WHEN l.id < 10 THEN l.id ELSE 10 END, l.label'
- );
- my $lst = tuwf->dbRowi('SELECT vid, vote, notes FROM ulist_vns WHERE uid =', \$self->authInfo->{id}, 'AND vid =', \$v->{id});
-
- Tr class => 'nostripe';
- td colspan => 2;
- VNWeb::HTML::elm_('UList.VNPage', undef, {
- uid => 1*$self->authInfo->{id},
- vid => 1*$v->{id},
- onlist => $lst->{vid}?\1:\0,
- canvote => $minreleased && $minreleased < strftime('%Y%m%d', gmtime) ? \1 : \0,
- vote => fmtvote($lst->{vote}).'',
- notes => $lst->{notes}||'',
- labels => [ map +{ id => 1*$_->{id}, label => $_->{label}, private => $_->{private}?\1:\0 }, @$labels ],
- selected => [ map $_->{id}, grep $_->{assigned}, @$labels ],
- });
- end;
- end;
-}
-
-
-sub _affiliate_links {
- my($self, $r) = @_;
-
- # If the same shop link has been added to multiple releases, use the 'first' matching type in this list.
- my @type = ('bundle', '', 'partial', 'trial', 'patch');
-
- # url => [$title, $url, $price, $type]
- my %links;
- for my $rel (@$r) {
- my $type = $rel->{patch} ? 4 :
- $rel->{type} eq 'trial' ? 3 :
- $rel->{type} eq 'partial' ? 2 :
- @{$rel->{vn}} > 1 ? 0 : 1;
-
- for my $l (grep $_->[2], $rel->{extlinks}->@*) {
- $links{$l->[1]} = [ @$l, min $type, $links{$l->[1]}[3]||9 ];
- }
- }
- return if !keys %links;
-
- use utf8;
- Tr id => 'buynow';
- td 'Shops';
- td;
- for my $l (sort { $a->[0] cmp $b->[0] || $a->[2] cmp $b->[2] } values %links) {
- b class => 'standout', '» ';
- a href => $l->[1];
- txt $l->[2];
- b class => 'grayedout', " @ ";
- txt $l->[0];
- b class => 'grayedout', " ($type[$l->[3]])" if $l->[3] != 1;
- end;
- br;
- }
- end;
- end;
-}
-
-
-sub _releases {
- my($self, $v, $r) = @_;
-
- div class => 'mainbox releases';
- h1 'Releases';
- if(!@$r) {
- p 'We don\'t have any information about releases of this visual novel yet...';
- end;
- return;
- }
-
- if($self->authInfo->{id}) {
- my $l = $self->dbRListGet(uid => $self->authInfo->{id}, rid => [map $_->{id}, @$r]);
- for my $i (@$l) {
- [grep $i->{rid} == $_->{id}, @$r]->[0]{ulist} = $i;
- }
- div id => 'vnrlist_code', class => 'hidden', $self->authGetCode('/xml/rlist.xml');
- }
-
- my %lang;
- my @lang = grep !$lang{$_}++, map @{$_->{languages}}, @$r;
-
- table;
- for my $l (@lang) {
- Tr class => 'lang';
- td colspan => 7;
- cssicon "lang $l", $LANGUAGE{$l};
- txt $LANGUAGE{$l};
- end;
- end;
- for my $rel (grep grep($_ eq $l, @{$_->{languages}}), @$r) {
- Tr;
- td class => 'tc1'; lit fmtdatestr $rel->{released}; end;
- td class => 'tc2', $rel->{minage} < 0 ? '' : minage $rel->{minage};
- td class => 'tc3';
- for (sort @{$rel->{platforms}}) {
- next if $_ eq 'oth';
- cssicon $_, $PLATFORM{$_};
- }
- cssicon "rt$rel->{type}", $rel->{type};
- end;
- td class => 'tc4';
- a href => "/r$rel->{id}", title => $rel->{original}||$rel->{title}, $rel->{title};
- b class => 'grayedout', ' (patch)' if $rel->{patch};
- end;
-
- td class => 'tc_icons';
- _release_icons($self, $rel);
- end;
-
- td class => 'tc5';
- if($self->authInfo->{id}) {
- a href => "/r$rel->{id}", id => "rlsel_$rel->{id}", class => 'vnrlsel',
- $rel->{ulist} ? $RLIST_STATUS{ $rel->{ulist}{status} } : '--';
- } else {
- txt ' ';
- }
- end;
- td class => 'tc6';
- $self->releaseExtLinks($rel);
- end;
- end 'tr';
- }
- }
- end 'table';
- end 'div';
-}
-
-
-# Creates an small sized img inside an abbr tag. Used for per-release information icons.
-sub _release_icon {
- my($class, $title, $img) = @_;
- abbr class => "release_icons_container release_icon_$class", title => $title;
- img src=> "$TUWF::OBJ->{url_static}/f/$img.svg", class => "release_icons", alt => $title;
- end;
-}
-
-sub _release_icons {
- my($self, $rel) = @_;
-
- # Voice column
- my $voice = $rel->{voiced};
- _release_icon $VOICED{$voice}{icon}, $VOICED{$voice}{txt}, 'voiced' if $voice;
-
- # Animations columns
- my $story_anim = $rel->{ani_story};
- _release_icon $ANIMATED{$story_anim}{story_icon}, "Story: $ANIMATED{$story_anim}{txt}", 'story_animated' if $story_anim;
-
- my $ero_anim = $rel->{ani_ero};
- _release_icon $ANIMATED{$ero_anim}{ero_icon}, "Ero: $ANIMATED{$ero_anim}{txt}", 'ero_animated' if $ero_anim;
-
- # Cost column
- _release_icon 'freeware', 'Freeware', 'free' if $rel->{freeware};
- _release_icon 'nonfree', 'Non-free', 'nonfree' unless $rel->{freeware};
-
- # Publisher type column
- if(!$rel->{patch}) {
- _release_icon 'doujin', 'Doujin', 'doujin' if $rel->{doujin};
- _release_icon 'commercial', 'Commercial', 'commercial' unless $rel->{doujin};
- }
-
- # Resolution column
- my $resolution = $rel->{resolution};
- if($resolution ne 'unknown') {
- my $resolution_type = $resolution eq 'nonstandard' ? 'custom' : $RESOLUTION{$resolution}{cat} eq 'widescreen' ? '16-9' : '4-3';
- # Ugly workaround: PC-98 has non-square pixels, thus not widescreen
- $resolution_type = '4-3' if $resolution_type eq '16-9' && grep $_ eq 'p98', @{$rel->{platforms}};
- _release_icon "res$resolution_type", $RESOLUTION{$resolution}{txt}, "resolution_$resolution_type";
- }
-
- # Media column
- if(@{$rel->{media}}) {
- my $icon = $MEDIUM{ $rel->{media}[0]{medium} }{icon};
- my $media_detail = join ', ', map fmtmedia($_->{medium}, $_->{qty}), @{$rel->{media}};
- _release_icon $icon, $media_detail, $icon;
- }
-
- _release_icon 'uncensor', 'Uncensored', 'uncensor' if $rel->{uncensored};
-
- # Notes column
- _release_icon 'notes', bb2text($rel->{notes}), 'notes' if $rel->{notes};
-}
-
-
-sub _screenshots {
- my($self, $v, $r) = @_;
-
- input id => 'nsfwhide_chk', type => 'checkbox', class => 'visuallyhidden', $self->authPref('show_nsfw') ? (checked => 'checked') : ();
- div class => 'mainbox', id => 'screenshots';
-
- if(grep $_->{nsfw}, @{$v->{screenshots}}) {
- p class => 'nsfwtoggle';
- txt 'Showing ';
- i id => 'nsfwshown', scalar grep(!$_->{nsfw}, @{$v->{screenshots}});
- span class => 'nsfw', scalar @{$v->{screenshots}};
- txt sprintf ' out of %d screenshot%s. ', scalar @{$v->{screenshots}}, @{$v->{screenshots}} == 1 ? '' : 's';
- label for => 'nsfwhide_chk', class => 'fake_link', 'show/hide NSFW';
- end;
- }
-
- h1 'Screenshots';
-
- for my $rel (@$r) {
- my @scr = grep $_->{rid} && $rel->{id} == $_->{rid}, @{$v->{screenshots}};
- next if !@scr;
- p class => 'rel';
- cssicon "lang $_", $LANGUAGE{$_} for (@{$rel->{languages}});
- cssicon $_, $PLATFORM{$_} for (@{$rel->{platforms}});
- a href => "/r$rel->{id}", $rel->{title};
- end;
- div class => 'scr';
- for (@scr) {
- my($w, $h) = imgsize($_->{width}, $_->{height}, @{$self->{scr_size}});
- a href => imgurl(sf => $_->{id}),
- class => sprintf('scrlnk%s', $_->{nsfw} ? ' nsfw':''),
- 'data-iv' => "$_->{width}x$_->{height}:scr";
- img src => imgurl(st => $_->{id}),
- width => $w, height => $h, alt => "Screenshot #$_->{id}";
- end;
- }
- end;
- }
- end 'div';
-}
-
-
-sub _stats {
- my($self, $v) = @_;
-
- my $stats = $self->dbVoteStats(vid => $v->{id}, 1);
- div class => 'mainbox';
- h1 'User stats';
- if(!grep $_->[0] > 0, @$stats) {
- p 'Nobody has voted on this visual novel yet...';
- } else {
- $self->htmlVoteStats(v => $v, $stats);
- }
- end;
-}
-
-
-sub _charspoillvl {
- my($vid, $c) = @_;
- my $minspoil = 5;
- $minspoil = $_->{vid} == $vid && $_->{spoil} < $minspoil ? $_->{spoil} : $minspoil
- for(@{$c->{vns}});
- return $minspoil;
-}
-
-
-sub _charsum {
- my($self, $l, $v) = @_;
- return if !@$l;
-
- my(@l, %done, $has_spoilers);
- for my $r (keys %CHAR_ROLE) {
- last if $r eq 'appears';
- for (grep grep($_->{role} eq $r, @{$_->{vns}}) && !$done{$_->{id}}++, @$l) {
- $_->{role} = $r;
- $has_spoilers = $has_spoilers || _charspoillvl $v->{id}, $_;
- push @l, $_;
- }
- }
-
- div class => 'mainbox charsum summarize charops', 'data-summarize-height' => 200, id => 'charops';
- $self->charOps(0, 'charsum') if $has_spoilers;
- h1 'Character summary';
- div class => 'charsum_list';
- for my $c (@l) {
- div class => 'charsum_bubble'.($has_spoilers ? ' '.charspoil(_charspoillvl $v->{id}, $c) : '');
- div class => 'name';
- i $CHAR_ROLE{$c->{role}}{txt};
- cssicon "gen $c->{gender}", $GENDER{$c->{gender}} if $c->{gender} ne 'unknown';
- a href => "/c$c->{id}", title => $c->{original}||$c->{name}, $c->{name};
- end;
- if(@{$c->{seiyuu}}) {
- div class => 'actor';
- txt 'Voiced by';
- @{$c->{seiyuu}} > 1 ? br : txt ' ';
- for my $s (sort { $a->{name} cmp $b->{name} } @{$c->{seiyuu}}) {
- a href => "/s$s->{sid}", title => $s->{original}||$s->{name}, $s->{name};
- b class => 'grayedout', $s->{note} if $s->{note};
- br;
- }
- end;
- }
- end;
- }
- end;
- end;
-}
-
-
-sub _staff {
- my ($self, $v) = @_;
- return if !@{$v->{credits}};
-
- div class => 'mainbox staff summarize', 'data-summarize-height' => 200, id => 'staff';
- h1 'Staff';
- for my $r (keys %CREDIT_TYPE) {
- my @s = grep $_->{role} eq $r, @{$v->{credits}};
- next if !@s;
- ul;
- li; b $CREDIT_TYPE{$r}; end;
- for(@s) {
- li;
- a href => "/s$_->{id}", title => $_->{original}||$_->{name}, $_->{name};
- b class => 'grayedout', $_->{note} if $_->{note};
- end;
- }
- end;
- }
- clearfloat;
- end;
-}
1;
diff --git a/lib/VNDB/Util/CommonHTML.pm b/lib/VNDB/Util/CommonHTML.pm
index 03b1bd28..c052f726 100644
--- a/lib/VNDB/Util/CommonHTML.pm
+++ b/lib/VNDB/Util/CommonHTML.pm
@@ -12,7 +12,7 @@ use POSIX 'ceil';
our @EXPORT = qw|
htmlMainTabs htmlDenied htmlHiddenMessage htmlRevision
- htmlEditMessage htmlItemMessage htmlVoteStats htmlSearchBox
+ htmlEditMessage htmlItemMessage htmlSearchBox
|;
@@ -214,88 +214,6 @@ sub htmlItemMessage {
}
-# generates two tables, one with a vote graph, other with recent votes
-# Only supports $type eq 'v' now.
-sub htmlVoteStats {
- my($self, $type, $obj, $stats) = @_;
-
- my($max, $count, $total) = (0, 0, 0);
- for (0..$#$stats) {
- $max = $stats->[$_][0] if $stats->[$_][0] > $max;
- $count += $stats->[$_][0];
- $total += $stats->[$_][1];
- }
- div class => 'votestats';
- table class => 'votegraph';
- thead; Tr;
- td colspan => 2, 'Vote stats';
- end; end;
- tfoot; Tr;
- td colspan => 2, sprintf '%d vote%s total, average %.2f%s', $count, $count == 1 ? '' : 's', $total/$count/10,
- $type eq 'v' ? ' ('.fmtrating(ceil($total/$count/10-1)||1).')' : '';
- end; end;
- for (reverse 0..$#$stats) {
- Tr;
- td class => 'number', $_+1;
- td class => 'graph';
- div style => 'width: '.($stats->[$_][0]/$max*250).'px', ' ';
- txt $stats->[$_][0];
- end;
- end;
- }
- end 'table';
-
- my $recent = $self->dbAlli('
- SELECT uv.vote,', VNWeb::DB::sql_totime('uv.vote_date '), 'as date, ', VNWeb::DB::sql_user(), '
- , NOT EXISTS(SELECT 1 FROM ulist_vns_labels uvl JOIN ulist_labels ul ON ul.uid = uvl.uid AND ul.id = uvl.lbl WHERE uvl.uid = uv.uid AND uvl.vid = uv.vid AND NOT ul.private) AS hide_list
- FROM ulist_vns uv
- JOIN users u ON u.id = uv.uid
- WHERE uv.vid =', \$obj->{id}, 'AND uv.vote IS NOT NULL
- AND NOT EXISTS(SELECT 1 FROM users u WHERE u.id = uv.uid AND u.ign_votes)
- ORDER BY uv.vote_date DESC
- LIMIT', \8
- );
-
- if(@$recent) {
- table class => 'recentvotes stripe';
- thead; Tr;
- td colspan => 3;
- txt 'Recent votes';
- b;
- txt '(';
- a href => "/$type$obj->{id}/votes", 'show all';
- txt ')';
- end;
- end;
- end; end;
- for (@$recent) {
- Tr;
- td;
- if($_->{hide_list}) {
- b class => 'grayedout', 'hidden';
- } else {
- VNWeb::HTML::user_($_);
- }
- end;
- td fmtvote $_->{vote};
- td fmtdate $_->{date};
- end;
- }
- end 'table';
- }
-
- clearfloat;
- if($type eq 'v' && $obj->{c_votecount}) {
- div;
- h3 'Ranking';
- p sprintf 'Popularity: ranked #%d with a score of %.2f', $obj->{p_ranking}, ($obj->{c_popularity}||0)*100;
- p sprintf 'Bayesian rating: ranked #%d with a rating of %.2f', $obj->{r_ranking}, $obj->{c_rating}/10;
- end;
- }
- end 'div';
-}
-
-
sub htmlSearchBox {
shift; VNWeb::HTML::searchbox_(@_);
}