246 lines
7.1 KiB
JavaScript
246 lines
7.1 KiB
JavaScript
/* The following functions are part of a minimal JS library I wrote for VNDB.org */
|
|
|
|
var expanded_icon = '▾';
|
|
var collapsed_icon = '▸';
|
|
|
|
var http_request = false;
|
|
function ajax(url, func, async) {
|
|
if(!async && http_request)
|
|
http_request.abort();
|
|
var req = (window.ActiveXObject) ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
|
|
if(req == null)
|
|
return alert("Your browser does not support the functionality this website requires.");
|
|
if(!async)
|
|
http_request = req;
|
|
req.onreadystatechange = function() {
|
|
if(!req || req.readyState != 4 || !req.responseText)
|
|
return;
|
|
if(req.status != 200)
|
|
return alert('Whoops, error! :(');
|
|
func(req);
|
|
};
|
|
url += (url.indexOf('?')>=0 ? ';' : '?')+(Math.floor(Math.random()*999)+1);
|
|
req.open('GET', url, true);
|
|
req.send(null);
|
|
}
|
|
|
|
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 t = arguments.length == 2 && typeof arguments[0] == 'string' ? arguments[0] : arguments.length == 3 ? arguments[1] : '*';
|
|
var c = arguments[arguments.length-1];
|
|
var l = byName(par, t);
|
|
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 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(' ');
|
|
}
|
|
|
|
|
|
|
|
// The tabs on man pages
|
|
(function(){
|
|
var ul = byId('manbuttons');
|
|
if(!ul)
|
|
return;
|
|
var res = byId('manres');
|
|
ul = byName(ul, 'ul')[0];
|
|
|
|
|
|
var table = function(tbl, prop) {
|
|
var t = tag('table', prop);
|
|
for(row in tbl) {
|
|
row = tbl[row];
|
|
var r = tag('tr', {});
|
|
for(col in row) {
|
|
col = row[col];
|
|
r.appendChild(tag('td',
|
|
col.bold ? tag('b', col.name) :
|
|
col.href ? tag('a', {href:col.href}, col.name) : col.name
|
|
));
|
|
}
|
|
t.appendChild(r);
|
|
}
|
|
return t;
|
|
};
|
|
|
|
var treeoldver = function() {
|
|
var lnk = this;
|
|
var ul = lnk;
|
|
var show = !lnk['data-shown'];
|
|
lnk['data-shown'] = show;
|
|
|
|
while(ul.nodeName.toLowerCase() != 'ul')
|
|
ul = ul.parentNode;
|
|
var l = ul.childNodes;
|
|
for(var i=0; i<l.length; i++) {
|
|
if(l[i].nodeName.toLowerCase() == 'li' && l[i]['data-oldver'])
|
|
setClass(l[i], 'hidden', !show);
|
|
}
|
|
|
|
setText(lnk, (show ? '- ' : '+ ')+lnk['data-hidnum']+' older versions');
|
|
return false;
|
|
};
|
|
|
|
var treeexpand = function() {
|
|
var sub = byName(this.parentNode, 'ul')[0] || byName(this.parentNode, 'table')[0];
|
|
var exp = hasClass(sub, 'hidden');
|
|
setClass(sub, 'hidden', !exp);
|
|
setText(this, getText(this).replace(/^[^ ]+/, exp ? expanded_icon : collapsed_icon));
|
|
return false;
|
|
};
|
|
|
|
var treeitem = function(n) {
|
|
var icon = n.name ? (n.expand ? expanded_icon : collapsed_icon)+' ' : '';
|
|
return tag('li', n.hide ? {'class':'hidden', 'data-oldver':true} : {},
|
|
tag('a', {href:'#', onclick: treeexpand}, icon+n.name),
|
|
n.i ? tag('i', n.i) : null,
|
|
n.childs ? treelist(n.childs, n.expand ? {} : {'class':'hidden'}) : null,
|
|
n.table ? table(n.table, n.expand ? {} : {'class':'hidden'}) : null
|
|
);
|
|
};
|
|
|
|
var treelist = function(lst, prop) {
|
|
var ul = tag('ul', prop);
|
|
var hidden = 0;
|
|
|
|
for(i in lst) {
|
|
var n = lst[i];
|
|
if(n.hide)
|
|
hidden++;
|
|
ul.appendChild(treeitem(lst[i]));
|
|
}
|
|
|
|
if(hidden > 0)
|
|
ul.appendChild(tag('li', {'class':'oldver'},
|
|
tag('a', {href:'#', onclick: treeoldver, 'data-hidnum':hidden}, '+ '+hidden+' older versions')
|
|
));
|
|
return ul;
|
|
};
|
|
|
|
var clearactive = function() {
|
|
setClass(res, 'hidden', true);
|
|
var l = byName(ul, 'a');
|
|
for(var i=0; i<l.length; i++) {
|
|
setClass(l[i], 'active', false);
|
|
if(l[i]['data-obj'])
|
|
setClass(l[i]['data-obj'], 'hidden', true);
|
|
}
|
|
return false;
|
|
};
|
|
|
|
var loading = tag('div', {'class':'hidden'}, 'Loading...');
|
|
|
|
var buttonclick = function() {
|
|
var btn = this;
|
|
var isactive = hasClass(btn, 'active');
|
|
clearactive();
|
|
if(isactive)
|
|
return false;
|
|
|
|
if(btn['data-obj']) {
|
|
setClass(btn['data-obj'], 'hidden', false);
|
|
} else {
|
|
setClass(loading, 'hidden', false);
|
|
ajax(btn['data-url'], function(r) {
|
|
setClass(loading, 'hidden', true);
|
|
r = JSON.parse(r.responseText);
|
|
btn['data-obj'] = tag('div', tag('p', btn['data-p']), treelist(r, {}));
|
|
res.appendChild(btn['data-obj']);
|
|
});
|
|
}
|
|
setClass(btn, 'active', true);
|
|
setClass(res, 'hidden', false);
|
|
return false;
|
|
};
|
|
|
|
res.insertBefore(tag('a', {id:'closebtn', href:'#', onclick: clearactive}, 'X'), res.firstChild);
|
|
res.appendChild(loading);
|
|
|
|
(function(){
|
|
var name = ul.getAttribute('data-name');
|
|
var hash = ul.getAttribute('data-hash');
|
|
var section = ul.getAttribute('data-section');
|
|
var locale = ul.getAttribute('data-locale');
|
|
|
|
ul.insertBefore(tag('li', ul.getAttribute('data-hasversions') > 0
|
|
? tag('a', {href:'#', onclick: buttonclick,
|
|
'data-url': '/json/tree.json?name='+name+';section='+section+';locale='+locale+';cur='+hash,
|
|
'data-p': 'Different versions of this manual page are available.'},
|
|
'versions')
|
|
: tag('i', 'versions')
|
|
), ul.childNodes[ul.childNodes.length-1]);
|
|
})();
|
|
})();
|