Skip to content

Commit cff0f85

Browse files
Release 20250820
1 parent 3045eb4 commit cff0f85

File tree

11 files changed

+211
-66
lines changed

11 files changed

+211
-66
lines changed

hlp-aguide/Help-cs.zip

114 Bytes
Binary file not shown.

hlp-aguide/Help-en.zip

74 Bytes
Binary file not shown.

hlp-user/Help-cs.zip

192 Bytes
Binary file not shown.

hlp-user/Help-en.zip

202 Bytes
Binary file not shown.

hlp/Help-cs.zip

81 Bytes
Binary file not shown.

hlp/Help-en.zip

64 Bytes
Binary file not shown.

hvdata/appmain.js

Lines changed: 198 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,169 @@
1+
const DEBUG_MODE = false;
2+
const DEBUG_MODE_RENDERER = DEBUG_MODE;
3+
const LOG_MINIMIZE_OBJECT = true;
4+
const LOG_MINIMIZE_DATE_ISO = false;
5+
6+
const $ = (name) => document.getElementById(name);
7+
const $O = (selector, parent = document) => parent?.querySelector(selector);
8+
const $A = (selector, parent = document) => parent?.querySelectorAll(selector);
9+
10+
function newUID(length = 8) {
11+
var str = '';
12+
13+
while (str.length <= length)
14+
str += Math.random().toString(36).slice(2);
15+
16+
str = str.slice(0, length);
17+
//log(`newUID of length ${length} emitted: ${str}`);
18+
19+
return str;
20+
}
21+
22+
const log = !DEBUG_MODE ?
23+
function log() {} :
24+
function log(msg, ...dataI) {
25+
if (!msg) return;
26+
27+
var severity = msg[0];
28+
const hasSeverity = msg[1] == ' ';
29+
30+
if (hasSeverity) {
31+
msg = msg.substring(2);
32+
} else {
33+
severity = undefined;
34+
}
35+
36+
const data = [msg];
37+
38+
if (LOG_MINIMIZE_OBJECT && severity?.toUpperCase() != 'E') {
39+
dataI.forEach((x, i) => {
40+
if (typeof x === 'object') {
41+
//dataI[i] = JSON.parse(JSON.stringify(x)); // unfortunately skips undefined members!
42+
const clean = Object.create(null);
43+
Object.assign(clean, dataI[i]);
44+
clean['__className'] = x.constructor.name;
45+
dataI[i] = clean;
46+
for (const [key, value] of Object.entries(dataI[i])) {
47+
if (value instanceof Date) {
48+
clean[key] = LOG_MINIMIZE_DATE_ISO ? value.toISOString() : value.toString();
49+
} else {
50+
clean[key] = value;
51+
}
52+
}
53+
}
54+
});
55+
}
56+
57+
if (dataI.length > 0)
58+
data.push(...dataI);
59+
60+
switch (severity?.toUpperCase()) {
61+
case 'W':
62+
console.warn(...data);
63+
break;
64+
65+
case 'E':
66+
console.error(...data);
67+
break;
68+
69+
default:
70+
if (hasSeverity) {
71+
msg = `${severity} ${msg}`;
72+
data[0] = msg;
73+
}
74+
console.log(...data);
75+
break;
76+
}
77+
}
78+
179
const PAR_NAME_DOC = 'd'; // Help file path
280

381
const id_JSAppRun = 'appRun';
482
const FILENAME_ZIP_ON_USER_INPUT = '!.zip';
83+
const FILENAME_DIR_LISTING = '__dir.lst';
584

685
function _T(id) {
786
return id;
887
}
988

10-
function appendField(target, id, defaultV = '', type = 'text') {
11-
target.innerHTML +=
89+
const FormFieldType = {
90+
TEXT: 'text',
91+
CHECKBOX: 'checkbox',
92+
FILE: 'file',
93+
};
94+
95+
function appendField(target, id, defaultV = '', type = FormFieldType.TEXT) {
96+
if (defaultV && type == FormFieldType.CHECKBOX)
97+
defaultV = `checked`;
98+
else if (defaultV)
99+
defaultV = `value="${defaultV}"`;
100+
else
101+
defaultV = '';
102+
103+
target.insertAdjacentHTML('beforeend',
12104
`<div class="form-row">
13-
<label for="${id}">${_T(id)}</label>
14-
<input type="${type}" id="${id}" value="${defaultV}" />
15-
</div>`;
105+
<label for="${id}" id="${id}-label">${_T(id)}</label>
106+
<input type="${type}" id="${id}" ${defaultV} />
107+
</div>`);
16108
}
17109

18-
function formCorsHelpFilesUpload()
110+
function appendFieldComboBox(target, id) {
111+
target.insertAdjacentHTML('beforeend',
112+
`<div class="form-row">
113+
<label for="${id}" id="${id}-label">${_T(id)}</label>
114+
<select id="${id}" />
115+
</div>`);
116+
}
117+
118+
function appendComboBoxItems(combobox, items, defaultV) {
119+
if (!combobox) return;
120+
items?.forEach((txt, i) => {
121+
let opt = new Option(txt, i);
122+
if (defaultV == txt || defaultV == i)
123+
opt.selected = true;
124+
combobox.add(opt);
125+
});
126+
}
127+
128+
function formCorsHelpFilesUpload(fieldHelpLangTitle = 'Help-(language).zip', fieldHvDataTitle = 'data.zip', formName = 'form', formInName = 'formIn')
19129
{
20-
const formO = document.getElementById('formIn');
21-
const fieldHvData = 'data.zip';
22-
const fieldHelpLang = 'Help-(language).zip';
130+
const formO = $(formInName);
131+
const fieldHvData = fieldHvDataTitle;
132+
const fieldHelpLang = fieldHelpLangTitle;
23133
//const fieldHelpBase = 'Help-.zip';
24-
const typeFile = 'file';
134+
const typeFile = FormFieldType.FILE;
25135

26136
appendField(formO, fieldHvData, '', typeFile);
27137
appendField(formO, fieldHelpLang, '', typeFile);
28138
//appendField(formO, fieldHelpBase, '', typeFile);
139+
140+
const button = document.createElement("button");
141+
button.type = "submit";
142+
button.textContent = "Send";
143+
formO.appendChild(button);
29144

30-
const formM = document.getElementById('form');
145+
const formM = $(formName);
31146
formM.addEventListener("submit", function(e) {
32147
e.preventDefault();
33148

34-
const hvData = document.getElementById(fieldHvData);
35-
const helpLang = document.getElementById(fieldHelpLang);
149+
const hvData = $(fieldHvData);
150+
const helpLang = $(fieldHelpLang);
36151

37152
if (!hvData?.files?.length || !helpLang?.files?.length)
38153
return;
39154

40155
const fileHvData = hvData.files[0];
41156
const fileHelpLang = helpLang.files[0];
42157

43-
// var fileHelpBase = document.getElementById(fieldHelpBase);
158+
// var fileHelpBase = $(fieldHelpBase);
44159

45160
// if (fileHelpBase?.files?.length)
46161
// fileHelpBase = fileHelpBase[0];
47162
// else
48163
// fileHelpBase = null;
49164

50-
document.getElementById(id_JSAppRun)?.remove();
51-
st = _Storage.add(STO_HELP, FILENAME_ZIP_ON_USER_INPUT, fileHelpLang).then(obsah => {
165+
$(id_JSAppRun)?.remove();
166+
var st = _Storage.add(STO_HELP, FILENAME_ZIP_ON_USER_INPUT, fileHelpLang).then(obsah => {
52167
main(fileHvData);
53168
const url = new URL(window.location.href);
54169
url.searchParams.set(PAR_NAME_DOC, FILENAME_ZIP_ON_USER_INPUT);
@@ -66,8 +181,8 @@ const STOF_B64 = 'base64';
66181
const DATA_FILE_PATH_BASE = 'hvdata/data';
67182

68183
const STORAGE_ENGINES = {
69-
'.zip': async (path) => newStorageZip(path),
70-
'/': async (path) => newStorageDir(path),
184+
'.zip': async (path) => await new StorageZip().init(path),
185+
'/': async (path) => await new StorageDir().init(path),
71186
};
72187

73188
var _Storage = (() => {
@@ -113,21 +228,35 @@ var _Storage = (() => {
113228
};
114229
})();
115230

116-
async function newStorageZip(path) {
117-
var storageO = await init(path);
231+
/**
232+
* @interface
233+
*/
234+
class IStorage {
235+
async init(path) {}
236+
async search(filePath, format) {}
237+
async getSubdirs(parentPath) {}
238+
async searchImage(filePath) {}
239+
}
118240

119-
async function init(path) {
120-
return await ZIPHelpers.loadZipFromUrl(path);
241+
class StorageZip extends IStorage {
242+
constructor() {
243+
super();
244+
this.storageO = null;
245+
}
246+
247+
async init(path) {
248+
this.storageO = await ZIPHelpers.loadZipFromUrl(path);
249+
return this;
121250
}
122251

123-
async function search(filePath, format = STOF_TEXT) {
124-
return await ZIPHelpers.searchArchiveForFile(filePath, storageO, format);
252+
async search(filePath, format = STOF_TEXT) {
253+
return await ZIPHelpers.searchArchiveForFile(filePath, this.storageO, format);
125254
}
126255

127-
async function getSubdirs(parentPath) {
256+
async getSubdirs(parentPath) {
128257
const subdirs = new Set();
129258

130-
storageO?.forEach((relativePath, file) => {
259+
this.storageO?.forEach((relativePath, file) => {
131260
if (relativePath.startsWith(parentPath) && relativePath !== parentPath)
132261
{
133262
const subPath = relativePath.slice(parentPath.length);
@@ -144,28 +273,37 @@ async function newStorageZip(path) {
144273
return [...subdirs];
145274
}
146275

147-
async function searchImage(filePath) {
148-
const content = await search(filePath, STOF_B64);
276+
async searchImage(filePath) {
277+
const content = await this.search(filePath, STOF_B64);
149278
if (!content) return null;
150279
var mimeType = 'image/' + filePath.split('.').pop().toLowerCase();
151280
return `data:${mimeType};base64,${content}`;
152281
}
153-
154-
return {
155-
search,
156-
getSubdirs,
157-
searchImage
158-
};
159282
}
160283

161-
async function newStorageDir(path) {
162-
var storageO = await init(path);
284+
function toText(ab) {
285+
if (!ab) return '';
286+
if (typeof ab === 'string') return ab;
287+
if (ab instanceof String) return ab.valueOf();
288+
289+
const decoder = new TextDecoder('utf-8');
290+
const text = decoder.decode(ab);
291+
return text;
292+
}
163293

164-
async function init(path) {
165-
return path.replace(/\/$/, '');
294+
class StorageDir extends IStorage {
295+
constructor() {
296+
super();
297+
this.storageO = null;
298+
}
299+
300+
async init(path) {
301+
this.storageO = path.replace(/\/$/, '');
302+
return this;
166303
}
167-
async function search(filePath, format = STOF_TEXT) {
168-
var fpath = `${storageO}/${filePath}`;
304+
305+
async search(filePath, format = STOF_TEXT) {
306+
var fpath = `${this.storageO}/${filePath}`;
169307
const doubleSlash = '//';
170308
const doubleSlashIndexLast = fpath.lastIndexOf(doubleSlash);
171309
const doubleSlashIndex = fpath.indexOf(doubleSlash);
@@ -176,9 +314,12 @@ async function newStorageDir(path) {
176314
replacement = '/';
177315

178316
fpath = fpath.slice(0, doubleSlashIndexLast) + replacement + fpath.slice(doubleSlashIndexLast + 2);
317+
} else {
318+
if (!fpath.startsWith('http') && !fpath.startsWith('ftp'))
319+
fpath = fpath.replace(doubleSlash, '/');
179320
}
180321

181-
const response = await fetchDataOrEmpty(fpath);
322+
const response = await this.fetchDataOrEmpty(fpath);
182323

183324
switch (format) {
184325
case STOF_B64:
@@ -196,16 +337,10 @@ async function newStorageDir(path) {
196337
}
197338
}
198339

199-
function toText(ab) {
200-
const decoder = new TextDecoder("utf-8");
201-
const text = decoder.decode(ab);
202-
return text;
203-
}
204-
205-
async function getSubdirs(parentPath) {
206-
const list = search(`${storageO}/${parentPath}/__dir.lst`, format = STOF_TEXT);
207-
const text = toText(list);
208-
text = text.trim().replace(/\r\n/g, "\n").split('\n');
340+
async getSubdirs(parentPath) {
341+
const list = await this.search(`${parentPath}/${FILENAME_DIR_LISTING}`, STOF_TEXT);
342+
var text = toText(list);
343+
text = rowsToArray(text.trim());
209344

210345
const subdirs = new Set();
211346
text?.forEach((line, index) => {
@@ -215,7 +350,7 @@ async function newStorageDir(path) {
215350
return [...subdirs];
216351
}
217352

218-
async function fetchDataOrEmpty(url) {
353+
async fetchDataOrEmpty(url) {
219354
try {
220355
const response = await fetchData(url);
221356
return response;
@@ -224,19 +359,13 @@ async function newStorageDir(path) {
224359
}
225360
}
226361

227-
async function searchImage(filePath) {
228-
const fpath = `${storageO}/${filePath}`;
229-
const response = await fetchDataOrEmpty(fpath);
362+
async searchImage(filePath) {
363+
const fpath = `${this.storageO}/${filePath}`;
364+
const response = await this.fetchDataOrEmpty(fpath);
230365
if (response.byteLength == 0)
231366
return null;
232367
return fpath;
233368
}
234-
235-
return {
236-
search,
237-
getSubdirs,
238-
searchImage
239-
};
240369
}
241370

242371
async function main(baseDataStream = null) {
@@ -298,20 +427,25 @@ const ZIPHelpers = (() => {
298427
})();
299428

300429
function appendCSS(id, content) {
301-
//if (document.getElementById(id)) return;
430+
//if ($(id)) return;
302431
const style = document.createElement('style');
303432
style.textContent = content;
304433
style.id = id;
305434
document.head.appendChild(style);
306435
}
307436

308437
function appendJavaScript(id, content, parentO) {
309-
if (document.getElementById(id)) return;
438+
if ($(id)) return;
310439
const script = document.createElement('script');
311440
script.type = 'text/javascript';
312441
script.textContent = content;
313442
script.id = id;
314443
parentO.appendChild(script);
315444
}
316445

317-
main();
446+
function rowsToArray(t) {
447+
if (!t) return;
448+
return t.replace(/\r\n|\r/g, '\n').split('\n');
449+
}
450+
451+
main();

hvdata/data.zip

49.5 KB
Binary file not shown.

index.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
<form id="form">
5252
<div id="formIn">
5353
</div>
54-
<button type="submit">Odeslat</button>
5554
</form>
5655
<script>
5756
formCorsHelpFilesUpload();

0 commit comments

Comments
 (0)