@cntwg/html-helper 0.0.27 → 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.023-20250827]
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 inner block ===
23
-
24
- const lpAllowedValues = new Map([
25
- [ 'before', 0 ],
26
- [ 'after', 1 ],
27
- [ 'default', 0 ],
28
- ]);
29
-
30
- /**
31
- * An input field type descriptor
32
- * @typedef {Object} ifcTypeDesc
33
- * @property {string} type - field general type
34
- * @property {string} subtype - field sub-type
35
- */
36
-
37
- /**
38
- * Returns field description by a given type.
39
- * @function getInputFieldTypeDescr
40
- * @param {string} value - field type
41
- * @returns {ifcTypeDesc}
42
- * @inner
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
- * Returns label position ID by its name.
73
- * @function getLabelPositionID
74
- * @param {string} value - label position identifier
75
- * @returns {number}
76
- * @inner
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
- * An options set for create ifc
100
- * @typedef {Object} OPT_ifcdesc
101
- * @property {HTMLElement} [host] - host element
102
- * @property {string} [idPref]
103
- * @property {string} [label] - text of a label
104
- * @property {object} [labelPosition]
105
- * @property {boolean} [useDelim]
106
- * @property {object} [baseClassID]
107
- * @property {string} [hint] - hint to show when empty
108
- * @property {string} [type] - field type
109
- * @property {boolean} [readonly] - mode flag
110
- */
111
-
112
- /**
113
- * An options set for `THtmlInputField`-class
114
- * @typedef {Object} OPT_ifcsett
115
- * @property {string} [idPref]
116
- * @property {(string|string[])} [baseClassID]
117
- * @property {string} [hint] - hint to show when empty
118
- * @property {string} [type] - field type
119
- * @property {boolean} [readonly=true] - mode flag
120
- */
121
-
122
- /**
123
- * A descriptor for an input field elements set.
124
- * @typedef {Object} ifcElementsDesc
125
- * @property {HTMLElement} host - host element
126
- * @property {HTMLElement} label - label element
127
- * @property {HTMLElement} field - field element
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
- * A controller status
146
- * @typedef {Object} statIFCtrl
147
- * @property {string} fldType - field general type
148
- * @property {string} fldSubType - field sub-type
149
- * @property {boolean} isReadOnly - mode flag
150
- * @property {boolean} isModified - indicates whether any changes was made
151
- * @inner
152
- */
153
- /** @type {statIFCtrl} */
154
- #_status;// = null;
155
- /** @type {Map<string, Function>} */
156
- #_events;// = null;
157
-
158
- /**
159
- * Creates an instance of an input field element
160
- * @param {string} name - <*reserved*>
161
- * @param {ifcElementsDesc} eholds - elements set
162
- * @param {OPT_ifcsett} [opt] - options
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
- * Tries to attach an element to a given target.
335
- * @param {HTMLElement} target - target element
336
- * @returns {boolean}
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
- * Checks if a value of an element is not set.
353
- * @returns {boolean}
354
- */
355
- isEmpty() {
356
- return isEmptyString(this.value);
357
- }
358
-
359
- /**
360
- * Checks if a value of an element is set.
361
- * @returns {boolean}
362
- */
363
- isNotEmpty() {
364
- return isNotEmptyString(this.value);
365
- }
366
-
367
- /**
368
- * Shows an element.
369
- * @returns {void}
370
- */
371
- show() {
372
- showHTMLElement(this.#_host);
373
- }
374
-
375
- /**
376
- * Hides an element.
377
- * @returns {void}
378
- */
379
- hide() {
380
- hideHTMLElement(this.#_host);
381
- }
382
-
383
- /**
384
- * @returns {void}
385
- * @todo not implemented yet.
386
- */
387
- clear() {
388
- // // TODO:
389
- }
390
-
391
- /**
392
- * Creates a new instance.
393
- * @param {string} name - <*reserved*>
394
- * @param {OPT_ifcdesc} opt - options
395
- * @returns {?THtmlInputField}
396
- * @static
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
- * Creates a new elements.
410
- * @param {string} name
411
- * @param {OPT_ifcdesc} [opt] - options
412
- * @param {boolean} [doRetChild=false] - mode flag
413
- * @returns {(HTMLElement|ifcElementsDesc)}
414
- * @static
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
- * Sets a callback function to handle event.
509
- * @param {string} name - event name
510
- * @param {func} evnt - callback function
511
- * @returns {void}
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;