2022-11-21 23:17:07 +00:00
|
|
|
<script>
|
|
|
|
|
|
|
|
var E = {
|
|
|
|
elemid: function(id, cback) { const e = document.getElementById(id); return E.do(e, cback) },
|
|
|
|
element: function(q, cback) { const e = document.querySelector(q); return E.do(e, cback) },
|
|
|
|
elements: function(q, cback) { const e = document.querySelectorAll(q); return E.do(e, cback) },
|
|
|
|
do: function(e, cback) {
|
|
|
|
if (typeof cback === 'function' && e !== null && e !== undefined)
|
|
|
|
return cback(e);
|
|
|
|
return e;
|
|
|
|
},
|
|
|
|
class: {
|
|
|
|
removeAll: function(elems, cls) {
|
|
|
|
if (typeof elems === 'string') elems = E.elements(elems);
|
|
|
|
elems.forEach(function(it) {
|
|
|
|
it.classList !== undefined &&
|
|
|
|
it.classList.remove(cls) });
|
|
|
|
},
|
|
|
|
addAll: function(elems, cls) {
|
|
|
|
if (typeof elems === 'string') elems = E.elements(elems);
|
|
|
|
elems.forEach(function(it) {
|
|
|
|
it.classList !== undefined &&
|
|
|
|
it.classList.add(cls) });
|
|
|
|
},
|
|
|
|
setAll: function(elems, cls) {
|
|
|
|
if (typeof elems === 'string') elems = E.elements(elems);
|
|
|
|
elems.forEach(function(it) { it.className = cls });
|
|
|
|
},
|
|
|
|
},
|
|
|
|
removeAll: function(query) {
|
|
|
|
return E.remove(E.elements(query));
|
|
|
|
},
|
|
|
|
remove: function(query) {
|
|
|
|
if (typeof query === 'string') {
|
|
|
|
const _ = E.element(query);
|
|
|
|
if (_ !== null) _.remove();
|
|
|
|
} else if (query instanceof NodeList) {
|
|
|
|
for (var i = 0; i < query.length; i++)
|
|
|
|
query[i].remove();
|
|
|
|
} else if (query instanceof Object) {
|
|
|
|
query.remove();
|
|
|
|
}
|
|
|
|
},
|
2022-11-23 00:18:34 +00:00
|
|
|
template: function(_id, cback) {
|
2022-11-25 00:44:03 +00:00
|
|
|
var tpl = E.elemid(_id+'-item');
|
|
|
|
if (tpl !== null) {
|
|
|
|
tpl = tpl.outerHTML;
|
|
|
|
tpl = tpl.replace('id="'+_id+'-item"','class="item"');
|
|
|
|
tpl = tpl.replace('data-src=', 'src=');
|
|
|
|
}
|
|
|
|
var elem = null;
|
|
|
|
elem = E.elemid(_id);
|
|
|
|
if (elem === null)
|
|
|
|
elem = E.element(_id);
|
|
|
|
if (elem === null)
|
|
|
|
return;
|
|
|
|
if (typeof cback === 'string')
|
|
|
|
elem.innerText = cback;
|
|
|
|
else elem.innerHTML = cback(tpl);
|
2022-11-23 00:18:34 +00:00
|
|
|
},
|
2022-11-28 02:03:20 +00:00
|
|
|
http_template: function(name, cback) {
|
|
|
|
const slug = 'html_cache__'+name.replaceAll('/','--');
|
|
|
|
if (window.cache.http === undefined)
|
|
|
|
window.cache.http = {};
|
|
|
|
if (window.cache.http[slug] !== undefined)
|
|
|
|
return cback(window.cache.http[slug]);
|
|
|
|
|
|
|
|
http.get('js/templates/'+name+'.html',
|
|
|
|
{}, function(data) {
|
|
|
|
data = data.trim();
|
|
|
|
window.cache.http[slug] = data;
|
|
|
|
cback(data);
|
|
|
|
});
|
|
|
|
},
|
2022-12-03 17:54:18 +00:00
|
|
|
custom: {
|
|
|
|
btncollapse_render: function() {
|
|
|
|
E.elements('button[id*="btncollapse-"]').forEach(function(it) {
|
|
|
|
it.setAttribute('onclick', 'E.custom.btncollapse_click(this)');
|
|
|
|
});
|
|
|
|
},
|
|
|
|
btncollapse_click: function(elem) {
|
|
|
|
const stat = elem.innerText.trim().toLowerCase();
|
|
|
|
const refelem = E.elemid(elem.id.replace('btncollapse-',''));
|
|
|
|
if (stat === 'hide') {
|
|
|
|
elem.innerText = 'show';
|
|
|
|
refelem.style.visibility = 'collapse';
|
|
|
|
refelem.style.height = '1px';
|
|
|
|
refelem.style.padding = 0;
|
|
|
|
refelem.style.margin = 0;
|
|
|
|
} else {
|
|
|
|
elem.innerText = 'hide';
|
|
|
|
refelem.removeAttribute('style');
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
2022-11-21 23:17:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
function isVisible(element) {
|
|
|
|
const rect = element.getBoundingClientRect();
|
|
|
|
return (
|
|
|
|
rect.top >= 0 &&
|
|
|
|
rect.left >= 0 &&
|
|
|
|
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
|
|
|
|
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function html2text(html) {
|
|
|
|
var e = document.createElement('div');
|
|
|
|
e.innerHTML = html;
|
|
|
|
const result = e.innerText;
|
|
|
|
e.remove();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
function JSON_to_URLEncoded(element,key,list) {
|
|
|
|
var list = list || [];
|
|
|
|
if (typeof(element) == 'object') {
|
|
|
|
for (var idx in element)
|
|
|
|
JSON_to_URLEncoded(element[idx],key?key+'['+idx+']':idx,list);
|
|
|
|
} else {
|
|
|
|
list.push(key+'='+encodeURIComponent(element));
|
|
|
|
}
|
|
|
|
return list.join('&');
|
|
|
|
}
|
|
|
|
|
|
|
|
// source: https://www.geeksforgeeks.org/how-to-get-the-javascript-function-parameter-names-values-dynamically/
|
|
|
|
function _get_func_params(func) {
|
|
|
|
// String representaation of the function code
|
|
|
|
var str = func.toString();
|
|
|
|
// Remove comments of the form /* ... */
|
|
|
|
// Removing comments of the form //
|
|
|
|
// Remove body of the function { ... }
|
|
|
|
// removing '=>' if func is arrow function
|
|
|
|
str = str.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
|
|
.replace(/\/\/(.)*/g, '')
|
|
|
|
.replace(/{[\s\S]*}/, '')
|
|
|
|
.replace(/=>/g, '')
|
|
|
|
.trim();
|
|
|
|
// Start parameter names after first '('
|
|
|
|
var start = str.indexOf("(") + 1;
|
|
|
|
// End parameter names is just before last ')'
|
|
|
|
var end = str.length - 1;
|
|
|
|
var result = str.substring(start, end).split(", ");
|
|
|
|
var params = [];
|
|
|
|
result.forEach(element => {
|
|
|
|
// Removing any default value
|
|
|
|
element = element.replace(/=[\s\S]*/g, '').trim();
|
|
|
|
if(element.length > 0)
|
|
|
|
params.push(element);
|
|
|
|
});
|
|
|
|
return params;
|
|
|
|
}
|
|
|
|
|
2022-12-05 15:31:15 +00:00
|
|
|
function del_hash_argument(key, fireevent) {
|
|
|
|
const hargs = get_hash_arguments();
|
|
|
|
if (hargs[key] === undefined) return;
|
|
|
|
|
|
|
|
fireevent = fireevent === undefined ? true : fireevent;
|
|
|
|
console.log(`DEL hash-argument: ${key} (fireevent: ${fireevent})`);
|
|
|
|
if (fireevent) delete window.hash_argument_nofirechange;
|
|
|
|
else window.hash_argument_nofirechange = true;
|
|
|
|
|
2022-11-28 13:25:12 +00:00
|
|
|
var hash = window.location.hash;
|
|
|
|
hash = hash.replace(new RegExp(';?'+key+'=[^;]+'),'');
|
|
|
|
hash = hash.replace('/;','/');
|
|
|
|
window.location.hash = hash;
|
|
|
|
}
|
|
|
|
|
2022-12-05 15:31:15 +00:00
|
|
|
function set_hash_argument(key, val, fireevent) {
|
|
|
|
fireevent = fireevent === undefined ? true : fireevent;
|
|
|
|
console.log(`SET hash-argument "${key}": ${val} (fireevent: ${fireevent})`);
|
|
|
|
if (fireevent) delete window.hash_argument_nofirechange;
|
|
|
|
else window.hash_argument_nofirechange = true;
|
|
|
|
|
2022-11-28 13:25:12 +00:00
|
|
|
var hargs = get_hash_arguments();
|
|
|
|
if (hargs[key] === undefined) {
|
|
|
|
window.location.hash += ';'+key+'='+val;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var hash = window.location.hash;
|
|
|
|
hash = hash.replace(new RegExp(key+'=[^;]+'),`${key}=${val}`);
|
|
|
|
window.location.hash = hash;
|
|
|
|
}
|
|
|
|
|
2022-11-28 02:03:20 +00:00
|
|
|
function get_hash_arguments() {
|
|
|
|
var args = window.location.hash.substring(1).trim().split('/');
|
|
|
|
if (args.length > 0 && args[0].trim() === '')
|
|
|
|
args = [];
|
|
|
|
return parse_hash_arguments(args[args.length-1]);
|
|
|
|
}
|
|
|
|
|
2022-11-24 23:21:52 +00:00
|
|
|
function parse_ini_config(str) { return parse_hash_arguments(str, '\n') }
|
|
|
|
function parse_hash_arguments(str,by) {
|
|
|
|
by = by || ';';
|
2022-11-24 01:34:20 +00:00
|
|
|
var args = {};
|
2022-11-24 23:21:52 +00:00
|
|
|
const ps = str.trim().split(by);
|
2022-11-24 01:34:20 +00:00
|
|
|
for (var i = 0; i < ps.length; i++) {
|
2022-11-24 23:21:52 +00:00
|
|
|
if (!ps[i].includes('='))
|
|
|
|
continue;
|
2022-11-24 01:34:20 +00:00
|
|
|
const k = ps[i].substr(0,ps[i].indexOf('='));
|
|
|
|
const v = ps[i].substr(ps[i].indexOf('=')+1);
|
|
|
|
if (k.trim() === '')
|
|
|
|
continue;
|
|
|
|
args[k] = v;
|
|
|
|
}
|
|
|
|
return args;
|
2022-11-23 00:18:34 +00:00
|
|
|
}
|
2022-11-24 01:34:20 +00:00
|
|
|
|
2022-11-25 00:44:03 +00:00
|
|
|
function human_field_name(str) {
|
|
|
|
str = ' '+str+' ';
|
|
|
|
return capitalize(
|
|
|
|
str.replaceAll('_', ' ')
|
|
|
|
.replaceAll(' api ',' API ')
|
|
|
|
.replaceAll(' db ',' DB ')
|
|
|
|
.replaceAll(' url ',' URL ')
|
|
|
|
.replaceAll(' psql ',' Postgres ')
|
|
|
|
.trim()
|
|
|
|
);
|
|
|
|
}
|
2022-12-05 15:31:15 +00:00
|
|
|
function sleep(ms){ return new Promise(resolve => setTimeout(resolve, ms)) }
|
2022-11-24 01:34:20 +00:00
|
|
|
function capitalize(str) { return str[0].toUpperCase() + str.substring(1) }
|
2022-11-21 23:17:07 +00:00
|
|
|
function printstack() { console.error(new Error().stack) }
|
|
|
|
function uuidv4() {
|
|
|
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
|
|
|
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
|
|
|
return v.toString(16);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
const http = {
|
|
|
|
request: function(method, path, payload, callbk) {
|
|
|
|
//console.log(path); printstack();
|
|
|
|
const httpdiv = document.getElementById('http');
|
|
|
|
const httpts = new Date().getTime();
|
|
|
|
if (httpdiv !== null)
|
|
|
|
httpdiv.innerHTML += '<div id="http-'+httpts+'">'+method+' '+path+'</div>';
|
|
|
|
payload = payload || null;
|
|
|
|
callbk = callbk || null;
|
|
|
|
const oReq = new XMLHttpRequest();
|
|
|
|
oReq.addEventListener("load", function() {
|
|
|
|
if (httpdiv !== null) {
|
|
|
|
const hit = document.getElementById('http-'+httpts);
|
|
|
|
if (hit !== null) hit.remove();
|
|
|
|
}
|
|
|
|
if (callbk) {
|
|
|
|
const ps = _get_func_params(callbk);
|
|
|
|
if (ps.includes('data') || ps.includes('text') ||
|
|
|
|
ps.includes('html') || ps.includes('plain'))
|
|
|
|
callbk(this.responseText);
|
|
|
|
else if (ps.includes('json') || ps.includes('js')) {
|
|
|
|
try { callbk(JSON.parse(this.responseText)) }
|
|
|
|
catch (SyntaxError) { callbk(undefined) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
oReq.open(method, path);
|
|
|
|
oReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
|
|
|
oReq.send(JSON_to_URLEncoded(payload));
|
|
|
|
},
|
|
|
|
get: function(path, payload, callbk) {
|
|
|
|
return http.request('GET', path, payload, callbk);
|
|
|
|
},
|
|
|
|
post: function(path, payload, callbk) {
|
|
|
|
return http.request('POST', path, payload, callbk);
|
|
|
|
},
|
|
|
|
API: {
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const toast = {
|
|
|
|
error: function(text, timeo) {
|
|
|
|
timeo = timeo || 7000;
|
|
|
|
return toast._show(text, 'error', 'exclamation-triangle', timeo);
|
|
|
|
},
|
|
|
|
info: function(text, timeo) {
|
|
|
|
timeo = timeo || 5000;
|
|
|
|
return toast._show(text, 'info', 'info-circle', timeo)
|
|
|
|
},
|
|
|
|
_show: function(text, type, fa, timeo) {
|
|
|
|
const id = 'toast-'+(new Date()).getTime();
|
|
|
|
var div = document.createElement('div');
|
|
|
|
div.id = id;
|
|
|
|
div.className = 'toast-container';
|
|
|
|
div.setAttribute('onclick', 'this.remove()');
|
|
|
|
div.innerHTML = '<div class="toast '+type+'"><p style="margin: auto 0 !important;font-size: 1.2em;line-height: 1.8em;">'+
|
|
|
|
'<i style="margin-right: 1em;font-size: 1.2em;position:relative;top:.1em" class="fa fa-'+fa+'"></i>'+text+'</p></div>';
|
|
|
|
document.body.appendChild(div);
|
|
|
|
setTimeout(function() {
|
|
|
|
const el = document.getElementById(id)
|
|
|
|
if (el !== undefined && el !== null) el.remove();
|
|
|
|
}, timeo);
|
|
|
|
},
|
|
|
|
};
|
|
|
|
</script>
|