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+
179const PAR_NAME_DOC = 'd' ; // Help file path
280
381const id_JSAppRun = 'appRun' ;
482const FILENAME_ZIP_ON_USER_INPUT = '!.zip' ;
83+ const FILENAME_DIR_LISTING = '__dir.lst' ;
584
685function _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';
66181const DATA_FILE_PATH_BASE = 'hvdata/data' ;
67182
68183const 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
73188var _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
242371async function main ( baseDataStream = null ) {
@@ -298,20 +427,25 @@ const ZIPHelpers = (() => {
298427} ) ( ) ;
299428
300429function 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
308437function 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 ( ) ;
0 commit comments