@cntwg/html-helper 0.0.17 → 0.0.19

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.
@@ -0,0 +1,242 @@
1
+ // [v0.1.049-20230614]
2
+
3
+ // === module init block ===
4
+
5
+ const {
6
+ isNotEmptyString,
7
+ isPlainObject, valueToArray,
8
+ TItemsICollection,
9
+ } = require('@ygracs/bsfoc-lib-js');
10
+
11
+ const {
12
+ isHTMLElement,
13
+ valueToIDString,
14
+ lockHtmlElement, unlockHtmlElement,
15
+ CSS_CLASS_STRING,
16
+ } = require('../html-helper-lib.js');
17
+
18
+ const {
19
+ pushEventHandler, triggerEventHandler,
20
+ readOnClickEventInfo,
21
+ } = require('./mod-hfunc.js');
22
+
23
+ const {
24
+ //CSS_CLASS_SELECTED,
25
+ CSS_CLASS_DISABLED,
26
+ //CSS_CLASS_HIDDEN,
27
+ } = CSS_CLASS_STRING;
28
+
29
+ const BTS_DEF_GROUP_NAME = 'all';
30
+
31
+ const etlHTagInputForBtn = new Set([
32
+ 'button', 'submit', 'reset', 'image',
33
+ ]);
34
+
35
+ // === module extra block (helper functions) ===
36
+
37
+ function isHTMLButton(obj){
38
+ let result = false;
39
+ if (isHTMLElement(obj)) {
40
+ switch (obj.tagName.toLowerCase()) {
41
+ case 'button': {
42
+ result = true;
43
+ break;
44
+ }
45
+ case 'input': {
46
+ result = etlHTagInputForBtn.has(obj.type.toLowerCase());
47
+ break;
48
+ }
49
+ default: {
50
+ break;
51
+ }
52
+ };
53
+ };
54
+ return result;
55
+ }
56
+
57
+ // === module main block (function definitions) ===
58
+
59
+ // === module main block (class definitions) ===
60
+
61
+ class THtmlButtonsSet {
62
+ #_btnCol = null;
63
+
64
+ constructor(){
65
+ // define default functions for manipulators
66
+ const __user_index_getter = (value) => {
67
+ return valueToIDString(value);
68
+ };
69
+ const __user_item_getter = (value) => {
70
+ return THtmlButtonsSet.isHTMLButton(value) ? value : null;
71
+ };
72
+ this.#_btnCol = new TItemsICollection({
73
+ userFn: {
74
+ checkIndexFn: isNotEmptyString,
75
+ readIndexFn: __user_index_getter,
76
+ checkItemFn: THtmlButtonsSet.isHTMLButton,
77
+ readItemFn: __user_item_getter,
78
+ },
79
+ });
80
+ }
81
+
82
+ get ItemNames(){
83
+ return this.#_btnCol.ItemNames;
84
+ }
85
+
86
+ get GroupNames(){
87
+ return this.#_btnCol.CategoryNames;
88
+ }
89
+
90
+ hasItem(name){
91
+ return this.#_btnCol.hasItem(name);
92
+ }
93
+
94
+ addItem(...args){
95
+ return this.#_btnCol.addItem(...args);
96
+ }
97
+
98
+ addItemToGroup(...args){
99
+ return this.#_btnCol.addItemToCategory(...args);
100
+ }
101
+
102
+ delItem(name){
103
+ return this.#_btnCol.delItem(name);
104
+ }
105
+
106
+ delItemFromGroup(...args){
107
+ return this.#_btnCol.delItemFromGroup(...args);
108
+ }
109
+
110
+ renameItem(oldName, newName){
111
+ return this.#_btnCol.renameItem(oldName, newName, false);
112
+ }
113
+
114
+ enableItem(name){
115
+ unlockHtmlElement(this.#_btnCol.getItem(name));
116
+ }
117
+
118
+ disableItem(name){
119
+ lockHtmlElement(this.#_btnCol.getItem(name));
120
+ }
121
+
122
+ hasGroup(name){
123
+ return this.#_btnCol.hasCategory(name);
124
+ }
125
+
126
+ addGroup(name){
127
+ return this.#_btnCol.addCategory(name);
128
+ }
129
+
130
+ delGroup(name){
131
+ return this.#_btnCol.delCategory(name);
132
+ }
133
+
134
+ renameGroup(oldName, newName){
135
+ return this.#_btnCol.renameCategory(oldName, newName, false);
136
+ }
137
+
138
+ enableGroup(value){
139
+ const group = this.#_btnCol.getCategory(value);
140
+ valueToArray(group).forEach(item => unlockHtmlElement(item));
141
+ }
142
+
143
+ disableGroup(value){
144
+ const group = this.#_btnCol.getCategory(value);
145
+ valueToArray(group).forEach(item => lockHtmlElement(item));
146
+ }
147
+
148
+ static get isHTMLButton(){
149
+ return isHTMLButton;
150
+ }
151
+
152
+ };
153
+
154
+ class THtmlButtonsControllerARCSet {
155
+ #_btnSet = null;
156
+ #_events = null;
157
+
158
+ constructor(opt) {
159
+ // load options
160
+ const _options = isPlainObject(opt) ? opt : {};
161
+ // load controls
162
+ let {
163
+ btnApply,
164
+ btnReset,
165
+ btnCancel,
166
+ } = _options;
167
+ if (!isHTMLButton(btnApply)) btnApply = null;
168
+ if (!isHTMLButton(btnReset)) btnReset = null;
169
+ if (!isHTMLButton(btnCancel)) btnCancel = null;
170
+ /*const controls = {
171
+ btnApply,
172
+ btnReset,
173
+ btnCancel,
174
+ };*/ // // TODO: ???
175
+ // init buttons set
176
+ const _btnSet = new THtmlButtonsSet();
177
+ this.#_btnSet = _btnSet;
178
+ _btnSet.addGroup('main');
179
+ _btnSet.addGroup('all');
180
+ if (btnApply) {
181
+ _btnSet.addItem('btn_apply', btnApply, 'main', 'all');
182
+ btnApply.addEventListener('click', e => this.#_on_btn_pressed(e, 'apply'));
183
+ };
184
+ if (btnReset) {
185
+ _btnSet.addItem('btn_reset', btnReset, 'main', 'all');
186
+ btnReset.addEventListener('click', e => this.#_on_btn_pressed(e, 'reset'));
187
+ };
188
+ if (btnCancel) {
189
+ _btnSet.addItem('btn_cancel', btnCancel, 'all');
190
+ btnCancel.addEventListener('click', e => this.#_on_btn_pressed(e, 'cancel'));
191
+ };
192
+ _btnSet.disableGroup('main');
193
+ // init events controller
194
+ this.#_events = new Map();
195
+ }
196
+
197
+ #_on_btn_pressed = (e, key) => {
198
+ //console.log(`THtmlListButtonsController._on_btn_pressed().key(${key}) ==> was called...`);
199
+ //e.preventDefault(); /* need to reconsider reason for use */
200
+ const { item, onClickNum } = readOnClickEventInfo(e);
201
+ if (
202
+ item instanceof HTMLElement
203
+ && (onClickNum === 0 || onClickNum === 1)
204
+ && !item.classList.contains(CSS_CLASS_DISABLED)
205
+ ) {
206
+ this.#_triggerEvent(`btn-${key}-pressed`, e);
207
+ };
208
+ }
209
+
210
+ #_triggerEvent = (name, ...args) => {
211
+ triggerEventHandler(this.#_events, name, ...args);
212
+ }
213
+
214
+ disableMain(){
215
+ this.#_btnSet.disableGroup('main');
216
+ }
217
+
218
+ enableMain(){
219
+ this.#_btnSet.enableGroup('main');
220
+ }
221
+
222
+ disableAll(){
223
+ this.#_btnSet.disableGroup('all');
224
+ }
225
+
226
+ enableAll(){
227
+ this.#_btnSet.enableGroup('all');
228
+ }
229
+
230
+ on(name, evnt){
231
+ pushEventHandler(this.#_events, name, evnt);
232
+ }
233
+ };
234
+
235
+ // === module exports block ===
236
+
237
+ exports.THtmlButtonsSet = THtmlButtonsSet;
238
+ exports.THtmlButtonsControllerARCSet = THtmlButtonsControllerARCSet;
239
+
240
+ exports.BTS_DEF_GROUP_NAME = BTS_DEF_GROUP_NAME;
241
+
242
+ exports.isHTMLButton = isHTMLButton;
@@ -0,0 +1,342 @@
1
+ // [v0.1.011-20230704]
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
+ function getInputFieldTypeDescr(value){
31
+ let fldType = readAsString(value, '', true);
32
+ if (fldType === '') fldType = 'default';
33
+ let fldSubType = '';
34
+ switch (fldType) {
35
+ case 'text':
36
+ case 'checkbox': {
37
+ break;
38
+ }
39
+ case 'switch': {
40
+ fldType = 'checkbox';
41
+ fldSubType = 'switch';
42
+ break;
43
+ }
44
+ case 'field':
45
+ case 'default': {
46
+ fldType = 'text';
47
+ break;
48
+ }
49
+ default: {
50
+ fldType = '';
51
+ break;
52
+ }
53
+ };
54
+ return { type: fldType, subtype: fldSubType };
55
+ };
56
+
57
+ function getLabelPositionID(value){
58
+ let key = readAsString(value, '', true);
59
+ if (!lpAllowedValues.has(key)) key = 'default';
60
+ return lpAllowedValues.get(key);
61
+ };
62
+
63
+ // === module main block ===
64
+
65
+ /***
66
+ * (* constant definitions *)
67
+ */
68
+
69
+ /***
70
+ * (* function definitions *)
71
+ */
72
+
73
+ /***
74
+ * (* class definitions *)
75
+ */
76
+
77
+ class THtmlInputField {
78
+ #_host = null;
79
+ #_label = null;
80
+ #_field = null;
81
+ #_id = '';
82
+ #_value = '';
83
+ #_options = null;
84
+ #_status = null;
85
+ #_events = null;
86
+
87
+ constructor(name, eholds, opt){
88
+ // load elements
89
+ const _eholds = isPlainObject(eholds) ? eholds : {};
90
+ let { host, label, field } = _eholds;
91
+ // save elements
92
+ if (!isHTMLElement(host)) host = null;
93
+ if (!isHTMLElement(label)) label = null;
94
+ if (!isHTMLElement(field)) field = null;
95
+ this.#_host = host;
96
+ this.#_label = label;
97
+ this.#_field = field;
98
+ // load options
99
+ const _options = isPlainObject(opt) ? opt : {};
100
+ let {
101
+ idPref,
102
+ baseClassID,
103
+ hint,
104
+ type: fldType,
105
+ readonly: isReadOnly,
106
+ } = _options;
107
+ let fldSubType = '';
108
+ ({ type: fldType, subtype: fldSubType } = getInputFieldTypeDescr(fldType));
109
+ isReadOnly = readAsBool(isReadOnly, true);
110
+ // save options
111
+ this.#_options = _options;
112
+ // save status
113
+ this.#_status = {
114
+ fldType,
115
+ fldSubType,
116
+ isReadOnly,
117
+ isModified: false,
118
+ };
119
+ // init an event instance controller
120
+ if (field) {
121
+ field.addEventListener('change', this.#_saveFieldData);
122
+ field.addEventListener('input', this.#_switchFieldStatusOnInput);
123
+ field.addEventListener('blur', this.#_switchFieldStatusOnBlur);
124
+ };
125
+ this.#_events = new Map();
126
+ }
127
+
128
+ get isModified(){
129
+ return this.#_status.isModified;
130
+ }
131
+
132
+ get value(){
133
+ const field = this.#_field;
134
+ let result = '';
135
+ if (field) {
136
+ const { fldType } = this.#_status;
137
+ result = fldType === 'checkbox' ? field.checked : field.value;
138
+ };
139
+ return result;
140
+ }
141
+
142
+ set value(value){
143
+ const field = this.#_field;
144
+ if (value !== undefined) {
145
+ const { fldType } = this.#_status;
146
+ if (fldType === 'checkbox') {
147
+ field.checked = value;
148
+ this.#_status.isModified = false;
149
+ } else {
150
+ let _value = readAsString(value, '', {
151
+ boolToString: true,
152
+ numberToString: true,
153
+ });
154
+ field.value = _value;
155
+ this.#_status.isModified = false;
156
+ if (_value === '') {
157
+ this.#_triggerEvent('value-empty', {
158
+ type: 'value-empty',
159
+ target: null,
160
+ });
161
+ };
162
+ };
163
+ };
164
+ }
165
+
166
+ #_triggerEvent = (name, ...args) => {
167
+ triggerEventHandler(this.#_events, name, ...args);
168
+ };
169
+
170
+ #_saveFieldData = (e) => {
171
+ e.preventDefault();
172
+ const target = e.target;
173
+ //***/console.log(':'+e.type+':'+target.getAttribute('id')+':\n:saveFieldData() => received OnChange-event');
174
+ // // TODO:
175
+ this.#_triggerEvent('value-changed', {
176
+ type: 'value-changed',
177
+ target,
178
+ });
179
+ };
180
+
181
+ #_switchFieldStatusOnInput = (e) => {
182
+ e.preventDefault();
183
+ const target = e.target;
184
+ //***/console.log(':'+e.type+':'+target.getAttribute('id')+':\n:switchFieldStatusOnInput() => received OnInput-event');
185
+ this.#_status.isModified = true;
186
+ // // TODO:
187
+ if (target.value === '') {
188
+ this.#_triggerEvent('value-empty', {
189
+ type: 'value-empty',
190
+ target,
191
+ });
192
+ };
193
+ };
194
+
195
+ #_switchFieldStatusOnBlur = (e) => {
196
+ e.preventDefault();
197
+ //***/console.log(':'+e.type+':'+e.target.getAttribute('id')+':\n:switchFieldStatusOnBlur() => received OnBlur-event');
198
+ // // TODO:
199
+ };
200
+
201
+ attachTo(target){
202
+ const host = this.#_host;
203
+ let result = false;
204
+ if (
205
+ isHTMLElement(target)
206
+ && isHTMLElement(host)
207
+ ) {
208
+ target.append(host);
209
+ result = true;
210
+ };
211
+ return result;
212
+ }
213
+
214
+ isEmpty(){
215
+ return isEmptyString(this.value);
216
+ }
217
+
218
+ isNotEmpty(){
219
+ return isNotEmptyString(this.value);
220
+ }
221
+
222
+ show(){
223
+ showHtmlElement(this.#_host);
224
+ }
225
+
226
+ hide(){
227
+ hideHtmlElement(this.#_host);
228
+ }
229
+
230
+ clear(){
231
+ // // TODO:
232
+ }
233
+
234
+ static create(name, opt){
235
+ const eholds = THtmlInputField.createElement(name, opt, true);
236
+ const { field } = eholds;
237
+ return (
238
+ isHTMLElement(field)
239
+ ? new THtmlInputField(name, eholds, opt)
240
+ : null
241
+ );
242
+ }
243
+
244
+ static createElement(name, opt, doRetChild){
245
+ const id = valueToIDString(name);
246
+ const _options = isPlainObject(opt) ? opt : {};
247
+ let fldSubType = '';
248
+ let {
249
+ host,
250
+ idPref,
251
+ label,
252
+ labelPosition,
253
+ useDelim,
254
+ baseClassID,
255
+ hint,
256
+ type: fldType,
257
+ readonly: isReadOnly,
258
+ } = _options;
259
+ if (!isPlainObject(baseClassID)) baseClassID = {};
260
+ let {
261
+ main: bcidMain,
262
+ host: bcidHost,
263
+ label: bcidLabel,
264
+ field: bcidField,
265
+ } = baseClassID;
266
+ bcidMain = valueToClassList(bcidMain);
267
+ bcidHost = valueToClassList(bcidHost);
268
+ bcidLabel = valueToClassList(bcidLabel);
269
+ bcidField = valueToClassList(bcidField);
270
+ idPref = valueToIDString(idPref);
271
+ hint = readAsString(hint, '', true);
272
+ ({ type: fldType, subtype: fldSubType } = getInputFieldTypeDescr(fldType));
273
+ if (fldSubType === 'switch') bcidField.push('switch');
274
+ labelPosition = getLabelPositionID(labelPosition);
275
+ if (typeof useDelim !== 'boolean') useDelim = true;
276
+ label = readAsString(label, '', true);
277
+ if (label !== '') label = `${label}${useDelim ? ':' : ''}`;
278
+ isReadOnly = readAsBool(isReadOnly, true);
279
+ let fldID = idPref === '' ? id : `${idPref}-${id}`;
280
+ if (!isHTMLElement(host)) {
281
+ host = createNewHtmlElement('div', {
282
+ class: bcidHost,
283
+ });
284
+ };
285
+ let lblHolder = null;
286
+ let fldHolder = null;
287
+ let items = [];
288
+ if (host) {
289
+ lblHolder = host.querySelector(`label[for="${fldID}"]`);
290
+ if (!lblHolder) {
291
+ lblHolder = createNewHtmlElement('label', {
292
+ text: label,
293
+ attr: {
294
+ for: fldID,
295
+ },
296
+ class: bcidLabel,
297
+ });
298
+ };
299
+ fldHolder = host.querySelector(`input#${fldID}`);
300
+ if (!fldHolder) {
301
+ fldHolder = createNewHtmlElement('input', {
302
+ id: fldID,
303
+ attr: {
304
+ type: fldType,
305
+ placeholder: hint,
306
+ },
307
+ class: bcidField,
308
+ });
309
+ };
310
+ if (fldHolder) {
311
+ if (isReadOnly) {
312
+ const attr = fldType === 'checkbox' ? 'disabled' : 'readOnly';
313
+ fldHolder[attr] = true;
314
+ };
315
+ if (lblHolder) items.push(lblHolder);
316
+ items.push(fldHolder);
317
+ };
318
+ const len = items.length;
319
+ if (len > 0) {
320
+ if (len === 2 && labelPosition === 1) {
321
+ items = [ items[1], items[0] ];
322
+ };
323
+ host.append(...items);
324
+ };
325
+ };
326
+ // // TODO:
327
+ return (
328
+ readAsBool(doRetChild, false)
329
+ ? { host, label: lblHolder, field: fldHolder }
330
+ : host
331
+ );
332
+ }
333
+
334
+ on(name, evnt){
335
+ pushEventHandler(this.#_events, name, evnt);
336
+ }
337
+
338
+ };
339
+
340
+ // === module exports block ===
341
+
342
+ module.exports.THtmlInputField = THtmlInputField;