@visa/nova-angular
Version:
Visa Product Design System Nova Angular library
210 lines • 30.7 kB
JavaScript
/**
* Copyright (c) 2025 Visa, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**/
import { Injectable } from '@angular/core';
import { AppReadyService } from '../_utilities/services/app-stable-check.service';
import { ComboboxFilterType } from './combobox.constants';
import * as i0 from "@angular/core";
import * as i1 from "../_utilities/services/app-stable-check.service";
/**
* Service containing optional functions for the ComboboxDirective.
*/
export class ComboboxService {
constructor(appReadyService) {
this.appReadyService = appReadyService;
}
/**
* The closeMenuOnItemClick method automatically closes the menu when an item is selected. <br />
* To keep the menu open after an item is selected, you must provide <code>[closeOnClick]="false"</code> to the combobox component.
* @param combobox Combobox to apply behavior to.
*/
closeMenuOnItemClick(combobox) {
combobox.listbox?.listItems?.forEach((item) => {
item.clicked.subscribe(() => {
combobox.floatingContainer?.floatingUIService?.hidefloatingUI();
});
});
// subscribe to changes in items and apply service function to these items as well
combobox.listbox?.listItems?.changes.subscribe(() => {
combobox.listbox?.listItems.forEach((item) => {
item.clicked.subscribe(() => {
combobox.floatingContainer?.floatingUIService?.hidefloatingUI();
});
});
});
}
/**
* The selectHighlightedOnMenuClose method selects the last highlighted item when the menu is closed.
* This method is called by default within <code>autoSelectItem</code>. <br />
* @param combobox Combobox to apply behavior to.
*/
selectHighlightedOnMenuClose(combobox) {
combobox.floatingContainer?.floatingUIService?.isShownEmitter.subscribe((isShown) => {
if (!this.appReadyService.isBrowserAndDomAvailable())
return; // return if app is not ready to access nativeElement
if (!isShown && combobox._lastHighlightedOnClose !== null) {
combobox.selectItem(combobox._lastHighlightedOnClose);
}
});
}
/**
* The autoFilterDisplayedItems method automatically filters the items shown in the combobox on initial render.
* If the items displayed on page load are not the full list you want to filter, please use a different function. This method filters items based on selection and input value changes. <br />
* To access the filtered list of <code>ListboxItemsDirective[]</code>, subscribe to the <code>filteredListEmitter</code>.
* @param combobox Combobox to apply behavior to.
*/
autoFilterDisplayedItems(combobox) {
if (!combobox.input || !combobox.listbox)
return;
let filteredListItems = [];
// filter list with defaultValue
if (combobox.value) {
if (combobox.listbox?.multiselect) {
combobox.value['value'].forEach((selectedValue) => {
const selectedItem = combobox.initialListItems.find((item) => item.value === selectedValue);
if (selectedItem) {
filteredListItems.push(selectedItem);
// combobox._prevActiveItem = selectedItem;
}
});
// don't update list on initial render for multiselect, only on input
}
else {
const selectedItem = combobox.initialListItems.find((item) => item.value === combobox.value['value']);
if (selectedItem) {
filteredListItems.push(selectedItem);
combobox._prevActiveItem = selectedItem;
}
this.updateList(combobox, filteredListItems);
}
}
combobox.input.inputEvent.subscribe((value) => {
if (!this.appReadyService.isBrowserAndDomAvailable())
return; // return if app is not ready to access nativeElement
// input value
filteredListItems = [];
combobox.initialListItems.forEach((item) => {
if (item.el.nativeElement.innerText.trim().toLowerCase().includes(value.toLowerCase())) {
// keep item in list if it includes the input value
filteredListItems.push(item);
}
});
this.updateList(combobox, filteredListItems);
});
combobox.itemSelected.subscribe((value) => {
if (combobox.listbox?.multiselect) {
// reset list on multiselect when option is selected
filteredListItems = combobox.initialListItems;
// if (filteredListItems && filteredListItems.length > 0)
// combobox._prevActiveItem = filteredListItems[filteredListItems.length - 1];
}
else {
// listbox item value
filteredListItems = [];
const selectedItem = combobox.initialListItems.find((item) => value?.includes(item.value));
if (selectedItem) {
filteredListItems.push(selectedItem);
combobox._prevActiveItem = selectedItem;
}
if (selectedItem)
filteredListItems.push(selectedItem);
}
this.updateList(combobox, filteredListItems);
});
}
/**
* The autoFilterBasedOnList method filters items in the combobox based on a specified list, which can differ from the initial list rendered. <br />
* This method allows customization of the filtering criteria, enabling you to filter items based on properties such as id, label, value, etc. To access the filtered list, subscribe to <code>the filteredListEmitter</code>, which emits the filtered list in the same shape as <code>fullList</code>. <br />
* This method is recommended over <code>autoFilterDisplayedItems</code> and can achieve the same functionality by calling <code>autoFilterBasedOnList(combobox, list, 'label')</code>.
* @param combobox Combobox to apply filter function to.
* @param fullList Full list of items to filter.
* @param condition Condition on which to filter items in fullList (this would be a property you've provided to the items in fullList).
*/
autoFilterBasedOnList(combobox, fullList, condition) {
const listData = fullList;
let filteredData = fullList;
if (!combobox)
return;
combobox.filter.subscribe((filterEvent) => {
filteredData = [];
if (filterEvent.type === ComboboxFilterType.SELECTION) {
if (combobox.listbox?.multiselect) {
filteredData = listData;
// if (filteredData && filteredData.length > 0) combobox._prevActiveItem = filteredData[filteredData.length - 1];
}
else {
// if an item is selected, the list should only include that item
filteredData = listData?.filter((item) => item[condition].toLowerCase() == filterEvent.input.toLowerCase());
if (filteredData && filteredData.length === 1)
combobox._prevActiveItem = filteredData[0];
}
}
else if (filterEvent.type === ComboboxFilterType.INPUT) {
listData.forEach((item) => {
if (item[condition].toLowerCase().includes(filterEvent.input.toLowerCase()))
filteredData.push(item);
});
}
else if (filterEvent.type === ComboboxFilterType.RESET) {
filteredData = listData;
}
this.updateList(combobox, filteredData);
});
}
/**
* The updateList method updates the combobox component with the given filtered list items,
setting the active and highlighted index appropriately. <br />
* This method is called by default within <code>autoFilterDisplayedItems</code> and <code>autoFilterBasedOnList</code>.
* @param combobox Combobox to update.
* @param filteredListItems Filtered array of listbox items.
*/
updateList(combobox, filteredListItems) {
if (combobox.listbox?.multiselect) {
// reset multiselect keyboard traversal altogether
combobox._activeIndex = null;
combobox._highlightedIndex = null;
}
else if (combobox._prevActiveItem && filteredListItems.includes(combobox._prevActiveItem)) {
combobox._activeIndex = filteredListItems.findIndex((item) => item === combobox._prevActiveItem);
}
else {
combobox._activeIndex = null;
combobox._highlightedIndex = null;
}
combobox.filteredListEmitter.emit(filteredListItems);
}
/**
* The autoSelectItem method highlights the first list item based on user input. <br />
* This ensures that when the menu closes, if an input value was entered, an item is selected.
* @param combobox Combobox to apply automatic selection to.
*/
autoSelectItem(combobox) {
this.selectHighlightedOnMenuClose(combobox);
combobox.input?.inputEvent.subscribe(() => {
if (combobox.input.value)
combobox.highlightIndex(0);
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ComboboxService, deps: [{ token: i1.AppReadyService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ComboboxService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ComboboxService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: i1.AppReadyService }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tYm9ib3guc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL2xpYnMvbm92YS1saWIvc3JjL2xpYi9jb21ib2JveC9jb21ib2JveC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7SUFlSTtBQUNKLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGlEQUFpRCxDQUFDO0FBRWxGLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDOzs7QUFHMUQ7O0dBRUc7QUFJSCxNQUFNLE9BQU8sZUFBZTtJQUMxQixZQUFvQixlQUFnQztRQUFoQyxvQkFBZSxHQUFmLGVBQWUsQ0FBaUI7SUFBRyxDQUFDO0lBQ3hEOzs7O09BSUc7SUFDSCxvQkFBb0IsQ0FBQyxRQUEyQjtRQUM5QyxRQUFRLENBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUM1QyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7Z0JBQzFCLFFBQVEsQ0FBQyxpQkFBaUIsRUFBRSxpQkFBaUIsRUFBRSxjQUFjLEVBQUUsQ0FBQztZQUNsRSxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsa0ZBQWtGO1FBQ2xGLFFBQVEsQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQ2xELFFBQVEsQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO2dCQUMzQyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7b0JBQzFCLFFBQVEsQ0FBQyxpQkFBaUIsRUFBRSxpQkFBaUIsRUFBRSxjQUFjLEVBQUUsQ0FBQztn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TTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqICAgICAgICAgICAgICBDb3B5cmlnaHQgKGMpIDIwMjUgVmlzYSwgSW5jLlxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICoqL1xuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQXBwUmVhZHlTZXJ2aWNlIH0gZnJvbSAnLi4vX3V0aWxpdGllcy9zZXJ2aWNlcy9hcHAtc3RhYmxlLWNoZWNrLnNlcnZpY2UnO1xuaW1wb3J0IHsgTGlzdGJveEl0ZW1Db21wb25lbnQgfSBmcm9tICcuLi9saXN0Ym94LWl0ZW0vbGlzdGJveC1pdGVtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBDb21ib2JveEZpbHRlclR5cGUgfSBmcm9tICcuL2NvbWJvYm94LmNvbnN0YW50cyc7XG5pbXBvcnQgeyBDb21ib2JveERpcmVjdGl2ZSB9IGZyb20gJy4vY29tYm9ib3guZGlyZWN0aXZlJztcblxuLyoqXG4gKiBTZXJ2aWNlIGNvbnRhaW5pbmcgb3B0aW9uYWwgZnVuY3Rpb25zIGZvciB0aGUgQ29tYm9ib3hEaXJlY3RpdmUuXG4gKi9cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIENvbWJvYm94U2VydmljZSB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgYXBwUmVhZHlTZXJ2aWNlOiBBcHBSZWFkeVNlcnZpY2UpIHt9XG4gIC8qKlxuICAgKiBUaGXCoGNsb3NlTWVudU9uSXRlbUNsaWNrwqBtZXRob2QgYXV0b21hdGljYWxseSBjbG9zZXMgdGhlIG1lbnUgd2hlbiBhbiBpdGVtIGlzIHNlbGVjdGVkLiA8YnIgLz5cbiAgICogVG8ga2VlcCB0aGUgbWVudSBvcGVuIGFmdGVyIGFuIGl0ZW0gaXMgc2VsZWN0ZWQsIHlvdSBtdXN0IHByb3ZpZGUgPGNvZGU+W2Nsb3NlT25DbGlja109XCJmYWxzZVwiPC9jb2RlPiB0byB0aGUgY29tYm9ib3ggY29tcG9uZW50LlxuICAgKiBAcGFyYW0gY29tYm9ib3ggQ29tYm9ib3ggdG8gYXBwbHkgYmVoYXZpb3IgdG8uXG4gICAqL1xuICBjbG9zZU1lbnVPbkl0ZW1DbGljayhjb21ib2JveDogQ29tYm9ib3hEaXJlY3RpdmUpIHtcbiAgICBjb21ib2JveC5saXN0Ym94Py5saXN0SXRlbXM/LmZvckVhY2goKGl0ZW0pID0+IHtcbiAgICAgIGl0ZW0uY2xpY2tlZC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICBjb21ib2JveC5mbG9hdGluZ0NvbnRhaW5lcj8uZmxvYXRpbmdVSVNlcnZpY2U/LmhpZGVmbG9hdGluZ1VJKCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIHN1YnNjcmliZSB0byBjaGFuZ2VzIGluIGl0ZW1zIGFuZCBhcHBseSBzZXJ2aWNlIGZ1bmN0aW9uIHRvIHRoZXNlIGl0ZW1zIGFzIHdlbGxcbiAgICBjb21ib2JveC5saXN0Ym94Py5saXN0SXRlbXM/LmNoYW5nZXMuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIGNvbWJvYm94Lmxpc3Rib3g/Lmxpc3RJdGVtcy5mb3JFYWNoKChpdGVtKSA9PiB7XG4gICAgICAgIGl0ZW0uY2xpY2tlZC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgIGNvbWJvYm94LmZsb2F0aW5nQ29udGFpbmVyPy5mbG9hdGluZ1VJU2VydmljZT8uaGlkZWZsb2F0aW5nVUkoKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGXCoHNlbGVjdEhpZ2hsaWdodGVkT25NZW51Q2xvc2XCoG1ldGhvZCBzZWxlY3RzIHRoZSBsYXN0IGhpZ2hsaWdodGVkIGl0ZW0gd2hlbiB0aGUgbWVudSBpcyBjbG9zZWQuXG4gICAqIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCBieSBkZWZhdWx0IHdpdGhpbiA8Y29kZT5hdXRvU2VsZWN0SXRlbTwvY29kZT4uIDxiciAvPlxuICAgKiBAcGFyYW0gY29tYm9ib3ggQ29tYm9ib3ggdG8gYXBwbHkgYmVoYXZpb3IgdG8uXG4gICAqL1xuICBzZWxlY3RIaWdobGlnaHRlZE9uTWVudUNsb3NlKGNvbWJvYm94OiBDb21ib2JveERpcmVjdGl2ZSkge1xuICAgIGNvbWJvYm94LmZsb2F0aW5nQ29udGFpbmVyPy5mbG9hdGluZ1VJU2VydmljZT8uaXNTaG93bkVtaXR0ZXIuc3Vic2NyaWJlKChpc1Nob3duKSA9PiB7XG4gICAgICBpZiAoIXRoaXMuYXBwUmVhZHlTZXJ2aWNlLmlzQnJvd3NlckFuZERvbUF2YWlsYWJsZSgpKSByZXR1cm47IC8vIHJldHVybiBpZiBhcHAgaXMgbm90IHJlYWR5IHRvIGFjY2VzcyBuYXRpdmVFbGVtZW50XG4gICAgICBpZiAoIWlzU2hvd24gJiYgY29tYm9ib3guX2xhc3RIaWdobGlnaHRlZE9uQ2xvc2UgIT09IG51bGwpIHtcbiAgICAgICAgY29tYm9ib3guc2VsZWN0SXRlbShjb21ib2JveC5fbGFzdEhpZ2hsaWdodGVkT25DbG9zZSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlwqBhdXRvRmlsdGVyRGlzcGxheWVkSXRlbXPCoG1ldGhvZCBhdXRvbWF0aWNhbGx5IGZpbHRlcnMgdGhlIGl0ZW1zIHNob3duIGluIHRoZSBjb21ib2JveCBvbiBpbml0aWFsIHJlbmRlci5cbiAgICogSWYgdGhlIGl0ZW1zIGRpc3BsYXllZCBvbiBwYWdlIGxvYWQgYXJlIG5vdCB0aGUgZnVsbCBsaXN0IHlvdSB3YW50IHRvIGZpbHRlciwgcGxlYXNlIHVzZSBhIGRpZmZlcmVudCBmdW5jdGlvbi4gVGhpcyBtZXRob2QgZmlsdGVycyBpdGVtcyBiYXNlZCBvbiBzZWxlY3Rpb24gYW5kIGlucHV0IHZhbHVlIGNoYW5nZXMuIDxiciAvPlxuICAgKiBUbyBhY2Nlc3MgdGhlIGZpbHRlcmVkIGxpc3Qgb2bCoDxjb2RlPkxpc3Rib3hJdGVtc0RpcmVjdGl2ZVtdPC9jb2RlPiwgc3Vic2NyaWJlIHRvIHRoZSA8Y29kZT5maWx0ZXJlZExpc3RFbWl0dGVyPC9jb2RlPi5cbiAgICogQHBhcmFtIGNvbWJvYm94IENvbWJvYm94IHRvIGFwcGx5IGJlaGF2aW9yIHRvLlxuICAgKi9cbiAgYXV0b0ZpbHRlckRpc3BsYXllZEl0ZW1zKGNvbWJvYm94OiBDb21ib2JveERpcmVjdGl2ZSkge1xuICAgIGlmICghY29tYm9ib3guaW5wdXQgfHwgIWNvbWJvYm94Lmxpc3Rib3gpIHJldHVybjtcbiAgICBsZXQgZmlsdGVyZWRMaXN0SXRlbXM6IExpc3Rib3hJdGVtQ29tcG9uZW50W10gPSBbXTtcblxuICAgIC8vIGZpbHRlciBsaXN0IHdpdGggZGVmYXVsdFZhbHVlXG4gICAgaWYgKGNvbWJvYm94LnZhbHVlKSB7XG4gICAgICBpZiAoY29tYm9ib3gubGlzdGJveD8ubXVsdGlzZWxlY3QpIHtcbiAgICAgICAgY29tYm9ib3gudmFsdWVbJ3ZhbHVlJ10uZm9yRWFjaCgoc2VsZWN0ZWRWYWx1ZTogc3RyaW5nIHwgbnVtYmVyKSA9PiB7XG4gICAgICAgICAgY29uc3Qgc2VsZWN0ZWRJdGVtID0gY29tYm9ib3guaW5pdGlhbExpc3RJdGVtcy5maW5kKChpdGVtKSA9PiBpdGVtLnZhbHVlID09PSBzZWxlY3RlZFZhbHVlKTtcbiAgICAgICAgICBpZiAoc2VsZWN0ZWRJdGVtKSB7XG4gICAgICAgICAgICBmaWx0ZXJlZExpc3RJdGVtcy5wdXNoKHNlbGVjdGVkSXRlbSk7XG4gICAgICAgICAgICAvLyBjb21ib2JveC5fcHJldkFjdGl2ZUl0ZW0gPSBzZWxlY3RlZEl0ZW07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgLy8gZG9uJ3QgdXBkYXRlIGxpc3Qgb24gaW5pdGlhbCByZW5kZXIgZm9yIG11bHRpc2VsZWN0LCBvbmx5IG9uIGlucHV0XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBzZWxlY3RlZEl0ZW0gPSBjb21ib2JveC5pbml0aWFsTGlzdEl0ZW1zLmZpbmQoKGl0ZW0pID0+IGl0ZW0udmFsdWUgPT09IGNvbWJvYm94LnZhbHVlWyd2YWx1ZSddKTtcbiAgICAgICAgaWYgKHNlbGVjdGVkSXRlbSkge1xuICAgICAgICAgIGZpbHRlcmVkTGlzdEl0ZW1zLnB1c2goc2VsZWN0ZWRJdGVtKTtcbiAgICAgICAgICBjb21ib2JveC5fcHJldkFjdGl2ZUl0ZW0gPSBzZWxlY3RlZEl0ZW07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51cGRhdGVMaXN0KGNvbWJvYm94LCBmaWx0ZXJlZExpc3RJdGVtcyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29tYm9ib3guaW5wdXQuaW5wdXRFdmVudC5zdWJzY3JpYmUoKHZhbHVlKSA9PiB7XG4gICAgICBpZiAoIXRoaXMuYXBwUmVhZHlTZXJ2aWNlLmlzQnJvd3NlckFuZERvbUF2YWlsYWJsZSgpKSByZXR1cm47IC8vIHJldHVybiBpZiBhcHAgaXMgbm90IHJlYWR5IHRvIGFjY2VzcyBuYXRpdmVFbGVtZW50XG4gICAgICAvLyBpbnB1dCB2YWx1ZVxuICAgICAgZmlsdGVyZWRMaXN0SXRlbXMgPSBbXTtcbiAgICAgIGNvbWJvYm94LmluaXRpYWxMaXN0SXRlbXMuZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICBpZiAoaXRlbS5lbC5uYXRpdmVFbGVtZW50LmlubmVyVGV4dC50cmltKCkudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh2YWx1ZS50b0xvd2VyQ2FzZSgpKSkge1xuICAgICAgICAgIC8vIGtlZXAgaXRlbSBpbiBsaXN0IGlmIGl0IGluY2x1ZGVzIHRoZSBpbnB1dCB2YWx1ZVxuICAgICAgICAgIGZpbHRlcmVkTGlzdEl0ZW1zLnB1c2goaXRlbSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgdGhpcy51cGRhdGVMaXN0KGNvbWJvYm94LCBmaWx0ZXJlZExpc3RJdGVtcyk7XG4gICAgfSk7XG5cbiAgICBjb21ib2JveC5pdGVtU2VsZWN0ZWQuc3Vic2NyaWJlKCh2YWx1ZSkgPT4ge1xuICAgICAgaWYgKGNvbWJvYm94Lmxpc3Rib3g/Lm11bHRpc2VsZWN0KSB7XG4gICAgICAgIC8vIHJlc2V0IGxpc3Qgb24gbXVsdGlzZWxlY3Qgd2hlbiBvcHRpb24gaXMgc2VsZWN0ZWRcbiAgICAgICAgZmlsdGVyZWRMaXN0SXRlbXMgPSBjb21ib2JveC5pbml0aWFsTGlzdEl0ZW1zO1xuICAgICAgICAvLyBpZiAoZmlsdGVyZWRMaXN0SXRlbXMgJiYgZmlsdGVyZWRMaXN0SXRlbXMubGVuZ3RoID4gMClcbiAgICAgICAgLy8gICBjb21ib2JveC5fcHJldkFjdGl2ZUl0ZW0gPSBmaWx0ZXJlZExpc3RJdGVtc1tmaWx0ZXJlZExpc3RJdGVtcy5sZW5ndGggLSAxXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGxpc3Rib3ggaXRlbSB2YWx1ZVxuICAgICAgICBmaWx0ZXJlZExpc3RJdGVtcyA9IFtdO1xuICAgICAgICBjb25zdCBzZWxlY3RlZEl0ZW0gPSBjb21ib2JveC5pbml0aWFsTGlzdEl0ZW1zLmZpbmQoKGl0ZW0pID0+XG4gICAgICAgICAgKHZhbHVlIGFzIChzdHJpbmcgfCBudW1iZXIpW10pPy5pbmNsdWRlcyhpdGVtLnZhbHVlKVxuICAgICAgICApO1xuICAgICAgICBpZiAoc2VsZWN0ZWRJdGVtKSB7XG4gICAgICAgICAgZmlsdGVyZWRMaXN0SXRlbXMucHVzaChzZWxlY3RlZEl0ZW0pO1xuICAgICAgICAgIGNvbWJvYm94Ll9wcmV2QWN0aXZlSXRlbSA9IHNlbGVjdGVkSXRlbTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2VsZWN0ZWRJdGVtKSBmaWx0ZXJlZExpc3RJdGVtcy5wdXNoKHNlbGVjdGVkSXRlbSk7XG4gICAgICB9XG4gICAgICB0aGlzLnVwZGF0ZUxpc3QoY29tYm9ib3gsIGZpbHRlcmVkTGlzdEl0ZW1zKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGXCoGF1dG9GaWx0ZXJCYXNlZE9uTGlzdMKgbWV0aG9kIGZpbHRlcnMgaXRlbXMgaW4gdGhlIGNvbWJvYm94IGJhc2VkIG9uIGEgc3BlY2lmaWVkIGxpc3QsIHdoaWNoIGNhbiBkaWZmZXIgZnJvbSB0aGUgaW5pdGlhbCBsaXN0IHJlbmRlcmVkLiA8YnIgLz5cbiAgICogVGhpcyBtZXRob2QgYWxsb3dzIGN1c3RvbWl6YXRpb24gb2YgdGhlIGZpbHRlcmluZyBjcml0ZXJpYSwgZW5hYmxpbmcgeW91IHRvIGZpbHRlciBpdGVtcyBiYXNlZCBvbiBwcm9wZXJ0aWVzIHN1Y2ggYXMgaWQsIGxhYmVsLCB2YWx1ZSwgZXRjLiBUbyBhY2Nlc3MgdGhlIGZpbHRlcmVkIGxpc3QsIHN1YnNjcmliZSB0byA8Y29kZT50aGXCoGZpbHRlcmVkTGlzdEVtaXR0ZXI8L2NvZGU+LCB3aGljaCBlbWl0cyB0aGUgZmlsdGVyZWQgbGlzdCBpbiB0aGUgc2FtZSBzaGFwZSBhcyA8Y29kZT5mdWxsTGlzdDwvY29kZT4uIDxiciAvPlxuICAgKiBUaGlzIG1ldGhvZCBpcyByZWNvbW1lbmRlZCBvdmVyIDxjb2RlPmF1dG9GaWx0ZXJEaXNwbGF5ZWRJdGVtczwvY29kZT4gYW5kIGNhbiBhY2hpZXZlIHRoZSBzYW1lIGZ1bmN0aW9uYWxpdHkgYnkgY2FsbGluZyA8Y29kZT5hdXRvRmlsdGVyQmFzZWRPbkxpc3QoY29tYm9ib3gsIGxpc3QsICdsYWJlbCcpPC9jb2RlPi5cbiAgICogQHBhcmFtIGNvbWJvYm94IENvbWJvYm94IHRvIGFwcGx5IGZpbHRlciBmdW5jdGlvbiB0by5cbiAgICogQHBhcmFtIGZ1bGxMaXN0IEZ1bGwgbGlzdCBvZiBpdGVtcyB0byBmaWx0ZXIuXG4gICAqIEBwYXJhbSBjb25kaXRpb24gQ29uZGl0aW9uIG9uIHdoaWNoIHRvIGZpbHRlciBpdGVtcyBpbiBmdWxsTGlzdCAodGhpcyB3b3VsZCBiZSBhIHByb3BlcnR5IHlvdSd2ZSBwcm92aWRlZCB0byB0aGUgaXRlbXMgaW4gZnVsbExpc3QpLlxuICAgKi9cbiAgYXV0b0ZpbHRlckJhc2VkT25MaXN0KGNvbWJvYm94OiBDb21ib2JveERpcmVjdGl2ZSwgZnVsbExpc3Q6IGFueVtdLCBjb25kaXRpb246IHN0cmluZykge1xuICAgIGNvbnN0IGxpc3REYXRhID0gZnVsbExpc3Q7XG4gICAgbGV0IGZpbHRlcmVkRGF0YTogYW55W10gPSBmdWxsTGlzdDtcblxuICAgIGlmICghY29tYm9ib3gpIHJldHVybjtcblxuICAgIGNvbWJvYm94LmZpbHRlci5zdWJzY3JpYmUoKGZpbHRlckV2ZW50KSA9PiB7XG4gICAgICBmaWx0ZXJlZERhdGEgPSBbXTtcbiAgICAgIGlmIChmaWx0ZXJFdmVudC50eXBlID09PSBDb21ib2JveEZpbHRlclR5cGUuU0VMRUNUSU9OKSB7XG4gICAgICAgIGlmIChjb21ib2JveC5saXN0Ym94Py5tdWx0aXNlbGVjdCkge1xuICAgICAgICAgIGZpbHRlcmVkRGF0YSA9IGxpc3REYXRhO1xuICAgICAgICAgIC8vIGlmIChmaWx0ZXJlZERhdGEgJiYgZmlsdGVyZWREYXRhLmxlbmd0aCA+IDApIGNvbWJvYm94Ll9wcmV2QWN0aXZlSXRlbSA9IGZpbHRlcmVkRGF0YVtmaWx0ZXJlZERhdGEubGVuZ3RoIC0gMV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gaWYgYW4gaXRlbSBpcyBzZWxlY3RlZCwgdGhlIGxpc3Qgc2hvdWxkIG9ubHkgaW5jbHVkZSB0aGF0IGl0ZW1cbiAgICAgICAgICBmaWx0ZXJlZERhdGEgPSBsaXN0RGF0YT8uZmlsdGVyKChpdGVtKSA9PiBpdGVtW2NvbmRpdGlvbl0udG9Mb3dlckNhc2UoKSA9PSBmaWx0ZXJFdmVudC5pbnB1dC50b0xvd2VyQ2FzZSgpKTtcbiAgICAgICAgICBpZiAoZmlsdGVyZWREYXRhICYmIGZpbHRlcmVkRGF0YS5sZW5ndGggPT09IDEpIGNvbWJvYm94Ll9wcmV2QWN0aXZlSXRlbSA9IGZpbHRlcmVkRGF0YVswXTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChmaWx0ZXJFdmVudC50eXBlID09PSBDb21ib2JveEZpbHRlclR5cGUuSU5QVVQpIHtcbiAgICAgICAgbGlzdERhdGEuZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICAgIGlmIChpdGVtW2NvbmRpdGlvbl0udG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhmaWx0ZXJFdmVudC5pbnB1dC50b0xvd2VyQ2FzZSgpKSkgZmlsdGVyZWREYXRhLnB1c2goaXRlbSk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmIChmaWx0ZXJFdmVudC50eXBlID09PSBDb21ib2JveEZpbHRlclR5cGUuUkVTRVQpIHtcbiAgICAgICAgZmlsdGVyZWREYXRhID0gbGlzdERhdGE7XG4gICAgICB9XG4gICAgICB0aGlzLnVwZGF0ZUxpc3QoY29tYm9ib3gsIGZpbHRlcmVkRGF0YSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlwqB1cGRhdGVMaXN0wqBtZXRob2QgdXBkYXRlcyB0aGUgY29tYm9ib3ggY29tcG9uZW50IHdpdGggdGhlIGdpdmVuIGZpbHRlcmVkIGxpc3QgaXRlbXMsXG4gICBzZXR0aW5nIHRoZSBhY3RpdmUgYW5kIGhpZ2hsaWdodGVkIGluZGV4IGFwcHJvcHJpYXRlbHkuIDxiciAvPlxuICAgKiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgYnkgZGVmYXVsdCB3aXRoaW4gPGNvZGU+YXV0b0ZpbHRlckRpc3BsYXllZEl0ZW1zPC9jb2RlPiBhbmQgPGNvZGU+YXV0b0ZpbHRlckJhc2VkT25MaXN0PC9jb2RlPi5cbiAgICogQHBhcmFtIGNvbWJvYm94IENvbWJvYm94IHRvIHVwZGF0ZS5cbiAgICogQHBhcmFtIGZpbHRlcmVkTGlzdEl0ZW1zIEZpbHRlcmVkIGFycmF5IG9mIGxpc3Rib3ggaXRlbXMuXG4gICAqL1xuICB1cGRhdGVMaXN0KGNvbWJvYm94OiBDb21ib2JveERpcmVjdGl2ZSwgZmlsdGVyZWRMaXN0SXRlbXM6IExpc3Rib3hJdGVtQ29tcG9uZW50W10pIHtcbiAgICBpZiAoY29tYm9ib3gubGlzdGJveD8ubXVsdGlzZWxlY3QpIHtcbiAgICAgIC8vIHJlc2V0IG11bHRpc2VsZWN0IGtleWJvYXJkIHRyYXZlcnNhbCBhbHRvZ2V0aGVyXG4gICAgICBjb21ib2JveC5fYWN0aXZlSW5kZXggPSBudWxsO1xuICAgICAgY29tYm9ib3guX2hpZ2hsaWdodGVkSW5kZXggPSBudWxsO1xuICAgIH0gZWxzZSBpZiAoY29tYm9ib3guX3ByZXZBY3RpdmVJdGVtICYmIGZpbHRlcmVkTGlzdEl0ZW1zLmluY2x1ZGVzKGNvbWJvYm94Ll9wcmV2QWN0aXZlSXRlbSkpIHtcbiAgICAgIGNvbWJvYm94Ll9hY3RpdmVJbmRleCA9IGZpbHRlcmVkTGlzdEl0ZW1zLmZpbmRJbmRleCgoaXRlbSkgPT4gaXRlbSA9PT0gY29tYm9ib3guX3ByZXZBY3RpdmVJdGVtKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29tYm9ib3guX2FjdGl2ZUluZGV4ID0gbnVsbDtcbiAgICAgIGNvbWJvYm94Ll9oaWdobGlnaHRlZEluZGV4ID0gbnVsbDtcbiAgICB9XG5cbiAgICBjb21ib2JveC5maWx0ZXJlZExpc3RFbWl0dGVyLmVtaXQoZmlsdGVyZWRMaXN0SXRlbXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZcKgYXV0b1NlbGVjdEl0ZW3CoG1ldGhvZCBoaWdobGlnaHRzIHRoZSBmaXJzdCBsaXN0IGl0ZW0gYmFzZWQgb24gdXNlciBpbnB1dC4gPGJyIC8+XG4gICAqIFRoaXMgZW5zdXJlcyB0aGF0IHdoZW4gdGhlIG1lbnUgY2xvc2VzLCBpZiBhbiBpbnB1dCB2YWx1ZSB3YXMgZW50ZXJlZCwgYW4gaXRlbSBpcyBzZWxlY3RlZC5cbiAgICogQHBhcmFtIGNvbWJvYm94IENvbWJvYm94IHRvIGFwcGx5IGF1dG9tYXRpYyBzZWxlY3Rpb24gdG8uXG4gICAqL1xuICBhdXRvU2VsZWN0SXRlbShjb21ib2JveDogQ29tYm9ib3hEaXJlY3RpdmUpIHtcbiAgICB0aGlzLnNlbGVjdEhpZ2hsaWdodGVkT25NZW51Q2xvc2UoY29tYm9ib3gpO1xuXG4gICAgY29tYm9ib3guaW5wdXQ/LmlucHV0RXZlbnQuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIGlmIChjb21ib2JveC5pbnB1dC52YWx1ZSkgY29tYm9ib3guaGlnaGxpZ2h0SW5kZXgoMCk7XG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==