@cntwg/html-helper 0.0.26 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,521 +0,0 @@
1
- // [v0.1.022-20250509]
2
-
3
- // === module init block ===
4
-
5
- const {
6
- readAsBool, readAsString,
7
- isEmptyString, isNotEmptyString,
8
- isPlainObject,
9
- } = require('@ygracs/bsfoc-lib-js');
10
-
11
- const {
12
- isHTMLElement, createNewHTMLElement,
13
- valueToIDString, valueToClassList,
14
- readAsAttrValue,
15
- showHTMLElement, hideHTMLElement,
16
- } = require('../html-helper-lib.js');
17
-
18
- const {
19
- pushEventHandler, triggerEventHandler,
20
- } = require('./mod-hfunc.js');
21
-
22
- // === module extra block (helper functions) ===
23
-
24
- const lpAllowedValues = new Map([
25
- [ 'before', 0 ],
26
- [ 'after', 1 ],
27
- [ 'default', 0 ],
28
- ]);
29
-
30
- /**
31
- * @typedef {Object} ifcTypeDesc
32
- * @property {string} type - field general type
33
- * @property {string} subtype - field sub-type
34
- * @description An input field type description
35
- */
36
-
37
- /**
38
- * @function getInputFieldTypeDescr
39
- * @param {string} value - field type
40
- * @returns {ifcTypeDesc}
41
- * @inner
42
- * @description Returns field description by a given type.
43
- */
44
- function getInputFieldTypeDescr(value) {
45
- let fldType = readAsString(value, { useTrim: true });
46
- if (fldType === '') fldType = 'default';
47
- let fldSubType = '';
48
- switch (fldType) {
49
- case 'text':
50
- case 'checkbox': {
51
- break;
52
- }
53
- case 'switch': {
54
- fldType = 'checkbox';
55
- fldSubType = 'switch';
56
- break;
57
- }
58
- case 'field':
59
- case 'default': {
60
- fldType = 'text';
61
- fldSubType = 'field';
62
- break;
63
- }
64
- default: {
65
- fldType = '';
66
- }
67
- };
68
- return { type: fldType, subtype: fldSubType };
69
- };
70
-
71
- /**
72
- * @function getLabelPositionID
73
- * @param {string} value - label position identifier
74
- * @returns {number}
75
- * @inner
76
- * @description Returns label position ID by its name.
77
- */
78
- function getLabelPositionID(value) {
79
- let key = readAsString(value, { useTrim: true });
80
- if (!lpAllowedValues.has(key)) key = 'default';
81
- return lpAllowedValues.get(key);
82
- };
83
-
84
- // === module main block ===
85
-
86
- /***
87
- * (* constant definitions *)
88
- */
89
-
90
- /***
91
- * (* function definitions *)
92
- */
93
-
94
- /***
95
- * (* class definitions *)
96
- */
97
-
98
- /**
99
- * @typedef {Object} OPT_ifcdesc
100
- * @property {HTMLElement} [host] - host element
101
- * @property {string} [idPref]
102
- * @property {string} [label] - text of a label
103
- * @property {object} [labelPosition]
104
- * @property {boolean} [useDelim]
105
- * @property {object} [baseClassID]
106
- * @property {string} [hint] - hint to show when empty
107
- * @property {string} [type] - field type
108
- * @property {boolean} [readonly] - mode flag
109
- * @description An options set for create ifc
110
- */
111
-
112
- /**
113
- * @typedef {Object} OPT_ifcsett
114
- * @property {string} [idPref]
115
- * @property {(string|string[])} [baseClassID]
116
- * @property {string} [hint] - hint to show when empty
117
- * @property {string} [type] - field type
118
- * @property {boolean} [readonly=true] - mode flag
119
- * @description An options set for `THtmlInputField`-class
120
- */
121
-
122
- /**
123
- * @typedef {Object} ifcElementsDesc
124
- * @property {HTMLElement} host - host element
125
- * @property {HTMLElement} label - label element
126
- * @property {HTMLElement} field - field element
127
- * @description A description for input field elements set.
128
- */
129
-
130
- /**
131
- * @classdesc This class implements an interface of an input field element
132
- */
133
- class THtmlInputField {
134
- /** @type {?HTMLElement} */
135
- #_host;// = null;
136
- /** @type {?HTMLElement} */
137
- #_label;// = null;
138
- /** @type {?HTMLElement} */
139
- #_field;// = null;
140
- #_id = '';
141
- #_value = '';
142
- /** @type {OPT_ifcsett} */
143
- #_options = null;
144
- /**
145
- * @typedef {Object} statIFCtrl
146
- * @property {string} fldType - field general type
147
- * @property {string} fldSubType - field sub-type
148
- * @property {boolean} isReadOnly - mode flag
149
- * @property {boolean} isModified - indicates whether any changes was made
150
- * @inner
151
- * @description A controller status
152
- */
153
- /** @type {statIFCtrl} */
154
- #_status;// = null;
155
- /** @type {Map<string, Function>} */
156
- #_events;// = null;
157
-
158
- /**
159
- * @param {string} name - <*reserved*>
160
- * @param {ifcElementsDesc} eholds - elements set
161
- * @param {OPT_ifcsett} [opt] - options
162
- * @description Creates an instance of an input field element
163
- */
164
- constructor(name, eholds, opt) {
165
- // load elements
166
- const _eholds = isPlainObject(eholds) ? eholds : {};
167
- let { host, label, field } = _eholds;
168
- // save elements
169
- if (!isHTMLElement(host)) host = null;
170
- if (!isHTMLElement(label)) label = null;
171
- if (!isHTMLElement(field)) field = null;
172
- this.#_host = host;
173
- this.#_label = label;
174
- this.#_field = field;
175
- // load options
176
- const _options = isPlainObject(opt) ? opt : {};
177
- let {
178
- idPref,
179
- baseClassID,
180
- hint,
181
- type: fldType,
182
- readonly: isReadOnly,
183
- } = _options;
184
- let fldSubType = '';
185
- ({ type: fldType, subtype: fldSubType } = getInputFieldTypeDescr(fldType));
186
- isReadOnly = readAsBool(isReadOnly, true);
187
- // save options
188
- this.#_options = _options;
189
- // save status
190
- /** @type {statIFCtrl} */
191
- this.#_status = {
192
- fldType,
193
- fldSubType,
194
- isReadOnly,
195
- isModified: false,
196
- };
197
- // init an event instance controller
198
- if (field) {
199
- field.addEventListener('change', this.#_saveFieldData);
200
- field.addEventListener('input', this.#_switchFieldStatusOnInput);
201
- field.addEventListener('blur', this.#_switchFieldStatusOnBlur);
202
- };
203
- this.#_events = new Map();
204
- }
205
-
206
- /**
207
- * Indicates whether element value was modified.
208
- * @type {boolean}
209
- * @readonly
210
- */
211
- get isModified() {
212
- return this.#_status.isModified;
213
- }
214
-
215
- /**
216
- * Returns an input element origin type.
217
- * @since v0.0.23
218
- * @type {string}
219
- * @readonly
220
- */
221
- get type() {
222
- return this.#_status.fldType;
223
- }
224
-
225
- /**
226
- * Containes an element value.
227
- * @type {string}
228
- * @fires THtmlInputField#value-empty
229
- */
230
- get value() {
231
- const field = this.#_field;
232
- const result = this.type === 'checkbox' ? field.checked : field.value;
233
- return result;
234
- }
235
-
236
- set value(value) {
237
- const field = this.#_field;
238
- if (value !== undefined) {
239
- if (this.type === 'checkbox') {
240
- field.checked = value;
241
- this.#_status.isModified = false;
242
- } else {
243
- let _value = readAsString(value, {
244
- boolToString: true,
245
- numberToString: true,
246
- });
247
- field.value = _value;
248
- this.#_status.isModified = false;
249
- if (_value === '') {
250
- /**
251
- * @see THtmlInputField#value-empty
252
- */
253
- this.#_triggerEvent('value-empty', {
254
- type: 'value-empty',
255
- target: null,
256
- });
257
- };
258
- };
259
- };
260
- }
261
-
262
- /**
263
- * @param {string} name - event name
264
- * @param {...any} args
265
- * @returns {void}
266
- * @private
267
- * @see triggerEventHandler
268
- */
269
- #_triggerEvent = (name, ...args) => {
270
- triggerEventHandler(this.#_events, name, ...args);
271
- };
272
-
273
- /**
274
- * @param {object} e - event
275
- * @returns {void}
276
- * @private
277
- * @fires THtmlInputField#value-changed
278
- */
279
- #_saveFieldData = (e) => {
280
- e.preventDefault();
281
- const target = e.target;
282
- //***/console.log(':'+e.type+':'+target.getAttribute('id')+':\n:saveFieldData() => received OnChange-event');
283
- // // TODO:
284
- /**
285
- * @event THtmlInputField#value-changed
286
- * @type {Object}
287
- * @property {string} type - event type
288
- * @property {object} target
289
- */
290
- this.#_triggerEvent('value-changed', {
291
- type: 'value-changed',
292
- target,
293
- });
294
- };
295
-
296
- /**
297
- * @param {object} e - event
298
- * @returns {void}
299
- * @private
300
- * @fires THtmlInputField#value-empty
301
- */
302
- #_switchFieldStatusOnInput = (e) => {
303
- e.preventDefault();
304
- const target = e.target;
305
- //***/console.log(':'+e.type+':'+target.getAttribute('id')+':\n:switchFieldStatusOnInput() => received OnInput-event');
306
- this.#_status.isModified = true;
307
- // // TODO:
308
- if (target.value === '') {
309
- /**
310
- * @event THtmlInputField#value-empty
311
- * @type {Object}
312
- * @property {string} type - event type
313
- * @property {object} target
314
- */
315
- this.#_triggerEvent('value-empty', {
316
- type: 'value-empty',
317
- target,
318
- });
319
- };
320
- };
321
-
322
- /**
323
- * @param {object} e - event
324
- * @returns {void}
325
- * @private
326
- */
327
- #_switchFieldStatusOnBlur = (e) => {
328
- e.preventDefault();
329
- //***/console.log(':'+e.type+':'+e.target.getAttribute('id')+':\n:switchFieldStatusOnBlur() => received OnBlur-event');
330
- // // TODO:
331
- };
332
-
333
- /**
334
- * @param {HTMLElement} target - target element
335
- * @returns {boolean}
336
- * @description Tries to attach an element to a given target.
337
- */
338
- attachTo(target) {
339
- const host = this.#_host;
340
- let result = false;
341
- if (
342
- isHTMLElement(target)
343
- && isHTMLElement(host)
344
- ) {
345
- target.append(host);
346
- result = true;
347
- };
348
- return result;
349
- }
350
-
351
- /**
352
- * @returns {boolean}
353
- * @description Checks if a value of an element is not set.
354
- */
355
- isEmpty() {
356
- return isEmptyString(this.value);
357
- }
358
-
359
- /**
360
- * @returns {boolean}
361
- * @description Checks if a value of an element is set.
362
- */
363
- isNotEmpty() {
364
- return isNotEmptyString(this.value);
365
- }
366
-
367
- /**
368
- * @returns {void}
369
- * @description Shows an element.
370
- */
371
- show() {
372
- showHTMLElement(this.#_host);
373
- }
374
-
375
- /**
376
- * @returns {void}
377
- * @description Hides an element.
378
- */
379
- hide() {
380
- hideHTMLElement(this.#_host);
381
- }
382
-
383
- /**
384
- * @returns {void}
385
- * @description not implemented yet.
386
- */
387
- clear() {
388
- // // TODO:
389
- }
390
-
391
- /**
392
- * @param {string} name - <*reserved*>
393
- * @param {OPT_ifcdesc} opt - options
394
- * @returns {?THtmlInputField}
395
- * @static
396
- * @description Creates a new instance.
397
- */
398
- static create(name, opt) {
399
- const eholds = THtmlInputField.createElement(name, opt, true);
400
- const { field } = eholds;
401
- return (
402
- isHTMLElement(field)
403
- ? new THtmlInputField(name, eholds, opt)
404
- : null
405
- );
406
- }
407
-
408
- /**
409
- * @param {string} name
410
- * @param {OPT_ifcdesc} [opt] - options
411
- * @param {boolean} [doRetChild=false] - mode flag
412
- * @returns {(HTMLElement|ifcElementsDesc)}
413
- * @static
414
- * @description Creates a new elements.
415
- */
416
- static createElement(name, opt, doRetChild) {
417
- const id = valueToIDString(name);
418
- const _options = isPlainObject(opt) ? opt : {};
419
- let fldSubType = '';
420
- /** @type {OPT_ifcdesc} */
421
- let {
422
- host,
423
- idPref,
424
- label,
425
- labelPosition,
426
- useDelim,
427
- baseClassID,
428
- hint,
429
- type: fldType,
430
- readonly: isReadOnly,
431
- } = _options;
432
- if (!isPlainObject(baseClassID)) baseClassID = {};
433
- let {
434
- main: bcidMain,
435
- host: bcidHost,
436
- label: bcidLabel,
437
- field: bcidField,
438
- } = baseClassID;
439
- bcidMain = valueToClassList(bcidMain);
440
- bcidHost = valueToClassList(bcidHost);
441
- bcidLabel = valueToClassList(bcidLabel);
442
- bcidField = valueToClassList(bcidField);
443
- idPref = valueToIDString(idPref);
444
- hint = readAsString(hint, { useTrim: true });
445
- ({ type: fldType, subtype: fldSubType } = getInputFieldTypeDescr(fldType));
446
- if (fldSubType === 'switch') bcidField.push('switch');
447
- labelPosition = getLabelPositionID(labelPosition);
448
- if (typeof useDelim !== 'boolean') useDelim = true;
449
- label = readAsString(label, { useTrim: true });
450
- if (label !== '') label = `${label}${useDelim ? ':' : ''}`;
451
- isReadOnly = readAsBool(isReadOnly, true);
452
- let fldID = idPref === '' ? id : `${idPref}-${id}`;
453
- if (!isHTMLElement(host)) {
454
- host = createNewHTMLElement('div', {
455
- classNames: bcidHost,
456
- });
457
- };
458
- let lblHolder = null;
459
- let fldHolder = null;
460
- let items = [];
461
- if (host) {
462
- lblHolder = host.querySelector(`label[for="${fldID}"]`);
463
- if (!lblHolder) {
464
- lblHolder = createNewHTMLElement('label', {
465
- text: label,
466
- attr: {
467
- for: fldID,
468
- },
469
- classNames: bcidLabel,
470
- });
471
- };
472
- fldHolder = host.querySelector(`input#${fldID}`);
473
- if (!fldHolder) {
474
- fldHolder = createNewHTMLElement('input', {
475
- id: fldID,
476
- attr: {
477
- type: fldType,
478
- placeholder: hint,
479
- },
480
- classNames: bcidField,
481
- });
482
- };
483
- if (fldHolder) {
484
- if (isReadOnly) {
485
- const attr = fldType === 'checkbox' ? 'disabled' : 'readOnly';
486
- fldHolder[attr] = true;
487
- };
488
- if (lblHolder) items.push(lblHolder);
489
- items.push(fldHolder);
490
- };
491
- const len = items.length;
492
- if (len > 0) {
493
- if (len === 2 && labelPosition === 1) {
494
- items = [ items[1], items[0] ];
495
- };
496
- host.append(...items);
497
- };
498
- };
499
- // // TODO:
500
- return (
501
- readAsBool(doRetChild, false)
502
- ? { host, label: lblHolder, field: fldHolder }
503
- : host
504
- );
505
- }
506
-
507
- /**
508
- * @param {string} name - event name
509
- * @param {func} evnt - callback function
510
- * @returns {void}
511
- * @description Sets a callback function to handle event.
512
- */
513
- on(name, evnt) {
514
- pushEventHandler(this.#_events, name, evnt);
515
- }
516
-
517
- };
518
-
519
- // === module exports block ===
520
-
521
- module.exports.THtmlInputField = THtmlInputField;