"use strict";
var section,
listMain, listLists, listCats, indexCats, listorder = 0, LIST_CELLS = 5,
showcat = undefined, curList = -1, curSide = 0, curHigh = -1, curHighId,
editing = false;
function $(id){
return document.getElementById(id);
}
function http(method, url, callback, body){
var r = new XMLHttpRequest();
r.onreadystatechange = function() {
if (r.readyState == 4)
callback(r.responseText);
};
r.open(method, url, true);
r.send(body);
}
function today(){
var o = new Date(),
d = [o.getDate(), o.getMonth()+1, o.getFullYear()];
for(var i = 0; i < d.length; ++i)
d[i] = (d[i] < 10 ? "0" : "")+d[i];
return d.join(".");
}
function stav(msg){
$("stav").innerHTML = msg;
}
function encode(t){
return encodeURIComponent(t);
}
function encodeObject(o){
return encode(JSON.stringify(o));
}
function log(text){
http("post", "/log:"+encode(text), noop);
}
function posunSeznam(){
var e = $("list"),
top = $("header").clientHeight;
e.style.marginTop = top+"px";
e.getElementsByTagName("thead")[0].style.top = (top-1)+"px";
}
function exit(){
document.getElementsByTagName("body")[0].innerHTML = '
';
http("post", "/exit", stav);
}
function noop(){}
function highlight(ev){
var e = ev.target;
if(e.localName == "td") e = e.parentElement;
if(e.localName != "tr") return;
if(curHigh != -1){
if(editing){
curHigh = +e.getAttribute("data-i");
newRecordCb({target: editing.getElementsByTagName("button")[0]});
return;
}
else unhighlight();
}
if(e.children.length == LIST_CELLS){
var ne = document.createElement("td");
ne.innerHTML = ''
+''
+' '
+' '
+' ';
e.appendChild(ne);
if(curList == -1) ne.children[0].children[0].style.display = "none";
}
e.className = "highlight";
curHigh = +e.getAttribute("data-i");
}
function edit(ev){
var td = ev.target.parentElement.parentElement,
tr = td.parentElement,
c = tr.children,
data = listMain[curHigh];
editing = tr;
c[0].innerHTML = '';
c[1].innerHTML = '';
c[2].innerHTML = '';
var chunks = ['')
c[3].innerHTML = chunks.join("");
c[4].innerHTML = '';
for(var i = 0; i < LIST_CELLS; ++i)
c[i].children[0].value = data[i+1];
c[0].children[0].focus();
td.innerHTML = ''
+' ';
}
function editCancel(ev){
var tr = ev.target.parentElement.parentElement,
c = tr.children,
id = tr.getAttribute("data-i"),
data = listMain[id];
editing = false;
for(var i = 0; i < 3; ++i)
c[i].innerHTML = data[i+1];
c[3].innerHTML = (data[4] != undefined && indexCats[data[4]] || "");
c[4].innerHTML = data[4+1];
tr.removeChild(c[LIST_CELLS]);
if(curHigh == id)
highlight({target: tr});
}
function remove(){
if(!confirm('Opravdu smazat "'+listMain[curHigh][2]+'"?'))
return;
editing = false;
stav("Odstraňování...");
http("post", "/list:-1:"+curHigh, updateListMainCb);
}
function unhighlight(){
if(curHigh == -1) return;
var e = document.getElementsByClassName("highlight")[0];
if(!e) return;
e.className = "";
curHigh = -1;
var c = e.children[LIST_CELLS];
if(c && c.children[0].className == "admin")
e.removeChild(c);
}
function getList(id, callback){
http("get", "/list:"+id, callback);
}
function updateListMainCb(res){
curHighId = curHigh == -1 ? undefined : listMain[curHigh][1];
try{
listMain = JSON.parse(res);
}catch(e){
stav(res);
return;
}
curHigh = -1;
for(var i = 0; i < listMain.length; ++i)
if(listMain[i][1] === curHighId){ curHigh = i; break; }
renderListMain();
stav("");
}
function setsort(col){
listorder = col + 1;
renderListMain();
}
function numericCompare(a,b){
a = a[1][listorder];
b = b[1][listorder];
var enda = 0, endb = 0;
if(typeof a == "number"){
if(typeof b == "number"){
return a - b;
}
a = a.toString();
enda = a.indexOf(".");
if(enda == -1)
enda = a.length;
++enda;
}
else if(typeof b == "number"){
b = b.toString();
endb = b.indexOf(".");
if(endb == -1)
endb = b.length;
++endb;
}
if(!enda) while(enda <= a.length && !isNaN(a.substring(0,enda))) ++enda;
if(!endb) while(endb <= b.length && !isNaN(b.substring(0,endb))) ++endb;
if(enda != endb)
return enda - endb;
return a.localeCompare(b);
}
function filterListMain(){
var list = [];
for(var i = 0; i < listMain.length; ++i){
var li = listMain[i];
if(li[0] == section && (showcat === undefined || li[4] === showcat)){
list.push([i,li]);
}
}
if(listorder>0) list.sort(numericCompare);
return list;
}
function renderListMain(){
var chunks = [], high = -1, list = filterListMain();
if(!list.length)
chunks.push('Žádná položka k zobrazení |
');
else for(var j = 0; j < list.length; ++j){
var i = list[j][0],
li = list[j][1];
for(var k = li.length; k < 6; ++k)
li[k] = "";
if(i == curHigh) high = j;
chunks.push(
'', li[1], ' | ', li[2],
' | ', li[3], ' | ',
(li[4] != undefined && indexCats[li[4]] || ""),
' | ', li[5], ' |
'
);
}
$("listbody").innerHTML = chunks.join("");
if(high != -1)
highlight({target: $("listbody").children[high]});
}
function newRecord(){
if($("newid")) {
$("newid").focus();
return;
}
var e = document.createElement("tr");
e.setAttribute("data-i","-1");
var chunks = [' | | ',
' | | | ',
' ',
' | ')
e.innerHTML = chunks.join("");
$("listbody").appendChild(e);
e.children[0].children[0].focus();
}
function newRecordCb(ev){
var tr = ev.target.parentElement.parentElement,
idx = tr.getAttribute("data-i"),
e = tr.children[0].children[0],
ne = tr.children[1].children[0],
id = e.value,
name = ne.value,
date = tr.children[2].children[0].value,
cat = tr.children[3].children[0].value,
note = tr.children[4].children[0].value;
if(!id.length){
stav("Chybí číslo");
e.focus();
return;
}
for(var i = 0; i < listMain.length; ++i)
if(section == listMain[i][0] && id == listMain[i][1] && i != idx){
stav("Číslo je již obsazené");
e.focus();
return;
}
if(!name.length){
stav("Chybí název");
ne.focus();
return;
}
if(id.length && !isNaN(id)) id = +id;
var arr = [section, id, name, date];
if(cat.length || note.length){
if(cat.length && !isNaN(cat))
cat = +cat;
arr.push(cat);
if(note.length)
arr.push(note);
}
else if(!date.length){
arr.pop();
}
stav("Ukládání...");
editing = false;
http("post", "/list:-1:"+idx+":"+encodeObject(arr), updateListMainCb);
}
function newRecordCancel(){
var e = $("newid").parentElement.parentElement;
e.parentElement.removeChild(e);
}
function exportList(){
var table = [["Číslo","Název","Kategorie","Poznámka"]]; // idx 1, 2, *4, 5
var list = filterListMain();
if(!list.length)
table.push(["","Žádná položka k zobrazení"]);
else for(var i = 0; i < list.length; ++i){
var li = list[i][1];
var row = [li[1], li[2]];
if(li.length > 4 && (typeof li[4] == "number" || (li.length > 5 && li[5].length) )) { // cat or note present
if(typeof li[4] == "number")
row.push(indexCats[li[4]]);
else if(li.length > 5 && li[5].length)
row.push("");
if(li.length > 5 && li[5].length)
row.push(li[5]);
}
table.push(row);
}
exportTable(
$("sectionswitch").children[section].innerHTML
+ (showcat === undefined ? "" : (" - " + indexCats[li[4]]))
+ " - " + new Date().toLocaleDateString(),
table
);
}
function exportSubList(){
getList(listID(curList), exportSubListCb);
}
function exportSubListCb(items){
items = JSON.parse(items);
var table = [["","Číslo","Název","Poznámka"]]; // idx #, *1, *2, *5
if(!items.length)
table.push(["","","Seznam je prázdný"])
else for(var i = 0; i < items.length; ++i){
var name = '(odstraněná)',
note, id = items[i];
for(var j = 0; j < listMain.length; ++j){
if(listMain[j][0] == section && listMain[j][1] == id){
name = listMain[j][2];
note = listMain[j][5];
break;
}
}
var row = [i+1+".", id, name];
if(typeof note != "undefined")
row.push(note);
table.push(row);
}
exportTable(listName(curList), table);
}
function exportTable(title, table){
var colWidth = [];
for(var i = 0; i < table[0].length; ++i)
colWidth[i] = 0;
for(var i = 0; i < table.length; ++i)
for(var j = 0; j < table[i].length; ++j) {
switch(typeof table[i][j]) {
case "undefined": table[i][j] = ""; break;
case "string": break;
case "number": table[i][j] = table[i][j].toString(); break;
}
if(colWidth[j] < table[i][j].length)
colWidth[j] = table[i][j].length;
}
var rows = [title,"=================================================="];
for(var i = 0; i < table.length; ++i) {
for(var j = 0; j < table[i].length; ++j) {
if(j+1 < table[i].length) {
while(table[i][j].length < colWidth[j])
table[i][j] += " ";
}
}
rows.push(table[i].join(" "));
}
exportFile(title + ".txt", rows.join("\n"));
}
function exportFile(name, content){
let a = document.createElement('a');
a.href = URL.createObjectURL(new Blob([content], {type: 'text/plain'}));
a.download = name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
function listID(i){
return listLists[i][1];
}
function listName(i){
return listLists[i][2];
}
function newSide(){
if($("newname")) return;
var e = document.createElement("div");
e.innerHTML = '';
$("sidebar").appendChild(e);
$("newname").focus();
posunSeznam();
}
function newSideCb(){
var name = $("newname").value;
if(!name.length) return;
stav("Vytváření...");
var newid = 0;
var list = curSide == 1 ? listCats : listLists;
for(var i = 0; i < list.length; ++i)
if(list[i][1] > newid)
newid = list[i][1]; // last used cats/lists list entry id
if(curSide == 1)
for(var i = 0; i < listMain.length; ++i)
if(listMain[i][4] > newid)
newid = listMain[i][4]; // last used cat id
++newid;
http("post", "/list:"+(curSide-4)+":-1:"+encodeObject([section, newid, name]), function(res){
var list;
try{
list = JSON.parse(res);
}catch(e){
stav(res);
return;
}
if(curSide == 1){
updateListCats(list);
showCats();
var e = document.getElementsByClassName("newcat");
for(var i = 0; i < e.length; ++i){
var ne = document.createElement("option");
ne.value = newid
ne.innerHTML = name
e[i].appendChild(ne);
}
}
else{
listLists = list;
showLists();
}
stav("");
});
}
function showList(i){
$("sublistname").innerHTML = listName(i);
$("sublistbody").innerHTML = 'Načítání seznamu... |
'
$("sublist").style.display = "";
curList = i;
posunSeznam();
getList(listID(i), showListCb);
}
function showListCb(items){
items = JSON.parse(items);
var chunks = [];
if(!items.length)
chunks.push('Seznam je prázdný |
')
else for(var i = 0; i < items.length; ++i){
var name = '(odstraněná)',
note, id = items[i];
for(var j = 0; j < listMain.length; ++j){
if(listMain[j][0] == section && listMain[j][1] == id){
name = listMain[j][2];
note = listMain[j][5];
break;
}
}
chunks.push(
'', (i+1), ' | ', id,
' | ', name, ' | ', note, ' | '
);
if(i > 0)
chunks.push('');
chunks.push(' | ');
if(i < items.length - 1)
chunks.push('');
chunks.push(
' | |
'
);
}
$("sublistbody").innerHTML = chunks.join("");
var la = document.getElementsByClassName("listAdd");
for(var i = 0; i < la.length; ++i)
la[i].style.display = "";
closeSidebar();
//posunSeznam();
}
function listUpdateFn(str){
http("post", "/list:"+listID(curList)+str, function(res){
try{
JSON.parse(res);
showListCb(res);
stav("");
}catch(e){
stav(res);
}
});
}
function listAdd(){
if(curList == -1 || curHigh == -1) return;
var id = listMain[curHigh][1];
stav("Přidávání do seznamu...");
listUpdateFn(":-1:"+encodeObject(id));
}
function listSwap(i){
stav("Změna pořadí v seznamu...");
listUpdateFn(":"+i+":s");
}
function listRemove(i){
if(!confirm('Opravdu odstranit položku ze seznamu?'))
return;
stav("Odstraňování ze seznamu...");
listUpdateFn(":"+i)
}
function renameList(){
var e = $("sublistname");
if(e.children.length) return;
e.innerHTML = ''
+'>';
e = $("newname");
e.value = listName(curList);
e.focus();
}
function renameListCb(){
var i = curList;
var n = $("newname").value;
stav("Přejmenování seznamu...");
http("post", "/list:-2:"+curList+":"+encodeObject([section, listID(curList), n]),
function(res){
try{
listLists = JSON.parse(res);
}catch(e){
stav(res);
return;
}
if(curSide == 2)
showLists();
if(curList == i)
$("sublistname").innerHTML = n;
stav("");
}
);
}
function deleteList(){
if(!confirm('Opravdu odstranit seznam "'+listName(curList)+'"?'))
return;
stav("Odstraňování seznamu...");
http("post", "/list:-2:"+curList, function(res){
closeList();
try{
listLists = JSON.parse(res);
}catch(e){
stav(res);
return;
}
if(curSide == 2)
showLists();
stav("");
});
}
function closeList(){
var la = document.getElementsByClassName("listAdd");
for(var i = 0; i < la.length; ++i)
la[i].style.display = "none";
curList = -1;
$("sublist").style.display = "none";
posunSeznam();
}
function showSide(){
var chunks = [
'',
curSide == 1 ? "Kategorie" : "Seznamy",
'',
'
',
], list, show;
if(curSide == 1){
list = listCats;
show = 'Cat';
} else {
list = listLists;
show = 'List'
}
var olen = chunks.length;
for(var i = list.length - 1; i >= 0; --i)
if(list[i][0] == section)
chunks.push('',
list[i][2], '
');
if(olen == chunks.length)
chunks.push('Žádná položka k zobrazení
');
$("sidebar").innerHTML = chunks.join("");
posunSeznam();
}
function showLists(){
curSide = 2;
closeList();
showSide();
}
function showCats(){
curSide = 1;
showSide();
}
function showCat(i){
$("resetcat").style.display = "";
showcat = listCats[i][1];
renderListMain();
}
function resetCat(){
$("resetcat").style.display = "none";
showcat = undefined;
renderListMain();
}
function closeSidebar(){
curSide = 0;
$("sidebar").innerHTML = "";
posunSeznam();
}
function renderLists(){
renderListMain();
if(curSide == 1)
showCats();
else if(curSide == 2)
showLists();
if(curList != -1)
showList(curList);
}
function updateListCats(data){
listCats = data;
indexCats = [];
for(var i = 0; i < listCats.length; ++i)
indexCats[listCats[i][1]] = listCats[i][2];
}
function initLists(data){
data = JSON.parse(data);
listMain = data[0];// [ [section, cislo, nazev, datum_zarazeni, kategorie, poznamka] ]
listLists = data[1];// [ [section, serial, popis="Aktuální seznam"] ]
initSectionSwitch();
updateListCats(data[2]);
renderLists();
stav("");
}
function updatePerms(perms){
switch(+perms){
case 0: document.body.className = "nolocal noadmin"; break;
case 1: document.body.className = "nolocal"; break;
case 2: document.body.className = ""; break;
}
$("login").style.display = perms == 0 ? "" : "none";
$("logout").style.display = perms == 1 ? "" : "none";
posunSeznam();
}
function loginForm(){
$("loginform").style.display = "";
$("login").style.display = "none";
$("loginpw").focus();
posunSeznam();
}
function login(){
http("post", "/login", updatePerms, $("loginpw").value);
loginClose();
}
function loginClose(){
$("loginform").style.display = "none";
$("login").style.display = "";
$("loginpw").value = "";
posunSeznam();
}
function logout(){
http("post", "/login", function(){updatePerms(0);});
}
function initSectionArg(){
var l = document.location.href;
l = +l.substring(l.lastIndexOf("/")+2);
section = isNaN(l) ? 0 : l;
}
function initSectionSwitch(){
var e = $("sectionswitch");
var l = [];
for(var i = 0; i < listMain.length; ++i)
if(listMain[i][0] == -1)
l[listMain[i][1]] = "";
e.innerHTML = l.join(" ");
e = e.children[section];
e.innerHTML = e.children[0/* button, the only child */].innerHTML;
}
function newSection(){
$("newsection").style.display = "none";
$("newsectionform").style.display = "";
$("newsectionname").focus();
}
function newSectionCb(){
var name = $("newsectionname").value;
if(!name.length)
return;
stav("Vytváření sekce...");
newSectionClose();
var e = $("sectionswitch");
http("post", "/list:-1:-1:"+encodeObject([-1, e.children.length, name]), loadLists);
}
function newSectionClose(){
$("newsectionform").style.display = "none";
$("newsectionname").value = "";
$("newsection").style.display = "";
}
function switchSection(ev){
if(ev.target.localName != 'button')
return;
var p = ev.target.parentElement, // span
sections = p.parentElement.children; // #sectionswitch
var id = -1;
for(var i = 0; i < sections.length; ++i)
if(sections[i] == p){
id = i;
break;
}
if(id < 0)
return;
var prev = sections[section];
prev.innerHTML = '';
section = id;
if(typeof history.pushState == 'function'){
history.pushState(undefined, "", ":"+id);
}
p.innerHTML = ev.target.innerHTML;
if(curList != -1)
closeList();
renderLists();
}
function loadLists(){
stav("Načítání...");
getList(-4, initLists);
}
function loadPerms(){
http("get", "/perms", updatePerms);
}
window.onkeyup = function(ev){
if(ev.target == document.body && (ev.keyCode == 49 /*+*/ || ev.keyCode == 107 /*Num+*/))
newRecord();
else if(ev.keyCode == 13 && ev.target.tagName == "INPUT"){
switch(ev.target.parentElement.tagName){
case "DIV": case "SPAN":
ev.target.nextElementSibling.focus();
break;
case "TD":
ev.target.parentElement.nextElementSibling.children[0].focus();
break;
}
}
};
log(navigator.userAgent);
initSectionArg();
loadLists();
loadPerms();