reneco-hierarchized-picker 0.4.3-beta.9 → 0.5.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.
Files changed (34) hide show
  1. package/dist/cjs/loader.cjs.js +1 -1
  2. package/dist/cjs/reneco-hierarchized-picker.cjs.js +1 -1
  3. package/dist/cjs/reneco-hierarchized-picker_2.cjs.entry.js +509 -271
  4. package/dist/collection/components/hierarchized-picker/hierarchized-picker.css +10 -2
  5. package/dist/collection/components/hierarchized-picker/hierarchized-picker.js +391 -130
  6. package/dist/collection/components/search-input/search-input.js +1 -3
  7. package/dist/collection/components/treejs/index.js +49 -50
  8. package/dist/collection/core/options-manager.js +2 -0
  9. package/dist/collection/features/events/focus-handlers.js +15 -11
  10. package/dist/collection/features/keyboard-navigation/keyboard-navigation.js +83 -57
  11. package/dist/collection/features/tree/tree-utils.js +12 -3
  12. package/dist/collection/utils/conf-helper.js +4 -0
  13. package/dist/collection/utils/constants.js +4 -3
  14. package/dist/collection/utils/theme-utils.js +1 -0
  15. package/dist/custom-elements/index.js +509 -271
  16. package/dist/esm/loader.js +1 -1
  17. package/dist/esm/reneco-hierarchized-picker.js +1 -1
  18. package/dist/esm/reneco-hierarchized-picker_2.entry.js +509 -271
  19. package/dist/esm-es5/loader.js +1 -1
  20. package/dist/esm-es5/reneco-hierarchized-picker.js +1 -1
  21. package/dist/esm-es5/reneco-hierarchized-picker_2.entry.js +2 -2
  22. package/dist/reneco-hierarchized-picker/p-0e305bec.entry.js +1 -0
  23. package/dist/reneco-hierarchized-picker/p-73168a50.system.js +1 -1
  24. package/dist/reneco-hierarchized-picker/p-9027f23a.system.entry.js +3 -0
  25. package/dist/reneco-hierarchized-picker/reneco-hierarchized-picker.esm.js +1 -1
  26. package/dist/types/components/hierarchized-picker/hierarchized-picker.d.ts +13 -2
  27. package/dist/types/components.d.ts +6 -0
  28. package/dist/types/core/options-manager.d.ts +1 -1
  29. package/dist/types/features/keyboard-navigation/keyboard-navigation.d.ts +2 -1
  30. package/dist/types/features/tree/tree-utils.d.ts +1 -1
  31. package/dist/types/utils/utils.d.ts +1 -0
  32. package/package.json +1 -1
  33. package/dist/reneco-hierarchized-picker/p-934e9cf8.entry.js +0 -1
  34. package/dist/reneco-hierarchized-picker/p-9ddab37d.system.entry.js +0 -3
@@ -9,7 +9,7 @@ import { RawDataManager } from '../../core/raw-data-manager';
9
9
  import { OptionsManager } from '../../core/options-manager';
10
10
  import { fillTreeWithObject, completeCurrentTreeWithTree, getPropertyFromNode } from '../../features/tree/tree-utils';
11
11
  import { displayAutocompleteWithResults, clearAutocomplete } from '../../features/autocomplete/autocomplete';
12
- import { focusSearchInput, focusMainInput, focusInSearchEvent, focusOutSearchEvent, clickPickerModalArea, isInsidePicker } from '../../features/events/focus-handlers';
12
+ import { focusSearchInput, focusMainInput, focusInSearchEvent, focusOutSearchEvent, clickPickerModalArea } from '../../features/events/focus-handlers';
13
13
  import { setupKeyboardNavigation } from '../../features/keyboard-navigation/keyboard-navigation';
14
14
  export class HierarchizedPickerComponent {
15
15
  /**
@@ -78,14 +78,66 @@ export class HierarchizedPickerComponent {
78
78
  logError(messageToLog) {
79
79
  try {
80
80
  console.error('--- Hierarchized picker ' + this.componentID + ' ERROR ---', messageToLog);
81
+ this.lastErrorMessage = messageToLog;
81
82
  }
82
83
  catch (_a) {
83
- console.error('--- Hierarchized picker generic ERROR ---');
84
+ const genericErrorMessage = '--- Hierarchized picker generic ERROR ---';
85
+ this.lastErrorMessage = genericErrorMessage;
86
+ console.error(genericErrorMessage);
84
87
  }
88
+ this.errorRaised.emit(this.lastErrorMessage);
85
89
  }
86
90
  get theOptions() {
87
91
  return this.optionsManager.getOptions();
88
92
  }
93
+ diffKeys(obj1, obj2, prefix = '') {
94
+ const diffs = [];
95
+ const commonKeys = Object.keys(obj1 || {}).filter(key => obj2 && Object.prototype.hasOwnProperty.call(obj2, key));
96
+ for (const key of commonKeys) {
97
+ const fullKey = prefix ? `${prefix}.${key}` : key;
98
+ const val1 = obj1[key];
99
+ const val2 = obj2[key];
100
+ if (Array.isArray(val1) && Array.isArray(val2)) {
101
+ // Compare array length
102
+ if (val1.length !== val2.length) {
103
+ diffs.push(fullKey);
104
+ continue;
105
+ }
106
+ // Compare each element deeply
107
+ for (let i = 0; i < val1.length; i++) {
108
+ const v1 = val1[i];
109
+ const v2 = val2[i];
110
+ if (typeof v1 === 'object' &&
111
+ v1 !== null &&
112
+ typeof v2 === 'object' &&
113
+ v2 !== null) {
114
+ const subDiffs = this.diffKeys(v1, v2, `${fullKey}[${i}]`);
115
+ if (subDiffs.length > 0) {
116
+ diffs.push(fullKey);
117
+ break; // stop at first mismatch in array
118
+ }
119
+ }
120
+ else if (v1 !== v2) {
121
+ diffs.push(fullKey);
122
+ break;
123
+ }
124
+ }
125
+ }
126
+ else if (val1 &&
127
+ val2 &&
128
+ typeof val1 === 'object' &&
129
+ typeof val2 === 'object') {
130
+ // Recursive deep object comparison
131
+ const subDiffs = this.diffKeys(val1, val2, fullKey);
132
+ if (subDiffs.length > 0)
133
+ diffs.push(...subDiffs);
134
+ }
135
+ else if (val1 !== val2) {
136
+ diffs.push(fullKey);
137
+ }
138
+ }
139
+ return diffs;
140
+ }
89
141
  async setNewOption(newValue, oldValue = null) {
90
142
  this.ready = false;
91
143
  // --------------------------------------- DEPRECATED ?
@@ -104,6 +156,7 @@ export class HierarchizedPickerComponent {
104
156
  // });
105
157
  // ---------------------------------------
106
158
  // this.theOptions = newValue;
159
+ const savedOldValue = Object.assign({}, this.theOptions);
107
160
  if (oldValue && JSON.stringify(newValue.options) == JSON.stringify(oldValue.options)) {
108
161
  this.ready = true;
109
162
  return;
@@ -112,6 +165,7 @@ export class HierarchizedPickerComponent {
112
165
  newValue = JSON.parse(newValue);
113
166
  if (typeof oldValue == 'string')
114
167
  oldValue = JSON.parse(oldValue);
168
+ this.value = [];
115
169
  this.optionsManager.updateOptions(newValue);
116
170
  this.setDisplayedValue(this.value);
117
171
  const originOrNodeIdAreDifferent = !oldValue || (newValue.origin != oldValue.origin || newValue.options.StartNodeID != oldValue.options.StartNodeID);
@@ -129,11 +183,28 @@ export class HierarchizedPickerComponent {
129
183
  if (oldValue && JSON.stringify(newValue.options) != JSON.stringify(oldValue.options)) {
130
184
  this.value = [];
131
185
  }
132
- if ((newValue === null || newValue === void 0 ? void 0 : newValue.loading) == 'display') {
186
+ if ((newValue === null || newValue === void 0 ? void 0 : newValue.loading) == 'display' || (newValue && !newValue.loading)) {
133
187
  if ((oldValue && this.isChangeInOptions(newValue, oldValue)) || !oldValue) {
134
- this.rawDataManager = new RawDataManager(this.getOptionsAsIConf(this.optionsManager.getOptions()).token, this.optionsManager);
135
- await this.loadHierarchizedPicker(true);
136
- this.displayWhenLoaded();
188
+ if (!oldValue) {
189
+ oldValue = savedOldValue;
190
+ }
191
+ const propDiffs = this.diffKeys(oldValue, this.optionsManager.initializeOptions(newValue));
192
+ const noReloadProps = ["multiple"];
193
+ const ignoredProps = ["token"];
194
+ const filteredDiffs = propDiffs.filter(prop => !ignoredProps.includes(prop));
195
+ if (filteredDiffs.length == 1 && filteredDiffs.some(item => noReloadProps.includes(item))) {
196
+ const propChanged = filteredDiffs[0];
197
+ switch (propChanged) {
198
+ case "multiple":
199
+ document.querySelectorAll('#tree-area-' + this.componentID + ' .treejs-checkbox').forEach((item) => (item.style.display = (this.theOptions.multiple ? 'inline-block' : 'none')));
200
+ break;
201
+ }
202
+ }
203
+ else {
204
+ this.rawDataManager = new RawDataManager(this.getOptionsAsIConf(this.optionsManager.getOptions()).token, this.optionsManager);
205
+ await this.loadHierarchizedPicker(true);
206
+ this.displayWhenLoaded();
207
+ }
137
208
  }
138
209
  else {
139
210
  this.ready = true;
@@ -187,6 +258,9 @@ export class HierarchizedPickerComponent {
187
258
  async filterTree(searchedValue) {
188
259
  this.search(searchedValue);
189
260
  }
261
+ async getError() {
262
+ return Promise.resolve(this.lastErrorMessage);
263
+ }
190
264
  constructor() {
191
265
  this.modaleHeight = 200;
192
266
  this.modalePosition = 'bottom';
@@ -197,30 +271,101 @@ export class HierarchizedPickerComponent {
197
271
  this.lastSearchMatchCounter = 0; // Counter of number of matches for last search
198
272
  this.setValueOnClick = true; // Tells wether we edit the picker value on click in the tree
199
273
  this.mylog = console.log; // Custom log function for debug purposes
274
+ this.lastErrorMessage = '';
275
+ this.scrollToNode = (targetNodeId = null, displayChildren = false) => {
276
+ var _a;
277
+ let scrollToValue = 0;
278
+ let removeClosedAndLookUp = (element, editScroll = false) => {
279
+ var _a, _b, _c, _d;
280
+ const nodeId = element === null || element === void 0 ? void 0 : element.nodeId;
281
+ if (!element || !nodeId) {
282
+ return;
283
+ }
284
+ const node = this.loadedTreeJs.nodesById[nodeId];
285
+ if ((_b = (_a = node === null || node === void 0 ? void 0 : node.children) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.id) {
286
+ (_c = element.classList) === null || _c === void 0 ? void 0 : _c.remove('treejs-node__close');
287
+ }
288
+ if (editScroll) {
289
+ scrollToValue += element.offsetTop;
290
+ }
291
+ const parent = (_d = element.parentNode) === null || _d === void 0 ? void 0 : _d.closest('.treejs-node');
292
+ if (parent) {
293
+ removeClosedAndLookUp(parent, editScroll);
294
+ }
295
+ };
296
+ try {
297
+ if (targetNodeId) {
298
+ const targetNode = this.loadedTreeJs.liElementsById[targetNodeId];
299
+ if (targetNode) {
300
+ removeClosedAndLookUp(targetNode, true);
301
+ if (displayChildren && targetNode.classList.contains('treejs-node__close')) {
302
+ const leftSwitcher = targetNode.querySelector('.treejs-switcher');
303
+ if (leftSwitcher) {
304
+ (_a = this.loadedTreeJs) === null || _a === void 0 ? void 0 : _a.onSwitcherClick(leftSwitcher);
305
+ }
306
+ }
307
+ }
308
+ }
309
+ else {
310
+ const checkeds = document.querySelectorAll('#tree-area-' + this.componentID + ' .treejs-node__checked');
311
+ checkeds.forEach((item) => removeClosedAndLookUp(item, scrollToValue == 0));
312
+ }
313
+ }
314
+ catch (err) {
315
+ this.errorToLog = "Error in showSelectedNodes";
316
+ }
317
+ if (scrollToValue && this.scrollable) {
318
+ this.scrollable.scrollTop = scrollToValue;
319
+ }
320
+ };
200
321
  this.getShortenedFullpath = (realFullpath) => {
201
322
  var _a, _b, _c, _d;
323
+ if (!realFullpath)
324
+ return realFullpath;
325
+ //TODO if one day we want shortenedfulpaths from data loading :
326
+ // const rdmdata = (this.optionsManager.getOptions().source == "webservice" ? this.rawDataManager.getData() : this.rawDataManager.getData().data ?? null);
327
+ //TODO but for now we're doing :
328
+ if (this.optionsManager.getOptions().source !== "webservice")
329
+ return realFullpath;
202
330
  let toret = realFullpath;
203
- try {
204
- const property_nodeid = (this.optionsManager.getOptions().origin == 'classification' ? "startNode" : "StartNodeID");
205
- const property_value = this.optionsManager.getOptions().options[property_nodeid];
206
- if (property_value in ["0", 0])
207
- return toret;
208
- if (isNumeric(property_value)) {
209
- if (this.optionsManager.getOptions().origin == 'classification') {
210
- const { Translations, Properties } = this.rawDataManager.getData();
211
- const currentLanguage = this.optionsManager.getOptions().language;
212
- toret = ((_b = (_a = Translations[currentLanguage]) === null || _a === void 0 ? void 0 : _a.translated_name) !== null && _b !== void 0 ? _b : Properties === null || Properties === void 0 ? void 0 : Properties.System_Name) + realFullpath.replace(((_d = (_c = Translations[currentLanguage]) === null || _c === void 0 ? void 0 : _c.translated_fullpath) !== null && _d !== void 0 ? _d : Properties === null || Properties === void 0 ? void 0 : Properties.System_Fullpath), "");
331
+ const rdmdata = this.rawDataManager.getData();
332
+ if (rdmdata) {
333
+ try {
334
+ const propertyName_nodeid = (this.optionsManager.getOptions().origin == 'classification' ? "startNode" : "StartNodeID");
335
+ let propertyValue_nodeid = 0;
336
+ switch (this.optionsManager.getOptions().source) {
337
+ case "file":
338
+ //TODO maybe someday ... someday far !
339
+ return realFullpath;
340
+ case "data":
341
+ //TODO maybe someday ... someday far !
342
+ if (this.optionsManager.getOptions().origin == 'classification')
343
+ return realFullpath;
344
+ propertyValue_nodeid = this.theOptions.data.key;
345
+ break;
346
+ case "webservice":
347
+ propertyValue_nodeid = this.optionsManager.getOptions().options[propertyName_nodeid];
348
+ break;
213
349
  }
214
- else {
215
- const { fullpath, fullpathTranslated, title, valueTranslated } = this.rawDataManager.getData();
216
- toret = (valueTranslated !== null && valueTranslated !== void 0 ? valueTranslated : title) + realFullpath.replace((fullpathTranslated !== null && fullpathTranslated !== void 0 ? fullpathTranslated : fullpath), "");
350
+ if (["0", 0].includes(propertyValue_nodeid))
351
+ return toret;
352
+ if (isNumeric(propertyValue_nodeid)) {
353
+ if (this.optionsManager.getOptions().origin == 'classification') {
354
+ const { Translations, Properties } = rdmdata;
355
+ const currentLanguage = this.optionsManager.getOptions().language;
356
+ toret = ((_b = (_a = Translations[currentLanguage]) === null || _a === void 0 ? void 0 : _a.translated_name) !== null && _b !== void 0 ? _b : Properties === null || Properties === void 0 ? void 0 : Properties.System_Name) + realFullpath.replace(((_d = (_c = Translations[currentLanguage]) === null || _c === void 0 ? void 0 : _c.translated_fullpath) !== null && _d !== void 0 ? _d : Properties === null || Properties === void 0 ? void 0 : Properties.System_Fullpath), "");
357
+ }
358
+ else {
359
+ const { fullpath, fullpathTranslated, title, valueTranslated } = rdmdata;
360
+ toret = (valueTranslated !== null && valueTranslated !== void 0 ? valueTranslated : title) + realFullpath.replace((fullpathTranslated !== null && fullpathTranslated !== void 0 ? fullpathTranslated : fullpath), "");
361
+ }
217
362
  }
363
+ else
364
+ this.errorToLog = "Error in getShortenedFullpath : startnode is not number";
365
+ }
366
+ catch (error) {
367
+ this.errorToLog = "Error in getShortenedFullpath " + error.toString();
218
368
  }
219
- else
220
- this.errorToLog = "Error in getFullpath : startnode is not number";
221
- }
222
- catch (error) {
223
- this.errorToLog = "Error in getFullpath " + error.toString();
224
369
  }
225
370
  return toret;
226
371
  };
@@ -272,7 +417,6 @@ export class HierarchizedPickerComponent {
272
417
  }
273
418
  componentDidLoad() {
274
419
  this.mylog('----- componentDidLoad beginning -----');
275
- setupKeyboardNavigation(this, this.navigateInTree);
276
420
  focusMainInput(this);
277
421
  }
278
422
  displayWhenLoaded() {
@@ -316,6 +460,8 @@ export class HierarchizedPickerComponent {
316
460
  this.optionsManager.getOptions().openTreeWhenLoaded = false;
317
461
  if (!this.optionsManager.getOptions().displayRootNode)
318
462
  this.optionsManager.getOptions().displayRootNode = false;
463
+ if (!this.optionsManager.getOptions().keyboardNavigation)
464
+ this.optionsManager.getOptions().keyboardNavigation = false;
319
465
  if (!this.optionsManager.getOptions().dragAndDropEnabled)
320
466
  this.optionsManager.getOptions().dragAndDropEnabled = false;
321
467
  if (!this.optionsManager.getOptions().defaultValueIsFullpath)
@@ -333,21 +479,50 @@ export class HierarchizedPickerComponent {
333
479
  }
334
480
  await Promise.all(this.optionsManager.getOptions().defaultValue.map(async (element) => {
335
481
  if (this.optionsManager.getOptions().defaultValueIsFullpath || (!(typeof element == 'number') && !strIsNumeric(element))) {
336
- if (this.optionsManager.getOptions().source !== 'webservice') {
337
- let errormsg = 'The loading of nodes based on fullpath is only available on webservice mode for now!';
482
+ if (!defaultFromFullpaths) {
483
+ defaultFromFullpaths = [];
484
+ }
485
+ let errormsg = '';
486
+ switch (this.optionsManager.getOptions().source) {
487
+ case 'file':
488
+ errormsg = 'The loading of nodes based on fullpath is not available on file mode for now!';
489
+ break;
490
+ case 'data':
491
+ if (this.theOptions.origin == 'classification') {
492
+ errormsg = 'The loading of nodes based on fullpath is not available on file mode for the classification context for now!';
493
+ break;
494
+ }
495
+ const searchIdInData = function (treeData) {
496
+ if (treeData.data.fullpath === element || treeData.data.fullpathTranslated === element) {
497
+ return treeData.key;
498
+ }
499
+ if (treeData.children && treeData.children.length > 0) {
500
+ for (const childTree of treeData.children) {
501
+ const foundId = searchIdInData(childTree);
502
+ if (foundId) {
503
+ return foundId;
504
+ }
505
+ }
506
+ }
507
+ return null;
508
+ };
509
+ if (element) {
510
+ const foundId = searchIdInData(this.theOptions.data);
511
+ if (foundId)
512
+ defaultFromFullpaths.push(foundId);
513
+ }
514
+ break;
515
+ case 'webservice':
516
+ const valtopush = await this.rawDataManager.fetchNodeIdFromFullpath(element, this.optionsManager.getOptions()).catch(err => { this.displayPickerError(err); });
517
+ if (valtopush) {
518
+ defaultFromFullpaths.push(valtopush);
519
+ }
520
+ break;
521
+ }
522
+ if (errormsg.length > 0) {
338
523
  this.displayPickerError(errormsg);
339
524
  this.errorToLog = errormsg;
340
525
  autoAssignReach = false;
341
- return;
342
- }
343
- else {
344
- if (!defaultFromFullpaths) {
345
- defaultFromFullpaths = [];
346
- }
347
- const valtopush = await this.rawDataManager.fetchNodeIdFromFullpath(element, this.optionsManager.getOptions()).catch(err => { this.displayPickerError(err); });
348
- if (valtopush) {
349
- defaultFromFullpaths.push(valtopush);
350
- }
351
526
  }
352
527
  }
353
528
  }));
@@ -355,7 +530,7 @@ export class HierarchizedPickerComponent {
355
530
  this.optionsManager.getOptions().defaultValue = defaultFromFullpaths;
356
531
  }
357
532
  if (this.optionsManager.getOptions().options) {
358
- if (!this.optionsManager.getOptions().options.Reach && this.optionsManager.getOptions().defaultValue.length > 0) {
533
+ if (this.optionsManager.getOptions().defaultValue.length > 0) {
359
534
  if (autoAssignReach) {
360
535
  this.optionsManager.getOptions().options.Reach = this.optionsManager.getOptions().defaultValue.map(element => {
361
536
  return Number(element);
@@ -385,10 +560,16 @@ export class HierarchizedPickerComponent {
385
560
  this.mylog('----- HIERARCHIZED-PICKER DEBUG MODE ON -----');
386
561
  }
387
562
  // Setup component unique ID
388
- if (this.optionsManager.getOptions().id)
563
+ if (this.optionsManager.getOptions().id) {
389
564
  this.componentID = this.optionsManager.getOptions().id;
390
- else if (!this.componentID)
391
- this.componentID = (Array.from(document.querySelectorAll('reneco-hierarchized-picker')).indexOf(this.el) + 1).toString();
565
+ }
566
+ else if (!this.componentID) {
567
+ let componentID = (Array.from(document.querySelectorAll('reneco-hierarchized-picker')).indexOf(this.el) + 1);
568
+ while (document.querySelectorAll(`#hierarchized-picker-${componentID}`).length > 0) {
569
+ componentID++;
570
+ }
571
+ this.componentID = componentID.toString();
572
+ }
392
573
  if (!this.optionsManager.getOptions())
393
574
  return;
394
575
  this.optionsManager.updateDefaultValue();
@@ -456,7 +637,7 @@ export class HierarchizedPickerComponent {
456
637
  this.ignoreOptionsChanges = false;
457
638
  }
458
639
  catch (_b) {
459
- console.error('Error loading webservice data!');
640
+ this.errorToLog = 'Error loading webservice data!';
460
641
  }
461
642
  }
462
643
  displayPickerError(errorMsg = '') {
@@ -468,11 +649,11 @@ export class HierarchizedPickerComponent {
468
649
  }
469
650
  this.displayedValue = errorMsg;
470
651
  this.isDisabled = true;
471
- errorMsg = this.errorToLog;
652
+ this.errorToLog = errorMsg;
472
653
  }
473
654
  }
474
655
  catch (_a) {
475
- console.error(errorMsg);
656
+ this.errorToLog = errorMsg;
476
657
  }
477
658
  }
478
659
  getApiSearchURL() {
@@ -492,17 +673,17 @@ export class HierarchizedPickerComponent {
492
673
  }
493
674
  }
494
675
  // TODO > Celine would rather like the context (thesaurus or position) to be extracted another way
495
- getContextualApiURL(init = false) {
496
- const { options, url } = this.optionsManager.getOptions();
676
+ getContextualApiURL(init = false, forcedOptions = null) {
677
+ const { options, url } = forcedOptions || this.optionsManager.getOptions();
497
678
  if (init && options.Reach) {
498
- // Use a base URL for relative paths
499
- const base = window.location.origin; // fallback for relative URLs
679
+ const base = window.location.origin;
500
680
  const parsedUrl = new URL(url, base);
501
- const pathSegments = parsedUrl.pathname.split('/');
502
- let dynamicType = pathSegments[pathSegments.length - 2];
503
- if (['thesaurus', 'position'].indexOf(dynamicType) == -1)
504
- dynamicType = pathSegments[pathSegments.length - 1];
505
- const newPathname = `/api/v1/classification/reach/${dynamicType}`;
681
+ const pathSegments = parsedUrl.pathname.split('/').filter(Boolean);
682
+ const idx = pathSegments.indexOf("getTree");
683
+ if (idx !== -1) {
684
+ pathSegments[idx] = "reach";
685
+ }
686
+ const newPathname = "/" + pathSegments.join("/");
506
687
  return `${parsedUrl.origin}${newPathname}`;
507
688
  }
508
689
  return url;
@@ -573,7 +754,7 @@ export class HierarchizedPickerComponent {
573
754
  }
574
755
  })
575
756
  .catch(err => {
576
- console.error('err', err);
757
+ this.errorToLog = err;
577
758
  });
578
759
  }
579
760
  else {
@@ -592,29 +773,26 @@ export class HierarchizedPickerComponent {
592
773
  }
593
774
  })
594
775
  .catch(error => {
595
- console.error("---- MY ERROR ---- ", error);
776
+ this.errorToLog = error;
596
777
  try {
597
778
  this.errorToLog = 'getDataFromSource 1 rejected:' + JSON.stringify(error, replacer, 2);
598
779
  }
599
780
  catch (_a) {
600
- console.error('getDataFromSource 2 rejected:', JSON.stringify(error, replacer, 2));
781
+ this.errorToLog = JSON.stringify(error, replacer, 2);
601
782
  }
602
783
  });
603
784
  }
604
785
  }
605
786
  else {
606
- if (this.searchToDisplay > -1 && searchID == this.searchToDisplay) {
607
- this.rawDataManager.getData().children.forEach((value, _) => {
608
- completeCurrentTreeWithTree(this.loadedTreeJs, value, this.optionsManager.getOptions());
609
- });
610
- displayAutocompleteWithResults(this.rawDataManager.getData(), searched, this.optionsManager, this.editValue.bind(this), this.showTree.bind(this));
787
+ if (this.optionsManager.getOptions().source == 'data') {
788
+ displayResults(this.rawDataManager.getData());
789
+ if (!searched) {
790
+ this.setSearchResults([]);
791
+ }
611
792
  }
612
- const data = !this.optionsManager.getOptions().displayRootNode ? this.rawDataManager.getData().children : [this.rawDataManager.getData()];
613
- const treeToDisplay = fillTreeWithObject([], data, searched, this.optionsManager.getOptions());
614
- if (searched) {
615
- this.setSearchResults(treeToDisplay);
793
+ else {
794
+ console.error("Unhandled picker settings for search scenario !!");
616
795
  }
617
- this.displayTree(treeToDisplay);
618
796
  }
619
797
  }
620
798
  async triggerTreeDisplay(dataToLoad, searched) {
@@ -696,11 +874,31 @@ export class HierarchizedPickerComponent {
696
874
  this.showSelectedNodes();
697
875
  this.deactivateNodesOutOfDepthSettings();
698
876
  // Hides checkboxes in non multiple context
699
- if (!this.optionsManager.getOptions().multiple) {
700
- document.querySelectorAll('#tree-area-' + this.componentID + ' .treejs-checkbox').forEach((item) => (item.style.display = 'none'));
701
- }
877
+ document.querySelectorAll('#tree-area-' + this.componentID + ' .treejs-checkbox').forEach((item) => (item.style.display = (this.theOptions.multiple ? 'inline-block' : 'none')));
702
878
  }
703
879
  onItemContextMenuItemClick(e) {
880
+ if (e.target && e.target.id) {
881
+ function getDirectParentAndDepth(nodesById, targetId) {
882
+ // Find the direct parent
883
+ const parent = Object.values(nodesById).find(node => { var _a; return (_a = node.children) === null || _a === void 0 ? void 0 : _a.some(child => child.id === targetId); }) || null;
884
+ if (!nodesById[targetId])
885
+ return null; // target not found
886
+ // Depth is 0 for root nodes, 1 for children of root, etc.
887
+ let depth = 0;
888
+ let current = targetId;
889
+ while (true) {
890
+ const directParent = Object.values(nodesById).find(node => { var _a; return (_a = node.children) === null || _a === void 0 ? void 0 : _a.some(child => child.id === current); });
891
+ if (!directParent)
892
+ break;
893
+ depth++;
894
+ current = directParent.id;
895
+ }
896
+ return { parent, depth };
897
+ }
898
+ const result = getDirectParentAndDepth(this.loadedTreeJs.nodesById, e.target.id);
899
+ e.target.depth = result.depth;
900
+ e.target.parentId = result.parent.id;
901
+ }
704
902
  this.itemContextMenuItemClick.emit(e);
705
903
  }
706
904
  setNodeAsSelected(id, treeToUpdate, userClick) {
@@ -709,8 +907,10 @@ export class HierarchizedPickerComponent {
709
907
  (this.loadedTreeJs.liElementsById[id] && this.loadedTreeJs.liElementsById[id].classList.value && this.loadedTreeJs.liElementsById[id].classList.value.indexOf('readonly_node') != -1)) {
710
908
  return;
711
909
  }
712
- if (treeToUpdate.getValues().indexOf(id.toString()) != -1)
910
+ if (!userClick && treeToUpdate.getValues().indexOf(id.toString()) != -1)
713
911
  return;
912
+ if (this.loadedTreeJs && !this.theOptions.multiple)
913
+ this.loadedTreeJs.emptyNodesCheckStatus();
714
914
  this.ignoreOptionsChanges = true;
715
915
  // Override of treejs normal workaround =>> DONT EDIT IT!
716
916
  // ----- BEGIN -----
@@ -747,46 +947,29 @@ export class HierarchizedPickerComponent {
747
947
  * This method display the current selected node to the user by expanding all it's parent nodes and scrolling inside the tree
748
948
  */
749
949
  async showSelectedNodes(addDelay = false) {
750
- if (this.optionsManager.getOptions().multiple) {
751
- console.warn('You are not allowed to scroll to selected nodes in multiple mode');
752
- return;
753
- }
754
- const scrollToNode = () => {
755
- let scrollToValue = 0;
756
- let removeClosedAndLookUp = (element) => {
757
- var _a, _b, _c, _d;
758
- const nodeId = element === null || element === void 0 ? void 0 : element.nodeId;
759
- if (!element || !nodeId) {
760
- return;
761
- }
762
- const node = this.loadedTreeJs.nodesById[nodeId];
763
- if ((_b = (_a = node === null || node === void 0 ? void 0 : node.children) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.id) {
764
- (_c = element.classList) === null || _c === void 0 ? void 0 : _c.remove('treejs-node__close');
765
- }
766
- scrollToValue += element.offsetTop;
767
- const parent = (_d = element.parentNode) === null || _d === void 0 ? void 0 : _d.closest('.treejs-node');
768
- if (parent) {
769
- removeClosedAndLookUp(parent);
770
- }
771
- };
772
- try {
773
- const checkeds = document.querySelectorAll('#tree-area-' + this.componentID + ' .treejs-node__checked');
774
- checkeds.forEach((item) => removeClosedAndLookUp(item));
775
- }
776
- catch (err) {
777
- // console.error("Error in showSelectedNodes", err);
778
- }
779
- if (scrollToValue && this.scrollable) {
780
- this.scrollable.scrollTop = scrollToValue;
781
- }
782
- };
950
+ // if (this.optionsManager.getOptions().multiple) {
951
+ // console.warn('You are not allowed to scroll to selected nodes in multiple mode');
952
+ // return;
953
+ // }
783
954
  if (addDelay) {
784
955
  setTimeout(() => {
785
- scrollToNode();
956
+ this.scrollToNode();
786
957
  }, 200);
787
958
  }
788
959
  else {
789
- scrollToNode();
960
+ this.scrollToNode();
961
+ }
962
+ }
963
+ async scrollToNodeWithId(targetNodeId, displayChildren = false) {
964
+ const targetNode = this.loadedTreeJs.liElementsById[targetNodeId];
965
+ if (!targetNode) {
966
+ const contextualApiParams = this.getContextualApiParams(Object.assign(Object.assign({}, this.theOptions.options), { Reach: [targetNodeId] }), null, true);
967
+ const contextualApiURL = this.getContextualApiURL(true, Object.assign(Object.assign({}, this.theOptions), { options: contextualApiParams }));
968
+ this.rawDataManager.getFromClassification(contextualApiURL, contextualApiParams, document.querySelector("#hierarchized-picker-" + this.componentID + " .loader"))
969
+ .then(data => {
970
+ completeCurrentTreeWithTree(this.loadedTreeJs, data, this.theOptions);
971
+ this.scrollToNode(targetNodeId, displayChildren);
972
+ });
790
973
  }
791
974
  }
792
975
  showTree(focused) {
@@ -795,10 +978,10 @@ export class HierarchizedPickerComponent {
795
978
  clearAutocomplete();
796
979
  if (!this.canload || !this.optionsManager.getOptions().displayTree)
797
980
  return;
798
- const isStillInsidePicker = isInsidePicker(this, document.activeElement);
981
+ const isStillInsidePicker = false; // TODO put back? >> isInsidePicker(this, document.activeElement);
799
982
  if ((focused === 'hide' || this.isDisabled) && !isStillInsidePicker) {
800
983
  this.hasFocus = ['hide'];
801
- const elem = document.querySelector('#hierarchized-picker-' + this.componentID + ' .hierarchized-picker-search input');
984
+ const elem = document.querySelector('#hierarchized-picker-' + this.componentID + ' input.hierarchized-picker-search');
802
985
  if (elem) {
803
986
  elem.value = '';
804
987
  }
@@ -819,16 +1002,16 @@ export class HierarchizedPickerComponent {
819
1002
  }
820
1003
  const previousShownTree = this.shownTree;
821
1004
  this.shownTree = this.hasFocus.length > 0;
822
- if (this.shownTree && !previousShownTree) {
823
- console.log("component value", document.querySelector('#hierarchized-picker-input-' + this.componentID));
824
- console.log("shouldOpenModalAbove", this.shouldOpenModalAbove(document.querySelector('#hierarchized-picker-input-' + this.componentID), this.modaleHeight));
1005
+ if (this.shownTree && !previousShownTree && this.optionsManager.getOptions().mode == 'input') {
825
1006
  if (this.shouldOpenModalAbove(document.querySelector('#hierarchized-picker-input-' + this.componentID), this.modaleHeight)) {
826
1007
  this.modalePosition = 'top';
827
1008
  }
828
1009
  else {
829
1010
  this.modalePosition = 'bottom';
830
1011
  }
831
- focusSearchInput(this);
1012
+ setTimeout(() => focusSearchInput(this), 100);
1013
+ //TODO, this this at the good location ?
1014
+ setupKeyboardNavigation(this, this.optionsManager, this.navigateInTree);
832
1015
  }
833
1016
  }
834
1017
  // Changes the value of the component with passed node
@@ -841,9 +1024,12 @@ export class HierarchizedPickerComponent {
841
1024
  return item.nodeid == node.id;
842
1025
  });
843
1026
  // If the passed node already exists in the array of values, remove it
844
- if (userClick && result > -1) {
845
- this.value.splice(result, 1);
846
- } // Else, add the node to the array of values
1027
+ if (result > -1) {
1028
+ if (userClick)
1029
+ this.value.splice(result, 1);
1030
+ else
1031
+ return;
1032
+ }
847
1033
  else {
848
1034
  if (this.optionsManager.getOptions().multiple) {
849
1035
  this.value = [
@@ -869,13 +1055,23 @@ export class HierarchizedPickerComponent {
869
1055
  }
870
1056
  this.setDisplayedValue(this.value);
871
1057
  }
1058
+ getShortpathFromFullpath(fullpath) {
1059
+ if (!fullpath || fullpath.indexOf('>') == -1)
1060
+ return fullpath;
1061
+ return fullpath.substring(fullpath.lastIndexOf(">") + 1);
1062
+ }
872
1063
  setDisplayedValue(value = null) {
873
1064
  if (!value)
874
1065
  value = this.value;
875
- this.displayedValue = value.map(item => {
876
- var _a, _b;
877
- return (_b = (this.optionsManager.getOptions().isFullpath ? this.getShortenedFullpath((_a = item.fullpathTranslated) !== null && _a !== void 0 ? _a : item.fullpath) : item.shortpathTranslated)) !== null && _b !== void 0 ? _b : `Node ${item.nodeid}`;
1066
+ const toDisplay = value.map(item => {
1067
+ var _a, _b, _c;
1068
+ return (this.optionsManager.getOptions().source == 'data'
1069
+ ?
1070
+ (_a = (this.optionsManager.getOptions().language == 'fr' ? this.getShortpathFromFullpath(item.fullpathTranslated) : this.getShortpathFromFullpath(item.fullpath))) !== null && _a !== void 0 ? _a : `Node ${item.nodeid}`
1071
+ :
1072
+ (_c = (this.optionsManager.getOptions().isFullpath ? this.getShortenedFullpath((_b = item.fullpathTranslated) !== null && _b !== void 0 ? _b : item.fullpath) : item.shortpathTranslated)) !== null && _c !== void 0 ? _c : `Node ${item.nodeid}`);
878
1073
  }).join(';');
1074
+ this.displayedValue = toDisplay;
879
1075
  }
880
1076
  // Search a value in the tree and triggers a search when necessary
881
1077
  search(searched) {
@@ -942,10 +1138,11 @@ export class HierarchizedPickerComponent {
942
1138
  if (init) {
943
1139
  this.formatDefaultValue();
944
1140
  this.showSelectedNodes();
1141
+ this.checkFields(this.value);
945
1142
  }
946
1143
  })
947
1144
  .catch(error => {
948
- console.error('getDataFromSource 3 classification rejected:', error);
1145
+ this.errorToLog = error;
949
1146
  });
950
1147
  }
951
1148
  else {
@@ -958,7 +1155,7 @@ export class HierarchizedPickerComponent {
958
1155
  }
959
1156
  })
960
1157
  .catch(error => {
961
- console.error('getDataFromSource 3 legacy rejected:', error);
1158
+ this.errorToLog = error;
962
1159
  });
963
1160
  }
964
1161
  }
@@ -979,7 +1176,7 @@ export class HierarchizedPickerComponent {
979
1176
  let enrichedValues = [];
980
1177
  if (values) {
981
1178
  values.forEach(element => {
982
- var _a, _b;
1179
+ var _a, _b, _c;
983
1180
  let intNodeid = element.nodeid || element.ID || element.key || undefined;
984
1181
  if (typeof intNodeid === 'string' && isNumeric(intNodeid)) {
985
1182
  intNodeid = parseInt(intNodeid);
@@ -989,15 +1186,15 @@ export class HierarchizedPickerComponent {
989
1186
  enrichedValues.push({
990
1187
  nodeid: intNodeid,
991
1188
  shortpathTranslated: (_a = treeNode.text) !== null && _a !== void 0 ? _a : `Node ${intNodeid}`,
992
- fullpathTranslated: (_b = treeNode.fullpath) !== null && _b !== void 0 ? _b : null,
1189
+ fullpathTranslated: (_b = treeNode.fullpathTranslated) !== null && _b !== void 0 ? _b : null,
1190
+ fullpath: (_c = treeNode.fullpath) !== null && _c !== void 0 ? _c : null,
993
1191
  hasChildren: treeNode.children && treeNode.children.length > 0
994
1192
  });
995
- this.setNodeAsSelected(intNodeid, this.loadedTreeJs, false);
996
1193
  }
997
1194
  else {
998
- this.setNodeAsSelected(intNodeid, this.loadedTreeJs, false);
999
1195
  console.warn("Node not found in Tree for:", intNodeid);
1000
1196
  }
1197
+ this.setNodeAsSelected(intNodeid, this.loadedTreeJs, false);
1001
1198
  });
1002
1199
  }
1003
1200
  this.setDisplayedValue(enrichedValues);
@@ -1007,8 +1204,19 @@ export class HierarchizedPickerComponent {
1007
1204
  formatDefaultValue() {
1008
1205
  let found = 0;
1009
1206
  let that = this;
1207
+ let fieldsToCheck = [];
1208
+ function addToFieldsToCheck(item) {
1209
+ if (Array.isArray(item)) {
1210
+ item.forEach(el => addToFieldsToCheck(el));
1211
+ }
1212
+ else {
1213
+ const exists = fieldsToCheck.some(el => (el.nodeid || el.ID) == (item.nodeid || item.ID));
1214
+ if (!exists) {
1215
+ fieldsToCheck.push(item);
1216
+ }
1217
+ }
1218
+ }
1010
1219
  let recursive = function (children) {
1011
- //158424
1012
1220
  children.forEach(element => {
1013
1221
  that.theOptions.defaultValue.forEach(dfValue => {
1014
1222
  if (typeof dfValue == 'string' && isNumeric(dfValue)) {
@@ -1018,7 +1226,7 @@ export class HierarchizedPickerComponent {
1018
1226
  if ((typeof dfValue == 'string' && getPropertyFromNode(element, 'Properties').FullPath == dfValue) ||
1019
1227
  (typeof dfValue == 'number' && getPropertyFromNode(element, 'ID') == dfValue)) {
1020
1228
  element.nodeid = element.id;
1021
- that.checkFields([element]);
1229
+ addToFieldsToCheck([element]);
1022
1230
  found++;
1023
1231
  }
1024
1232
  }
@@ -1028,7 +1236,7 @@ export class HierarchizedPickerComponent {
1028
1236
  (typeof dfValue == 'string' && getPropertyFromNode(element, 'fullpathTranslated') == dfValue) ||
1029
1237
  (typeof dfValue == 'number' && getPropertyFromNode(element, 'key') == dfValue)) {
1030
1238
  element.nodeid = element.key;
1031
- that.checkFields([element]);
1239
+ addToFieldsToCheck([element]);
1032
1240
  found++;
1033
1241
  }
1034
1242
  }
@@ -1040,6 +1248,7 @@ export class HierarchizedPickerComponent {
1040
1248
  if (this.rawDataManager.getData()) {
1041
1249
  recursive([this.rawDataManager.getData()]);
1042
1250
  }
1251
+ that.checkFields(fieldsToCheck);
1043
1252
  if (this.theOptions.defaultValue.length != found) {
1044
1253
  if (found == 0) {
1045
1254
  try {
@@ -1065,6 +1274,8 @@ export class HierarchizedPickerComponent {
1065
1274
  .join('; ');
1066
1275
  }
1067
1276
  shouldOpenModalAbove(inputElement, modaleHeight) {
1277
+ if (this.optionsManager.getOptions().mode != 'input')
1278
+ return false;
1068
1279
  const inputRect = inputElement.getBoundingClientRect();
1069
1280
  const spaceLeft = window.innerHeight - inputRect.y;
1070
1281
  return spaceLeft < modaleHeight;
@@ -1088,7 +1299,7 @@ export class HierarchizedPickerComponent {
1088
1299
  clickPickerModalArea(this, event);
1089
1300
  } }, h("div", { class: "loader", ref: el => {
1090
1301
  this.loader = el;
1091
- } }, h("div", { class: "loader-inner" }, "Loading...")), h("div", { class: `hierarchized-picker-modal ${!this.ready ? 'hidden' : ''}` }, h("search-input", { placeholder: getLanguageValue(this.optionsManager.getOptions().searchPlaceholder, this.optionsManager.getOptions().language, defaultLanguage), onInputFocus: () => focusInSearchEvent(this), onInputBlur: () => focusOutSearchEvent(this, event), onSearch: (event) => this.search(event.detail) }), h("ul", { id: "autocomplete-results-area" }), h("div", { id: 'tree-area-' + this.componentID, class: 'hierarchized-picker-tree hierarchized-picker-tree-area ' + this.pickerClass }))))) : (h("div", { class: 'hierarchized-picker-raw-tree-area' + (this.isDisabled ? ' readonly' : ''), onClick: event => {
1302
+ } }, h("div", { class: "loader-inner" }, "Loading...")), h("div", { class: `hierarchized-picker-modal ${!this.ready ? 'hidden' : ''}`, tabindex: "0" }, h("search-input", { placeholder: getLanguageValue(this.optionsManager.getOptions().searchPlaceholder, this.optionsManager.getOptions().language, defaultLanguage), onInputFocus: () => focusInSearchEvent(this), onInputBlur: () => focusOutSearchEvent(this, event), onSearch: (event) => this.search(event.detail) }), h("ul", { id: "autocomplete-results-area" }), h("div", { id: 'tree-area-' + this.componentID, class: 'hierarchized-picker-tree hierarchized-picker-tree-area ' + this.pickerClass }))))) : (h("div", { class: 'hierarchized-picker-raw-tree-area' + (this.isDisabled ? ' readonly' : ''), tabindex: "0", onClick: event => {
1092
1303
  clickPickerModalArea(this, event);
1093
1304
  } }, h("div", { class: "loader", ref: el => {
1094
1305
  this.loader = el;
@@ -1311,6 +1522,21 @@ export class HierarchizedPickerComponent {
1311
1522
  "resolved": "any",
1312
1523
  "references": {}
1313
1524
  }
1525
+ }, {
1526
+ "method": "errorRaised",
1527
+ "name": "errorRaised",
1528
+ "bubbles": true,
1529
+ "cancelable": true,
1530
+ "composed": true,
1531
+ "docs": {
1532
+ "tags": [],
1533
+ "text": "This event is emitted when the picker suffers an error"
1534
+ },
1535
+ "complexType": {
1536
+ "original": "any",
1537
+ "resolved": "any",
1538
+ "references": {}
1539
+ }
1314
1540
  }];
1315
1541
  }
1316
1542
  static get methods() {
@@ -1408,6 +1634,22 @@ export class HierarchizedPickerComponent {
1408
1634
  "tags": []
1409
1635
  }
1410
1636
  },
1637
+ "getError": {
1638
+ "complexType": {
1639
+ "signature": "() => Promise<string>",
1640
+ "parameters": [],
1641
+ "references": {
1642
+ "Promise": {
1643
+ "location": "global"
1644
+ }
1645
+ },
1646
+ "return": "Promise<string>"
1647
+ },
1648
+ "docs": {
1649
+ "text": "",
1650
+ "tags": []
1651
+ }
1652
+ },
1411
1653
  "clearPicker": {
1412
1654
  "complexType": {
1413
1655
  "signature": "() => Promise<void>",
@@ -1434,9 +1676,6 @@ export class HierarchizedPickerComponent {
1434
1676
  "references": {
1435
1677
  "Promise": {
1436
1678
  "location": "global"
1437
- },
1438
- "HTMLElement": {
1439
- "location": "global"
1440
1679
  }
1441
1680
  },
1442
1681
  "return": "Promise<void>"
@@ -1445,6 +1684,28 @@ export class HierarchizedPickerComponent {
1445
1684
  "text": "This method display the current selected node to the user by expanding all it's parent nodes and scrolling inside the tree",
1446
1685
  "tags": []
1447
1686
  }
1687
+ },
1688
+ "scrollToNodeWithId": {
1689
+ "complexType": {
1690
+ "signature": "(targetNodeId: any, displayChildren?: boolean) => Promise<void>",
1691
+ "parameters": [{
1692
+ "tags": [],
1693
+ "text": ""
1694
+ }, {
1695
+ "tags": [],
1696
+ "text": ""
1697
+ }],
1698
+ "references": {
1699
+ "Promise": {
1700
+ "location": "global"
1701
+ }
1702
+ },
1703
+ "return": "Promise<void>"
1704
+ },
1705
+ "docs": {
1706
+ "text": "",
1707
+ "tags": []
1708
+ }
1448
1709
  }
1449
1710
  };
1450
1711
  }