@cntwg/html-helper 0.0.14 → 0.0.16

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,6 +1,6 @@
1
- >|***rev.*:**|0.1.9|
1
+ >|***rev.*:**|0.1.11|
2
2
  >|:---|---:|
3
- >|date:|2022-09-12|
3
+ >|date:|2022-09-25|
4
4
 
5
5
  ## Introduction
6
6
 
@@ -26,6 +26,7 @@ The `options` structure has listed below:
26
26
  |option name|value type|default value|description|
27
27
  |:---|---|---:|:---|
28
28
  |`autoHideNewItems`|`boolean`|`false`|alters behavior of the `addItem` class method. If set to `true`, the item which was added to a container members will be automatically hidden|
29
+ |`markCurrentItem`|`boolean`|`false`|alters behavior of the `setCurIndex` class method. If set to `true`, the item which was added to a container members will be automatically marked as current|
29
30
 
30
31
  #### class properties
31
32
 
@@ -75,11 +76,15 @@ This method tries to find a given item in the list and if it is found returns it
75
76
 
76
77
  ##### **srchIndexByAttr(name, value)**
77
78
 
78
- This method tries to find an item by its given attribute in the list and if it is found returns its index.
79
+ This method tries to find an item that has an attribute with a given `name` and `value` in the list and if it is found its index is returned.
80
+
81
+ The `value` can be a `boolean`, `number` or a `string`. If it is not given the empty string value is used. In any other cases the method will failed.
82
+
83
+ > Note: In case when a `value` is an empty string the method will accept any item with an attribute which name is equal to a given `name` regardless of a value such attribute has.
79
84
 
80
85
  ##### **srchIndexByID(value)**
81
86
 
82
- This method tries to find an item by its `ID`-attribute in the list and if it is found returns its index.
87
+ This method tries to find an item by its `ID`-attribute in the list and if it is found returns its index (*see description of `srchIndexByAttr` method for details how a `value` parameter is used*).
83
88
 
84
89
  ##### **setCurIndex(value)**
85
90
 
@@ -95,11 +100,11 @@ This method returns an item addressed by a given `index`.
95
100
 
96
101
  ##### **getItemByAttr(name, value)**
97
102
 
98
- This method tries to find an item by its given attribute in the list and if found returns it.
103
+ This method tries to find an item by its given attribute in the list and if found returns it (*see description of `srchIndexByAttr` method for details how a `value` parameter is used*).
99
104
 
100
105
  ##### **getItemByID(value)**
101
106
 
102
- This method tries to find an item by its `ID`-attribute in the list and if found returns it.
107
+ This method tries to find an item by its `ID`-attribute in the list and if found returns it (*see description of `srchIndexByAttr` method for details how a `value` parameter is used*).
103
108
 
104
109
  ##### **addItem(item\[, options])**
105
110
 
@@ -141,7 +146,7 @@ This method checks whether or not an item addressed by an `index` is hidden and
141
146
 
142
147
  ### **THtmlItemsListController**
143
148
 
144
- This class implements a controller that provide mechanism for menaging a list container and its elements placed on an HTML-form.
149
+ This class implements a controller that provide mechanism for managing a list container and its elements placed on an HTML-form.
145
150
 
146
151
  #### class constructor
147
152
 
@@ -157,6 +162,7 @@ The `options` structure has listed below:
157
162
  |option name|value type|default value|description|
158
163
  |:---|---|---:|:---|
159
164
  |`autoHideNewItems`|`boolean`|`false`|alters behavior of the `addItem` class method. If set to `true`, the item which was added to a container members will be automatically hidden|
165
+ |`markCurrentItem`|`boolean`|`false`|alters behavior of the `setCurIndex` class method. If set to `true`, the item which was added to a container members will be automatically marked as current|
160
166
  |`showStubsIfEmpty`|`boolean`|`false`|if set, in case of the empty list, the default stub-item will be displayed|
161
167
  |`allowGroupSelection`|`boolean`|`false`|if set the more than one element can be selected in the list|
162
168
  |`allowSelectionLocks`|`boolean`|`false`|<*reserved, experimental*>|
@@ -277,7 +283,7 @@ This method checks whether or not an item addressed by an `index` is hidden and
277
283
 
278
284
  This method sets event handler for the list event addressed by `name` parameter.
279
285
 
280
- > Note: for current implementation you can't reset or set new event handler (especailly another one) if a hanlder with the same name exists already.
286
+ > Note: for current implementation you can't reset or set new event handler (especially another one) if a handler with the same name exists already.
281
287
 
282
288
  #### class events
283
289
 
@@ -290,8 +296,8 @@ The class generates the events listed in the table bellow:
290
296
  |`item-added`|fired when an item was added to the list|
291
297
  |`item-removed`|fired when an item was deleted from the list. It will not occur in case the item is the last.|
292
298
  |`current-item-chosen`|fired when an item was choosen as current|
293
- |`item-selected`|fired when an item was marked as selested in the list|
294
- |`item-unselected`|fired when an item was marked as unselested in the list|
299
+ |`item-selected`|fired when an item was marked as selected in the list|
300
+ |`item-unselected`|fired when an item was unmarked as selected in the list|
295
301
  |`item-hidden`|fired when an item was marked as hidden in the list|
296
302
  |`item-shown`|fired when an item was marked as non-hidden in the list|
297
303
 
@@ -339,7 +345,7 @@ This class method tries to include a given `item` to a set members with a label
339
345
 
340
346
  The `actForce` parameter if given alters the method behaviour:
341
347
 
342
- - If set to `true` it force replacements of an existing item which label is qual to `name`;
348
+ - If set to `true` it force replacements of an existing item which label is equal to `name`;
343
349
  - If set to `false` and item with the same label already exists the method will failed;
344
350
  - If parameter is not given or not of a `boolean` type its default value meant to be `false`.
345
351
 
@@ -400,6 +406,6 @@ The `options` parameter is an `object` that contains the following set of parame
400
406
  |:---|---|---:|:---|
401
407
  |`useClear`|`boolean`|`true`|if set to `true`, before the load of the items, the list is cleared|
402
408
  |`load_as_new`|`boolean`|`true`|*will deprecate (use `useClear` instead)*|
403
- |`force`|`boolean`|`false`|if set to `true`, the item which is allready present will be replaced with a new one|
409
+ |`force`|`boolean`|`false`|if set to `true`, the item which is already present will be replaced with a new one|
404
410
 
405
411
  If the `options` parameter is a `boolean` value it treats as a `options.useClear` option.
@@ -1,6 +1,6 @@
1
- >|***rev.*:**|0.1.3|
1
+ >|***rev.*:**|0.1.4|
2
2
  >|:---|---:|
3
- >|date:|2022-09-03|
3
+ >|date:|2022-09-22|
4
4
 
5
5
  ## Introduction
6
6
 
@@ -116,3 +116,7 @@ The `options` structure has listed below:
116
116
  If succeed, the function returned `HTMLElement` and `null` if failed.
117
117
 
118
118
  This function make all the jobs under the hood. So there is no need to call DOM-object directly in many situations.
119
+
120
+ #### **valueToIDString(value)**
121
+
122
+ This function tries to convert a given `value` to `ID_STRING`. If failed an empty string is returned.
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- // [v0.1.009-20220912]
1
+ // [v0.1.010-20220922]
2
2
 
3
3
  // === module init block ===
4
4
 
@@ -43,6 +43,7 @@ exports.BTS_DEF_GROUP_NAME = html_bts.BTS_DEF_GROUP_NAME;
43
43
  exports.THtmlListButtonsController = html_list_btn.THtmlListButtonsController;
44
44
 
45
45
  // experimental
46
+ exports.valueToIDString = html_helper.valueToIDString;
46
47
  exports.createNewHtmlElement = html_helper.createNewHtmlElement;
47
48
 
48
49
  exports.classes = {
@@ -51,4 +52,5 @@ exports.classes = {
51
52
  THtmlItemsListController: exports.THtmlItemsListController,
52
53
  THtmlButtonsSet: exports.THtmlButtonsSet,
53
54
  THtmlListButtonsController: exports.THtmlListButtonsController,
55
+ THtmlButtonsControllerARCSet: exports.THtmlButtonsControllerARCSet,
54
56
  };
@@ -1,4 +1,4 @@
1
- // [v0.1.042-20220912]
1
+ // [v0.1.043-20220922]
2
2
 
3
3
  // === module init block ===
4
4
 
@@ -10,6 +10,7 @@ const {
10
10
 
11
11
  const {
12
12
  isHTMLElement, CSS_CLASS_STRING,
13
+ valueToIDString,
13
14
  } = require('./html-helper-lib.js');
14
15
 
15
16
  const {
@@ -53,7 +54,8 @@ class THtmlButtonsSet {
53
54
  constructor(){
54
55
  // define default functions for manipulators
55
56
  const __user_index_getter = (value) => {
56
- return readAsString(value, '', { useTrim: true, numberToString: true });
57
+ //return readAsString(value, '', { useTrim: true, numberToString: true });
58
+ return valueToIDString(value);
57
59
  };
58
60
  const __user_item_getter = (value) => {
59
61
  return THtmlButtonsSet.isHTMLButton(value) ? value : null;
@@ -1,12 +1,12 @@
1
- // [v0.1.036-20220902]
1
+ // [v0.1.051-20221009]
2
2
 
3
3
  // === module init block ===
4
4
 
5
5
  const {
6
- readAsBool, readAsNumber, readAsString,
7
- isEmptyString,
8
- isNotEmptyString,
9
- isArray, isObject,
6
+ //readAsBool,
7
+ readAsNumber,
8
+ //valueToIndex,
9
+ //isArray, isObject,
10
10
  isPlainObject,
11
11
  TItemsListEx,
12
12
  } = require('@ygracs/bsfoc-lib-js');
@@ -15,6 +15,7 @@ const {
15
15
  isHTMLElement, isSelectedHTMLElement, isHiddenHTMLElement,
16
16
  showHtmlElement, hideHtmlElement,
17
17
  selectHtmlElement, unselectHtmlElement,
18
+ markHtmlElementAsCurrent, unmarkCurrentHtmlElement,
18
19
  CSS_CLASS_STRING,
19
20
  } = require('./html-helper-lib.js');
20
21
 
@@ -24,10 +25,35 @@ const {
24
25
  CSS_CLASS_SELECTED,
25
26
  CSS_CLASS_DISABLED,
26
27
  CSS_CLASS_HIDDEN,
28
+ CSS_CLASS_CURRENT,
29
+ CSS_CLASS_ACTIVE,
27
30
  } = CSS_CLASS_STRING;
28
31
 
32
+ const ILC_SMODE_DEF = 0;
33
+ const ILC_SMODE_SHFT = 1;
34
+ const ILC_SMODE_CTRL = 2;
35
+
29
36
  // === module extra block (helper functions) ===
30
37
 
38
+ function readAsAttrValue(value){
39
+ let result = null;
40
+ switch (typeof value) {
41
+ case 'boolean':
42
+ result = value.toString();
43
+ break;
44
+ case 'number':
45
+ if (Number.isNaN(value)) break;
46
+ result = value.toString();
47
+ break;
48
+ case 'string':
49
+ result = value.trim();
50
+ break;
51
+ default:
52
+ break;
53
+ };
54
+ return result;
55
+ };
56
+
31
57
  // === module main block (function definitions) ===
32
58
 
33
59
  // === module main block (class definitions) ===
@@ -36,16 +62,33 @@ class THtmlItemsListContainer {
36
62
  #_host = null;
37
63
  #_items = null;
38
64
  #_options = null;
65
+ #_status = null;
39
66
 
40
67
  constructor(host, opt) {
41
- this.#_items = new TItemsListEx();
68
+ // check host
42
69
  this.#_host = isHTMLElement(host) ? host : null;
70
+ // init items container
71
+ const _items = new TItemsListEx();
72
+ this.#_items = _items;
43
73
  // load options
44
74
  const _options = isPlainObject(opt) ? opt : {};
45
- let { autoHideNewItems, } = _options;
46
- if (typeof autoHideNewItems !== 'boolean') autoHideNewItems = false;
75
+ let {
76
+ autoHideNewItems,
77
+ markCurrentItem,
78
+ } = _options;
79
+ if (typeof autoHideNewItems !== 'boolean') {
80
+ _options.autoHideNewItems = autoHideNewItems = false;
81
+ };
82
+ if (typeof markCurrentItem !== 'boolean') {
83
+ _options.markCurrentItem = markCurrentItem = false;
84
+ };
85
+ // init status
86
+ const _status = {
87
+ curIndex: _items.curIndex,
88
+ curItem: _items.curItem,
89
+ };
90
+ this.#_status = _status;
47
91
  // save options
48
- _options.autoHideNewItems = autoHideNewItems;
49
92
  this.#_options = _options;
50
93
  }
51
94
 
@@ -80,7 +123,11 @@ class THtmlItemsListContainer {
80
123
 
81
124
  clear(){
82
125
  this.#_items.clear();
83
- if (this.#_host) this.#_host.innerHTML = '';
126
+ const _status = this.#_status;
127
+ _status.curIndex = this.curIndex;
128
+ _status.curItem = this.curItem;
129
+ const _host = this.#_host;
130
+ if (_host) _host.innerHTML = '';
84
131
  }
85
132
 
86
133
  isEmpty(){
@@ -103,22 +150,20 @@ class THtmlItemsListContainer {
103
150
  return isHTMLElement(item) ? this.#_items.srchIndex(item) : -1;
104
151
  }
105
152
 
106
- srchIndexByAttr(name, value){
107
- let index = -1;
153
+ srchIndexByAttr(name, value = ''){
108
154
  const _name = typeof name === 'string' ? name.trim() : '';
109
- const _value = readAsString(value, '', {
110
- useTrim: true,
111
- numberToString: true,
112
- boolToString: true,
113
- });
114
- if (_name !== '' && _value !== '') {
155
+ const _value = readAsAttrValue(value);
156
+ let index = -1;
157
+ if (_name !== '' && _value !== null) {
158
+ const acceptAnyVal = _value === '';
159
+ const _items = this.#_items;
115
160
  let item = null;
116
- for (let i = 0; i < this.count; i++) {
117
- item = this.getItem(i);
161
+ for (let i = 0; i < _items.count; i++) {
162
+ item = _items.getItem(i);
118
163
  if (
119
164
  isHTMLElement(item)
120
165
  && item.hasAttribute(_name)
121
- && item.getAttribute(_name) === _value
166
+ && (acceptAnyVal || item.getAttribute(_name) === _value)
122
167
  ) {
123
168
  index = i;
124
169
  break;
@@ -133,11 +178,29 @@ class THtmlItemsListContainer {
133
178
  };
134
179
 
135
180
  setCurIndex(index){
136
- return this.#_items.setIndex(index);
181
+ const isSUCCEED = this.#_items.setIndex(index);
182
+ if (isSUCCEED) {
183
+ const markCurrentItem = this.#_options.markCurrentItem;
184
+ const _status = this.#_status;
185
+ if (markCurrentItem && _status.curIndex !== -1) {
186
+ unmarkCurrentHtmlElement(_status.curItem);
187
+ };
188
+ const item = this.getItem(index);
189
+ _status.curIndex = Number(index);
190
+ _status.curItem = item;
191
+ if (markCurrentItem) markHtmlElementAsCurrent(item);
192
+ };
193
+ return isSUCCEED;
137
194
  }
138
195
 
139
196
  rstCurIndex(){
197
+ const _status = this.#_status;
198
+ if (this.#_options.markCurrentItem && _status.curIndex !== -1) {
199
+ unmarkCurrentHtmlElement(_status.curItem);
200
+ };
140
201
  this.#_items.rstIndex();
202
+ _status.curIndex = this.#_items.curIndex;
203
+ _status.curItem = this.curItem;
141
204
  }
142
205
 
143
206
  getItem(index){
@@ -145,59 +208,51 @@ class THtmlItemsListContainer {
145
208
  return isHTMLElement(item) ? item : null;
146
209
  }
147
210
 
148
- getItemByAttr(name, value = ''){
149
- let _name = '';
150
- let item = null;
151
- let index = -1;
152
- value = readAsString(value, '', {
153
- useTrim: true,
154
- numberToString: true,
155
- boolToString: true,
156
- });
157
- if (typeof name === 'string' && ((_name = name.trim()) !== '')){
158
- const useAnyName = isEmptyString(name);
159
- const useAnyVal = isEmptyString(value);
160
- for (let i = 0; i < this.count; i++) {
161
- item = this.getItem(i);
162
- if (
163
- isHTMLElement(item)
164
- && item.hasAttribute(_name)
165
- && (useAnyVal || item.getAttribute(_name) === value)
166
- ) {
167
- index = i;
168
- break;
169
- };
170
- };
171
- };
172
- return index !== -1 ? item : null;
211
+ getItemByAttr(...args){
212
+ return this.getItem(this.srchIndexByAttr(...args));
173
213
  }
174
214
 
175
215
  getItemByID(value){
176
- return this.getItemByAttr('id', value);
216
+ return this.getItem(this.srchIndexByID(value));
177
217
  }
178
218
 
179
219
  addItem(item, opt){
180
- let index = isHTMLElement(item) ? this.#_items.addItemEx(item, opt) : -1;
181
- let isSUCCEED = index !== -1;
220
+ const forceCI = typeof opt === 'boolean' ? opt : false;
221
+ const index = (
222
+ isHTMLElement(item)
223
+ ? this.#_items.addItemEx(item, false)
224
+ : -1
225
+ );
226
+ const isSUCCEED = index !== -1;
182
227
  if (isSUCCEED) {
183
228
  if (this.#_options.autoHideNewItems) hideHtmlElement(item);
184
- if (this.#_host) this.#_host.appendChild(item);
229
+ if (forceCI) this.setCurIndex(index);
230
+ if (this.#_host) this.#_host.append(item);
185
231
  };
186
232
  return isSUCCEED ? index : -1;
187
233
  }
188
234
 
189
235
  delItem(index, opt){
190
- let item = this.#_items.delItemEx(index, opt);
191
- let isSUCCEED = isHTMLElement(item);
192
- if (isSUCCEED && this.#_host && this.#_host.contains(item)) {
193
- this.#_host.removeChild(item);
236
+ const forceCI = typeof opt === 'boolean' ? opt : true;
237
+ const _items = this.#_items;
238
+ const item = _items.delItemEx(index, forceCI);
239
+ const isSUCCEED = isHTMLElement(item);
240
+ if (isSUCCEED) {
241
+ const index = _items.curIndex;
242
+ if (index === -1) {
243
+ this.rstCurIndex();
244
+ } else {
245
+ this.setCurIndex(_items.curIndex);
246
+ };
247
+ if (this.#_host) item.remove();
194
248
  };
195
249
  return isSUCCEED;
196
250
  }
197
251
 
198
252
  selectItem(index, opt){
199
- let isSUCCEED = selectHtmlElement(this.#_items.getItem(index));
200
- if (isSUCCEED && readAsBool(opt, false)) this.#_items.setIndex(index);
253
+ const forceCI = typeof opt === 'boolean' ? opt : false;
254
+ const isSUCCEED = selectHtmlElement(this.#_items.getItem(index));
255
+ if (isSUCCEED && forceCI) this.setCurIndex(index);
201
256
  return isSUCCEED;
202
257
  }
203
258
 
@@ -227,7 +282,6 @@ class THtmlItemsListController extends THtmlItemsListContainer {
227
282
  #_host = null;
228
283
  #_stubs = null;
229
284
  #_selects = null;
230
- #_visibles = null;
231
285
  #_options = null;
232
286
  #_status = null;
233
287
  #_events = null;
@@ -242,21 +296,23 @@ class THtmlItemsListController extends THtmlItemsListContainer {
242
296
  super(_host, _options);
243
297
  // load options
244
298
  let {
245
- autoHideNewItems,
299
+ //autoHideNewItems, // [*] processed by parent
300
+ //markCurrentItem, // [*] processed by parent
246
301
  showStubsIfEmpty,
247
302
  allowGroupSelection,
248
303
  allowSelectionLocks,
249
304
  stubs: stubsList,
250
305
  } = _options;
251
- if (typeof autoHideNewItems !== 'boolean') autoHideNewItems = false;
252
- if (typeof showStubsIfEmpty !== 'boolean') showStubsIfEmpty = false;
253
- if (typeof allowGroupSelection !== 'boolean') allowGroupSelection = false;
254
- if (typeof allowSelectionLocks !== 'boolean') allowSelectionLocks = false;
306
+ if (typeof showStubsIfEmpty !== 'boolean') {
307
+ _options.showStubsIfEmpty = showStubsIfEmpty = false;
308
+ };
309
+ if (typeof allowGroupSelection !== 'boolean') {
310
+ _options.allowGroupSelection = allowGroupSelection = false;
311
+ };
312
+ if (typeof allowSelectionLocks !== 'boolean') {
313
+ _options.allowSelectionLocks = allowSelectionLocks = false;
314
+ };
255
315
  // save options
256
- _options.autoHideNewItems = autoHideNewItems;
257
- _options.showStubsIfEmpty = showStubsIfEmpty;
258
- _options.allowGroupSelection = allowGroupSelection;
259
- _options.allowSelectionLocks = allowSelectionLocks;
260
316
  this.#_options = _options;
261
317
  // init status flags set
262
318
  const _status = {
@@ -264,6 +320,9 @@ class THtmlItemsListController extends THtmlItemsListContainer {
264
320
  isStubItemShown: false,
265
321
  isHostEnabled: isHostEnabled,
266
322
  catchEventOnHost: false,
323
+ execDelItem: false,
324
+ execDelItemDI: -1,
325
+ execDelItemCI: -1,
267
326
  }
268
327
  // bind ref to host
269
328
  this.#_host = _host;
@@ -271,8 +330,6 @@ class THtmlItemsListController extends THtmlItemsListContainer {
271
330
  this.#_stubs = new THtmlStubItemsSet(_host, stubsList);
272
331
  // init index of selected items
273
332
  this.#_selects = new Set();
274
- // init index of visible items
275
- this.#_visibles = new Set();
276
333
  // init events controller
277
334
  this.#_events = new Map();
278
335
  if (isHostEnabled) {
@@ -287,23 +344,31 @@ class THtmlItemsListController extends THtmlItemsListContainer {
287
344
 
288
345
  #_on_will_select_item = (e) => {
289
346
  //console.log('THtmlItemsListController._on_will_select_item() ==> was called...');
290
- //console.log('CHECK: e => ditail:['+e.detail+']');
291
- //console.log('CHECK: e => phase:['+e.eventPhase+']');
292
347
  //e.preventDefault(); /* need to reconsider reason for use */
348
+ const {
349
+ eventPhase,
350
+ target,
351
+ currentTarget,
352
+ ctrlKey,
353
+ shiftKey,
354
+ } = e;
355
+ //console.log('CHECK: e => ditail:['+e.detail+']');
356
+ //console.log('CHECK: e => phase:['+eventPhase+']');
357
+ const onClickNum = readAsNumber(e.detail, 0);
293
358
  const _status = this.#_status;
294
359
  const { isSelectionLocked, catchEventOnHost } = _status;
295
- const on_click_num = readAsNumber(e.detail, 0);
296
360
  let curItem = null;
297
- switch (e.eventPhase) {
298
- //*case 1:
361
+ switch (eventPhase) {
299
362
  //* // NOTE: currently on eventPhase = 2 and 3
300
- case 2:
363
+ //*case 1:
301
364
  /**/// capturing stage
302
- curItem = e.target;
365
+ case 2:
366
+ /**/// target stage
367
+ if (target !== this.#_host) curItem = target;
303
368
  break;
304
369
  case 3:
305
370
  /**/// bubblig stage
306
- curItem = catchEventOnHost ? e.target : e.currentTarget;
371
+ curItem = catchEventOnHost ? target : currentTarget;
307
372
  break;
308
373
  default:
309
374
  break;
@@ -311,61 +376,15 @@ class THtmlItemsListController extends THtmlItemsListContainer {
311
376
  if (
312
377
  !isSelectionLocked
313
378
  && curItem instanceof HTMLElement
314
- && (on_click_num === 0 || on_click_num === 1)
379
+ && (onClickNum === 0 || onClickNum === 1)
315
380
  && !curItem.classList.contains(CSS_CLASS_DISABLED)
316
381
  ) {
317
- const key_ctrl = readAsBool(e.ctrlKey, false);
318
- const key_shft = readAsBool(e.shiftKey, false);
319
- //console.log('CHECK: e => isShiftKeyPressed:['+key_ctrl+']');
320
- //console.log('CHECK: e => isCtrlKeyPressed:['+key_shft+']');
321
- let c_index = this.curIndex;
322
- let n_index = this.srchIndex(curItem);
323
- //console.log('THtmlItemsListController._on_will_select_item() ==> current:['+c_index+']');
324
- //console.log('THtmlItemsListController._on_will_select_item() ==> next:['+n_index+']');
325
- let act_in_mode = 0;
326
- let act_unsel_grp = false;
327
- if (this.#_options.allowGroupSelection) {
328
- if (c_index !== -1) {
329
- if (key_ctrl) {
330
- act_in_mode = 2;
331
- } else if (key_shft) {
332
- act_in_mode = 1;
333
- } else if (this.#_selects.size > 0) {
334
- //console.log('THtmlItemsListController._on_will_select_item() ==> _selects.size:['+this.#_selects.size+']');
335
- act_unsel_grp = true;
336
- };
337
- };
338
- };
339
- //console.log('THtmlItemsListController._on_will_select_item() ==> mode:['+act_in_mode+']');
340
- //console.log('THtmlItemsListController._on_will_select_item() ==> act_unsel_grp:['+act_unsel_grp+']');
341
- if (act_unsel_grp) {
342
- for (let item of this.#_selects) {
343
- c_index = this.srchIndex(item);
344
- if (c_index !== -1) this.unselectItem(c_index);
345
- };
346
- c_index = -1;
347
- };
348
- if (act_in_mode === 1) {
349
- if (c_index > n_index) [ c_index, n_index ] = [ n_index, c_index ];
350
- let t_index = 0;
351
- for (let item of this.#_selects) {
352
- t_index = this.srchIndex(item);
353
- if (t_index !== -1) this.unselectItem(t_index);
354
- };
355
- this.#_selects.clear();
356
- for (let i = c_index; i < n_index + 1; i++) {
357
- this.selectItem(i, false);
358
- };
359
- } else if (act_in_mode === 2) {
360
- if (this.isSelectedItem(n_index)) {
361
- this.unselectItem(n_index);
362
- } else {
363
- this.selectItem(n_index, false);
364
- };
365
- } else if (c_index !== n_index) {
366
- if (c_index !== -1) this.unselectItem(c_index);
367
- this.selectItem(n_index, true);
368
- };
382
+ //console.log('CHECK: e => tag:['+curItem.tagName+']');
383
+ this.#_selectItemEx(curItem, {
384
+ ctrlKey: ctrlKey,
385
+ shiftKey: shiftKey,
386
+ forceCI: true,
387
+ });
369
388
  };
370
389
  };
371
390
 
@@ -378,8 +397,10 @@ class THtmlItemsListController extends THtmlItemsListContainer {
378
397
  };
379
398
 
380
399
  get SelectedItems(){
400
+ const _selects = this.#_selects;
401
+ // // TODO: consider to use: `[...<value>]`
381
402
  let result = [];
382
- for (let item of this.#_selects) {
403
+ for (let item of _selects) {
383
404
  if (item) result.push(item);
384
405
  };
385
406
  return result;
@@ -397,7 +418,6 @@ class THtmlItemsListController extends THtmlItemsListContainer {
397
418
  // // TODO: clear event handler on elements if set
398
419
  super.clear();
399
420
  this.#_selects.clear();
400
- this.#_visibles.clear();
401
421
  if (this.#_options.showStubsIfEmpty) {
402
422
  // show default stub-item
403
423
  this.#_status.isStubItemShown = this.#_stubs.showDefItem();
@@ -415,34 +435,52 @@ class THtmlItemsListController extends THtmlItemsListContainer {
415
435
  this.#_status.isSelectionLocked = false;
416
436
  }
417
437
 
418
- setCurIndex(index){
438
+ #_setCurIndex(index){
419
439
  const isSUCCEED = super.setCurIndex(index);
420
440
  if (isSUCCEED) this.#_triggerEvent('current-item-chosen', {
421
441
  index: Number(index),
422
442
  item: null,
423
443
  });
424
444
  return isSUCCEED;
445
+ };
446
+
447
+ setCurIndex(index){
448
+ return this.selectItem(index, true);
449
+ }
450
+
451
+ rstCurIndex(){
452
+ const {
453
+ execDelItem,
454
+ execDelItemDI,
455
+ execDelItemCI,
456
+ } = this.#_status;
457
+ if (execDelItem) {
458
+ let index = execDelItemCI;
459
+ if (execDelItemCI !== -1) index--;
460
+ if (index !== -1 && execDelItemDI !== execDelItemCI) {
461
+ this.unselectItem(index);
462
+ };
463
+ };
464
+ super.rstCurIndex();
425
465
  }
426
466
 
427
467
  addItem(item, opt){
428
- let index = super.addItem(item, false);
429
- let newItem = index !== -1 ? super.getItem(index) : null;
430
- if (newItem) {
431
- const _options = this.#_options;
468
+ const index = super.addItem(item, false);
469
+ if (index !== -1) {
470
+ const { autoHideNewItems, showStubsIfEmpty } = this.#_options;
432
471
  const _status = this.#_status;
433
- if (!_status.catchEventOnHost) {
472
+ const { catchEventOnHost, isStubItemShown } = _status;
473
+ if (!catchEventOnHost) {
434
474
  // set event handler on element if it is not set on host
435
- newItem.addEventListener('click', this.#_on_will_select_item);
475
+ item.addEventListener('click', this.#_on_will_select_item);
436
476
  };
437
477
  // TODO: consider if a "boolean" <opt> is enough
438
- let setItemAsCur = typeof opt === 'boolean' ? opt : false;
439
- if (_options.autoHideNewItems && !setItemAsCur) {
440
- super.hideItem(index);
441
- } else {
478
+ const forceCI = typeof opt === 'boolean' ? opt : false;
479
+ if (!autoHideNewItems) {
442
480
  if (index === 0) {
443
481
  if (
444
- _options.showStubsIfEmpty
445
- && _status.isStubItemShown
482
+ showStubsIfEmpty
483
+ && isStubItemShown
446
484
  && this.#_stubs.hideDefItem()
447
485
  ) {
448
486
  // hide default stub-item
@@ -450,38 +488,53 @@ class THtmlItemsListController extends THtmlItemsListContainer {
450
488
  };
451
489
  this.#_triggerEvent('first-item-added', {
452
490
  index: index,
453
- item: newItem,
491
+ item: item,
454
492
  });
455
493
  };
456
494
  this.#_triggerEvent('item-added', {
457
495
  index: index,
458
- item: newItem,
496
+ item: item,
497
+ });
498
+ };
499
+ if (forceCI) {
500
+ this.#_selectItemEx(item, {
501
+ ctrlKey: false,
502
+ shiftKey: false,
503
+ forceCI: forceCI,
459
504
  });
460
505
  };
461
- if (setItemAsCur) this.setCurIndex(index);
462
506
  };
463
507
  return index;
464
508
  }
465
509
 
466
510
  delItem(index, opt){
467
- let item = super.getItem(index);
468
- let isSUCCEED = isHTMLElement(item) ? super.delItem(index, opt) : false;
511
+ const item = super.getItem(index);
512
+ const _status = this.#_status;
513
+ let isSUCCEED = isHTMLElement(item);
514
+ if (isSUCCEED) {
515
+ _status.execDelItem = true;
516
+ _status.execDelItemCI = this.curIndex;
517
+ _status.execDelItemDI = Number(index);
518
+ isSUCCEED = super.delItem(index, opt);
519
+ _status.execDelItemDI = -1;
520
+ _status.execDelItemCI = -1;
521
+ _status.execDelItem = false;
522
+ };
469
523
  if (isSUCCEED) {
470
524
  const _options = this.#_options;
471
- const _status = this.#_status;
472
525
  if (!_status.catchEventOnHost) {
473
526
  // remove event handler on element if it was set by addItem()
474
527
  item.removeEventListener('click', this.#_on_will_select_item);
475
528
  };
476
- this.#_selects.delete(item);
477
- this.#_visibles.delete(item);
478
529
  if (this.isEmpty()) {
530
+ this.#_selects.clear();
479
531
  if (_options.showStubsIfEmpty) {
480
532
  // show default stub-item
481
533
  _status.isStubItemShown = this.#_stubs.showDefItem();
482
534
  };
483
535
  this.#_triggerEvent('list-clear');
484
536
  } else {
537
+ this.#_selects.delete(item);
485
538
  this.#_triggerEvent('item-removed', {
486
539
  index: Number(index),
487
540
  item: item,
@@ -491,22 +544,84 @@ class THtmlItemsListController extends THtmlItemsListContainer {
491
544
  return isSUCCEED;
492
545
  }
493
546
 
494
- selectItem(index, opt){
495
- let item = super.getItem(index);
496
- let isSUCCEED = selectHtmlElement(item);
547
+ #_selectItem(index){
548
+ const item = super.getItem(index);
549
+ const isSUCCEED = selectHtmlElement(item);
497
550
  if (isSUCCEED) {
498
551
  this.#_selects.add(item);
499
552
  this.#_triggerEvent('item-selected', {
500
553
  index: Number(index),
501
554
  item: item,
502
555
  });
503
- if (readAsBool(opt, false)) isSUCCEED = this.setCurIndex(index);
556
+ };
557
+ return isSUCCEED;
558
+ }
559
+
560
+ #_selectItemEx(item, opt){
561
+ const _selects = this.#_selects;
562
+ let {
563
+ ctrlKey = false,
564
+ shiftKey = false,
565
+ forceCI = false,
566
+ } = opt;
567
+ let mode = ILC_SMODE_DEF;
568
+ let doUnSelGrp = false;
569
+ let indexCI = this.curIndex;
570
+ let indexNI = this.srchIndex(item);
571
+ if (indexCI !== -1) {
572
+ if (this.#_options.allowGroupSelection) {
573
+ if (shiftKey) {
574
+ mode = ILC_SMODE_SHFT;
575
+ if (_selects.size > 0) doUnSelGrp = true;
576
+ } else if (ctrlKey) {
577
+ mode = ILC_SMODE_CTRL;
578
+ } else if (_selects.size > 0) {
579
+ doUnSelGrp = true;
580
+ };
581
+ } else if (_selects.size > 0) {
582
+ doUnSelGrp = true;
583
+ };
584
+ };
585
+ if (doUnSelGrp) {
586
+ for (let item of _selects) {
587
+ this.unselectItem(this.srchIndex(item));
588
+ };
589
+ _selects.clear();
590
+ };
591
+ switch (mode) {
592
+ case ILC_SMODE_SHFT:
593
+ if (indexCI > indexNI) [ indexCI, indexNI ] = [ indexNI, indexCI ];
594
+ for (let i = indexCI; i < indexNI + 1; i++) {
595
+ this.#_selectItem(i);
596
+ };
597
+ break;
598
+ case ILC_SMODE_CTRL:
599
+ this.#_selectItem(this.srchIndex(item));
600
+ break;
601
+ default:
602
+ if (this.#_selectItem(this.srchIndex(item))) {
603
+ if (forceCI) this.#_setCurIndex(indexNI);
604
+ };
605
+ break;
606
+ };
607
+ }
608
+
609
+ selectItem(index, opt){
610
+ const item = super.getItem(index);
611
+ let isSUCCEED = isHTMLElement(item);
612
+ if (isSUCCEED) {
613
+ const forceCI = typeof opt === 'boolean' ? opt : false;
614
+ this.#_selectItemEx(item, {
615
+ ctrlKey: false,
616
+ shiftKey: false,
617
+ forceCI: forceCI,
618
+ });
504
619
  };
505
620
  return isSUCCEED;
506
621
  }
507
622
 
508
623
  unselectItem(index){
509
- let item = super.getItem(index);
624
+ const item = super.getItem(index);
510
625
  let isSUCCEED = unselectHtmlElement(item);
511
626
  if (isSUCCEED) {
512
627
  this.#_selects.delete(item);
@@ -519,10 +634,9 @@ class THtmlItemsListController extends THtmlItemsListContainer {
519
634
  }
520
635
 
521
636
  hideItem(index){
522
- let item = super.getItem(index);
637
+ const item = super.getItem(index);
523
638
  let isSUCCEED = hideHtmlElement(item);
524
639
  if (isSUCCEED) {
525
- this.#_visibles.delete(item);
526
640
  this.#_triggerEvent('item-hidden', {
527
641
  index: Number(index),
528
642
  item: item,
@@ -532,10 +646,9 @@ class THtmlItemsListController extends THtmlItemsListContainer {
532
646
  }
533
647
 
534
648
  showItem(index){
535
- let item = super.getItem(index);
649
+ const item = super.getItem(index);
536
650
  let isSUCCEED = showHtmlElement(item);
537
651
  if (isSUCCEED) {
538
- this.#_visibles.add(item);
539
652
  this.#_triggerEvent('item-shown', {
540
653
  index: Number(index),
541
654
  item: item,
@@ -554,7 +667,6 @@ class THtmlItemsListController extends THtmlItemsListContainer {
554
667
  /* NOTE:
555
668
  * for current you can't reset or set new one on the same event
556
669
  */
557
- //console.log('THtmlItemsListController.on() ==> event:['+name+'] - already exists...');
558
670
  };
559
671
  };
560
672
  }
@@ -1,4 +1,4 @@
1
- // [v0.1.013-20220903]
1
+ // [v0.1.014-20220922]
2
2
 
3
3
  // === module init block ===
4
4
 
@@ -134,6 +134,23 @@ function valueToClassList(value, opt){
134
134
  return result;
135
135
  };
136
136
 
137
+ function valueToIDString(value){
138
+ let result = '';
139
+ switch (typeof value) {
140
+ case 'number':
141
+ if (Number.isNaN(value) || value < 0) break;
142
+ if (Number.isInteger(value)) result = value.toString();
143
+ break;
144
+ case 'string':
145
+ result = value.trim();
146
+ // // TODO: check if a valid character sequencies
147
+ break;
148
+ default:
149
+ break;
150
+ };
151
+ return result;
152
+ };
153
+
137
154
  function createNewHtmlElement(tagName, opt){
138
155
  let _tag = typeof tagName === 'string' ? tagName.trim() : '';
139
156
  if (_tag === '') return null;
@@ -147,8 +164,7 @@ function createNewHtmlElement(tagName, opt){
147
164
  data: dset,
148
165
  } = opt;
149
166
  // set an element id
150
- id = typeof id === 'string' ? id.trim() : '';
151
- if (id !== '') item.setAttribute('id', id);
167
+ if ((id = valueToIDString(id)) !== '') item.setAttribute('id', id);
152
168
  // set an element text context
153
169
  if (typeof text === 'string') {
154
170
  item.appendChild(document.createTextNode(text));
@@ -226,3 +242,4 @@ exports.valueToClassList = valueToClassList;
226
242
 
227
243
  // experimental
228
244
  exports.createNewHtmlElement = createNewHtmlElement;
245
+ exports.valueToIDString = valueToIDString;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cntwg/html-helper",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "description": "A base HTML-helper library for js",
5
5
  "author": "ygracs <cs70th-om@rambler.ru>",
6
6
  "license": "MIT",
@@ -40,6 +40,7 @@
40
40
  "@ygracs/bsfoc-lib-js": "^0.1.2"
41
41
  },
42
42
  "devDependencies": {
43
- "jest": "^27.5.1"
43
+ "jest": "^29.0.3",
44
+ "jest-environment-jsdom": "^29.0.3"
44
45
  }
45
46
  }
package/CHANGELOG.md DELETED
@@ -1,123 +0,0 @@
1
- #### *v0.0.14*
2
-
3
- Pre-release version.
4
-
5
- > - `html-ctrls-list.md` updated;
6
- > - some fixes in `html-ctrls/list-stubs.js` module;
7
- > - alter behavior for the `loadItems` method of a `THtmlStubItemsSet` class in case when its `options` parameter is set to `boolean` (see `html-ctrls-list.md` for details);
8
- > - added method `rstDefItem` to `THtmlStubItemsSet` class;
9
- > - added `THtmlButtonsControllerARCSet` class;
10
-
11
- #### *v0.0.13*
12
-
13
- Pre-release version.
14
-
15
- > - `html-helper-lib.md` updated;
16
- > - `html-ctrls-btn.md` updated;
17
- > - `html-ctrls-list.md` updated;
18
- > - some fixes in `html-helper-lib.js` module;
19
- > - some fixes in `html-ctrls-btn.js` module;
20
- > - some fixes in `html-ctrls-list.js` module;
21
- > - move definition of `THtmlStubItemsSet` from `html-ctrls-list.js` module to `html-ctrls/lists-stubs.js` submodule;
22
- > - add function `valueToClassList` into `html-helper-lib.js` module;
23
- > - updated dependency on `@ygracs/bsfoc-lib-js` module to v0.1.2.
24
-
25
- #### *v0.0.12*
26
-
27
- Pre-release version.
28
-
29
- > - updated dependency on `@ygracs/bsfoc-lib-js` module to v0.1.1.
30
-
31
- #### *v0.0.11*
32
-
33
- Pre-release version.
34
-
35
- > - `html-ctrls-btn.md` updated;
36
- > - `html-ctrls-list.md` updated;
37
- > - some fixes in `html-ctrls-list.js` module;
38
- > - some fixes in `html-ctrls-btn.js` module.
39
-
40
- #### *v0.0.10*
41
-
42
- Pre-release version.
43
-
44
- > - `html-ctrls-btn.md` updated;
45
- > - added `THtmlListButtonsController` class;
46
-
47
- #### *v0.0.9*
48
-
49
- Pre-release version.
50
-
51
- > - switch dependency from `@cntwg/bsfoc-lib-js` module to `@ygracs/bsfoc-lib-js` module.
52
-
53
- #### *v0.0.8*
54
-
55
- Pre-release version.
56
-
57
- > - updated dependency on `@cntwg/bsfoc-lib-js` module to v0.0.11.
58
-
59
- #### *v0.0.7*
60
-
61
- Pre-release version.
62
-
63
- > - updated dependency on `@cntwg/bsfoc-lib-js` module to v0.0.10;
64
- > - some fixes in `html-helper-lib.js` module;
65
- > - some fixes in `html-ctrls-list.js` module.
66
-
67
- #### *v0.0.6*
68
-
69
- Pre-release version.
70
-
71
- > - `html-ctrls-btn.md` updated;
72
- > - `html-ctrls-list.md` updated;
73
- > - `html-helper-lib.md` updated;
74
- > - some fixes in `html-ctrls-btn.js` module;
75
- > - some fixes in `html-ctrls-list.js` module.
76
-
77
- #### *v0.0.5*
78
-
79
- Pre-release version.
80
-
81
- > - `$module/test/README.md` added;
82
- > - updated dependency on `@cntwg/bsfoc-lib-js` module to v0.0.8;
83
- > - `html-ctrls-list.md` updated;
84
- > - added `minIndex` property to `THtmlItemsListContainer` class;
85
- > - some fixes in `html-ctrls-list.js` module;
86
- > - added 'classes' property for module exports;
87
- > - MIT-license applied.
88
-
89
- #### *v0.0.4*
90
-
91
- Pre-release version.
92
-
93
- > - updated dependency on `@cntwg/bsfoc-lib-js` module to v0.0.5.
94
-
95
- #### *v0.0.3*
96
-
97
- Pre-release version.
98
-
99
- > - added `activateHTMLElements` function;
100
- > - added `inactivateHTMLElements` function;
101
- > - added `createNewHtmlElement` function (experimental);
102
- > - `html-helper-lib.md` updated;
103
- > - `html-ctrls-btn.md` updated;
104
- > - `html-ctrls-list.md` updated.
105
-
106
- #### *v0.0.2*
107
-
108
- Pre-release version.
109
-
110
- > - `README.md` added;
111
- > - `html-helper-lib.md` added to `doc`;
112
- > - `html-ctrls-btn.md` added to `doc`;
113
- > - `html-ctrls-list.md` added to `doc`;
114
- > - added `CSS_CLASS_ACTIVE` constant to `CSS_CLASS_STRING`;
115
- > - added `isActiveHTMLElement` function;
116
- > - added `markHtmlElementAsActive` function;
117
- > - added `unmarkActiveHtmlElement` function;
118
- > - `html-btn-ctrl.js` was renamed `html-ctrls-btn.js`;
119
- > - `html-list-ctrl.js` was renamed `html-ctrls-list.js`.
120
-
121
- #### *v0.0.1*
122
-
123
- Pre-release version.