summaryrefslogtreecommitdiff
path: root/data
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2009-10-07 11:03:59 +0200
committerYorhel <git@yorhel.nl>2009-10-07 11:22:37 +0200
commite0161bd219a3004a3affdecd04d54a85f5cf9e1d (patch)
tree1761fcb2d6c9f5b76dabef82083221e9147eeaca /data
parentbafb8b134744cba74a3a019fefb36091b0e19d13 (diff)
JS: Moved script.js to data/ and added jsgen.pl to process it
While this 'processing' is currently limited to minifying the file if JavaScript::Minifier::XS is available, this change would make it a lot easier to make the strings in the JS code translatable.
Diffstat (limited to 'data')
-rw-r--r--data/script.js1758
1 files changed, 1758 insertions, 0 deletions
diff --git a/data/script.js b/data/script.js
new file mode 100644
index 00000000..07ad9866
--- /dev/null
+++ b/data/script.js
@@ -0,0 +1,1758 @@
+/* function/attribute prefixes:
+ * date -> Date selector
+ * dd -> dropdown
+ * ds -> dropdown search
+ * iv -> image viewer
+ * jt -> Javascript Tabs
+ * med -> Release media selector
+ * rl -> Release List dropdown
+ * rpr -> Release <-> producer linking
+ * rvn -> Release <-> visual novel linking
+ * scr -> VN screenshot uploader
+ * tgl -> VN tag linking
+ * tvs -> VN page tag spoilers
+ * vnr -> VN relation editor
+ */
+var expanded_icon = '▾';
+var collapsed_icon = '▸';
+
+/* M I N I M A L J A V A S C R I P T L I B R A R Y */
+
+var http_request = false;
+function ajax(url, func) {
+ if(http_request)
+ http_request.abort();
+ http_request = (window.ActiveXObject) ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
+ if(http_request == null)
+ return alert("Your browser does not support the functionality this website requires.");
+ http_request.onreadystatechange = function() {
+ if(!http_request || http_request.readyState != 4 || !http_request.responseText)
+ return;
+ if(http_request.status != 200)
+ return alert('Whoops, error! :(');
+ func(http_request);
+ };
+ url += (url.indexOf('?')>=0 ? ';' : '?')+(Math.floor(Math.random()*999)+1);
+ http_request.open('GET', url, true);
+ http_request.send(null);
+}
+
+function setCookie(n,v) {
+ var date = new Date();
+ date.setTime(date.getTime()+(365*24*60*60*1000));
+ document.cookie = n+'='+v+'; expires='+date.toGMTString()+'; path=/';
+}
+function getCookie(n) {
+ var l = document.cookie.split(';');
+ for(var i=0; i<l.length; i++) {
+ var c = l[i];
+ while(c.charAt(0) == ' ')
+ c = c.substring(1,c.length);
+ if(c.indexOf(n+'=') == 0)
+ return c.substring(n.length+1,c.length);
+ }
+ return null;
+}
+
+function x(y) { // deprecated
+ return document.getElementById(y)
+}
+function byId(n) {
+ return document.getElementById(n)
+}
+function byName(){
+ var d = arguments.length > 1 ? arguments[0] : document;
+ var n = arguments.length > 1 ? arguments[1] : arguments[0];
+ return d.getElementsByTagName(n);
+}
+function byClass() { // [class], [parent, class], [tagname, class], [parent, tagname, class]
+ var par = typeof arguments[0] == 'object' ? arguments[0] : document;
+ var tag = arguments.length == 2 && typeof arguments[0] == 'string' ? arguments[0] : arguments.length == 3 ? arguments[1] : '*';
+ var c = arguments[arguments.length-1];
+ var l = byName(par, tag);
+ var ret = [];
+ for(var i=0; i<l.length; i++)
+ if(hasClass(l[i], c))
+ ret[ret.length] = l[i];
+ return ret;
+}
+
+/* wrapper around DOM element creation
+ * tag('string') -> createTextNode
+ * tag('tagname', tag(), 'string', ..) -> createElement(), appendChild(), ..
+ * tag('tagname', { class: 'meh', title: 'Title' }) -> createElement(), setAttribute()..
+ * tag('tagname', { <attributes> }, <elements>) -> create, setattr, append */
+function tag() {
+ if(arguments.length == 1)
+ return typeof arguments[0] != 'object' ? document.createTextNode(arguments[0]) : arguments[0];
+ var el = typeof document.createElementNS != 'undefined'
+ ? document.createElementNS('http://www.w3.org/1999/xhtml', arguments[0])
+ : document.createElement(arguments[0]);
+ for(var i=1; i<arguments.length; i++) {
+ if(arguments[i] == null)
+ continue;
+ if(typeof arguments[i] == 'object' && !arguments[i].appendChild) {
+ for(attr in arguments[i]) {
+ if(attr == 'style')
+ el.setAttribute(attr, arguments[i][attr]);
+ else
+ el[ attr == 'class' ? 'className' : attr == 'for' ? 'htmlFor' : attr ] = arguments[i][attr];
+ }
+ } else
+ el.appendChild(tag(arguments[i]));
+ }
+ return el;
+}
+function addBody(el) {
+ if(document.body.appendChild)
+ document.body.appendChild(el);
+ else if(document.documentElement.appendChild)
+ document.documentElement.appendChild(el);
+ else if(document.appendChild)
+ document.appendChild(el);
+}
+function setContent() {
+ setText(arguments[0], '');
+ for(var i=1; i<arguments.length; i++)
+ arguments[0].appendChild(tag(arguments[i]));
+}
+function getText(obj) {
+ return obj.textContent || obj.innerText || '';
+}
+function setText(obj, txt) {
+ if(obj.textContent != null)
+ obj.textContent = txt;
+ else
+ obj.innerText = txt;
+}
+
+function listClass(obj) {
+ var n = obj.className;
+ if(!n)
+ return [];
+ return n.split(/ /);
+}
+function hasClass(obj, c) {
+ var l = listClass(obj);
+ for(var i=0; i<l.length; i++)
+ if(l[i] == c)
+ return true;
+ return false;
+}
+function setClass(obj, c, set) {
+ var l = listClass(obj);
+ var n = [];
+ if(set) {
+ n = l;
+ if(!hasClass(obj, c))
+ n[n.length] = c;
+ } else {
+ for(var i=0; i<l.length; i++)
+ if(l[i] != c)
+ n[n.length] = l[i];
+ }
+ obj.className = n.join(' ');
+}
+
+function shorten(v, l) {
+ return v.length > l ? v.substr(0, l-3)+'...' : v;
+}
+
+
+
+
+/* I M A G E V I E W E R */
+
+function ivInit() {
+ var init = 0;
+ var l = byName('a');
+ for(var i=0;i<l.length;i++)
+ if(l[i].rel.substr(0,3) == 'iv:') {
+ init++;
+ l[i].onclick = ivView;
+ }
+ if(init && !byId('iv_view')) {
+ addBody(tag('div', {id: 'iv_view'},
+ tag('b', {id:'ivimg'}, ''),
+ tag('br', null),
+ tag('a', {href:'#', id:'ivfull'}, ''),
+ tag('a', {href:'#', onclick: ivClose, id:'ivclose'}, 'close'),
+ tag('a', {href:'#', onclick: ivView, id:'ivprev'}, '« previous'),
+ tag('a', {href:'#', onclick: ivView, id:'ivnext'}, 'next »')
+ ));
+ addBody(tag('b', {id:'ivimgload'}, 'Loading...'));
+ }
+}
+
+function ivView(what) {
+ what = what && what.rel ? what : this;
+ var u = what.href;
+ var opt = what.rel.split(':');
+ var view = byId('iv_view');
+ var next = byId('ivnext');
+ var prev = byId('ivprev');
+ var full = byId('ivfull');
+
+ // fix prev/next links (if any)
+ if(opt[2]) {
+ var ol = byName('a');
+ var l=[];
+ for(i=0;i<ol.length;i++)
+ if(ol[i].rel.substr(0,3) == 'iv:' && ol[i].rel.indexOf(':'+opt[2]) > 4 && !hasClass(ol[i], 'hidden') && ol[i].id != 'ivprev' && ol[i].id != 'ivnext')
+ l[l.length] = ol[i];
+ for(i=0;i<l.length;i++)
+ if(l[i].href == u) {
+ next.style.visibility = l[i+1] ? 'visible' : 'hidden';
+ next.href = l[i+1] ? l[i+1].href : '#';
+ next.rel = l[i+1] ? l[i+1].rel : '';
+ prev.style.visibility = l[i-1] ? 'visible' : 'hidden';
+ prev.href = l[i-1] ? l[i-1].href : '#';
+ prev.rel = l[i-1] ? l[i-1].rel : '';
+ }
+ } else
+ next.style.visibility = prev.style.visibility = 'hidden';
+
+ // calculate dimensions
+ var w = Math.floor(opt[1].split('x')[0]);
+ var h = Math.floor(opt[1].split('x')[1]);
+ var ww = typeof(window.innerWidth) == 'number' ? window.innerWidth : document.documentElement.clientWidth;
+ var wh = typeof(window.innerHeight) == 'number' ? window.innerHeight : document.documentElement.clientHeight;
+ var st = typeof(window.pageYOffset) == 'number' ? window.pageYOffset : document.body && document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop;
+ if(w+100 > ww || h+70 > wh) {
+ full.href = u;
+ setText(full, w+'x'+h);
+ full.style.visibility = 'visible';
+ if(w/h > ww/wh) { // width++
+ h *= (ww-100)/w;
+ w = ww-100;
+ } else { // height++
+ w *= (wh-70)/h;
+ h = wh-70;
+ }
+ } else
+ full.style.visibility = 'hidden';
+ var dw = w;
+ var dh = h+20;
+ dw = dw < 200 ? 200 : dw;
+
+ // update document
+ view.style.display = 'block';
+ setContent(byId('ivimg'), tag('img', {src:u, onclick:ivClose,
+ onload: function() { byId('ivimgload').style.top='-400px'; },
+ style: 'width: '+w+'px; height: '+h+'px'
+ }));
+ view.style.width = dw+'px';
+ view.style.height = dh+'px';
+ view.style.left = ((ww - dw) / 2 - 10)+'px';
+ view.style.top = ((wh - dh) / 2 + st - 20)+'px';
+ byId('ivimgload').style.left = ((ww - 100) / 2 - 10)+'px';
+ byId('ivimgload').style.top = ((wh - 20) / 2 + st)+'px';
+ return false;
+}
+
+function ivClose() {
+ byId('iv_view').style.display = 'none';
+ byId('iv_view').style.top = '-5000px';
+ byId('ivimgload').style.top = '-400px';
+ setText(byId('ivimg'), '');
+ return false;
+}
+
+ivInit();
+
+
+
+
+/* D R O P D O W N */
+
+function ddInit(obj, align, contents) {
+ obj.dd_align = align; // see ddRefresh for details
+ obj.dd_contents = contents;
+ document.onmousemove = ddMouseMove;
+ document.onscroll = ddHide;
+ if(!byId('dd_box'))
+ addBody(tag('div', {id:'dd_box', dd_used: false}));
+}
+
+function ddHide() {
+ var box = byId('dd_box');
+ setText(box, '');
+ box.style.left = '-500px';
+ box.dd_used = false;
+ box.dd_lnk = null;
+}
+
+function ddMouseMove(e) {
+ e = e || window.event;
+ var lnk = e.target || e.srcElement;
+ while(lnk && (lnk.nodeType == 3 || !lnk.dd_align))
+ lnk = lnk.parentNode;
+ var box = byId('dd_box');
+ if(!box.dd_used && !lnk)
+ return;
+
+ if(box.dd_used) {
+ var mouseX = e.pageX || (e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft);
+ var mouseY = e.pageY || (e.clientY + document.body.scrollTop + document.documentElement.scrollTop);
+ if((mouseX < ddx-10 || mouseX > ddx+box.offsetWidth+10 || mouseY < ddy-10 || mouseY > ddy+box.offsetHeight+10)
+ || (lnk && lnk == box.dd_lnk))
+ ddHide();
+ }
+
+ if(!box.dd_used && lnk) {
+ box.dd_lnk = lnk;
+ box.dd_used = true;
+ if(!ddRefresh())
+ ddHide();
+ }
+}
+
+function ddRefresh() {
+ var box = byId('dd_box');
+ if(!box.dd_used)
+ return false;
+ var lnk = box.dd_lnk;
+ var content = lnk.dd_contents(lnk, box);
+ if(content == null)
+ return false;
+ setContent(box, content);
+
+ var o = lnk;
+ ddx = ddy = 0;
+ do {
+ ddx += o.offsetLeft;
+ ddy += o.offsetTop;
+ } while(o = o.offsetParent);
+
+ if(lnk.dd_align == 'left')
+ ddx -= box.offsetWidth;
+ if(lnk.dd_align == 'tagmod')
+ ddx += lnk.offsetWidth-35;
+ box.style.left = ddx+'px';
+ box.style.top = ddy+'px';
+ return true;
+}
+
+
+// release list dropdown on VN pages
+
+var rstat = [ 'Unknown', 'Pending', 'Obtained', 'On loan', 'Deleted' ];
+var vstat = [ 'Unknown', 'Playing', 'Finished', 'Stalled', 'Dropped' ];
+function rlDropDown(lnk) {
+ var relid = lnk.id.substr(6);
+ var st = getText(lnk).split(' / ');
+ if(st[0].indexOf('loading') >= 0)
+ return null;
+
+ var rs = tag('ul', tag('li', tag('b', 'Release status')));
+ var vs = tag('ul', tag('li', tag('b', 'Play status')));
+ for(var i=0;i<rstat.length;i++) {
+ if(st[0] && st[0].indexOf(rstat[i]) >= 0)
+ rs.appendChild(tag('li', tag('i', rstat[i])));
+ else
+ rs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'r'+i, onclick:rlMod}, rstat[i])));
+ }
+ for(var i=0;i<vstat.length;i++) {
+ if(st[0] && st[0].indexOf(vstat[i]) >= 0)
+ vs.appendChild(tag('li', tag('i', vstat[i])));
+ else
+ vs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'v'+i, onclick:rlMod}, vstat[i])));
+ }
+
+ return tag('div', {'class':'vrdd'}, rs, vs, st[0] == '--' ? null :
+ tag('ul', {'class':'full'}, tag('li', tag('a', {href:'#', rl_rid: relid, rl_act:'del', onclick:rlMod}, 'Remove from VN List')))
+ );
+}
+
+function rlMod() {
+ var lnk = byId('rlsel_'+this.rl_rid);
+ ddHide();
+ setContent(lnk, tag('b', {'class': 'patch'}, 'loading...'));
+ ajax('/xml/rlist.xml?id='+this.rl_rid+';e='+this.rl_act, function(hr) {
+ // TODO: get rid of innerHTML here...
+ lnk.innerHTML = hr.responseXML.getElementsByTagName('rlist')[0].firstChild.nodeValue;
+ });
+ return false;
+}
+
+{
+ var l = byClass('a', 'vnrlsel');
+ for(var i=0;i<l.length;i++)
+ ddInit(l[i], 'left', rlDropDown);
+}
+
+
+
+
+/* J A V A S C R I P T T A B S */
+
+function jtInit() {
+ if(!byId('jt_select'))
+ return;
+ var sel = '';
+ var first = '';
+ var l = byName(byId('jt_select'), 'a');
+ if(l.length < 1)
+ return;
+ for(var i=0; i<l.length; i++) {
+ l[i].onclick = jtSel;
+ if(!first)
+ first = l[i].id;
+ if(location.hash && l[i].id == 'jt_sel_'+location.hash.substr(1))
+ sel = l[i].id;
+ }
+ if(!sel)
+ sel = first;
+ jtSel(sel, 1);
+}
+
+function jtSel(which, nolink) {
+ which = typeof(which) == 'string' ? which : which && which.id ? which.id : this.id;
+ which = which.substr(7);
+
+ var l = byName(byId('jt_select'), 'a');
+ for(var i=0;i<l.length;i++) {
+ var name = l[i].id.substr(7);
+ if(name != 'all')
+ byId('jt_box_'+name).style.display = name == which || which == 'all' ? 'block' : 'none';
+ var tab = l[i].parentNode;
+ setClass(tab, 'tabselected', name == which);
+ }
+
+ if(!nolink)
+ location.href = '#'+which;
+ return false;
+}
+
+jtInit();
+
+
+
+
+/* V N P A G E T A G S P O I L E R S */
+
+function tvsInit() {
+ if(!byId('tagops'))
+ return;
+ var l = byName(byId('tagops'), 'a');
+ for(var i=0;i<l.length; i++)
+ l[i].onclick = tvsClick;
+ tvsSet(getCookie('tagspoil'), true);
+}
+
+function tvsClick() {
+ var sel;
+ var l = byName(byId('tagops'), 'a');
+ for(var i=0; i<l.length; i++)
+ if(l[i] == this) {
+ if(i < 3) {
+ tvsSet(i, null);
+ setCookie('tagspoil', i);
+ } else
+ tvsSet(null, i == 3 ? true : false);
+ }
+ return false;
+}
+
+function tvsSet(lvl, lim) {
+ /* set/get level and limit to/from the links */
+ var l = byName(byId('tagops'), 'a');
+ for(var i=0; i<l.length; i++) {
+ if(i < 3) { /* spoiler level */
+ if(lvl != null)
+ setClass(l[i], 'tsel', i == lvl);
+ if(lvl == null && hasClass(l[i], 'tsel'))
+ lvl = i;
+ } else { /* display limit (3 = summary) */
+ if(lim != null)
+ setClass(l[i], 'tsel', lim == (i == 3));
+ if(lim == null && hasClass(l[i], 'tsel'))
+ lim = i == 3;
+ }
+ }
+
+ /* update tag visibility */
+ l = byName(byId('vntags'), 'span');
+ lim = lim ? 15 : 999;
+ var s=0;
+ for(i=0;i<l.length;i++) {
+ var thislvl = l[i].className.substr(6, 1);
+ if(thislvl <= lvl && s < lim) {
+ setClass(l[i], 'hidden', false);
+ s++;
+ } else
+ setClass(l[i], 'hidden', true);
+ }
+ return false;
+}
+
+tvsInit();
+
+
+
+
+/* D A T E I N P U T */
+
+var months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
+
+function dateLoad(obj) {
+ var val = Math.floor(obj.value) || 0;
+ val = [ Math.floor(val/10000), Math.floor(val/100)%100, val%100 ];
+
+ var year = tag('select', {style: 'width: 70px', onchange: dateSerialize}, tag('option', {value:0}, '-year-'));
+ for(var i=1980; i<=(new Date()).getFullYear()+5; i++)
+ year.appendChild(tag('option', {value: i, selected: i==val[0]}, i));
+ year.appendChild(tag('option', {value: 9999, selected: val[0]==9999}, 'TBA'));
+
+ var month = tag('select', {style: 'width: 100px', onchange: dateSerialize}, tag('option', {value:99}, '-month-'));
+ for(var i=1; i<=12; i++)
+ month.appendChild(tag('option', {value: i, selected: i==val[1]}, months[i-1]));
+
+ var day = tag('select', {style: 'width: 70px', onchange: dateSerialize}, tag('option', {value:99}, '-day-'));
+ for(var i=1; i<=31; i++)
+ day.appendChild(tag('option', {value: i, selected: i==val[2]}, i));
+
+ obj.parentNode.insertBefore(tag('div', {date_obj: obj}, year, month, day), obj);
+}
+
+function dateSerialize() {
+ var div = this.parentNode;
+ var sel = byName(div, 'select');
+ var val = [
+ sel[0].options[sel[0].selectedIndex].value*1,
+ sel[1].options[sel[1].selectedIndex].value*1,
+ sel[2].options[sel[2].selectedIndex].value*1
+ ];
+ div.date_obj.value = val[0] == 0 ? 0 : val[0] == 9999 ? 99999999 : val[0]*10000+val[1]*100+(val[1]==99?99:val[2]);
+}
+
+{
+ var l = byClass('input', 'dateinput');
+ for(i=0; i<l.length; i++)
+ dateLoad(l[i]);
+}
+
+
+
+
+/* D R O P D O W N S E A R C H */
+
+function dsInit(obj, url, trfunc, serfunc, retfunc, parfunc) {
+ obj.setAttribute('autocomplete', 'off');
+ obj.onkeydown = dsKeyDown;
+ obj.onblur = function() { setTimeout(function () { byId('ds_box').style.top = '-500px'; }, 500) };
+ obj.ds_returnFunc = retfunc;
+ obj.ds_trFunc = trfunc;
+ obj.ds_serFunc = serfunc;
+ obj.ds_parFunc = parfunc;
+ obj.ds_searchURL = url;
+ obj.ds_selectedId = 0;
+ obj.ds_dosearch = null;
+ if(!byId('ds_box'))
+ addBody(tag('div', {id: 'ds_box', style: 'position: absolute; top: -500px'}, tag('b', 'Loading...')));
+}
+
+function dsKeyDown(ev) {
+ var c = document.layers ? ev.which : document.all ? event.keyCode : ev.keyCode;
+ var obj = this;
+
+ if(c == 9) // tab
+ return true;
+
+ // do some processing when the enter key has been pressed
+ if(c == 13) {
+ var frm = obj;
+ while(frm && frm.nodeName.toLowerCase() != 'form')
+ frm = frm.parentNode;
+ if(frm) {
+ var oldsubmit = frm.onsubmit;
+ frm.onsubmit = function() { return false };
+ setTimeout(function() { frm.onsubmit = oldsubmit }, 100);
+ }
+
+ 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();
+
+ byId('ds_box').style.top = '-500px';
+ setContent(byId('ds_box'), tag('b', 'Loading...'));
+ obj.ds_selectedId = 0;
+ if(obj.ds_dosearch) {
+ clearTimeout(obj.ds_dosearch);
+ obj.ds_dosearch = null;
+ }
+
+ return false;
+ }
+
+ // process up/down keys
+ if(c == 38 || c == 40) {
+ var l = byName(byId('ds_box'), 'tr');
+ if(l.length < 1)
+ return true;
+
+ // get new selected id
+ if(obj.ds_selectedId == 0) {
+ if(c == 38) // up
+ obj.ds_selectedId = l[l.length-1].id.substr(7);
+ else
+ obj.ds_selectedId = l[0].id.substr(7);
+ } else {
+ var sel = null;
+ for(var i=0; i<l.length; i++)
+ if(l[i].id == 'ds_box_'+obj.ds_selectedId) {
+ if(c == 38) // up
+ sel = i>0 ? l[i-1] : l[l.length-1];
+ else
+ sel = l[i+1] ? l[i+1] : l[0];
+ }
+ obj.ds_selectedId = sel.id.substr(7);
+ }
+
+ // set selected class
+ for(var i=0; i<l.length; i++)
+ setClass(l[i], 'selected', l[i].id == 'ds_box_'+obj.ds_selectedId);
+ return true;
+ }
+
+ // perform search after a timeout
+ if(obj.ds_dosearch)
+ clearTimeout(obj.ds_dosearch);
+ obj.ds_dosearch = setTimeout(function() {
+ dsSearch(obj);
+ }, 500);
+
+ return true;
+}
+
+function dsSearch(obj) {
+ var box = byId('ds_box');
+ var val = obj.ds_parFunc ? obj.ds_parFunc(obj.value) : obj.value;
+
+ clearTimeout(obj.ds_dosearch);
+ obj.ds_dosearch = null;
+
+ // hide the ds_box div
+ if(val.length < 2) {
+ box.style.top = '-500px';
+ setContent(box, tag('b', 'Loading...'));
+ obj.ds_selectedId = 0;
+ return;
+ }
+
+ // position the div
+ var ddx=0;
+ var ddy=obj.offsetHeight;
+ var o = obj;
+ do {
+ ddx += o.offsetLeft;
+ ddy += o.offsetTop;
+ } while(o = o.offsetParent);
+
+ box.style.position = 'absolute';
+ box.style.left = ddx+'px';
+ box.style.top = ddy+'px';
+ box.style.width = obj.offsetWidth+'px';
+
+ // perform search
+ ajax(obj.ds_searchURL + encodeURIComponent(val), function(hr) {
+ dsResults(hr, obj);
+ });
+}
+
+function dsResults(hr, obj) {
+ var lst = hr.responseXML.getElementsByTagName('item');
+ var box = byId('ds_box');
+ if(lst.length < 1) {
+ setContent(box, tag('b', 'No results...'));
+ obj.selectedId = 0;
+ return;
+ }
+
+ var tb = tag('tbody', null);
+ for(var i=0; i<lst.length; i++) {
+ var id = lst[i].getAttribute('id');
+ var tr = tag('tr', {id: 'ds_box_'+id, ds_itemData: lst[i]} );
+ setClass(tr, 'selected', obj.selectedId == id);
+
+ tr.onmouseover = function() {
+ obj.ds_selectedId = this.id.substr(7);
+ var l = byName(box, 'tr');
+ for(var j=0; j<l.length; j++)
+ setClass(l[j], 'selected', l[j].id == 'ds_box_'+obj.ds_selectedId);
+ };
+ tr.onmousedown = function() {
+ obj.value = obj.ds_serFunc(this.ds_itemData, obj);
+ if(obj.ds_returnFunc)
+ obj.ds_returnFunc();
+ box.style.top = '-500px';
+ obj.ds_selectedId = 0;
+ };
+
+ obj.ds_trFunc(lst[i], tr);
+ tb.appendChild(tr);
+ }
+ setContent(box, tag('table', tb));
+
+ if(obj.ds_selectedId != 0 && !byId('ds_box_'+obj.ds_selectedId))
+ obj.ds_selectedId = 0;
+}
+
+
+
+
+/* V I S U A L N O V E L R E L A T I O N S (/v+/edit) */
+
+function vnrLoad() {
+ // read the current relations
+ var rels = byId('vnrelations').value.split('|||');
+ for(var i=0; i<rels.length && rels[0].length>1; i++) {
+ var rel = rels[i].split(',', 3);
+ vnrAdd(rel[0], rel[1], rel[2]);
+ }
+ vnrEmpty();
+
+ // make sure the title is up-to-date
+ byId('title').onchange = function() {
+ var l = byClass(byId('jt_box_vn_rel'), 'td', 'tc_title');
+ for(i=0; i<l.length; i++)
+ setText(l[i], shorten(this.value, 40));
+ };
+
+ // bind the add-link
+ byName(byClass(byId('relation_new'), 'td', 'tc_add')[0], 'a')[0].onclick = vnrFormAdd;
+
+ // dropdown
+ dsInit(byName(byClass(byId('relation_new'), 'td', 'tc_vn')[0], 'input')[0], '/xml/vn.xml?q=', function(item, tr) {
+ tr.appendChild(tag('td', { style: 'text-align: right; padding-right: 5px'}, 'v'+item.getAttribute('id')));
+ tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40)));
+ }, function(item) {
+ return 'v'+item.getAttribute('id')+':'+item.firstChild.nodeValue;
+ }, vnrFormAdd);
+}
+
+function vnrAdd(rel, vid, title) {
+ var sel = tag('select', {onchange: vnrSerialize});
+ var ops = byName(byClass(byId('relation_new'), 'td', 'tc_rel')[0], 'select')[0].options;
+ for(var i=0; i<ops.length; i++)
+ sel.appendChild(tag('option', {value: ops[i].value, selected: ops[i].value==rel}, getText(ops[i])));
+
+ byId('relation_tbl').appendChild(tag('tr', {id:'relation_tr_'+vid},
+ tag('td', {'class':'tc_vn' }, 'v'+vid+':', tag('a', {href:'/v'+vid}, shorten(title, 40))),
+ tag('td', {'class':'tc_rel' }, 'is a ', sel, ' of'),
+ tag('td', {'class':'tc_title'}, shorten(byId('title').value, 40)),
+ tag('td', {'class':'tc_add' }, tag('a', {href:'#', onclick:vnrDel}, 'del'))
+ ));
+
+ vnrEmpty();
+}
+
+function vnrEmpty() {
+ var tbl = byId('relation_tbl');
+ if(byName(tbl, 'tr').length < 1)
+ tbl.appendChild(tag('tr', {id:'relation_tr_none'}, tag('td', {colspan:4}, 'No relations selected.')));
+ else if(byId('relation_tr_none'))
+ tbl.removeChild(byId('relation_tr_none'));
+}
+
+function vnrSerialize() {
+ var r = [];
+ var trs = byName(byId('relation_tbl'), 'tr');
+ for(var i=0; i<trs.length; i++) {
+ if(trs[i].id == 'relation_tr_none')
+ continue;
+ var rel = byName(byClass(trs[i], 'td', 'tc_rel')[0], 'select')[0];
+ r[r.length] = [
+ rel.options[rel.selectedIndex].value, // relation
+ trs[i].id.substr(12), // vid
+ getText(byName(byClass(trs[i], 'td', 'tc_vn')[0], 'a')[0]) // title
+ ].join(',');
+ }
+ byId('vnrelations').value = r.join('|||');
+}
+
+function vnrDel() {
+ var tr = this;
+ while(tr.nodeName.toLowerCase() != 'tr')
+ tr = tr.parentNode;
+ byId('relation_tbl').removeChild(tr);
+ vnrSerialize();
+ vnrEmpty();
+ return false;
+}
+
+function vnrFormAdd() {
+ var relnew = byId('relation_new');
+ var txt = byName(byClass(relnew, 'td', 'tc_vn')[0], 'input')[0];
+ var sel = byName(byClass(relnew, 'td', 'tc_rel')[0], 'select')[0];
+ var lnk = byName(byClass(relnew, 'td', 'tc_add')[0], 'a')[0];
+ var input = txt.value;
+
+ if(!input.match(/^v[0-9]+/)) {
+ alert('Visual novel textbox must start with an ID (e.g. v17)');
+ return false;
+ }
+
+ txt.disabled = sel.disabled = true;
+ txt.value = 'loading...';
+ setText(lnk, 'loading...');
+
+ ajax('/xml/vn.xml?q='+encodeURIComponent(input), function(hr) {
+ txt.disabled = sel.disabled = false;
+ txt.value = '';
+ setText(lnk, 'add');
+
+ var items = hr.responseXML.getElementsByTagName('item');
+ if(items.length < 1)
+ return alert('Visual novel not found!');
+
+ var id = items[0].getAttribute('id');
+ if(byId('relation_tr_'+id))
+ return alert('This visual novel has already been selected!');
+
+ vnrAdd(sel.selectedIndex, id, items[0].firstChild.nodeValue);
+ sel.selectedIndex = 0;
+ vnrSerialize();
+ });
+ return false;
+}
+
+if(byId('vnrelations'))
+ vnrLoad();
+
+
+
+
+/* R E L E A S E M E D I A (/r+/edit) */
+
+var medTypes = [ ];
+function medLoad() {
+ // load the medTypes and clear the div
+ var sel = byName(byId('media_div'), 'select')[0].options;
+ for(var i=0; i<sel.length; i++)
+ medTypes[medTypes.length] = [ sel[i].value, getText(sel[i]), !hasClass(sel[i], 'noqty') ];
+ setText(byId('media_div'), '');
+
+ // load the selected media
+ var med = byId('media').value.split(',');
+ for(var i=0; i<med.length && med[i].length > 1; i++)
+ medAdd(med[i].split(' ')[0], Math.floor(med[i].split(' ')[1]));
+
+ medAdd('', 0);
+}
+
+function medAdd(med, qty) {
+ var qsel = tag('select', {'class':'qty', onchange:medSerialize}, tag('option', {value:0}, '- quantity -'));
+ for(var i=1; i<=20; i++)
+ qsel.appendChild(tag('option', {value:i, selected: qty==i}, i));
+
+ var msel = tag('select', {'class':'medium', onchange: med == '' ? medFormAdd : medSerialize});
+ if(med == '')
+ msel.appendChild(tag('option', {value:''}, '- medium -'));
+ for(var i=0; i<medTypes.length; i++)
+ msel.appendChild(tag('option', {value:medTypes[i][0], selected: med==medTypes[i][0]}, medTypes[i][1]));
+
+ byId('media_div').appendChild(tag('span', qsel, msel,
+ med != '' ? tag('input', {type: 'button', 'class':'submit', onclick:medDel, value:'remove'}) : null
+ ));
+}
+
+function medDel() {
+ var span = this;
+ while(span.nodeName.toLowerCase() != 'span')
+ span = span.parentNode;
+ byId('media_div').removeChild(span);
+ medSerialize();
+ return false;
+}
+
+function medFormAdd() {
+ var span = this;
+ while(span.nodeName.toLowerCase() != 'span')
+ span = span.parentNode;
+ var med = byClass(span, 'select', 'medium')[0];
+ var qty = byClass(span, 'select', 'qty')[0];
+ if(!med.selectedIndex)
+ return;
+ medAdd(med.options[med.selectedIndex].value, qty.options[qty.selectedIndex].value);
+ byId('media_div').removeChild(span);
+ medAdd('', 0);
+ medSerialize();
+}
+
+function medSerialize() {
+ var r = [];
+ var meds = byName(byId('media_div'), 'span');
+ for(var i=0; i<meds.length-1; i++) {
+ var med = byClass(meds[i], 'select', 'medium')[0];
+ var qty = byClass(meds[i], 'select', 'qty')[0];
+
+ /* correct quantity if necessary */
+ if(medTypes[med.selectedIndex][2] && !qty.selectedIndex)
+ qty.selectedIndex = 1;
+ if(!medTypes[med.selectedIndex][2] && qty.selectedIndex)
+ qty.selectedIndex = 0;
+
+ r[r.length] = medTypes[med.selectedIndex][0] + ' ' + qty.selectedIndex;
+ }
+ byId('media').value = r.join(',');
+}
+
+if(byId('jt_box_rel_format'))
+ medLoad();
+
+
+
+
+/* V I S U A L N O V E L S C R E E N S H O T U P L O A D E R (/v+/edit) */
+
+var scrRel = [ [ 0, '-- select release --' ] ];
+var scrStaticURL;
+var scrUplNr = 0;
+
+function scrLoad() {
+ // get scrRel and scrStaticURL
+ var rel = byId('scr_rel');
+ scrStaticURL = rel.className;
+ for(var i=0; i<rel.options.length; i++)
+ scrRel[scrRel.length] = [ rel.options[i].value, getText(rel.options[i]) ];
+ rel.parentNode.removeChild(rel);
+
+ // load the current screenshots
+ var scr = byId('screenshots').value.split(' ');
+ for(i=0; i<scr.length && scr[i].length>1; i++) {
+ var r = scr[i].split(',');
+ scrAdd(r[0], r[1], r[2]);
+ }
+
+ scrLast();
+ scrCheckStatus();
+ scrSetSubmit();
+}
+
+function scrSetSubmit() {
+ var frm = byId('screenshots');
+ while(frm.nodeName.toLowerCase() != 'form')
+ frm = frm.parentNode;
+ oldfunc = frm.onsubmit;
+ frm.onsubmit = function() {
+ var loading = 0;
+ var norelease = 0;
+ var l = byName(byId('scr_table'), 'tr');
+ for(var i=0; i<l.length-1; i++) {
+ if(l[i].scr_status > 0)
+ loading = 1;
+ else if(byName(l[i], 'select')[0].selectedIndex == 0)
+ norelease = 1;
+ }
+ if(loading) {
+ alert('Please wait for the screenshots to be uploaded before submitting the form.');
+ return false;
+ } else if(norelease) {
+ alert('Please select the appropriate release for every screenshot');
+ return false;
+ } else if(oldfunc)
+ return oldfunc();
+ };
+}
+
+function scrURL(id, t) {
+ return scrStaticURL+'/s'+t+'/'+(id%100<10?'0':'')+(id%100)+'/'+id+'.jpg';
+}
+
+function scrAdd(id, nsfw, rel) {
+ // tr.scr_status = 0: done, 1: uploading, 2: waiting for thumbnail, 3: deleted
+
+ var tr = tag('tr', { id:'scr_tr_'+id, scr_id: id, scr_status: id?2:1, scr_rel: rel, scr_nsfw: nsfw},
+ tag('td', { 'class': 'thumb'}, 'loading...'),
+ tag('td',
+ tag('b', id ? 'Fetching thumbnail...' : 'Uploading screenshot'),
+ tag('br', null),
+ id ? null : 'This can take a while, depending on the file size and your upload speed.',
+ tag('br', null),
+ id ? null : tag('a', {href:'#', onclick:scrDel}, 'cancel')
+ )
+ );
+ byId('scr_table').appendChild(tr);
+ scrStripe();
+ return tr;
+}
+
+function scrLast() {
+ if(byId('scr_last'))
+ byId('scr_table').removeChild(byId('scr_last'));
+ var full = byName(byId('scr_table'), 'tr').length >= 10;
+
+ byId('scr_table').appendChild(tag('tr', {id:'scr_last'},
+ tag('td', {'class': 'thumb'}),
+ full ? tag('td',
+ tag('b', 'Enough screenshots'),
+ tag('br', null),
+ 'The limit of 10 screenshots per visual novel has been reached. ',
+ 'If you want to add a new screenshot, please remove an existing one first.'
+ ) : tag('td',
+ tag('b', 'Add screenshot'),
+ tag('br', null),
+ 'Image must be smaller than 5MB and in PNG or JPEG format.',
+ tag('br', null),
+ tag('input', {name:'scr_upload', id:'scr_upload', type:'file', 'class':'text'}),
+ tag('br', null),
+ tag('input', {type:'button', value:'Upload!', 'class':'submit', onclick:scrUpload})
+ )
+ ));
+ scrStripe();
+}
+
+function scrStripe() {
+ var l = byName(byId('scr_table'), 'tr');
+ for(var i=0; i<l.length; i++)
+ setClass(l[i], 'odd', i%2==0);
+}
+
+function scrCheckStatus() {
+ var ids = [];
+ var trs = byName(byId('scr_table'), 'tr');
+ for(var i=0; i<trs.length-1; i++)
+ if(trs[i].scr_status == 2)
+ ids[ids.length] = 'id='+trs[i].scr_id;
+ if(!ids.length)
+ return setTimeout(scrCheckStatus, 1000);
+
+ var ti = setTimeout(scrCheckStatus, 10000);
+ ajax('/xml/screenshots.xml?'+ids.join(';'), function(hr) {
+ var ls = hr.responseXML.getElementsByTagName('item');
+ for(var i=0; i<ls.length; i++) {
+ var tr = byId('scr_tr_'+ls[i].getAttribute('id'));
+ if(!tr || ls[i].getAttribute('processed') != '1')
+ continue;
+ tr.scr_status = 0; // ready
+
+ // image
+ var dim = ls[i].getAttribute('width')+'x'+ls[i].getAttribute('height');
+ setContent(byName(tr, 'td')[0],
+ tag('a', {href: scrURL(tr.scr_id, 'f'), rel:'iv:'+dim+':edit'},
+ tag('img', {src: scrURL(tr.scr_id, 't')})
+ )
+ );
+
+ // content
+ var rel = tag('select', {onchange: scrSerialize, 'class':'scr_relsel'});
+ for(var j=0; j<scrRel.length; j++)
+ rel.appendChild(tag('option', {value: scrRel[j][0], selected: tr.scr_rel == scrRel[j][0]}, scrRel[j][1]));
+ var nsfwid = 'scr_sfw_'+tr.scr_id;
+ setContent(byName(tr, 'td')[1],
+ tag('b', 'Screenshot #'+tr.scr_id),
+ ' (', tag('a', {href: '#', onclick:scrDel}, 'remove'), ')',
+ tag('br', null),
+ 'Full size: '+dim,
+ tag('br', null),
+ tag('br', null),
+ tag('input', {type:'checkbox', onclick:scrSerialize, id:nsfwid, name:nsfwid, checked: tr.scr_nsfw>0, 'class':'scr_nsfw'}),
+ tag('label', {'for':nsfwid}, 'This screenshot is NSFW'),
+ tag('br', null),
+ rel
+ );
+ }
+ scrSerialize();
+ ivInit();
+ clearTimeout(ti);
+ setTimeout(scrCheckStatus, 1000);
+ });
+}
+
+function scrDel(what) {
+ var tr = what && what.scr_status != null ? what : this;
+ while(tr.nodeName.toLowerCase() != 'tr')
+ tr = tr.parentNode;
+ tr.scr_status = 3;
+ byId('scr_table').removeChild(tr);
+ scrSerialize();
+ scrLast();
+ return false;
+}
+
+function scrUpload() {
+ scrUplNr++;
+
+ // create temporary form
+ var ifid = 'scr_upl_'+scrUplNr;
+ var frm = tag('form', {method: 'post', action:'/xml/screenshots.xml', target: ifid, enctype:'multipart/form-data'});
+ var ifr = tag('iframe', {id:ifid, name:ifid, src:'about:blank', onload:scrUploadComplete});
+ addBody(tag('div', {'class':'scr_uploader'}, ifr, frm));
+
+ // submit form and delete it
+ frm.appendChild(byId('scr_upload'));
+ frm.submit();
+ frm.parentNode.removeChild(frm);
+ ifr.scr_tr = scrAdd(0, 0, 0);
+ scrLast();
+ return false;
+}
+
+function scrUploadComplete() {
+ var ifr = this;
+ var fr = window.frames[ifr.id];
+ if(fr.location.href.indexOf('screenshots') < 0)
+ return;
+
+ var tr = ifr.scr_tr;
+ if(!tr || tr.scr_status == 3)
+ return;
+
+ try {
+ tr.scr_id = fr.window.document.getElementsByTagName('image')[0].getAttribute('id');
+ } catch(e) {
+ tr.scr_id = -10;
+ }
+ if(tr.scr_id < 0) {
+ alert(
+ tr.scr_id == -10 ?
+ 'Oops! Seems like something went wrong...\n'
+ +'Make sure the file you\'re uploading doesn\'t exceed 5MB in size.\n'
+ +'If that isn\'t the problem, then please report a bug.' :
+ tr.scr_id == -1 ?
+ 'Upload failed!\nOnly JPEG or PNG images are accepted.' :
+ 'Upload failed!\nNo file selected, or an empty file?'
+ );
+ return scrDel(tr);
+ }
+
+ tr.id = 'scr_tr_'+tr.scr_id;
+ tr.scr_status = 2;
+ setContent(byName(tr, 'td')[1],
+ tag('b', 'Generating thumbnail...'),
+ tag('br', null),
+ 'Note: if this takes longer than 30 seconds, there\'s probably something wrong on our side. ',
+ 'Please try again later or report a bug if that is the case.'
+ );
+
+ // remove the <div> in a timeout, otherwise some browsers think the page is still loading
+ setTimeout(function() { ifr.parentNode.parentNode.removeChild(ifr.parentNode) }, 100);
+}
+
+function scrSerialize() {
+ var r = [];
+ var l = byName(byId('scr_table'), 'tr');
+ for(var i=0; i<l.length-1; i++)
+ if(l[i].scr_status == 0)
+ r[r.length] = [
+ l[i].scr_id,
+ byClass(l[i], 'input', 'scr_nsfw')[0].checked ? 1 : 0,
+ scrRel[byClass(l[i], 'select', 'scr_relsel')[0].selectedIndex][0]
+ ].join(',');
+ byId('screenshots').value = r.join(' ');
+}
+
+if(x('jt_box_vn_scr'))
+ scrLoad();
+
+
+
+
+/* V I S U A L N O V E L T A G L I N K I N G (/v+/tagmod) */
+
+var tglSpoilers = [ 'neutral', 'no spoiler', 'minor spoiler', 'major spoiler' ];
+
+function tglLoad() {
+ // tag dropdown search
+ dsInit(byId('tagmod_tag'), '/xml/tags.xml?q=', function(item, tr) {
+ tr.appendChild(tag('td',
+ shorten(item.firstChild.nodeValue, 40),
+ item.getAttribute('meta') == 'yes' ? tag('b', {'class':'grayedout'}, ' meta') :
+ item.getAttribute('state') == 0 ? tag('b', {'class':'grayedout'}, ' awaiting moderation') : null
+ ));
+ }, function(item) {
+ return item.firstChild.nodeValue;
+ }, tglAdd);
+ byId('tagmod_add').onclick = tglAdd;
+
+ // JS'ify the voting bar and spoiler setting
+ tglStripe();
+ var trs = byName(byId('tagtable'), 'tr');
+ for(var i=0; i<trs.length; i++) {
+ var vote = byClass(trs[i], 'td', 'tc_myvote')[0];
+ vote.tgl_vote = getText(vote)*1;
+ tglVoteBar(vote);
+
+ var spoil = byClass(trs[i], 'td', 'tc_myspoil')[0];
+ spoil.tgl_spoil = getText(spoil)*1+1;
+ setText(spoil, tglSpoilers[spoil.tgl_spoil]);
+ ddInit(spoil, 'tagmod', tglSpoilDD);
+ spoil.onclick = tglSpoilNext;
+ }
+ tglSerialize();
+}
+
+function tglSpoilNext() {
+ if(++this.tgl_spoil >= tglSpoilers.length)
+ this.tgl_spoil = 0;
+ setText(this, tglSpoilers[this.tgl_spoil]);
+ tglSerialize();
+ ddRefresh();
+}
+
+function tglSpoilDD(lnk) {
+ var lst = tag('ul', null);
+ for(var i=0; i<tglSpoilers.length; i++)
+ lst.appendChild(tag('li', i == lnk.tgl_spoil
+ ? tag('i', tglSpoilers[i])
+ : tag('a', {href: '#', onclick:tglSpoilSet, tgl_td:lnk, tgl_sp:i}, tglSpoilers[i])
+ ));
+ return lst;
+}
+
+function tglSpoilSet() {
+ this.tgl_td.tgl_spoil = this.tgl_sp;
+ setText(this.tgl_td, tglSpoilers[this.tgl_sp]);
+ ddHide();
+ tglSerialize();
+ return false;
+}
+
+function tglVoteBar(td, vote) {
+ setText(td, '');
+ for(var i=-3; i<=3; i++)
+ td.appendChild(tag('a', {
+ 'class':'taglvl taglvl'+i, tgl_num: i,
+ onmouseover:tglVoteBarSel, onmouseout:tglVoteBarSel, onclick:tglVoteBarSel
+ }, ' '));
+ tglVoteBarSel(td, td.tgl_vote);
+ return false;
+}
+
+function tglVoteBarSel(td, vote) {
+ // nasty trick to make this function multifunctional
+ if(this && this.tgl_num != null) {
+ var e = td || window.event;
+ td = this.parentNode;
+ vote = this.tgl_num;
+ if(e.type.toLowerCase() == 'click') {
+ td.tgl_vote = vote;
+ tglSerialize();
+ }
+ if(e.type.toLowerCase() == 'mouseout')
+ vote = td.tgl_vote;
+ }
+ var l = byName(td, 'a');
+ var num;
+ for(var i=0; i<l.length; i++) {
+ num = l[i].tgl_num;
+ if(num == 0)
+ setText(l[i], vote || '-');
+ else
+ setClass(l[i], 'taglvlsel', num<0&&vote<=num || num>0&&vote>=num);
+ }
+}
+
+function tglAdd() {
+ var tg = byId('tagmod_tag');
+ var add = byId('tagmod_add');
+ tag.disabled = add.disabled = true;
+ add.value = 'loading...';
+
+ ajax('/xml/tags.xml?q=name:'+encodeURIComponent(tg.value), function(hr) {
+ tg.disabled = add.disabled = false;
+ tg.value = '';
+ add.value = 'Add tag';
+
+ var items = hr.responseXML.getElementsByTagName('item');
+ if(items.length < 1)
+ return alert('Item not found!');
+ if(items[0].getAttribute('meta') == 'yes')
+ return alert('Can\'t use meta tags here!');
+
+ var name = items[0].firstChild.nodeValue;
+ var id = items[0].getAttribute('id');
+ if(byId('tgl_'+id))
+ return alert('Tag is already present!');
+
+ var vote = tag('td', {'class':'tc_myvote', tgl_vote: 2}, '');
+ tglVoteBar(vote);
+ var spoil = tag('td', {'class':'tc_myspoil', tgl_spoil: 0}, tglSpoilers[0]);
+ ddInit(spoil, 'tagmod', tglSpoilDD);
+ spoil.onclick = tglSpoilNext;
+
+ byId('tagtable').appendChild(tag('tr', {id:'tgl_'+id},
+ tag('td', {'class':'tc_tagname'}, tag('a', {href:'/g'+id}, name)),
+ vote, spoil,
+ tag('td', {'class':'tc_allvote'}, '-'),
+ tag('td', {'class':'tc_allspoil'}, '-')
+ ));
+ tglStripe();
+ tglSerialize();
+ });
+}
+
+function tglStripe() {
+ var l = byName(byId('tagtable'), 'tr');
+ for(var i=0; i<l.length; i++)
+ setClass(l[i], 'odd', i%2);
+}
+
+function tglSerialize() {
+ var r = [];
+ var l = byName(byId('tagtable'), 'tr');
+ for(var i=0; i<l.length; i++) {
+ var vote = byClass(l[i], 'td', 'tc_myvote')[0].tgl_vote;
+ if(vote != 0)
+ r[r.length] = [
+ l[i].id.substr(4),
+ vote,
+ byClass(l[i], 'td', 'tc_myspoil')[0].tgl_spoil-1
+ ].join(',');
+ }
+ byId('taglinks').value = r.join(' ');
+}
+
+if(byId('taglinks'))
+ tglLoad();
+
+
+
+
+/* R E L E A S E -> V I S U A L N O V E L L I N K I N G (/r+/edit) */
+
+function rvnLoad() {
+ var vns = byId('vn').value.split('|||');
+ for(var i=0; i<vns.length && vns[i].length>1; i++)
+ rvnAdd(vns[i].split(',',2)[0], vns[i].split(',',2)[1]);
+ rvnEmpty();
+
+ dsInit(byId('vn_input'), '/xml/vn.xml?q=',
+ function(item, tr) {
+ tr.appendChild(tag('td', {style:'text-align: right; padding-right: 5px'}, 'v'+item.getAttribute('id')));
+ tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40)));
+ }, function(item) {
+ return 'v'+item.getAttribute('id')+':'+item.firstChild.nodeValue;
+ },
+ rvnFormAdd
+ );
+ byId('vn_add').onclick = rvnFormAdd;
+}
+
+function rvnAdd(id, title) {
+ x('vn_tbl').appendChild(tag('tr', {id:'rvn_'+id, rvn_id:id},
+ tag('td', {'class':'tc_title'}, 'v'+id+':', tag('a', {href:'/v'+id}, shorten(title, 40))),
+ tag('td', {'class':'tc_rm'}, tag('a', {href:'#', onclick:rvnDel}, 'remove'))
+ ));
+ rvnStripe();
+ rvnEmpty();
+}
+
+function rvnDel() {
+ var tr = this;
+ while(tr.nodeName.toLowerCase() != 'tr')
+ tr = tr.parentNode;
+ tr.parentNode.removeChild(tr);
+ rvnEmpty();
+ rvnSerialize();
+ rvnStripe();
+ return false;
+}
+
+function rvnEmpty() {
+ var tbl = byId('vn_tbl');
+ if(byName(tbl, 'tr').length < 1)
+ tbl.appendChild(tag('tr', {id:'rvn_tr_none'}, tag('td', {colspan:2}, 'Nothing selected.')));
+ else if(byId('rvn_tr_none'))
+ tbl.removeChild(byId('rvn_tr_none'));
+}
+
+function rvnStripe() {
+ var l = byName(byId('vn_tbl'), 'tr');
+ for(var i=0; i<l.length; i++)
+ setClass(l[i], 'odd', i%2);
+}
+
+function rvnFormAdd() {
+ var txt = byId('vn_input');
+ var lnk = byId('vn_add');
+ var val = txt.value;
+
+ if(!val.match(/^v[0-9]+/)) {
+ alert('Visual novel textbox must start with an ID (e.g. v17)');
+ return false;
+ }
+
+ txt.disabled = true;
+ txt.value = 'loading...';
+ setText(lnk, 'loading...');
+
+ ajax('/xml/vn.xml?q='+encodeURIComponent(val), function(hr) {
+ txt.disabled = false;
+ txt.value = '';
+ setText(lnk, 'add');
+
+ var items = hr.responseXML.getElementsByTagName('item');
+ if(items.length < 1)
+ return alert('Visual novel not found!');
+
+ var id = items[0].getAttribute('id');
+ if(byId('rvn_'+id))
+ return alert('VN already selected!');
+
+ rvnAdd(id, items[0].firstChild.nodeValue);
+ rvnSerialize();
+ });
+ return false;
+}
+
+function rvnSerialize() {
+ var r = [];
+ var l = byName(byId('vn_tbl'), 'tr');
+ for(var i=0; i<l.length; i++)
+ if(l[i].rvn_id)
+ r[r.length] = l[i].rvn_id + ',' + getText(byName(byClass(l[i], 'td', 'tc_title')[0], 'a')[0]);
+ byId('vn').value = r.join('|||');
+}
+
+if(byId('jt_box_rel_vn'))
+ rvnLoad();
+
+
+
+
+/* R E L E A S E -> P R O D U C E R L I N K I N G (/r+/edit) */
+
+function rprLoad() {
+ var ps = byId('producers').value.split('|||');
+ for(var i=0; i<ps.length && ps[i].length>1; i++)
+ rprAdd(ps[i].split(',',2)[0], ps[i].split(',',2)[1]);
+ rprEmpty();
+
+ dsInit(byId('producer_input'), '/xml/producers.xml?q=',
+ function(item, tr) {
+ tr.appendChild(tag('td', {style:'text-align: right; padding-right: 5px'}, 'p'+item.getAttribute('id')));
+ tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40)));
+ }, function(item) {
+ return 'p'+item.getAttribute('id')+':'+item.firstChild.nodeValue;
+ },
+ rprFormAdd
+ );
+ byId('producer_add').onclick = rprFormAdd;
+}
+
+function rprAdd(id, name) {
+ x('producer_tbl').appendChild(tag('tr', {id:'rpr_'+id, rpr_id:id},
+ tag('td', {'class':'tc_name'}, 'p'+id+':', tag('a', {href:'/p'+id}, shorten(name, 40))),
+ tag('td', {'class':'tc_rm'}, tag('a', {href:'#', onclick:rprDel}, 'remove'))
+ ));
+ rprStripe();
+ rprEmpty();
+}
+
+function rprDel() {
+ var tr = this;
+ while(tr.nodeName.toLowerCase() != 'tr')
+ tr = tr.parentNode;
+ tr.parentNode.removeChild(tr);
+ rprEmpty();
+ rprSerialize();
+ rprStripe();
+ return false;
+}
+
+function rprEmpty() {
+ var tbl = byId('producer_tbl');
+ if(byName(tbl, 'tr').length < 1)
+ tbl.appendChild(tag('tr', {id:'rpr_tr_none'}, tag('td', {colspan:2}, 'Nothing selected.')));
+ else if(byId('rpr_tr_none'))
+ tbl.removeChild(byId('rpr_tr_none'));
+}
+
+function rprStripe() {
+ var l = byName(byId('producer_tbl'), 'tr');
+ for(var i=0; i<l.length; i++)
+ setClass(l[i], 'odd', i%2);
+}
+
+function rprFormAdd() {
+ var txt = byId('producer_input');
+ var lnk = byId('producer_add');
+ var val = txt.value;
+
+ if(!val.match(/^p[0-9]+/)) {
+ alert('Producer textbox must start with an ID (e.g. p17)');
+ return false;
+ }
+
+ txt.disabled = true;
+ txt.value = 'loading...';
+ setText(lnk, 'loading...');
+
+ ajax('/xml/producers.xml?q='+encodeURIComponent(val), function(hr) {
+ txt.disabled = false;
+ txt.value = '';
+ setText(lnk, 'add');
+
+ var items = hr.responseXML.getElementsByTagName('item');
+ if(items.length < 1)
+ return alert('Producer not found!');
+
+ var id = items[0].getAttribute('id');
+ if(byId('rpr_'+id))
+ return alert('Producer already selected!');
+
+ rprAdd(id, items[0].firstChild.nodeValue);
+ rprSerialize();
+ });
+ return false;
+}
+
+function rprSerialize() {
+ var r = [];
+ var l = byName(byId('producer_tbl'), 'tr');
+ for(var i=0; i<l.length; i++)
+ if(l[i].rpr_id)
+ r[r.length] = l[i].rpr_id + ',' + getText(byName(byClass(l[i], 'td', 'tc_name')[0], 'a')[0]);
+ byId('producers').value = r.join('|||');
+}
+
+if(byId('jt_box_rel_prod'))
+ rprLoad();
+
+
+
+
+/* M I S C S T U F F */
+
+// search box
+{
+ var i = byId('sq');
+ i.onfocus = function () {
+ if(this.value == 'search') {
+ this.value = '';
+ this.style.fontStyle = 'normal'
+ }
+ };
+ i.onblur = function () {
+ if(this.value.length < 1) {
+ this.value = 'search';
+ this.style.fontStyle = 'italic'
+ }
+ };
+}
+
+// VN Voting (/v+)
+if(byId('votesel')) {
+ byId('votesel').onchange = function() {
+ var s = this.options[this.selectedIndex].value;
+ 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.\n"
+ +"Are you really sure this visual novel matches that description?"))
+ return;
+ 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.\n"
+ +"It is generally a bad idea to have more than three games in your vote list with this rating, choose carefully!"))
+ return;
+ if(s)
+ location.href = location.href.replace(/\.[0-9]+/, '')+'/vote?v='+s;
+ };
+}
+
+// Advanced search (/v/*, /r)
+if(byId('advselect')) {
+ byId('advselect').onclick = function() {
+ var box = byId('advoptions');
+ var hidden = !hasClass(box, 'hidden');
+ setClass(box, 'hidden', hidden);
+ setText(byName(this, 'i')[0], hidden ? collapsed_icon : expanded_icon);
+ return false;
+ };
+}
+
+// Spoiler filters -> cookie (/v/*)
+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 ? 1 : spoil)).checked = true;
+}
+
+// NSFW VN image toggle (/v+)
+if(byId('nsfw_show')) {
+ var msg = byId('nsfw_show');
+ var img = byId('nsfw_hid');
+ byName(msg, 'a')[0].onclick = function() {
+ msg.style.display = 'none';
+ img.style.display = 'block';
+ return false;
+ };
+ img.onclick = function() {
+ msg.style.display = 'block';
+ img.style.display = 'none';
+ };
+}
+
+// NSFW toggle for screenshots (/v+)
+if(byId('nsfwhide')) {
+ byId('nsfwhide').onclick = function() {
+ var shown = 0;
+ var l = byName(byId('screenshots'), 'div');
+ for(var i=0; i<l.length; i++) {
+ if(hasClass(l[i], 'nsfw')) {
+ var hidden = !hasClass(l[i], 'hidden');
+ setClass(l[i], 'hidden', hidden);
+ setClass(byName(l[i], 'a')[0], 'hidden', hidden); // for the image viewer
+ if(!hidden)
+ shown++;
+ } else
+ shown++;
+ }
+ setText(byId('nsfwshown'), shown);
+ return false;
+ };
+}
+
+// VN Wishlist dropdown box (/v+)
+if(byId('wishsel')) {
+ byId('wishsel').onchange = function() {
+ if(this.selectedIndex != 0)
+ location.href = location.href.replace(/\.[0-9]+/, '')
+ +'/wish?s='+this.options[this.selectedIndex].value;
+ };
+}
+
+// Release list dropdown box (/r+)
+if(byId('listsel')) {
+ byId('listsel').onchange = function() {
+ if(this.selectedIndex != 0)
+ location.href = location.href.replace(/\.[0-9]+/, '')
+ +'/list?e='+this.options[this.selectedIndex].value;
+ };
+}
+
+// BBCode spoiler tags
+{
+ var l = byClass('b', 'spoiler');
+ for(var i=0; i<l.length; i++) {
+ l[i].onmouseover = function() { setClass(this, 'spoiler', false); setClass(this, 'spoiler_shown', true) };
+ l[i].onmouseout = function() { setClass(this, 'spoiler', true); setClass(this, 'spoiler_shown', false) };
+ }
+}
+
+// vndb.org domain check
+if(location.hostname != 'vndb.org') {
+ addBody(tag('div', {id:'debug'},
+ tag('h2', 'This is not VNDB!'),
+ 'The real VNDB is ',
+ tag('a', {href:'http://vndb.org/'}, 'here'),
+ '.'
+ ));
+}
+
+// make some fields readonly when patch flag is set (/r+/edit)
+if(byId('jt_box_rel_geninfo')) {
+ var func = function() {
+ byId('doujin').disabled =
+ byId('resolution').disabled =
+ byId('voiced').disabled =
+ byId('ani_story').disabled =
+ byId('ani_ero').disabled =
+ byId('patch').checked;
+ };
+ func();
+ byId('patch').onclick = func;
+}
+
+// Batch edit wishlist 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();
+ };
+}
+
+// expand/collapse listings (/*/hist, /u+/posts)
+if(byId('expandlist')) {
+ var lnk = byId('expandlist');
+ setexpand = function() {
+ var exp = getCookie('histexpand') == 1;
+ setText(lnk, exp ? 'collapse' : 'expand');
+ var tbl = lnk;
+ while(tbl.nodeName.toLowerCase() != 'table')
+ tbl = tbl.parentNode;
+ var l = byClass(tbl, 'tr', 'collapse');
+ for(var i=0; i<l.length; i++)
+ setClass(l[i], 'hidden', !exp);
+ };
+ setexpand();
+ lnk.onclick = function () {
+ setCookie('histexpand', getCookie('histexpand') == 1 ? 0 : 1);
+ setexpand();
+ return false;
+ };
+}
+
+// collapse/expand row groups (/u+/tags, /u+/list) (limited to one table on a page)
+if(byId('expandall')) {
+ var table = byId('expandall');
+ while(table.nodeName.toLowerCase() != 'table')
+ table = table.parentNode;
+ var heads = byClass(table, 'td', 'collapse_but');
+ var allhid = false;
+
+ var alltoggle = function() {
+ allhid = !allhid;
+ var l = byClass(table, 'tr', 'collapse');
+ for(var i=0; i<l.length; i++)
+ setClass(l[i], 'hidden', allhid);
+ setText(byName(byId('expandall'), 'i')[0], allhid ? collapsed_icon : expanded_icon);
+ for(var i=0; i<heads.length; i++)
+ setText(byName(heads[i], 'i')[0], allhid ? collapsed_icon : expanded_icon);
+ return false;
+ }
+ byId('expandall').onclick = alltoggle;
+ alltoggle();
+
+ var singletoggle = function() {
+ var l = byClass(table, 'tr', 'collapse_'+this.id);
+ if(l.length < 1)
+ return;
+ var hid = !hasClass(l[0], 'hidden');
+ for(var i=0; i<l.length; i++)
+ setClass(l[i], 'hidden', hid);
+ setText(byName(this, 'i')[0], hid ? collapsed_icon : expanded_icon);
+ };
+ for(var i=0; i<heads.length; i++)
+ heads[i].onclick = singletoggle;
+}
+
+// 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'}, ' meta') : null,
+ item.getAttribute('state') == 0 ? tag('b', {'class': 'grayedout'}, ' awaiting moderation') : 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);
+}
+
+
+// spam protection on all forms
+setTimeout(function() {
+ for(i=1; i<document.forms.length; i++)
+ document.forms[i].action = document.forms[i].action.replace(/\/nospam\?/,'');
+}, 500);
+
+