/* function/attribute prefixes: * date -> Date selector * dd -> dropdown * ds -> dropdown search * iv -> image viewer * jt -> Javascript Tabs * med -> Release media selector * prr -> Producer relation editor * 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 createTextNode * tag('tagname', tag(), 'string', ..) -> createElement(), appendChild(), .. * tag('tagname', { class: 'meh', title: 'Title' }) -> createElement(), setAttribute().. * tag('tagname', { }, ) -> 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 l ? v.substr(0, l-3)+'...' : v; } /* maketext function, less powerful than the Perl equivalent: * - Only supports [_n], ~[, ~] * - When it finds [quant,_n,..], it will only return the first argument (and doesn't support ~ in an argument) * assumes that a TL structure called 'L10N_STR' is defined in the header of this file */ var mt_curlang = getCookie('l10n') || 'en'; function mt() { var key = arguments[0]; var val = L10N_STR[key] ? L10N_STR[key][mt_curlang] || L10N_STR[key].en : key; for(var i=1; i= 0) val = val.replace(expr, arguments[i]); } val = val.replace(/\[quant,_\d+\,([^,]+)[^\]]+\]/g, "$1"); while(val.indexOf('~[') >= 0 || val.indexOf('~]') >= 0) val = val.replace('~[', '[').replace('~]', ']'); return val; } /* 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 4 && !hasClass(ol[i], 'hidden') && ol[i].id != 'ivprev' && ol[i].id != 'ivnext') l[l.length] = ol[i]; for(i=0;i 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; if(lnk.dd_align == 'bottom') ddy += lnk.offsetHeight; box.style.left = ddx+'px'; box.style.top = ddy+'px'; return true; } // release list dropdown on VN pages function rlDropDown(lnk) { var relid = lnk.id.substr(6); var st = getText(lnk).split(' / '); if(st[0].indexOf(mt('_js_loading')) >= 0) return null; var rs = tag('ul', tag('li', tag('b', mt('_vnpage_uopt_relrstat')))); var vs = tag('ul', tag('li', tag('b', mt('_vnpage_uopt_relvstat')))); for(var i=0; i= 0) rs.appendChild(tag('li', tag('i', val))); else rs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'r'+rlst_rstat[i], onclick:rlMod}, val))); } for(var i=0; i= 0) vs.appendChild(tag('li', tag('i', val))); else vs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'v'+rlst_vstat[i], onclick:rlMod}, val))); } 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}, mt('_vnpage_uopt_reldel')))) ); } function rlMod() { var lnk = byId('rlsel_'+this.rl_rid); ddHide(); setContent(lnk, tag('b', {'class': 'grayedout'}, mt('_js_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;i0 ? 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; i1; 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 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}, mt('_redit_form_med_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:''}, mt('_redit_form_med_medium'))); for(var i=0; i1; 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 0) loading = 1; else if(byName(l[i], 'select')[0].selectedIndex == 0) norelease = 1; } if(loading) { alert(mt('_vnedit_scr_frmloading')); return false; } else if(norelease) { alert(mt('_vnedit_scr_frmnorel')); 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'}, mt('_js_loading')), tag('td', tag('b', mt(id ? '_vnedit_scr_fetching' : '_vnedit_scr_uploading')), tag('br', null), id ? null : mt('_vnedit_scr_upl_msg'), tag('br', null), id ? null : tag('a', {href:'#', onclick:scrDel}, mt('_vnedit_scr_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', mt('_vnedit_scr_full')), tag('br', null), mt('_vnedit_scr_full_msg') ) : tag('td', tag('b', mt('_vnedit_scr_add')), tag('br', null), mt('_vnedit_scr_imgnote'), tag('br', null), tag('input', {name:'scr_upload', id:'scr_upload', type:'file', 'class':'text'}), tag('br', null), tag('input', {type:'button', value:mt('_vnedit_scr_addbut'), 'class':'submit', onclick:scrUpload}) ) )); scrStripe(); } function scrStripe() { var l = byName(byId('scr_table'), 'tr'); for(var i=0; i0, 'class':'scr_nsfw'}), tag('label', {'for':nsfwid}, mt('_vnedit_scr_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(mt(tr.scr_id == -10 ? '_vnedit_scr_oops' : tr.scr_id == -1 ? '_vnedit_scr_errformat' : '_vnedit_scr_errempty')); return scrDel(tr); } tr.id = 'scr_tr_'+tr.scr_id; tr.scr_status = 2; setContent(byName(tr, 'td')[1], tag('b', mt('_vnedit_scr_genthumb')), tag('br', null), mt('_vnedit_scr_genthumb_msg') ); // remove the
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= 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; i0&&vote>=num); } } function tglAdd() { var tg = byId('tagmod_tag'); var add = byId('tagmod_add'); tag.disabled = add.disabled = true; add.value = mt('_js_loading'); ajax('/xml/tags.xml?q=name:'+encodeURIComponent(tg.value), function(hr) { tg.disabled = add.disabled = false; tg.value = ''; add.value = mt('_tagv_add'); var items = hr.responseXML.getElementsByTagName('item'); if(items.length < 1) return alert(mt('_tagv_notfound')); if(items[0].getAttribute('meta') == 'yes') return alert(mt('_tagv_nometa')); var name = items[0].firstChild.nodeValue; var id = items[0].getAttribute('id'); if(byId('tgl_'+id)) return alert(mt('_tagv_double')); 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 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; i1; 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) { byId('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}, mt('_redit_form_vn_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}, mt('_redit_form_vn_none')))); 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 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; i1; i++) { var val = ps[i].split(',',3); rprAdd(val[0], val[1], val[2]); } 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, role, name) { var roles = byId('producer_role').options; var rl = tag('select', {onchange:rprSerialize}); for(var i=0; i1; i++) { var rel = rels[i].split(',', 3); prrAdd(rel[0], rel[1], rel[2]); } prrEmpty(); // bind the add-link byName(byClass(byId('relation_new'), 'td', 'tc_add')[0], 'a')[0].onclick = prrFormAdd; // dropdown dsInit(byName(byClass(byId('relation_new'), 'td', 'tc_prod')[0], 'input')[0], '/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; }, prrFormAdd); } function prrAdd(rel, pid, title) { var sel = tag('select', {onchange: prrSerialize}); var ops = byName(byClass(byId('relation_new'), 'td', 'tc_rel')[0], 'select')[0].options; for(var i=0; i