@nys-cui/cui-formpill 0.1.0 → 0.2.1

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/cui-formpill.js +242 -27
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "main": "./dist/js/cui-formpill.js",
8
8
  "type": "module",
9
- "version": "0.1.0",
9
+ "version": "0.2.1",
10
10
  "scripts": {
11
11
  "clean": "rm -rf ./dist",
12
12
  "build": "npm run clean && cui --dep",
@@ -7,6 +7,7 @@ class CUI_FORMPILL_PILL extends HTMLElement {
7
7
 
8
8
  this.attachShadow({ mode: 'open' });
9
9
 
10
+ this._connected = false;
10
11
  this._state = {};
11
12
 
12
13
  this.oPropsToStateNames = {
@@ -50,8 +51,7 @@ class CUI_FORMPILL_PILL extends HTMLElement {
50
51
  setState(props) {
51
52
  // Need to map props to state variable names if we want to keep them prefixed.
52
53
  this._state = Object.assign(this._state, this.normalizeProps(props));
53
-
54
- this.render();
54
+ if (this._connected) this.render();
55
55
  }
56
56
 
57
57
  clearSlottedElements(slotName) {
@@ -90,7 +90,7 @@ class CUI_FORMPILL_PILL extends HTMLElement {
90
90
  this._state.sValue3 = (this.getAttribute('value3')) ? this.getAttribute('value3') : null;
91
91
  this._state.asValues = (this.getAttribute('values')) ? this.getAttribute('values') : null;
92
92
 
93
- this._initialState = this._state;
93
+ this._connected = true;
94
94
  this.render();
95
95
  }
96
96
 
@@ -142,7 +142,6 @@ class CUI_FORMPILL_PILL extends HTMLElement {
142
142
 
143
143
  removeButton.addEventListener('click', (e) => {
144
144
  this.remove();
145
-
146
145
  this.dispatchEvent(myEvent)
147
146
  })
148
147
 
@@ -187,7 +186,8 @@ class CUI_FORMPILL extends HTMLElement {
187
186
  "html": "sHtmlContent",
188
187
  "config": "configData",
189
188
  "addTitle": "sAddTitle",
190
- "updateTitle": "sUpdateTitle"
189
+ "updateTitle": "sUpdateTitle",
190
+ "value": "aoValue"
191
191
 
192
192
  }
193
193
 
@@ -205,15 +205,99 @@ class CUI_FORMPILL extends HTMLElement {
205
205
  </div>`;
206
206
  }
207
207
 
208
- setState(props) {
208
+ setInitialState(state) {
209
+ for (let [k, v] of Object.entries(this._state)) {
210
+ switch (k) {
211
+ case "adPills":
212
+ this._initialState[k] = [];
213
+ for (let pill of v) {
214
+ let copiedPill = document.createElement("cui-formpill-pill");
215
+ if (!state) {
216
+ for (const attrValue of structuredClone(pill.getAttributeNames()))
217
+ copiedPill.setAttribute(attrValue, pill.getAttribute(attrValue));
218
+
219
+ } else {
220
+
221
+ for (const attrValue of structuredClone(pill.getAttributeNames()))
222
+ copiedPill.setAttribute(attrValue, pill._state[pill.oPropsToStateNames[attrValue]]);
223
+
224
+ }
225
+ this._initialState[k].push(copiedPill);
226
+
227
+ }
228
+ break;
229
+
230
+ case "criteriaList":
231
+ this._initialState[k] = structuredClone(v);
232
+ break;
233
+
234
+ case "configData":
235
+ this._initialState[k] = structuredClone(v);
236
+ break;
237
+
238
+ default:
239
+ this._initialState[k] = v;
240
+
241
+ }
242
+
243
+ }
244
+ }
245
+
246
+ setState(props, bOverrideInitialState = false) {
209
247
  // Need to map props to state variable names if we want to keep them prefixed.
248
+ if (!this._initialState) this._initialState = {};
249
+
210
250
  this._state = Object.assign(this._state, this.normalizeProps(props));
211
251
 
212
252
  if (this._connected) {
213
253
  this.render();
214
254
  }
255
+
256
+ if (bOverrideInitialState) {
257
+ if (this._connected) {
258
+ this.setInitialState(true);
259
+ } else {
260
+ this.setInitialState();
261
+ }
262
+ }
215
263
  }
264
+ reset() {
265
+
266
+ for (const [k, v] of Object.entries(this._initialState)) {
267
+ switch (k) {
268
+ case "adPills":
269
+ this._state[k] = [];
270
+ for (const pill of v) {
271
+ const myEvent = new CustomEvent("pill-removed", {
272
+ detail: { pill: pill }
273
+ });
274
+ this.dispatchEvent(myEvent);
275
+ let copiedPill = document.createElement("cui-formpill-pill");
276
+ for (const attrValue of structuredClone(pill.getAttributeNames())) {
277
+ copiedPill.setAttribute(attrValue, pill.getAttribute(attrValue));
278
+ }
279
+ this._state[k].push(copiedPill);
280
+
281
+ }
282
+ break;
283
+
284
+ case "criteriaList":
285
+ this._state[k] = structuredClone(v);
286
+ break;
287
+
288
+ case "configData":
289
+ this._state[k] = structuredClone(v);
290
+ break;
291
+
292
+ default:
293
+ this._state[k] = v;
216
294
 
295
+ }
296
+
297
+ }
298
+
299
+ this.render(true);
300
+ }
217
301
  get label() {
218
302
 
219
303
  if (this.dLabelContents) {
@@ -270,15 +354,17 @@ class CUI_FORMPILL extends HTMLElement {
270
354
  this._state.sComponentKey = (this.getAttribute('componentKey')) ? this.getAttribute('componentKey') : "";
271
355
  this._state.bAccessibleHideLabel = this.hasAttribute('accessiblehidelabel') ? true : false;
272
356
  this._state.sPosition = (this.getAttribute('position')) ? this.getAttribute('position') : "bottom-center";
357
+ this._state.aoValue = (this.getAttribute('value')) ? this.getAttribute('value') : [];
273
358
 
274
359
  //Set initial state only once at connection to page. At this point any initial data should have been passed to the field.
275
360
  if (!this._initialState || this._initialState == null) {
276
361
  // Shallow clone for now unless it's determined we need a deep clone.
277
- this._initialState = { ...this._state };
362
+ this._initialState = {};
278
363
  }
279
364
 
280
- this._state.fGlobalBodyClick = this.globalBodyClick.bind(this);
365
+ this.fGlobalBodyClick = this.globalBodyClick.bind(this);
281
366
 
367
+ this.setInitialState();
282
368
  this.render();
283
369
  }
284
370
 
@@ -304,7 +390,7 @@ class CUI_FORMPILL extends HTMLElement {
304
390
  </div>`
305
391
  }
306
392
 
307
- render() {
393
+ render(reset = false) {
308
394
  this.clearShadowDom(this.shadowRoot);
309
395
  this.clearSlottedElements("menu-trigger");
310
396
  this.clearSlottedElements("labelContents");
@@ -312,6 +398,29 @@ class CUI_FORMPILL extends HTMLElement {
312
398
 
313
399
  this.shadowRoot.innerHTML = `${this.sFieldLayout} `;
314
400
 
401
+ this._state.adPills = [];
402
+
403
+ if (this._state.configData?.filterCriteria && !this._state.configData.filterCriteria.loadedPills) {
404
+ this._state.configData.filterCriteria.loadedPills = []
405
+ }
406
+
407
+ if (this._state.aoValue && this._state.aoValue.length > 0 && this._state.configData?.filterCriteria?.loadedPills && reset === false) {
408
+ this._state.configData.filterCriteria.loadedPills = []
409
+ for (let pill of this._state.aoValue) {
410
+ this._state.configData.filterCriteria.loadedPills.push(pill);
411
+ }
412
+ this.addPillfromJSON();
413
+
414
+ } else if (reset === true) {
415
+ if(this._state.configData?.filterCriteria?.loadedPills){
416
+
417
+ this._state.configData.filterCriteria.loadedPills = []
418
+ }
419
+ this.addPillfromJSON();
420
+ }
421
+
422
+
423
+
315
424
  let adSlots = this.shadowRoot.querySelectorAll('slot');
316
425
 
317
426
  if (adSlots.length) {
@@ -341,12 +450,40 @@ class CUI_FORMPILL extends HTMLElement {
341
450
  pillDiv.classList.add('pill-container');
342
451
  pillDiv.part = "pill-container"
343
452
  pillDiv.slot = "pill-container"
344
- let dTriggerElem = document.createElement('button');
453
+ this.appendChild(label);
454
+ this.appendChild(pillDiv);
345
455
 
456
+ let dTriggerElem = document.createElement('button');
346
457
  if (this._state.adPills.length > 0) {
458
+
347
459
  for (let i = 0; i < this._state.adPills.length; i++) {
460
+
348
461
  pillDiv.append(this._state.adPills[i])
462
+ const customEvent = new CustomEvent('pill-created', { detail: { pill: this._state.adPills[i] } });
463
+ this.dispatchEvent(customEvent);
464
+ this._state.adPills[i].addEventListener('pill_removed', (e) => {
465
+ let removedValue = e.detail.state.sValue1;
466
+ if (!this._state.criteriaList.some(item => item.value === removedValue)) {
467
+ this._state.criteriaList.unshift(this._state.configData.filterCriteria.items.find(item => item.value === removedValue));
468
+ }
469
+ const myEvent = new CustomEvent("pill-removed", {
470
+ detail: { pill: e.detail }
471
+ });
472
+ let index = this._state.adPills.findIndex(item => item._state == e.detail.state);
473
+
474
+ if (index > 0) {
475
+ this._state.adPills.splice(index, 1);
476
+
477
+ } else if (index === 0) {
478
+ this._state.adPills = [];
479
+ }
480
+ this.dispatchEvent(myEvent);
481
+ });
482
+ this.querySelectorAll('.pill-title')[pillDiv.children.length - 1].addEventListener('click', (e) => {
483
+ this.menuTriggerOnClick(e.target.closest("cui-formpill-pill"));
484
+ });
349
485
  }
486
+
350
487
  }
351
488
 
352
489
  dTriggerElem.title = this._state.sLabel;
@@ -383,10 +520,8 @@ class CUI_FORMPILL extends HTMLElement {
383
520
  dTriggerElem.prepend(addIconDiv);
384
521
  }
385
522
 
386
- this._state.dTriggerElem = dTriggerElem;
387
- this.appendChild(label)
388
- this.appendChild(pillDiv)
389
- this.appendChild(this._state.dTriggerElem);
523
+ this.dTriggerElem = dTriggerElem;
524
+ this.appendChild(this.dTriggerElem);
390
525
 
391
526
  window.addEventListener('resize', (e) => {
392
527
  this.windowResize(e);
@@ -455,11 +590,11 @@ class CUI_FORMPILL extends HTMLElement {
455
590
 
456
591
  dPopoverHeader.appendChild(dPopoverTitle);
457
592
 
458
- let closeButton = document.createElement('button');
593
+ let closeButton = document.createElement('button');
459
594
  closeButton.classList.add('close-button');
460
595
  closeButton.textContent = '×'
461
596
  dPopoverHeader.appendChild(closeButton);
462
- closeButton.addEventListener('click', () => {this.hidePopover()})
597
+ closeButton.addEventListener('click', () => { this.hidePopover() })
463
598
 
464
599
  let dPopoverFooter = document.createElement('div');
465
600
  dPopoverFooter.classList.add("popover-footer");
@@ -525,7 +660,7 @@ class CUI_FORMPILL extends HTMLElement {
525
660
 
526
661
  async displayPopover() {
527
662
 
528
- let adPopoverElements = await this.createPopover(this._state.dTriggerElem);
663
+ let adPopoverElements = await this.createPopover(this.dTriggerElem);
529
664
  let dPopoverBody = adPopoverElements[0];
530
665
  let dPopoverContent = adPopoverElements[1];
531
666
  let dMenuPopover = adPopoverElements[2];
@@ -541,7 +676,7 @@ class CUI_FORMPILL extends HTMLElement {
541
676
  if (this._state.configData) {
542
677
  if (this._state.configData.filterCriteria) {
543
678
  this.criteria = document.createElement('cui-listbox');
544
- this.criteria.setAttribute('search', '')
679
+ this.criteria.setAttribute('search', '');
545
680
  let items = []
546
681
 
547
682
  if (this._state.criteriaList === null) {
@@ -558,7 +693,7 @@ class CUI_FORMPILL extends HTMLElement {
558
693
  items.push(item);
559
694
  }
560
695
  }
561
-
696
+
562
697
  this.criteria.setState({ 'items': items, 'label': `${(this._state.configData.filterCriteria.fieldLabel) ? this._state.configData.filterCriteria.fieldLabel : 'Criteria'}` })
563
698
  this.criteria.setAttribute('required', '');
564
699
  this.criteria.setAttribute('componentKey', 'contextHeaderCriteria');
@@ -586,7 +721,7 @@ class CUI_FORMPILL extends HTMLElement {
586
721
  this.hidePopover();
587
722
  })
588
723
  }
589
- document.body.addEventListener('click', this._state.fGlobalBodyClick, false);
724
+ document.body.addEventListener('click', this.fGlobalBodyClick, false);
590
725
  });
591
726
 
592
727
 
@@ -644,7 +779,7 @@ class CUI_FORMPILL extends HTMLElement {
644
779
  this.hidePopover();
645
780
  })
646
781
  }
647
- document.body.addEventListener('click', this._state.fGlobalBodyClick, false);
782
+ document.body.addEventListener('click', this.fGlobalBodyClick, false);
648
783
  });
649
784
 
650
785
 
@@ -661,6 +796,7 @@ class CUI_FORMPILL extends HTMLElement {
661
796
  if (controls.options && controls.value) {
662
797
 
663
798
  this.method = document.createElement('cui-listbox');
799
+ if (controls.search) this.method.setAttribute('search', '');
664
800
  this.method.setState({ 'items': controls.options, 'label': `${(controls.fieldLabel) ? controls.fieldLabel : 'Method'}` });
665
801
  this.method.setAttribute('value', pill._state.sValue2)
666
802
  this.method.setAttribute('required', '');
@@ -743,6 +879,7 @@ class CUI_FORMPILL extends HTMLElement {
743
879
  if (controls.options && controls.value) {
744
880
 
745
881
  this.method = document.createElement('cui-listbox');
882
+ if (controls.search) this.method.setAttribute("search", "");
746
883
  this.method.setState({ 'items': controls.options, 'label': `${(controls.fieldLabel) ? controls.fieldLabel : 'Method'}` });
747
884
  this.method.setAttribute('required', '');
748
885
  this.method.setAttribute('componentKey', 'contextHeaderMethod');
@@ -764,6 +901,9 @@ class CUI_FORMPILL extends HTMLElement {
764
901
  if (controls.value.multiple) {
765
902
  this.dValueField.setAttribute('multiple', true)
766
903
  }
904
+ if (controls.value.search) {
905
+ this.dValueField.setAttribute('search', true)
906
+ }
767
907
  dPopoverBody.insertBefore(this.dValueField, dPopoverFooter);
768
908
  } else if (controls.value && controls.value.control) {
769
909
 
@@ -812,7 +952,6 @@ class CUI_FORMPILL extends HTMLElement {
812
952
  formPill.setAttribute('value2', this.method.value)
813
953
  formPill.setAttribute('value3', this.dValueField.value)
814
954
  let pillText = `${this.criteria._state.aItems.find(item => item.value === this.criteria.value)?.label}: ${this.dValueField.value}`
815
-
816
955
  if (sFor === 'update') {
817
956
  formPill.setState({
818
957
  'value1': this.criteria.value, 'value2': this.method.value, 'value3': this.dValueField.value,
@@ -836,10 +975,19 @@ class CUI_FORMPILL extends HTMLElement {
836
975
  if (!this._state.criteriaList.some(item => item.value === removedValue)) {
837
976
  this._state.criteriaList.unshift(this._state.configData.filterCriteria.items.find(item => item.value === removedValue));
838
977
  }
839
-
840
978
  const myEvent = new CustomEvent("pill-removed", {
841
979
  detail: { pill: e.detail }
842
980
  });
981
+
982
+ let index = this._state.adPills.findIndex(item => item._state == e.detail.state);
983
+
984
+ //if(index > 0){
985
+ this._state.adPills.splice(index, 1);
986
+
987
+ //}else if(index === 0){
988
+ //this._state.adPills = [];
989
+ //}
990
+
843
991
  this.dispatchEvent(myEvent);
844
992
  });
845
993
  }
@@ -855,8 +1003,6 @@ class CUI_FORMPILL extends HTMLElement {
855
1003
 
856
1004
  let curValue = this.criteria.value;
857
1005
  formPill.setAttribute('value1', curValue)
858
-
859
-
860
1006
  let pillText;
861
1007
  if (this.dValueField.value.indexOf(',') == -1) {
862
1008
  formPill.setAttribute('value2', this.dValueField.value)
@@ -908,6 +1054,15 @@ class CUI_FORMPILL extends HTMLElement {
908
1054
  const myEvent = new CustomEvent("pill-removed", {
909
1055
  detail: { pill: e.detail }
910
1056
  });
1057
+
1058
+ let index = this._state.adPills.findIndex(item => item._state == e.detail.state);
1059
+
1060
+ //if(index > 0){
1061
+ this._state.adPills.splice(index, 1);
1062
+
1063
+ //}else if(index === 0){
1064
+ // this._state.adPills = [];
1065
+ //}
911
1066
  this.dispatchEvent(myEvent);
912
1067
  });
913
1068
 
@@ -961,6 +1116,15 @@ class CUI_FORMPILL extends HTMLElement {
961
1116
  const myEvent = new CustomEvent("pill-removed", {
962
1117
  detail: { pill: e.detail }
963
1118
  });
1119
+ let index = this._state.adPills.findIndex(item => item._state == e.detail.state);
1120
+
1121
+ //if(index > 0){
1122
+ this._state.adPills.splice(index, 1);
1123
+
1124
+ //}else if(index === 0){
1125
+ //this._state.adPills = [];
1126
+ //}
1127
+
964
1128
  this.dispatchEvent(myEvent);
965
1129
  });
966
1130
  }
@@ -993,6 +1157,57 @@ class CUI_FORMPILL extends HTMLElement {
993
1157
 
994
1158
  }
995
1159
 
1160
+ addPillfromJSON() {
1161
+ if (this._state?.configData?.filterCriteria?.loadedPills) {
1162
+ for (let pill of this._state.configData.filterCriteria?.loadedPills) {
1163
+ let formPill;
1164
+ formPill = document.createElement('cui-formpill-pill');
1165
+ this._state.adPills.push(formPill);
1166
+
1167
+ for (const [k, v] of Object.entries(pill)) {
1168
+ formPill.setAttribute(k, v);
1169
+ }
1170
+
1171
+ let pillText;
1172
+
1173
+ if (pill.value2 != null && pill.value3 != null) {
1174
+ pillText = `${this._state.configData.filterCriteria.items.find(item => item.value === pill.value1)?.label}: ${pill.value3}`
1175
+ } else if (pill.values != null) {
1176
+ pillText = `${this._state.configData.filterCriteria.items.find(item => item.value === pill.value1)?.label}: ${pill.values}`
1177
+ } else if (pill.value2 != null) {
1178
+ pillText = `${this._state.configData.filterCriteria.items.find(item => item.value === pill.value1)?.label}: ${pill.value2}`
1179
+
1180
+ }
1181
+
1182
+ formPill.setAttribute('text', pillText.slice(0, 30) + (pillText.length > 30 ? "..." : ""))
1183
+ let items = [];
1184
+ if (this._state.criteriaList === null) {
1185
+ for (let item of this._state.configData.filterCriteria.items) {
1186
+ let lbValue = { 'label': item.label, 'value': item.value };
1187
+ if (item.multiple) {
1188
+ lbValue.multiple = item.multiple
1189
+ }
1190
+ items.push(lbValue);
1191
+ }
1192
+ this._state.criteriaList = items;
1193
+ } else {
1194
+ for (let item of this._state.criteriaList) {
1195
+ items.push(item);
1196
+ }
1197
+ }
1198
+ let updatedList = this._state.criteriaList.filter(item => {
1199
+ if (item.multiple) {
1200
+ return true;
1201
+ }
1202
+ return item.value !== pill.value1;
1203
+ });
1204
+
1205
+ this._state.criteriaList = updatedList;
1206
+
1207
+ }
1208
+ }
1209
+ }
1210
+
996
1211
  validateRegion(dRegion) {
997
1212
  let validationResult = this.cValidator.validateRegion(dRegion);
998
1213
 
@@ -1048,7 +1263,7 @@ class CUI_FORMPILL extends HTMLElement {
1048
1263
  this._state.dMenuPopover = null;
1049
1264
  }
1050
1265
 
1051
- document.body.removeEventListener('click', this._state.fGlobalBodyClick);
1266
+ document.body.removeEventListener('click', this.fGlobalBodyClick);
1052
1267
 
1053
1268
  this._state.bMenuDisplayed = false;
1054
1269
  }
@@ -1056,7 +1271,7 @@ class CUI_FORMPILL extends HTMLElement {
1056
1271
  disconnectedCallback() {
1057
1272
  this.hidePopover();
1058
1273
  // closeBtn.removeEventListener('click', (e));
1059
- document.body.removeEventListener('click', this._state.fGlobalBodyClick);
1274
+ document.body.removeEventListener('click', this.fGlobalBodyClick);
1060
1275
  }
1061
1276
 
1062
1277
  // Utility function function to clear all elements from shadow root.