inviton-powerduck 0.0.70 → 0.0.71

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.
@@ -16,1007 +16,1009 @@ import PowerduckState from "../../app/powerduck-state";
16
16
 
17
17
  type RowToString = (row) => string;
18
18
  export enum MultiselectMode {
19
- Tags = 0,
20
- Checkboxes = 1,
19
+ Tags = 0,
20
+ Checkboxes = 1,
21
21
  }
22
22
 
23
23
  export enum MultiSelectExclusivity {
24
- Inclusive = 0,
25
- Exclusive = 1,
24
+ Inclusive = 0,
25
+ Exclusive = 1,
26
26
  }
27
27
 
28
28
  export class DropdownOptionGroup {
29
- isOptGroup: true;
30
- text: string;
31
- children: Array<string> | Array<any>;
29
+ isOptGroup: true;
30
+ text: string;
31
+ children: Array<string> | Array<any>;
32
32
  }
33
33
 
34
34
  export interface DropdownListOption {
35
- id: number | string;
36
- text: string;
37
- dataRow?: any;
35
+ id: number | string;
36
+ text: string;
37
+ dataRow?: any;
38
38
  }
39
39
 
40
40
  export interface DropdownListButton {
41
- iconCss: string;
42
- cssClass?: string;
43
- clicked: (e: DropdownListButtonClickedArgs) => void;
41
+ iconCss: string;
42
+ cssClass?: string;
43
+ clicked: (e: DropdownListButtonClickedArgs) => void;
44
44
  }
45
45
 
46
46
  export interface DropdownListButtonClickedArgs {
47
- item: any;
47
+ item: any;
48
48
  }
49
49
 
50
50
  export interface DropdownListTagAddedArgs {
51
- closeSelection: boolean;
52
- tagArr: string[];
51
+ closeSelection: boolean;
52
+ tagArr: string[];
53
53
  }
54
54
 
55
55
  interface DropdownListArgs extends FormItemWrapperArgs {
56
- placeholder?: string;
57
- blocked?: boolean;
58
- disabled?: boolean
59
- disableSearch?: boolean
60
- options: Array<string> | Array<DropdownOptionGroup> | Array<any>;
61
- selected: string | any | Array<string> | Array<any>;
62
- displayMember?: string | RowToString;
63
- valueMember?: string | RowToString;
64
- multiselect?: boolean;
65
- multiselectMode?: MultiselectMode;
66
- closeOnSelect?: boolean;
67
- trailingButton?: DropdownTrailingButtonArgs;
68
- tags?: boolean;
69
- tagsSortable?: boolean;
70
- tagsShouldPrependContent?: boolean;
71
- tagsTemplate?: string;
72
- name?: string
73
- autocomplete?: string
74
- tagsAdded?: (e: DropdownListTagAddedArgs) => void;
75
- tagsButtons?: (item: any) => DropdownListButton[];
76
- tagsNewPlaceLast?: boolean;
77
- allowExclusiveSearch?: boolean;
78
- dropdownAutoWidth?: boolean;
79
- mobileShortMode?: boolean;
80
- changedEventDelay?: number;
81
- changed: (newValue: string | any | Array<string> | Array<any>, exclusivity?: MultiSelectExclusivity) => void;
82
- afterBound?: (elem: JQuery<Element>, select2Instance: any) => void;
83
- noResultsFound?: () => void;
84
- formatResult?: (state: DropdownDisplayArgs, originator?: string) => JQuery | string
85
- formatSelection?: (state: DropdownDisplayArgs, originator?: string) => JQuery | string
86
- customIdProperty?: string;
56
+ placeholder?: string;
57
+ blocked?: boolean;
58
+ disabled?: boolean
59
+ disableSearch?: boolean
60
+ containerCssClass?: string
61
+ options: Array<string> | Array<DropdownOptionGroup> | Array<any>;
62
+ selected: string | any | Array<string> | Array<any>;
63
+ displayMember?: string | RowToString;
64
+ valueMember?: string | RowToString;
65
+ multiselect?: boolean;
66
+ multiselectMode?: MultiselectMode;
67
+ closeOnSelect?: boolean;
68
+ trailingButton?: DropdownTrailingButtonArgs;
69
+ tags?: boolean;
70
+ tagsSortable?: boolean;
71
+ tagsShouldPrependContent?: boolean;
72
+ tagsTemplate?: string;
73
+ name?: string
74
+ autocomplete?: string
75
+ tagsAdded?: (e: DropdownListTagAddedArgs) => void;
76
+ tagsButtons?: (item: any) => DropdownListButton[];
77
+ tagsNewPlaceLast?: boolean;
78
+ allowExclusiveSearch?: boolean;
79
+ dropdownAutoWidth?: boolean;
80
+ mobileShortMode?: boolean;
81
+ changedEventDelay?: number;
82
+ changed: (newValue: string | any | Array<string> | Array<any>, exclusivity?: MultiSelectExclusivity) => void;
83
+ afterBound?: (elem: JQuery<Element>, select2Instance: any) => void;
84
+ noResultsFound?: () => void;
85
+ formatResult?: (state: DropdownDisplayArgs, originator?: string) => JQuery | string
86
+ formatSelection?: (state: DropdownDisplayArgs, originator?: string) => JQuery | string
87
+ customIdProperty?: string;
87
88
  }
88
89
 
89
90
  interface DropdownDisplayArgs {
90
- id: string;
91
- text: string;
92
- dataRow: any;
93
- children?: DropdownDisplayArgs[]
91
+ id: string;
92
+ text: string;
93
+ dataRow: any;
94
+ children?: DropdownDisplayArgs[]
94
95
  }
95
96
 
96
97
  interface DropdownCurrentData {
97
- data: DropdownDisplayArgs[];
98
- added: string[];
98
+ data: DropdownDisplayArgs[];
99
+ added: string[];
99
100
  }
100
101
 
101
102
  export interface DropdownTrailingButtonArgs {
102
- cssClass: string;
103
- icon: string;
104
- text: string;
105
- clicked: (row: any) => void;
103
+ cssClass: string;
104
+ icon: string;
105
+ text: string;
106
+ clicked: (row: any) => void;
106
107
  }
107
108
 
108
109
  class DropdownSelect2Helper {
109
- static getSelect2Instance(s2Elem: JQuery<Element>): any {
110
- return $(s2Elem).data("select2");
111
- }
110
+ static getSelect2Instance(s2Elem: JQuery<Element>): any {
111
+ return $(s2Elem).data("select2");
112
+ }
112
113
  }
113
114
 
114
115
  @Component
115
116
  class DropdownListComponent extends TsxComponent<DropdownListArgs> implements DropdownListArgs {
116
- @Prop() label!: string;
117
- @Prop() labelButtons!: DropdownButtonItemArgs[];
118
- @Prop() blocked!: boolean;
119
- @Prop() mandatory!: boolean;
120
- @Prop() hint: string;
121
- @Prop() subtitle!: string;
122
- @Prop() name!: string
123
- @Prop() cssClass!: string
124
- @Prop() autocomplete!: string
125
- @Prop() appendIcon: string;
126
- @Prop() prependIcon: string;
127
- @Prop() appendIconClicked: () => void;
128
- @Prop() prependIconClicked: () => void;
129
- @Prop() appendClicked: () => void;
130
- @Prop() prependClicked: () => void;
131
- @Prop() allowExclusiveSearch!: boolean;
132
- @Prop() showClearValueButton!: boolean
133
- @Prop() options!: Array<string> | Array<any>;
134
- @Prop() displayMember!: (row) => string | string;
135
- @Prop() valueMember!: (row) => string | string;
136
- @Prop() selected!: string | any | Array<string> | Array<any>;
137
- @Prop() changed: (newValue: string | any | Array<string> | Array<any>, exclusivity?: MultiSelectExclusivity) => void;
138
- @Prop() afterBound: (elem: JQuery<Element>, select2Instance: any) => void;
139
- @Prop() maxWidth?: number;
140
- @Prop() multiselect!: boolean;
141
- @Prop() multiselectMode!: MultiselectMode;
142
- @Prop() trailingButton!: DropdownTrailingButtonArgs;
143
- @Prop() closeOnSelect!: boolean;
144
- @Prop() tags!: boolean;
145
- @Prop() tagsSortable?: boolean;
146
- @Prop() tagsShouldPrependContent!: boolean;
147
- @Prop() tagsTemplate!: string;
148
- @Prop() tagsButtons!: (item: any) => DropdownListButton[];
149
- @Prop() tagsAdded: (e: DropdownListTagAddedArgs) => void;
150
- @Prop() tagsNewPlaceLast?: boolean;
151
- @Prop() wrap!: boolean;
152
- @Prop() mobileShortMode!: boolean;
153
- @Prop() dropdownAutoWidth!: boolean;
154
- @Prop() changedEventDelay!: number;
155
- @Prop() placeholder: string;
156
- @Prop() noResultsFound: () => void;
157
- @Prop() marginType?: MarginType;
158
- @Prop() formatResult: (state: DropdownDisplayArgs) => JQuery | string;
159
- @Prop() formatSelection: (state: DropdownDisplayArgs) => JQuery | string;
160
- @Prop() disabled?: boolean
161
- @Prop() disableSearch?: boolean
162
- @Prop() customIdProperty?: string;
163
-
164
- currentSelected: string | any | Array<string> | Array<any> = this.selected;
165
- pendingChangeTimeout: any = null;
166
- preventDefaultTimeout: any = null;
167
- preventDefaultTrigger: boolean = null;
168
- currentExclusivity: MultiSelectExclusivity = null;
169
- skipChange: boolean = false;
170
- searchWasActive: boolean = false;
171
-
172
- raiseChangedEvent(valArr: DropdownDisplayArgs[], updateSelect2: boolean) {
173
- this.populateValidationDeclaration();
174
-
175
- var selVal: any = valArr.map((p) => p.dataRow);
176
- if (this.multiselect != true) {
177
- selVal = selVal[0];
178
- }
179
-
180
- this.currentSelected = selVal;
181
- if (this.changed != null) {
182
- this.changed(selVal, this.currentExclusivity);
183
- }
184
-
185
- if (updateSelect2) {
186
- this.updateSelect2();
187
- }
188
- }
189
-
190
- getValueFromArr(paramArr: string[], row): string {
191
- for (var i = 0, len = paramArr.length; i < len; i++) {
192
- var val = row[paramArr[i]];
193
- if (val == null) {
194
- val = row[capitalize(paramArr[i])];
195
- }
196
-
197
- if (val != null) {
198
- if (PortalUtils.isString(val) && val.length > 0) {
199
- return val;
200
- } else if (PortalUtils.isNumber(val)) {
201
- return val.toString();
202
- } else if (PortalUtils.isFunction(val)) {
203
- return val.call(row, row);
204
- }
205
- }
206
- }
207
-
208
- return null;
209
- }
210
- getReflectedRowValue(row: any, isValueMember: boolean): string {
211
- var member = isValueMember ? this.valueMember : this.displayMember;
212
- if (member == null) {
213
- if (isValueMember) {
214
- if (this.customIdProperty?.length > 0) {
215
- return this.getValueFromArr([this.customIdProperty], row);
216
- }
217
- return this.getValueFromArr(["id", "uuid"], row);
218
- } else {
219
- return this.getValueFromArr(["name", "text", "identifier"], row);
220
- }
221
- } else if (PortalUtils.isString(member)) {
222
- return row[member as any];
223
- } else if (PortalUtils.isNumber(member)) {
224
- return row[member as any].toString();
225
- } else if (PortalUtils.isFunction(member)) {
226
- return member.call(row, row);
227
- }
228
- }
229
-
230
- getOptions(preserveOptGroups?: boolean): DropdownDisplayArgs[] {
231
- var retVal: DropdownDisplayArgs[] = [];
232
- var opts = this.options as any;
233
-
234
- if (opts != null && opts.length > 0) {
235
- var firstItem = opts[0];
236
- if (PortalUtils.isString(firstItem)) {
237
- opts.forEach((item) => retVal.push({ id: item, text: item, dataRow: item }));
238
- } else if (PortalUtils.isNumber(firstItem)) {
239
- opts.forEach((item) => retVal.push({ id: item.toString(), text: item.toString(), dataRow: item.toString() }));
240
- } else if ((firstItem as DropdownOptionGroup).isOptGroup == true) {
241
- opts.forEach((optGroup: DropdownOptionGroup) => {
242
- let groupArr: Array<DropdownDisplayArgs> = [];
243
- let preserve = preserveOptGroups == true;
244
-
245
- if (!preserve) {
246
- groupArr = retVal;
247
- groupArr.push({
248
- id: -99438273213,
249
- text: optGroup.text,
250
- dataRow: optGroup,
251
- isOptionGroup: true,
252
- } as any);
253
- } else {
254
- let groupDef = {
255
- text: optGroup.text,
256
- children: groupArr,
257
- };
258
-
259
- retVal.push(groupDef as any);
260
- }
261
-
262
- optGroup.children.forEach((item) => {
263
- groupArr.push({
264
- id: this.getReflectedRowValue(item, true),
265
- text: this.getReflectedRowValue(item, false),
266
- dataRow: item,
267
- });
268
- });
269
- });
270
- } else {
271
- opts.forEach((item) => {
272
- retVal.push({
273
- id: this.getReflectedRowValue(item, true),
274
- text: this.getReflectedRowValue(item, false),
275
- dataRow: item,
276
- });
277
- });
278
- }
279
- }
280
-
281
- return retVal;
282
- }
283
-
284
- getSelectedItems(): DropdownDisplayArgs[] {
285
- var opts = this.getOptions();
286
- if (this.currentSelected == null || opts.length == 0) {
287
- return [];
288
- }
289
-
290
- var retArr: DropdownDisplayArgs[] = [];
291
- var selItemArr: Array<string> = PortalUtils.isArray(this.currentSelected) ? this.currentSelected : [this.currentSelected];
292
-
293
- selItemArr.forEach((arrItem) => {
294
- var selItem: string;
295
- if (PortalUtils.isString(arrItem) || PortalUtils.isNumber(arrItem)) {
296
- selItem = arrItem.toString();
297
- } else {
298
- selItem = this.getReflectedRowValue(arrItem, true);
299
- }
300
-
301
- for (var i = 0, len = opts.length; i < len; i++) {
302
- var ci = opts[i];
303
- if (ci.id == selItem) {
304
- retArr.push(ci);
305
- break;
306
- }
307
- }
308
- });
309
-
310
- return retArr;
311
- }
312
-
313
- getMobileSelectionText(): string {
314
- var opts = this.getOptions();
315
- var selectedItems = this.getSelectedItems();
316
-
317
- if (selectedItems.length > 2 || (this.mobileShortMode == true && selectedItems.length > 0)) {
318
- return PowerduckState.getResourceValue('itemsOutOfArray').replace('{0}', selectedItems.length.toString()).replace('{1}', opts.length.toString());
319
- } else if (selectedItems.length == 1) {
320
- return selectedItems[0].text;
321
- } else {
322
- return selectedItems.map((p) => p.text).join(", ");
323
- }
324
- }
325
-
326
- getRootBaseCssClass(): string {
327
- return (
328
- "s2-fw-root" +
329
- (!isNullOrEmpty(this.appendIcon) || !isNullOrEmpty(this.hint) ? " s2-append-icon" : "") +
330
- (!isNullOrEmpty(this.prependIcon) ? " s2-prepend-icon" : "") +
331
- (this.cssClass ? " " + this.cssClass : "")
332
- );
333
- }
334
-
335
- close() {
336
- $(this.$el).find(".make-select2")["select2"]("close");
337
- }
338
-
339
- render(h) {
340
- //Dummy stuff to ensure reactivity
341
- let dummyCss: string = "";
342
- if (this.currentSelected != null) {
343
- dummyCss += "ddl-dummy-selected" + this.currentSelected.toString().substring(0, 1);
344
- }
345
- if (this.options != null) {
346
- dummyCss += "opts";
347
- }
348
-
349
- return (
350
- <FormItemWrapper
351
- label={this.label}
352
- mandatory={this.mandatory}
353
- wrap={this.wrap}
354
- appendIcon={this.appendIcon}
355
- prependIcon={this.prependIcon}
356
- hint={this.hint}
357
- appendClicked={this.appendClicked}
358
- prependClicked={this.prependClicked}
359
- marginType={this.marginType}
360
- maxWidth={this.maxWidth}
361
- validationState={this.validationState}
362
- cssClass={dummyCss}
363
- subtitle={this.subtitle}
364
- labelButtons={this.labelButtons}
365
- appendIconClicked={this.appendIconClicked}
366
- prependIconClicked={this.prependIconClicked}
367
- showClearValueButton={this.showClearValueButton}
368
- >
369
- {this.renderDropdown(h)}
370
- </FormItemWrapper>
371
- );
372
- }
373
-
374
- renderDropdown(h) {
375
- if (this.useMobile()) {
376
- return this.renderMobileComponent(h);
377
- } else {
378
- return this.renderSelectComponent(h);
379
- }
380
- }
381
-
382
- renderSelectComponent(h) {
383
- return (
384
- <div class={this.getRootBaseCssClass() + (this.useMultiCheckbxoes() ? " s2-multi-chb" : "")}>
385
- <LoadingIndicator visible={this.blocked} />
386
- <select name={this.name} autocomplete={this.autocomplete} class={PowerduckState.getFormControlCssClass() + " make-select2"}></select>
387
- </div>
388
- );
389
- }
390
-
391
- renderMobileComponent(h) {
392
- var selectedText = this.getMobileSelectionText();
393
- if (selectedText == null || selectedText.length == 0) {
394
- selectedText = this.placeholder || "";
395
- }
396
-
397
- if (isNullOrEmpty(selectedText) && this.multiselect == true) {
398
- selectedText = "[" + PowerduckState.getResourceValue('all') + "]";
399
- }
400
-
401
- return (
402
- <span onClick={(e) => this.showMobilePicker(e)} class={"select2 select2-container select2-container--default s2-pseudo maxwidth-input " + this.getRootBaseCssClass()} dir="ltr">
403
- <span class="selection">
404
- <span class="select2-selection select2-selection--single" role="combobox" aria-haspopup="true">
405
- <span class="select2-selection__rendered mbl-ddl-text" title={selectedText} style="font-size: inherit;">
406
- {selectedText}
407
- </span>
408
- <span class="select2-selection__arrow" role="presentation">
409
- <b role="presentation"></b>
410
- </span>
411
- </span>
412
- </span>
413
- <span class="dropdown-wrapper" aria-hidden="true"></span>
414
- </span>
415
- );
416
- }
417
-
418
- getFormatResult() {
419
- if (this.trailingButton) {
420
- var self = this;
421
- return function (row) {
422
- var retVal = $(
423
- '<span class="s2-ri-withtb">' +
424
- row.text +
425
- '<button class="s2-trailing-button ' +
426
- (self.trailingButton.cssClass || "") +
427
- ' btn-sm">' +
428
- (self.trailingButton.icon != null ? '<i class="' + self.trailingButton.icon + '"></i> ' : "") +
429
- (self.trailingButton.text || "") +
430
- "</button></span>"
431
- );
432
- retVal.find("button").click(function (e) {
433
- try {
434
- clearTimeout(self.preventDefaultTimeout);
435
- self.preventDefaultTrigger = null;
436
- } catch (e) { }
437
-
438
- e.preventDefault();
439
- e.stopPropagation();
440
- e.stopImmediatePropagation();
441
-
442
- if (self.trailingButton.clicked != null) {
443
- self.trailingButton.clicked(row.dataRow);
444
- }
445
-
446
- return false;
447
- });
448
-
449
- return retVal;
450
- };
451
- }
452
-
453
- if (this.formatResult) {
454
- return this.formatResult;
455
- }
456
-
457
- return null;
458
- }
459
-
460
- isOptionGroupBinding(): boolean {
461
- if (this.options == null) {
462
- return false;
463
- }
464
-
465
- let firstOpt = this.options[0];
466
- if (firstOpt != null && (firstOpt as DropdownOptionGroup).isOptGroup == true) {
467
- return true;
468
- }
469
-
470
- return false;
471
- }
472
-
473
- showMobilePicker(e) {
474
- var opts = this.getOptions();
475
- var selectedItems = this.getSelectedItems();
476
- var dropDown = new FilterableSelect({
477
- animate: true,
478
- elem: null,
479
- cancelCss: "btn",
480
- confirmCss: "btn btn-primary",
481
- cssClass: this.cssClass,
482
- cancelText: PowerduckState.getResourceValue('cancel'),
483
- clickEventName: "click",
484
- data: opts,
485
- filterText: PowerduckState.getResourceValue('search') + "...",
486
- pagingCount: 99999,
487
- multiselect: this.multiselect == true,
488
- allowExclusiveSearch: this.allowExclusiveSearch == true,
489
- exclusiveInclusive: this.currentExclusivity,
490
- autoInputFocus: !PortalUtils.treatAsMobileDevice(),
491
- selectedIds: selectedItems.map((p) => p.id),
492
- useListviewBuilder: false,
493
- formatSelection: this.formatSelection,
494
- formatResult: this.getFormatResult(),
495
- onItemSelected: (items, exclusivity) => {
496
- this.currentExclusivity = exclusivity;
497
- this.raiseChangedEvent(items, true);
498
- this.setMobilePickerInputText(items);
499
- },
500
- });
501
-
502
- dropDown.onCancel = function () {
503
- selectedItems = null;
504
- dropDown = null;
505
- };
506
-
507
- dropDown.open();
508
- }
509
-
510
- setMobilePickerInputText(items: DropdownDisplayArgs[]): void {
511
- var selectedText = this.getMobileSelectionText();
512
- var textContext = $(this.$el).find(".mbl-ddl-text") as any;
513
- var isPlaceholder = items.length == 0;
514
-
515
- if (isNullOrEmpty(selectedText)) {
516
- selectedText = this.placeholder;
517
- }
518
-
519
- if (isNullOrEmpty(selectedText) && this.multiselect == true) {
520
- selectedText = "[" + PowerduckState.getResourceValue('all') + "]";
521
- }
522
-
523
- if (this.formatResult == null) {
524
- textContext.attr("title", selectedText);
525
- textContext.text(selectedText);
526
- } else {
527
- var item: any;
528
- if (items != null && items.length > 0) {
529
- item = items[0];
530
- }
531
-
532
- var result = this.formatResult(item);
533
- if (result["jquery"]) {
534
- textContext.html("");
535
- textContext.append(result);
536
- } else {
537
- textContext.text(result as any);
538
- }
539
- }
540
-
541
- if (isPlaceholder) {
542
- textContext.addClass("dd-placeholder");
543
- } else {
544
- textContext.removeClass("dd-placeholder");
545
- }
546
- }
547
-
548
- useMobile() {
549
- return PortalUtils.treatAsMobileDevice() && !this.tags && !PortalUtils.isInIframe();
550
- }
551
-
552
- useSelect2() {
553
- return !this.useMobile();
554
- }
555
-
556
- useMultiCheckbxoes() {
557
- return this.multiselect == true && this.multiselectMode == MultiselectMode.Checkboxes;
558
- }
559
-
560
- getCurrentSelect2Data(): DropdownCurrentData {
561
- var selArr: DropdownDisplayArgs[] = [];
562
- var addArr: string[] = [];
563
- var cOpts = this.getOptions();
564
- var currData = $(this.$el).find(".make-select2")["select2"]("data");
565
- this.currentExclusivity = ($(this.$el).find(".make-select2").data("select2") as any).exclusivity;
566
-
567
- currData.forEach((item) => {
568
- var optItem = cOpts.filter((p) => p.id == item.id)[0];
569
- if (optItem != null) {
570
- selArr.push(optItem);
571
- } else if (this.tags && this.tagsAdded != null) {
572
- addArr.push(item.id.replaceAll(this.getSelect2AddResource(), ""));
573
- }
574
- });
575
-
576
- return {
577
- data: selArr,
578
- added: addArr,
579
- };
580
- }
581
-
582
- getSelect2AddResource(): string {
583
- return " (" + PowerduckState.getResourceValue('add') + ")";
584
- }
585
-
586
- bindSelect2TagsButton(select2Instance) {
587
- let $selection = select2Instance.$selection as JQuery<Element>;
588
- if ($selection.attr("data-ddbtn-bound") != "yeah") {
589
- let self = this;
590
- $selection.attr("data-ddbtn-bound", "yeah");
591
- $selection.on("click", ".dll-clickable-button", function (e) {
592
- let $this = $(this);
593
- let buttonIndex = $this.attr("data-index");
594
- let selectionData = $this.parent().parent().parent().data("data");
595
- let opts = self.getOptions();
596
- let dataItem = opts.filter((p) => p.id == selectionData.id)[0];
597
-
598
- (self.tagsButtons(dataItem)[buttonIndex] as DropdownListButton).clicked({
599
- item: dataItem != null ? dataItem.dataRow : null,
600
- });
601
-
602
- e.preventDefault();
603
- e.stopPropagation();
604
- e.stopImmediatePropagation();
605
- });
606
- }
607
- }
608
-
609
- updateSelect2() {
610
- if (this.useSelect2()) {
611
- var self = this;
612
- var opts = this.getOptions();
613
- var s2Constructor: "select2MultiCheckboxes" | "select2" = this.useMultiCheckbxoes() ? "select2MultiCheckboxes" : "select2";
614
- var selected = this.getSelectedItems();
615
- var s2Elem = this.getSelect2RootElement();
616
- var alreadyBound = true;
617
-
618
- if (this.disabled == true) {
619
- s2Elem.attr('disabled', 'true');
620
- } else {
621
- s2Elem.removeAttr('disabled');
622
- }
623
-
624
- if (s2Elem.attr("data-vebound") != "true") {
625
- alreadyBound = false;
626
- s2Elem
627
- .attr("data-vebound", "true")
628
- .change(function (e) {
629
- if (self.skipChange) {
630
- self.skipChange = false;
631
- return;
632
- }
633
-
634
- if (self.pendingChangeTimeout != null) {
635
- clearTimeout(self.pendingChangeTimeout);
636
- }
637
-
638
- let forceClose = false;
639
- if (self.tags == true) {
640
- let currentData = self.getCurrentSelect2Data();
641
- if (!isNullOrEmpty(currentData.added) && self.tagsAdded != null) {
642
- let eventArgs: DropdownListTagAddedArgs = {
643
- closeSelection: false,
644
- tagArr: currentData.added,
645
- };
646
-
647
- self.tagsAdded(eventArgs);
648
- forceClose = eventArgs.closeSelection;
649
- }
650
- }
651
-
652
- try {
653
- let searchElem = DropdownSelect2Helper.getSelect2Instance(s2Elem).selection.$search[0];
654
- if (searchElem != null) {
655
- self.searchWasActive = searchElem == document.activeElement;
656
- } else {
657
- self.searchWasActive = false;
658
- }
659
- } catch (e) {
660
- self.searchWasActive = false;
661
- }
662
-
663
- if (forceClose) {
664
- self.searchWasActive = false;
665
- }
666
-
667
- if (self.changedEventDelay == null || self.changedEventDelay == 0) {
668
- self.raiseChangedEvent(self.getCurrentSelect2Data().data, false);
669
- } else {
670
- self.pendingChangeTimeout = setTimeout(function () {
671
- self.pendingChangeTimeout = null;
672
- self.raiseChangedEvent(self.getCurrentSelect2Data().data, false);
673
- }, self.changedEventDelay);
674
- }
675
- })
676
- .on("select2:close", function () {
677
- if (self.pendingChangeTimeout != null) {
678
- clearTimeout(self.pendingChangeTimeout);
679
- self.pendingChangeTimeout = null;
680
- self.raiseChangedEvent(self.getCurrentSelect2Data().data, false);
681
- }
682
- })
683
- .on("select2:opening", function (e) {
684
- if ((self as any).preventOpen) {
685
- e.preventDefault();
686
- e.stopImmediatePropagation();
687
- e.stopPropagation();
688
- }
689
- })
690
- .on("select2:unselect", function (e) {
691
- (self as any).preventOpen = true;
692
- setTimeout(() => {
693
- (self as any).preventOpen = false;
694
- }, 50);
695
- })
696
- .on("select2:selecting", function (e) {
697
- if (self.trailingButton) {
698
- try {
699
- let clickTarget = $((e["params"] as any).args.originalEvent.target);
700
- if (clickTarget.hasClass("s2-trailing-button") || clickTarget.parent().hasClass("s2-trailing-button")) {
701
- return false;
702
- }
703
- } catch (e) { }
704
- }
705
- })
706
- .on("select2:closing", function (e) {
707
- if (self.trailingButton) {
708
- if (self.preventDefaultTrigger == false) {
709
- self.preventDefaultTrigger = null;
710
- } else {
711
- self.preventDefaultTimeout = setTimeout(function () {
712
- self.preventDefaultTrigger = false;
713
- s2Elem["select2"]("close");
714
- }, 50);
715
-
716
- return false;
717
- }
718
- }
719
- });
720
- }
721
-
722
- let dataChanged = false;
723
- let optsChanged = false;
724
- let domOpts = s2Elem.find("option");
725
- let currentSelected: string[];
726
- let cs2v = s2Elem.val();
727
-
728
- //Get current state of the DOM value
729
- if (cs2v != null) {
730
- currentSelected = (this.multiselect ? cs2v : [cs2v]) as any;
731
- } else {
732
- currentSelected = [];
733
- }
734
-
735
- //Determine if value changed somehow
736
- if (currentSelected.length != selected.length) {
737
- dataChanged = true;
738
- } else if (currentSelected.length == 0 && selected.length == 0) {
739
- dataChanged = false;
740
- } else {
741
- for (let i = 0, len = selected.length; i < len; i++) {
742
- let cItem = selected[i];
743
- if (currentSelected.filter((p) => p == cItem.id)[0] == null) {
744
- dataChanged = true;
745
- }
746
- }
747
- }
748
-
749
- //Determine if options changed
750
- if (domOpts.length != opts.length) {
751
- optsChanged = true;
752
- } else if (domOpts.length == 0 && opts.length == 0) {
753
- optsChanged = false;
754
- } else {
755
- for (let i = 0, len = domOpts.length; i < len; i++) {
756
- let domOption = domOpts[i] as HTMLOptionElement;
757
- let existingOpt = opts.filter((p) => p.id == domOption.value)[0];
758
- if (existingOpt == null) {
759
- optsChanged = true;
760
- break;
761
- } else if (existingOpt.text != domOption.innerText) {
762
- optsChanged = true;
763
- break;
764
- }
765
- }
766
- }
767
-
768
- //If nothing changed and the control is already bound break the operation
769
- if (dataChanged == false && optsChanged == false && alreadyBound) {
770
- return;
771
- }
772
-
773
- let allOpts = opts;
774
- if (this.isOptionGroupBinding()) {
775
- opts = this.getOptions(true);
776
- allOpts = [];
777
- (opts as unknown as DropdownOptionGroup[]).forEach((optGroup) => {
778
- optGroup.children.forEach((item) => {
779
- allOpts.push(item as any);
780
- });
781
- });
782
- }
783
-
784
- allOpts.forEach((item) => {
785
- item["selected"] = selected.filter((p) => p.id == item.id).length > 0;
786
- });
787
-
788
- s2Elem.find("option").each((i, l) => {
789
- $(l).remove();
790
- });
791
-
792
- s2Elem.find("optgroup").each((i, l) => {
793
- $(l).remove();
794
- });
795
-
796
- var s2Args = {
797
- allowExclusiveSearch: this.allowExclusiveSearch == true,
798
- minimumResultsForSearch: this.disableSearch == true ? -1 : 0,
799
- closeOnSelect: this.closeOnSelect != false && !this.useMultiCheckbxoes(),
800
- placeholder: this.placeholder,
801
- allowClear: this.placeholder != null && this.placeholder.length > 0,
802
- multiple: this.multiselect == true,
803
- dropdownAutoWidth: this.dropdownAutoWidth == true,
804
- tags: this.tags == true,
805
- data: opts,
806
- language: {
807
- noResults: function () {
808
- if (self.noResultsFound != null) {
809
- self.noResultsFound();
810
- }
811
-
812
- return PowerduckState.getResourceValue('noResultsFound');
813
- },
814
- },
815
- };
816
-
817
- var formatResult = this.getFormatResult();
818
- if (formatResult != null) {
819
- s2Args["templateResult"] = formatResult;
820
- }
821
-
822
- if (this.formatSelection != null) {
823
- s2Args["templateSelection"] = this.formatSelection;
824
- }
825
-
826
- let modalContent = $(this.$el).closest(".modal-content");
827
- if (modalContent.length > 0) {
828
- s2Args["dropdownParent"] = modalContent;
829
- }
830
-
831
- let validTagsButtons = false;
832
- let tagsTemplate = this.tagsTemplate;
833
- if (this.tags == true && this.tagsAdded != null) {
834
- s2Args["createTag"] = function (params) {
835
- var term = $.trim(params.term);
836
- if (term === "") {
837
- return null;
838
- }
839
-
840
- return {
841
- id: term,
842
- text: term + self.getSelect2AddResource(),
843
- newTag: true, // add additional parameters
844
- };
845
- };
846
-
847
- if (this.tagsNewPlaceLast != false) {
848
- s2Args["insertTag"] = function (data, tag) {
849
- // Insert the tag at the end of the results
850
- data.push(tag);
851
- };
852
- }
853
-
854
- if (this.tagsButtons != null) {
855
- if (tagsTemplate == null && this.tagsShouldPrependContent != false && this.formatSelection == null) {
856
- validTagsButtons = true;
857
- tagsTemplate =
858
- '<li class="select2-selection__choice select2-selection__choice-with-button"><span class="select2-selection__choice__remove" role="presentation"><i class="fas fa-times"></i></span></li>';
859
- s2Args["templateSelection"] = function (state): string | JQuery {
860
- if (!state) return "";
861
- if (!state.id) return state.text;
862
-
863
- let dataItem = allOpts.filter((p) => p.id.toString() == state.id)[0];
864
- if (dataItem == null) {
865
- return state.text;
866
- }
867
-
868
- let builder =
869
- '<span class="ddl-dropdown-resultroot"><span class="ddl-dropdown-resultwrap"><span class="ddl-result-text">' + PortalUtils.htmlEscape(dataItem.text) + "</span>";
870
- (self.tagsButtons(dataItem) || ([] as DropdownListButton[])).forEach((button, i) => {
871
- builder +=
872
- '<span class="ddl-result-button dll-clickable-button ' +
873
- button.cssClass +
874
- '" data-index="' +
875
- i +
876
- '" role="presentation"><i class="' +
877
- button.iconCss +
878
- '"></i></span>';
879
- });
880
-
881
- return $(builder + "</span></span>");
882
- };
883
- } else {
884
- console.log("Skipping tagsButtons - one of required conditions not met");
885
- }
886
- }
887
- }
888
-
889
- s2Elem[s2Constructor](s2Args);
890
-
891
- if (s2Args.tags) {
892
- if (!isNullOrEmpty(tagsTemplate)) {
893
- DropdownSelect2Helper.getSelect2Instance(s2Elem).selection.selectionContainer = function () {
894
- let retVal = $(tagsTemplate);
895
- if (self.tagsShouldPrependContent != false) {
896
- let oldAppend = retVal.append;
897
- retVal.append = function (elem) {
898
- retVal.prepend(elem);
899
- retVal.append = oldAppend;
900
- } as any;
901
- }
902
-
903
- return retVal;
904
- };
905
- }
906
-
907
- if (this.tagsSortable == true) {
908
- var ul = $(this.$el).find(".select2-container ul");
909
- if (ul.length > 0) {
910
- new Sortable(ul[0], {
911
- animation: 150,
912
- handle: ".select2-selection__choice",
913
- onEnd: (evt) => {
914
- const oldIndex = evt.oldIndex;
915
- let newIndex = evt.newIndex;
916
-
917
- if (newIndex > oldIndex) {
918
- newIndex -= 1;
919
- }
920
-
921
- const sel = this.currentSelected as any[];
922
- if (sel == null || sel[oldIndex] == null) {
923
- return;
924
- }
925
-
926
- const clonedArr = [...sel];
927
- const removedItems = clonedArr.splice(oldIndex, 1);
928
-
929
- console.log("oldIndex: " + oldIndex);
930
- console.log("newIndex: " + newIndex);
931
- console.log("removedItems: " + JSON.stringify(removedItems));
932
-
933
- clonedArr.splice(newIndex, 0, removedItems[0]);
934
-
935
- console.log("clonedArr: " + JSON.stringify(clonedArr));
936
-
937
- this.changed(clonedArr);
938
- },
939
- });
940
- }
941
- }
942
-
943
- // var ul = selectElem.prev('.select2-container').first('ul');
944
- // ul.sortable({
945
- // placeholder: 'ui-state-highlight',
946
- // items: 'li:not(.select2-search-field)',
947
- // tolerance: 'pointer',
948
- // stop: function () {
949
- // onElementValueChange(element, valueAccessor, allBindingsAccessor, viewModel);
950
- // }
951
- // });
952
- }
953
-
954
- if (this.afterBound != null) {
955
- this.afterBound(s2Elem, DropdownSelect2Helper.getSelect2Instance(s2Elem));
956
- }
957
-
958
- if (validTagsButtons) {
959
- this.bindSelect2TagsButton(DropdownSelect2Helper.getSelect2Instance(s2Elem));
960
- }
961
-
962
- if (selected.length > 0) {
963
- let selectedIds = selected.map((p) => p.id);
964
- if (self.multiselect) {
965
- s2Elem.val(selectedIds);
966
- } else {
967
- s2Elem.val(selectedIds[0]);
968
- }
969
- } else {
970
- s2Elem.val(null);
971
- s2Elem[s2Constructor]("val", "");
972
- }
973
-
974
- if (self.searchWasActive == true) {
975
- self.searchWasActive = false;
976
-
977
- this.$nextTick(() => {
978
- setTimeout(() => {
979
- this.focusSelect2Search();
980
- }, 0);
981
- });
982
- }
983
-
984
- self.skipChange = true;
985
- s2Elem.trigger("change");
986
- }
987
- }
988
-
989
- getSelect2RootElement(): JQuery<Element> {
990
- return $(this.$el).find(".make-select2");
991
- }
992
-
993
- focusSelect2Search() {
994
- $(this.$el).find(".select2-search__field").focus();
995
- }
996
-
997
- mounted() {
998
- this.currentSelected = this.selected;
999
- this.updateSelect2();
1000
-
1001
- this.$nextTick(() => {
1002
- this.setMobilePickerInputText(this.getSelectedItems());
1003
- });
1004
- }
1005
-
1006
- @Watch("selected")
1007
- updateValue() {
1008
- this.currentSelected = this.selected;
1009
- }
1010
-
1011
- updated() {
1012
- this.updateSelect2();
1013
- }
1014
-
1015
- beforeUnmount() {
1016
- try {
1017
- $(this.$el).find(".make-select2")["select2"]("destroy");
1018
- } catch (e) { }
1019
- }
117
+ @Prop() label!: string;
118
+ @Prop() labelButtons!: DropdownButtonItemArgs[];
119
+ @Prop() blocked!: boolean;
120
+ @Prop() mandatory!: boolean;
121
+ @Prop() hint: string;
122
+ @Prop() subtitle!: string;
123
+ @Prop() name!: string
124
+ @Prop() cssClass!: string
125
+ @Prop() autocomplete!: string
126
+ @Prop() appendIcon: string;
127
+ @Prop() prependIcon: string;
128
+ @Prop() appendIconClicked: () => void;
129
+ @Prop() prependIconClicked: () => void;
130
+ @Prop() appendClicked: () => void;
131
+ @Prop() prependClicked: () => void;
132
+ @Prop() allowExclusiveSearch!: boolean;
133
+ @Prop() showClearValueButton!: boolean
134
+ @Prop() options!: Array<string> | Array<any>;
135
+ @Prop() displayMember!: (row) => string | string;
136
+ @Prop() valueMember!: (row) => string | string;
137
+ @Prop() selected!: string | any | Array<string> | Array<any>;
138
+ @Prop() changed: (newValue: string | any | Array<string> | Array<any>, exclusivity?: MultiSelectExclusivity) => void;
139
+ @Prop() afterBound: (elem: JQuery<Element>, select2Instance: any) => void;
140
+ @Prop() maxWidth?: number;
141
+ @Prop() multiselect!: boolean;
142
+ @Prop() multiselectMode!: MultiselectMode;
143
+ @Prop() trailingButton!: DropdownTrailingButtonArgs;
144
+ @Prop() closeOnSelect!: boolean;
145
+ @Prop() tags!: boolean;
146
+ @Prop() tagsSortable?: boolean;
147
+ @Prop() tagsShouldPrependContent!: boolean;
148
+ @Prop() tagsTemplate!: string;
149
+ @Prop() tagsButtons!: (item: any) => DropdownListButton[];
150
+ @Prop() tagsAdded: (e: DropdownListTagAddedArgs) => void;
151
+ @Prop() tagsNewPlaceLast?: boolean;
152
+ @Prop() wrap!: boolean;
153
+ @Prop() mobileShortMode!: boolean;
154
+ @Prop() dropdownAutoWidth!: boolean;
155
+ @Prop() changedEventDelay!: number;
156
+ @Prop() placeholder: string;
157
+ @Prop() noResultsFound: () => void;
158
+ @Prop() marginType?: MarginType;
159
+ @Prop() formatResult: (state: DropdownDisplayArgs) => JQuery | string;
160
+ @Prop() formatSelection: (state: DropdownDisplayArgs) => JQuery | string;
161
+ @Prop() disabled?: boolean
162
+ @Prop() disableSearch?: boolean
163
+ @Prop() containerCssClass?: string
164
+ @Prop() customIdProperty?: string;
165
+
166
+ currentSelected: string | any | Array<string> | Array<any> = this.selected;
167
+ pendingChangeTimeout: any = null;
168
+ preventDefaultTimeout: any = null;
169
+ preventDefaultTrigger: boolean = null;
170
+ currentExclusivity: MultiSelectExclusivity = null;
171
+ skipChange: boolean = false;
172
+ searchWasActive: boolean = false;
173
+
174
+ raiseChangedEvent(valArr: DropdownDisplayArgs[], updateSelect2: boolean) {
175
+ this.populateValidationDeclaration();
176
+
177
+ var selVal: any = valArr.map((p) => p.dataRow);
178
+ if (this.multiselect != true) {
179
+ selVal = selVal[0];
180
+ }
181
+
182
+ this.currentSelected = selVal;
183
+ if (this.changed != null) {
184
+ this.changed(selVal, this.currentExclusivity);
185
+ }
186
+
187
+ if (updateSelect2) {
188
+ this.updateSelect2();
189
+ }
190
+ }
191
+
192
+ getValueFromArr(paramArr: string[], row): string {
193
+ for (var i = 0, len = paramArr.length; i < len; i++) {
194
+ var val = row[paramArr[i]];
195
+ if (val == null) {
196
+ val = row[capitalize(paramArr[i])];
197
+ }
198
+
199
+ if (val != null) {
200
+ if (PortalUtils.isString(val) && val.length > 0) {
201
+ return val;
202
+ } else if (PortalUtils.isNumber(val)) {
203
+ return val.toString();
204
+ } else if (PortalUtils.isFunction(val)) {
205
+ return val.call(row, row);
206
+ }
207
+ }
208
+ }
209
+
210
+ return null;
211
+ }
212
+ getReflectedRowValue(row: any, isValueMember: boolean): string {
213
+ var member = isValueMember ? this.valueMember : this.displayMember;
214
+ if (member == null) {
215
+ if (isValueMember) {
216
+ if (this.customIdProperty?.length > 0) {
217
+ return this.getValueFromArr([this.customIdProperty], row);
218
+ }
219
+ return this.getValueFromArr(["id", "uuid"], row);
220
+ } else {
221
+ return this.getValueFromArr(["name", "text", "identifier"], row);
222
+ }
223
+ } else if (PortalUtils.isString(member)) {
224
+ return row[member as any];
225
+ } else if (PortalUtils.isNumber(member)) {
226
+ return row[member as any].toString();
227
+ } else if (PortalUtils.isFunction(member)) {
228
+ return member.call(row, row);
229
+ }
230
+ }
231
+
232
+ getOptions(preserveOptGroups?: boolean): DropdownDisplayArgs[] {
233
+ var retVal: DropdownDisplayArgs[] = [];
234
+ var opts = this.options as any;
235
+
236
+ if (opts != null && opts.length > 0) {
237
+ var firstItem = opts[0];
238
+ if (PortalUtils.isString(firstItem)) {
239
+ opts.forEach((item) => retVal.push({ id: item, text: item, dataRow: item }));
240
+ } else if (PortalUtils.isNumber(firstItem)) {
241
+ opts.forEach((item) => retVal.push({ id: item.toString(), text: item.toString(), dataRow: item.toString() }));
242
+ } else if ((firstItem as DropdownOptionGroup).isOptGroup == true) {
243
+ opts.forEach((optGroup: DropdownOptionGroup) => {
244
+ let groupArr: Array<DropdownDisplayArgs> = [];
245
+ let preserve = preserveOptGroups == true;
246
+
247
+ if (!preserve) {
248
+ groupArr = retVal;
249
+ groupArr.push({
250
+ id: -99438273213,
251
+ text: optGroup.text,
252
+ dataRow: optGroup,
253
+ isOptionGroup: true,
254
+ } as any);
255
+ } else {
256
+ let groupDef = {
257
+ text: optGroup.text,
258
+ children: groupArr,
259
+ };
260
+
261
+ retVal.push(groupDef as any);
262
+ }
263
+
264
+ optGroup.children.forEach((item) => {
265
+ groupArr.push({
266
+ id: this.getReflectedRowValue(item, true),
267
+ text: this.getReflectedRowValue(item, false),
268
+ dataRow: item,
269
+ });
270
+ });
271
+ });
272
+ } else {
273
+ opts.forEach((item) => {
274
+ retVal.push({
275
+ id: this.getReflectedRowValue(item, true),
276
+ text: this.getReflectedRowValue(item, false),
277
+ dataRow: item,
278
+ });
279
+ });
280
+ }
281
+ }
282
+
283
+ return retVal;
284
+ }
285
+
286
+ getSelectedItems(): DropdownDisplayArgs[] {
287
+ var opts = this.getOptions();
288
+ if (this.currentSelected == null || opts.length == 0) {
289
+ return [];
290
+ }
291
+
292
+ var retArr: DropdownDisplayArgs[] = [];
293
+ var selItemArr: Array<string> = PortalUtils.isArray(this.currentSelected) ? this.currentSelected : [this.currentSelected];
294
+
295
+ selItemArr.forEach((arrItem) => {
296
+ var selItem: string;
297
+ if (PortalUtils.isString(arrItem) || PortalUtils.isNumber(arrItem)) {
298
+ selItem = arrItem.toString();
299
+ } else {
300
+ selItem = this.getReflectedRowValue(arrItem, true);
301
+ }
302
+
303
+ for (var i = 0, len = opts.length; i < len; i++) {
304
+ var ci = opts[i];
305
+ if (ci.id == selItem) {
306
+ retArr.push(ci);
307
+ break;
308
+ }
309
+ }
310
+ });
311
+
312
+ return retArr;
313
+ }
314
+
315
+ getMobileSelectionText(): string {
316
+ var opts = this.getOptions();
317
+ var selectedItems = this.getSelectedItems();
318
+
319
+ if (selectedItems.length > 2 || (this.mobileShortMode == true && selectedItems.length > 0)) {
320
+ return PowerduckState.getResourceValue('itemsOutOfArray').replace('{0}', selectedItems.length.toString()).replace('{1}', opts.length.toString());
321
+ } else if (selectedItems.length == 1) {
322
+ return selectedItems[0].text;
323
+ } else {
324
+ return selectedItems.map((p) => p.text).join(", ");
325
+ }
326
+ }
327
+
328
+ getRootBaseCssClass(): string {
329
+ return (
330
+ "s2-fw-root" +
331
+ (!isNullOrEmpty(this.appendIcon) || !isNullOrEmpty(this.hint) ? " s2-append-icon" : "") +
332
+ (!isNullOrEmpty(this.prependIcon) ? " s2-prepend-icon" : "") +
333
+ (this.cssClass ? " " + this.cssClass : "")
334
+ );
335
+ }
336
+
337
+ close() {
338
+ $(this.$el).find(".make-select2")["select2"]("close");
339
+ }
340
+
341
+ render(h) {
342
+ //Dummy stuff to ensure reactivity
343
+ let dummyCss: string = "";
344
+ if (this.currentSelected != null) {
345
+ dummyCss += "ddl-dummy-selected" + this.currentSelected.toString().substring(0, 1);
346
+ }
347
+ if (this.options != null) {
348
+ dummyCss += "opts";
349
+ }
350
+
351
+ return (
352
+ <FormItemWrapper
353
+ label={this.label}
354
+ mandatory={this.mandatory}
355
+ wrap={this.wrap}
356
+ appendIcon={this.appendIcon}
357
+ prependIcon={this.prependIcon}
358
+ hint={this.hint}
359
+ appendClicked={this.appendClicked}
360
+ prependClicked={this.prependClicked}
361
+ marginType={this.marginType}
362
+ maxWidth={this.maxWidth}
363
+ validationState={this.validationState}
364
+ cssClass={dummyCss}
365
+ subtitle={this.subtitle}
366
+ labelButtons={this.labelButtons}
367
+ appendIconClicked={this.appendIconClicked}
368
+ prependIconClicked={this.prependIconClicked}
369
+ showClearValueButton={this.showClearValueButton}
370
+ >
371
+ {this.renderDropdown(h)}
372
+ </FormItemWrapper>
373
+ );
374
+ }
375
+
376
+ renderDropdown(h) {
377
+ if (this.useMobile()) {
378
+ return this.renderMobileComponent(h);
379
+ } else {
380
+ return this.renderSelectComponent(h);
381
+ }
382
+ }
383
+
384
+ renderSelectComponent(h) {
385
+ return (
386
+ <div class={this.getRootBaseCssClass() + (this.useMultiCheckbxoes() ? " s2-multi-chb" : "")}>
387
+ <LoadingIndicator visible={this.blocked} />
388
+ <select name={this.name} autocomplete={this.autocomplete} class={PowerduckState.getFormControlCssClass() + " make-select2"}></select>
389
+ </div>
390
+ );
391
+ }
392
+
393
+ renderMobileComponent(h) {
394
+ var selectedText = this.getMobileSelectionText();
395
+ if (selectedText == null || selectedText.length == 0) {
396
+ selectedText = this.placeholder || "";
397
+ }
398
+
399
+ if (isNullOrEmpty(selectedText) && this.multiselect == true) {
400
+ selectedText = "[" + PowerduckState.getResourceValue('all') + "]";
401
+ }
402
+
403
+ return (
404
+ <span onClick={(e) => this.showMobilePicker(e)} class={"select2 select2-container select2-container--default s2-pseudo maxwidth-input " + this.getRootBaseCssClass()} dir="ltr">
405
+ <span class="selection">
406
+ <span class="select2-selection select2-selection--single" role="combobox" aria-haspopup="true">
407
+ <span class="select2-selection__rendered mbl-ddl-text" title={selectedText} style="font-size: inherit;">
408
+ {selectedText}
409
+ </span>
410
+ <span class="select2-selection__arrow" role="presentation">
411
+ <b role="presentation"></b>
412
+ </span>
413
+ </span>
414
+ </span>
415
+ <span class="dropdown-wrapper" aria-hidden="true"></span>
416
+ </span>
417
+ );
418
+ }
419
+
420
+ getFormatResult() {
421
+ if (this.trailingButton) {
422
+ var self = this;
423
+ return function (row) {
424
+ var retVal = $(
425
+ '<span class="s2-ri-withtb">' +
426
+ row.text +
427
+ '<button class="s2-trailing-button ' +
428
+ (self.trailingButton.cssClass || "") +
429
+ ' btn-sm">' +
430
+ (self.trailingButton.icon != null ? '<i class="' + self.trailingButton.icon + '"></i> ' : "") +
431
+ (self.trailingButton.text || "") +
432
+ "</button></span>"
433
+ );
434
+ retVal.find("button").click(function (e) {
435
+ try {
436
+ clearTimeout(self.preventDefaultTimeout);
437
+ self.preventDefaultTrigger = null;
438
+ } catch (e) { }
439
+
440
+ e.preventDefault();
441
+ e.stopPropagation();
442
+ e.stopImmediatePropagation();
443
+
444
+ if (self.trailingButton.clicked != null) {
445
+ self.trailingButton.clicked(row.dataRow);
446
+ }
447
+
448
+ return false;
449
+ });
450
+
451
+ return retVal;
452
+ };
453
+ }
454
+
455
+ if (this.formatResult) {
456
+ return this.formatResult;
457
+ }
458
+
459
+ return null;
460
+ }
461
+
462
+ isOptionGroupBinding(): boolean {
463
+ if (this.options == null) {
464
+ return false;
465
+ }
466
+
467
+ let firstOpt = this.options[0];
468
+ if (firstOpt != null && (firstOpt as DropdownOptionGroup).isOptGroup == true) {
469
+ return true;
470
+ }
471
+
472
+ return false;
473
+ }
474
+
475
+ showMobilePicker(e) {
476
+ var opts = this.getOptions();
477
+ var selectedItems = this.getSelectedItems();
478
+ var dropDown = new FilterableSelect({
479
+ animate: true,
480
+ elem: null,
481
+ cancelCss: "btn",
482
+ confirmCss: "btn btn-primary",
483
+ cssClass: this.cssClass,
484
+ cancelText: PowerduckState.getResourceValue('cancel'),
485
+ clickEventName: "click",
486
+ containerCssClass: this.containerCssClass,
487
+ data: opts,
488
+ filterText: PowerduckState.getResourceValue('search') + "...",
489
+ pagingCount: 99999,
490
+ multiselect: this.multiselect == true,
491
+ allowExclusiveSearch: this.allowExclusiveSearch == true,
492
+ exclusiveInclusive: this.currentExclusivity,
493
+ autoInputFocus: !PortalUtils.treatAsMobileDevice(),
494
+ selectedIds: selectedItems.map((p) => p.id),
495
+ useListviewBuilder: false,
496
+ formatSelection: this.formatSelection,
497
+ formatResult: this.getFormatResult(),
498
+ onItemSelected: (items, exclusivity) => {
499
+ this.currentExclusivity = exclusivity;
500
+ this.raiseChangedEvent(items, true);
501
+ this.setMobilePickerInputText(items);
502
+ },
503
+ });
504
+
505
+ dropDown.onCancel = function () {
506
+ selectedItems = null;
507
+ dropDown = null;
508
+ };
509
+
510
+ dropDown.open();
511
+ }
512
+
513
+ setMobilePickerInputText(items: DropdownDisplayArgs[]): void {
514
+ var selectedText = this.getMobileSelectionText();
515
+ var textContext = $(this.$el).find(".mbl-ddl-text") as any;
516
+ var isPlaceholder = items.length == 0;
517
+
518
+ if (isNullOrEmpty(selectedText)) {
519
+ selectedText = this.placeholder;
520
+ }
521
+
522
+ if (isNullOrEmpty(selectedText) && this.multiselect == true) {
523
+ selectedText = "[" + PowerduckState.getResourceValue('all') + "]";
524
+ }
525
+
526
+ if (this.formatResult == null) {
527
+ textContext.attr("title", selectedText);
528
+ textContext.text(selectedText);
529
+ } else {
530
+ var item: any;
531
+ if (items != null && items.length > 0) {
532
+ item = items[0];
533
+ }
534
+
535
+ var result = this.formatResult(item);
536
+ if (isNullOrEmpty(result)) {
537
+ textContext.attr("title", selectedText);
538
+ textContext.text(selectedText);
539
+ } else if (result["jquery"]) {
540
+ textContext.html("");
541
+ textContext.append(result);
542
+ } else {
543
+ textContext.text(result as any);
544
+ }
545
+ }
546
+
547
+ if (isPlaceholder) {
548
+ textContext.addClass("dd-placeholder");
549
+ } else {
550
+ textContext.removeClass("dd-placeholder");
551
+ }
552
+ }
553
+
554
+ useMobile() {
555
+ return PortalUtils.treatAsMobileDevice() && !this.tags && !PortalUtils.isInIframe();
556
+ }
557
+
558
+ useSelect2() {
559
+ return !this.useMobile();
560
+ }
561
+
562
+ useMultiCheckbxoes() {
563
+ return this.multiselect == true && this.multiselectMode == MultiselectMode.Checkboxes;
564
+ }
565
+
566
+ getCurrentSelect2Data(): DropdownCurrentData {
567
+ var selArr: DropdownDisplayArgs[] = [];
568
+ var addArr: string[] = [];
569
+ var cOpts = this.getOptions();
570
+ var currData = $(this.$el).find(".make-select2")["select2"]("data");
571
+ this.currentExclusivity = ($(this.$el).find(".make-select2").data("select2") as any).exclusivity;
572
+
573
+ currData.forEach((item) => {
574
+ var optItem = cOpts.filter((p) => p.id == item.id)[0];
575
+ if (optItem != null) {
576
+ selArr.push(optItem);
577
+ } else if (this.tags && this.tagsAdded != null) {
578
+ addArr.push(item.id.replaceAll(this.getSelect2AddResource(), ""));
579
+ }
580
+ });
581
+
582
+ return {
583
+ data: selArr,
584
+ added: addArr,
585
+ };
586
+ }
587
+
588
+ getSelect2AddResource(): string {
589
+ return " (" + PowerduckState.getResourceValue('add') + ")";
590
+ }
591
+
592
+ bindSelect2TagsButton(select2Instance) {
593
+ let $selection = select2Instance.$selection as JQuery<Element>;
594
+ if ($selection.attr("data-ddbtn-bound") != "yeah") {
595
+ let self = this;
596
+ $selection.attr("data-ddbtn-bound", "yeah");
597
+ $selection.on("click", ".dll-clickable-button", function (e) {
598
+ let $this = $(this);
599
+ let buttonIndex = $this.attr("data-index");
600
+ let selectionData = $this.parent().parent().parent().data("data");
601
+ let opts = self.getOptions();
602
+ let dataItem = opts.filter((p) => p.id == selectionData.id)[0];
603
+
604
+ (self.tagsButtons(dataItem)[buttonIndex] as DropdownListButton).clicked({
605
+ item: dataItem != null ? dataItem.dataRow : null,
606
+ });
607
+
608
+ e.preventDefault();
609
+ e.stopPropagation();
610
+ e.stopImmediatePropagation();
611
+ });
612
+ }
613
+ }
614
+
615
+ updateSelect2() {
616
+ if (this.useSelect2()) {
617
+ var self = this;
618
+ var opts = this.getOptions();
619
+ var s2Constructor: "select2MultiCheckboxes" | "select2" = this.useMultiCheckbxoes() ? "select2MultiCheckboxes" : "select2";
620
+ var selected = this.getSelectedItems();
621
+ var s2Elem = this.getSelect2RootElement();
622
+ var alreadyBound = true;
623
+
624
+ if (this.disabled == true) {
625
+ s2Elem.attr('disabled', 'true');
626
+ } else {
627
+ s2Elem.removeAttr('disabled');
628
+ }
629
+
630
+ if (s2Elem.attr("data-vebound") != "true") {
631
+ alreadyBound = false;
632
+ s2Elem
633
+ .attr("data-vebound", "true")
634
+ .change(function (e) {
635
+ if (self.skipChange) {
636
+ self.skipChange = false;
637
+ return;
638
+ }
639
+
640
+ if (self.pendingChangeTimeout != null) {
641
+ clearTimeout(self.pendingChangeTimeout);
642
+ }
643
+
644
+ let forceClose = false;
645
+ if (self.tags == true) {
646
+ let currentData = self.getCurrentSelect2Data();
647
+ if (!isNullOrEmpty(currentData.added) && self.tagsAdded != null) {
648
+ let eventArgs: DropdownListTagAddedArgs = {
649
+ closeSelection: false,
650
+ tagArr: currentData.added,
651
+ };
652
+
653
+ self.tagsAdded(eventArgs);
654
+ forceClose = eventArgs.closeSelection;
655
+ }
656
+ }
657
+
658
+ try {
659
+ let searchElem = DropdownSelect2Helper.getSelect2Instance(s2Elem).selection.$search[0];
660
+ if (searchElem != null) {
661
+ self.searchWasActive = searchElem == document.activeElement;
662
+ } else {
663
+ self.searchWasActive = false;
664
+ }
665
+ } catch (e) {
666
+ self.searchWasActive = false;
667
+ }
668
+
669
+ if (forceClose) {
670
+ self.searchWasActive = false;
671
+ }
672
+
673
+ if (self.changedEventDelay == null || self.changedEventDelay == 0) {
674
+ self.raiseChangedEvent(self.getCurrentSelect2Data().data, false);
675
+ } else {
676
+ self.pendingChangeTimeout = setTimeout(function () {
677
+ self.pendingChangeTimeout = null;
678
+ self.raiseChangedEvent(self.getCurrentSelect2Data().data, false);
679
+ }, self.changedEventDelay);
680
+ }
681
+ })
682
+ .on("select2:close", function () {
683
+ if (self.pendingChangeTimeout != null) {
684
+ clearTimeout(self.pendingChangeTimeout);
685
+ self.pendingChangeTimeout = null;
686
+ self.raiseChangedEvent(self.getCurrentSelect2Data().data, false);
687
+ }
688
+ })
689
+ .on("select2:opening", function (e) {
690
+ if ((self as any).preventOpen) {
691
+ e.preventDefault();
692
+ e.stopImmediatePropagation();
693
+ e.stopPropagation();
694
+ }
695
+ })
696
+ .on("select2:unselect", function (e) {
697
+ (self as any).preventOpen = true;
698
+ setTimeout(() => {
699
+ (self as any).preventOpen = false;
700
+ }, 50);
701
+ })
702
+ .on("select2:selecting", function (e) {
703
+ if (self.trailingButton) {
704
+ try {
705
+ let clickTarget = $((e["params"] as any).args.originalEvent.target);
706
+ if (clickTarget.hasClass("s2-trailing-button") || clickTarget.parent().hasClass("s2-trailing-button")) {
707
+ return false;
708
+ }
709
+ } catch (e) { }
710
+ }
711
+ })
712
+ .on("select2:closing", function (e) {
713
+ if (self.trailingButton) {
714
+ if (self.preventDefaultTrigger == false) {
715
+ self.preventDefaultTrigger = null;
716
+ } else {
717
+ self.preventDefaultTimeout = setTimeout(function () {
718
+ self.preventDefaultTrigger = false;
719
+ s2Elem["select2"]("close");
720
+ }, 50);
721
+
722
+ return false;
723
+ }
724
+ }
725
+ });
726
+ }
727
+
728
+ let dataChanged = false;
729
+ let optsChanged = false;
730
+ let domOpts = s2Elem.find("option");
731
+ let currentSelected: string[];
732
+ let cs2v = s2Elem.val();
733
+
734
+ //Get current state of the DOM value
735
+ if (cs2v != null) {
736
+ currentSelected = (this.multiselect ? cs2v : [cs2v]) as any;
737
+ } else {
738
+ currentSelected = [];
739
+ }
740
+
741
+ //Determine if value changed somehow
742
+ if (currentSelected.length != selected.length) {
743
+ dataChanged = true;
744
+ } else if (currentSelected.length == 0 && selected.length == 0) {
745
+ dataChanged = false;
746
+ } else {
747
+ for (let i = 0, len = selected.length; i < len; i++) {
748
+ let cItem = selected[i];
749
+ if (currentSelected.filter((p) => p == cItem.id)[0] == null) {
750
+ dataChanged = true;
751
+ }
752
+ }
753
+ }
754
+
755
+ //Determine if options changed
756
+ if (domOpts.length != opts.length) {
757
+ optsChanged = true;
758
+ } else if (domOpts.length == 0 && opts.length == 0) {
759
+ optsChanged = false;
760
+ } else {
761
+ for (let i = 0, len = domOpts.length; i < len; i++) {
762
+ let domOption = domOpts[i] as HTMLOptionElement;
763
+ let existingOpt = opts.filter((p) => p.id == domOption.value)[0];
764
+ if (existingOpt == null) {
765
+ optsChanged = true;
766
+ break;
767
+ } else if (existingOpt.text != domOption.innerText) {
768
+ optsChanged = true;
769
+ break;
770
+ }
771
+ }
772
+ }
773
+
774
+ //If nothing changed and the control is already bound break the operation
775
+ if (dataChanged == false && optsChanged == false && alreadyBound) {
776
+ return;
777
+ }
778
+
779
+ let allOpts = opts;
780
+ if (this.isOptionGroupBinding()) {
781
+ opts = this.getOptions(true);
782
+ allOpts = [];
783
+ (opts as unknown as DropdownOptionGroup[]).forEach((optGroup) => {
784
+ optGroup.children.forEach((item) => {
785
+ allOpts.push(item as any);
786
+ });
787
+ });
788
+ }
789
+
790
+ allOpts.forEach((item) => {
791
+ item["selected"] = selected.filter((p) => p.id == item.id).length > 0;
792
+ });
793
+
794
+ s2Elem.find("option").each((i, l) => {
795
+ $(l).remove();
796
+ });
797
+
798
+ s2Elem.find("optgroup").each((i, l) => {
799
+ $(l).remove();
800
+ });
801
+
802
+ var s2Args = {
803
+ allowExclusiveSearch: this.allowExclusiveSearch == true,
804
+ minimumResultsForSearch: this.disableSearch == true ? -1 : 0,
805
+ closeOnSelect: this.closeOnSelect != false && !this.useMultiCheckbxoes(),
806
+ placeholder: this.placeholder,
807
+ allowClear: this.placeholder != null && this.placeholder.length > 0,
808
+ multiple: this.multiselect == true,
809
+ dropdownAutoWidth: this.dropdownAutoWidth == true,
810
+ tags: this.tags == true,
811
+ data: opts,
812
+ language: {
813
+ noResults: function () {
814
+ if (self.noResultsFound != null) {
815
+ self.noResultsFound();
816
+ }
817
+
818
+ return PowerduckState.getResourceValue('noResultsFound');
819
+ },
820
+ },
821
+ };
822
+
823
+ var formatResult = this.getFormatResult();
824
+ if (formatResult != null) {
825
+ s2Args["templateResult"] = formatResult;
826
+ }
827
+
828
+ if (this.formatSelection != null) {
829
+ s2Args["templateSelection"] = this.formatSelection;
830
+ }
831
+
832
+ let modalContent = $(this.$el).closest(".modal-content");
833
+ if (modalContent.length > 0) {
834
+ s2Args["dropdownParent"] = modalContent;
835
+ }
836
+
837
+ let validTagsButtons = false;
838
+ let tagsTemplate = this.tagsTemplate;
839
+ if (this.tags == true && this.tagsAdded != null) {
840
+ s2Args["createTag"] = function (params) {
841
+ var term = $.trim(params.term);
842
+ if (term === "") {
843
+ return null;
844
+ }
845
+
846
+ return {
847
+ id: term,
848
+ text: term + self.getSelect2AddResource(),
849
+ newTag: true, // add additional parameters
850
+ };
851
+ };
852
+
853
+ if (this.tagsNewPlaceLast != false) {
854
+ s2Args["insertTag"] = function (data, tag) {
855
+ // Insert the tag at the end of the results
856
+ data.push(tag);
857
+ };
858
+ }
859
+
860
+ if (this.tagsButtons != null) {
861
+ if (tagsTemplate == null && this.tagsShouldPrependContent != false && this.formatSelection == null) {
862
+ validTagsButtons = true;
863
+ tagsTemplate =
864
+ '<li class="select2-selection__choice select2-selection__choice-with-button"><span class="select2-selection__choice__remove" role="presentation"><i class="fas fa-times"></i></span></li>';
865
+ s2Args["templateSelection"] = function (state): string | JQuery {
866
+ if (!state) return "";
867
+ if (!state.id) return state.text;
868
+
869
+ let dataItem = allOpts.filter((p) => p.id.toString() == state.id)[0];
870
+ if (dataItem == null) {
871
+ return state.text;
872
+ }
873
+
874
+ let builder =
875
+ '<span class="ddl-dropdown-resultroot"><span class="ddl-dropdown-resultwrap"><span class="ddl-result-text">' + PortalUtils.htmlEscape(dataItem.text) + "</span>";
876
+ (self.tagsButtons(dataItem) || ([] as DropdownListButton[])).forEach((button, i) => {
877
+ builder +=
878
+ '<span class="ddl-result-button dll-clickable-button ' +
879
+ button.cssClass +
880
+ '" data-index="' +
881
+ i +
882
+ '" role="presentation"><i class="' +
883
+ button.iconCss +
884
+ '"></i></span>';
885
+ });
886
+
887
+ return $(builder + "</span></span>");
888
+ };
889
+ } else {
890
+ console.log("Skipping tagsButtons - one of required conditions not met");
891
+ }
892
+ }
893
+ }
894
+
895
+ s2Elem[s2Constructor](s2Args);
896
+
897
+ if (this.containerCssClass?.length > 0) {
898
+ s2Elem.data('select2').$dropdown.addClass(this.containerCssClass);
899
+ }
900
+
901
+ if (s2Args.tags) {
902
+ if (!isNullOrEmpty(tagsTemplate)) {
903
+ DropdownSelect2Helper.getSelect2Instance(s2Elem).selection.selectionContainer = function () {
904
+ let retVal = $(tagsTemplate);
905
+ if (self.tagsShouldPrependContent != false) {
906
+ let oldAppend = retVal.append;
907
+ retVal.append = function (elem) {
908
+ retVal.prepend(elem);
909
+ retVal.append = oldAppend;
910
+ } as any;
911
+ }
912
+
913
+ return retVal;
914
+ };
915
+ }
916
+
917
+ if (this.tagsSortable == true) {
918
+ var ul = $(this.$el).find(".select2-container ul");
919
+ if (ul.length > 0) {
920
+ new Sortable(ul[0], {
921
+ animation: 150,
922
+ handle: ".select2-selection__choice",
923
+ onEnd: (evt) => {
924
+ const oldIndex = evt.oldIndex;
925
+ let newIndex = evt.newIndex;
926
+
927
+ if (newIndex > oldIndex) {
928
+ newIndex -= 1;
929
+ }
930
+
931
+ const sel = this.currentSelected as any[];
932
+ if (sel == null || sel[oldIndex] == null) {
933
+ return;
934
+ }
935
+
936
+ const clonedArr = [...sel];
937
+ const removedItems = clonedArr.splice(oldIndex, 1);
938
+ clonedArr.splice(newIndex, 0, removedItems[0]);
939
+ this.changed(clonedArr);
940
+ },
941
+ });
942
+ }
943
+ }
944
+
945
+ // var ul = selectElem.prev('.select2-container').first('ul');
946
+ // ul.sortable({
947
+ // placeholder: 'ui-state-highlight',
948
+ // items: 'li:not(.select2-search-field)',
949
+ // tolerance: 'pointer',
950
+ // stop: function () {
951
+ // onElementValueChange(element, valueAccessor, allBindingsAccessor, viewModel);
952
+ // }
953
+ // });
954
+ }
955
+
956
+ if (this.afterBound != null) {
957
+ this.afterBound(s2Elem, DropdownSelect2Helper.getSelect2Instance(s2Elem));
958
+ }
959
+
960
+ if (validTagsButtons) {
961
+ this.bindSelect2TagsButton(DropdownSelect2Helper.getSelect2Instance(s2Elem));
962
+ }
963
+
964
+ if (selected.length > 0) {
965
+ let selectedIds = selected.map((p) => p.id);
966
+ if (self.multiselect) {
967
+ s2Elem.val(selectedIds);
968
+ } else {
969
+ s2Elem.val(selectedIds[0]);
970
+ }
971
+ } else {
972
+ s2Elem.val(null);
973
+ s2Elem[s2Constructor]("val", "");
974
+ }
975
+
976
+ if (self.searchWasActive == true) {
977
+ self.searchWasActive = false;
978
+
979
+ this.$nextTick(() => {
980
+ setTimeout(() => {
981
+ this.focusSelect2Search();
982
+ }, 0);
983
+ });
984
+ }
985
+
986
+ self.skipChange = true;
987
+ s2Elem.trigger("change");
988
+ }
989
+ }
990
+
991
+ getSelect2RootElement(): JQuery<Element> {
992
+ return $(this.$el).find(".make-select2");
993
+ }
994
+
995
+ focusSelect2Search() {
996
+ $(this.$el).find(".select2-search__field").focus();
997
+ }
998
+
999
+ mounted() {
1000
+ this.currentSelected = this.selected;
1001
+ this.updateSelect2();
1002
+
1003
+ this.$nextTick(() => {
1004
+ this.setMobilePickerInputText(this.getSelectedItems());
1005
+ });
1006
+ }
1007
+
1008
+ @Watch("selected")
1009
+ updateValue() {
1010
+ this.currentSelected = this.selected;
1011
+ }
1012
+
1013
+ updated() {
1014
+ this.updateSelect2();
1015
+ }
1016
+
1017
+ beforeUnmount() {
1018
+ try {
1019
+ $(this.$el).find(".make-select2")["select2"]("destroy");
1020
+ } catch (e) { }
1021
+ }
1020
1022
  }
1021
1023
 
1022
1024
  const DropdownList = toNative(DropdownListComponent)