UNPKG

carbon-components-angular

Version:
128 lines 19.5 kB
import { Injectable } from "@angular/core"; import { Subscription } from "rxjs"; import { position } from "@carbon/utils-position"; import { closestAttr } from "carbon-components-angular/utils"; import * as i0 from "@angular/core"; import * as i1 from "carbon-components-angular/placeholder"; import * as i2 from "carbon-components-angular/utils"; const defaultOffset = { top: 0, left: 0 }; export class DropdownService { constructor(placeholderService, animationFrameService) { this.placeholderService = placeholderService; this.animationFrameService = animationFrameService; /** * Maintains an Event Observable Subscription for the global requestAnimationFrame. * requestAnimationFrame is tracked only if the `Dropdown` is appended to the body otherwise we don't need it */ this.animationFrameSubscription = new Subscription(); this._offset = defaultOffset; } set offset(value) { this._offset = Object.assign({}, defaultOffset, value); } get offset() { return this._offset; } /** * Appends the menu to the body, or a `cds-placeholder` (if defined) * * @param parentRef container to position relative to * @param menuRef menu to be appended to body * @param classList any extra classes we should wrap the container with */ appendToBody(parentRef, menuRef, classList) { // build the dropdown list container menuRef.style.display = "block"; const dropdownWrapper = document.createElement("div"); dropdownWrapper.className = `dropdown ${classList}`; dropdownWrapper.style.width = parentRef.offsetWidth + "px"; dropdownWrapper.style.position = "absolute"; dropdownWrapper.appendChild(menuRef); // append it to the placeholder if (this.placeholderService.hasPlaceholderRef()) { this.placeholderService.appendElement(dropdownWrapper); // or append it directly to the body } else { document.body.appendChild(dropdownWrapper); } this.menuInstance = dropdownWrapper; this.animationFrameSubscription = this.animationFrameService.tick.subscribe(() => { this.positionDropdown(parentRef, dropdownWrapper); }); // run one position in sync, so we're less likely to have the view "jump" as we focus this.positionDropdown(parentRef, dropdownWrapper); return dropdownWrapper; } /** * Reattach the dropdown menu to the parent container * @param hostRef container to append to */ appendToDropdown(hostRef) { // if the instance is already removed don't try and remove it again if (!this.menuInstance) { return; } const instance = this.menuInstance; const menu = instance.firstElementChild; // clean up the instance this.menuInstance = null; menu.style.display = "none"; hostRef.appendChild(menu); this.animationFrameSubscription.unsubscribe(); if (this.placeholderService.hasPlaceholderRef() && this.placeholderService.hasElement(instance)) { this.placeholderService.removeElement(instance); } else if (document.body.contains(instance)) { document.body.removeChild(instance); } return instance; } /** * position an open dropdown relative to the given parentRef */ updatePosition(parentRef) { this.positionDropdown(parentRef, this.menuInstance); } ngOnDestroy() { this.animationFrameSubscription.unsubscribe(); } positionDropdown(parentRef, menuRef) { if (!menuRef) { return; } let leftOffset = 0; const boxMenu = menuRef.querySelector(".cds--list-box__menu"); if (boxMenu) { // If the parentRef and boxMenu are in a different left position relative to the // window, the the boxMenu position has already been flipped and a check needs to be done // to see if it needs to stay flipped. if (parentRef.getBoundingClientRect().left !== boxMenu.getBoundingClientRect().left) { // The getBoundingClientRect().right of the boxMenu if it were hypothetically flipped // back into the original position before the flip. const testBoxMenuRightEdgePos = parentRef.getBoundingClientRect().left - boxMenu.getBoundingClientRect().left + boxMenu.getBoundingClientRect().right; if (testBoxMenuRightEdgePos > (window.innerWidth || document.documentElement.clientWidth)) { leftOffset = parentRef.offsetWidth - boxMenu.offsetWidth; } // If it has not already been flipped, check if it is necessary to flip, ie. if the // boxMenu is outside of the right viewPort. } else if (boxMenu.getBoundingClientRect().right > (window.innerWidth || document.documentElement.clientWidth)) { leftOffset = parentRef.offsetWidth - boxMenu.offsetWidth; } } // If cds-placeholder has a parent with a position(relative|fixed|absolute) account for the parent offset const closestMenuWithPos = closestAttr("position", ["relative", "fixed", "absolute"], menuRef.parentElement); const topPos = closestMenuWithPos ? closestMenuWithPos.getBoundingClientRect().top * -1 : this.offset.top; const leftPos = closestMenuWithPos ? closestMenuWithPos.getBoundingClientRect().left * -1 : this.offset.left + leftOffset; let pos = position.findAbsolute(parentRef, menuRef, "bottom"); pos = position.addOffset(pos, topPos, leftPos); position.setElement(menuRef, pos); } } DropdownService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DropdownService, deps: [{ token: i1.PlaceholderService }, { token: i2.AnimationFrameService }], target: i0.ɵɵFactoryTarget.Injectable }); DropdownService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DropdownService }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DropdownService, decorators: [{ type: Injectable }], ctorParameters: function () { return [{ type: i1.PlaceholderService }, { type: i2.AnimationFrameService }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJvcGRvd24uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kcm9wZG93bi9kcm9wZG93bi5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQXlCLE1BQU0sZUFBZSxDQUFDO0FBRWxFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDcEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRWxELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQzs7OztBQUU5RCxNQUFNLGFBQWEsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO0FBRzFDLE1BQU0sT0FBTyxlQUFlO0lBcUIzQixZQUNXLGtCQUFzQyxFQUN0QyxxQkFBNEM7UUFENUMsdUJBQWtCLEdBQWxCLGtCQUFrQixDQUFvQjtRQUN0QywwQkFBcUIsR0FBckIscUJBQXFCLENBQXVCO1FBVnZEOzs7V0FHRztRQUNPLCtCQUEwQixHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFFaEQsWUFBTyxHQUFHLGFBQWEsQ0FBQztJQUsvQixDQUFDO0lBdkJKLElBQVcsTUFBTSxDQUFDLEtBQXNDO1FBQ3ZELElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsYUFBYSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFFRCxJQUFXLE1BQU07UUFDaEIsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQ3JCLENBQUM7SUFtQkQ7Ozs7OztPQU1HO0lBQ0gsWUFBWSxDQUFDLFNBQXNCLEVBQUUsT0FBb0IsRUFBRSxTQUFTO1FBQ25FLG9DQUFvQztRQUNwQyxPQUFPLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDaEMsTUFBTSxlQUFlLEdBQUcsUUFB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SSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksR0FBRyxVQUFVLENBQUM7UUFFMUgsSUFBSSxHQUFHLEdBQUcsUUFBUSxDQUFDLFlBQVksQ0FBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQzlELEdBQUcsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFL0MsUUFBUSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDbkMsQ0FBQzs7NEdBcklXLGVBQWU7Z0hBQWYsZUFBZTsyRkFBZixlQUFlO2tCQUQzQixVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgRWxlbWVudFJlZiwgT25EZXN0cm95IH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IFBsYWNlaG9sZGVyU2VydmljZSB9IGZyb20gXCJjYXJib24tY29tcG9uZW50cy1hbmd1bGFyL3BsYWNlaG9sZGVyXCI7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tIFwicnhqc1wiO1xuaW1wb3J0IHsgcG9zaXRpb24gfSBmcm9tIFwiQGNhcmJvbi91dGlscy1wb3NpdGlvblwiO1xuaW1wb3J0IHsgQW5pbWF0aW9uRnJhbWVTZXJ2aWNlIH0gZnJvbSBcImNhcmJvbi1jb21wb25lbnRzLWFuZ3VsYXIvdXRpbHNcIjtcbmltcG9ydCB7IGNsb3Nlc3RBdHRyIH0gZnJvbSBcImNhcmJvbi1jb21wb25lbnRzLWFuZ3VsYXIvdXRpbHNcIjtcblxuY29uc3QgZGVmYXVsdE9mZnNldCA9IHsgdG9wOiAwLCBsZWZ0OiAwIH07XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBEcm9wZG93blNlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuXHRwdWJsaWMgc2V0IG9mZnNldCh2YWx1ZTogeyB0b3A/OiBudW1iZXIsIGxlZnQ/OiBudW1iZXIgfSkge1xuXHRcdHRoaXMuX29mZnNldCA9IE9iamVjdC5hc3NpZ24oe30sIGRlZmF1bHRPZmZzZXQsIHZhbHVlKTtcblx0fVxuXG5cdHB1YmxpYyBnZXQgb2Zmc2V0KCkge1xuXHRcdHJldHVybiB0aGlzLl9vZmZzZXQ7XG5cdH1cblx0LyoqXG5cdCAqIHJlZmVyZW5jZSB0byB0aGUgYm9keSBhcHBlbmRlZCBtZW51XG5cdCAqL1xuXHRwcm90ZWN0ZWQgbWVudUluc3RhbmNlOiBIVE1MRWxlbWVudDtcblxuXHQvKipcblx0ICogTWFpbnRhaW5zIGFuIEV2ZW50IE9ic2VydmFibGUgU3Vic2NyaXB0aW9uIGZvciB0aGUgZ2xvYmFsIHJlcXVlc3RBbmltYXRpb25GcmFtZS5cblx0ICogcmVxdWVzdEFuaW1hdGlvbkZyYW1lIGlzIHRyYWNrZWQgb25seSBpZiB0aGUgYERyb3Bkb3duYCBpcyBhcHBlbmRlZCB0byB0aGUgYm9keSBvdGhlcndpc2Ugd2UgZG9uJ3QgbmVlZCBpdFxuXHQgKi9cblx0cHJvdGVjdGVkIGFuaW1hdGlvbkZyYW1lU3Vic2NyaXB0aW9uID0gbmV3IFN1YnNjcmlwdGlvbigpO1xuXG5cdHByb3RlY3RlZCBfb2Zmc2V0ID0gZGVmYXVsdE9mZnNldDtcblxuXHRjb25zdHJ1Y3Rvcihcblx0XHRwcm90ZWN0ZWQgcGxhY2Vob2xkZXJTZXJ2aWNlOiBQbGFjZWhvbGRlclNlcnZpY2UsXG5cdFx0cHJvdGVjdGVkIGFuaW1hdGlvbkZyYW1lU2VydmljZTogQW5pbWF0aW9uRnJhbWVTZXJ2aWNlXG5cdCkge31cblxuXHQvKipcblx0ICogQXBwZW5kcyB0aGUgbWVudSB0byB0aGUgYm9keSwgb3IgYSBgY2RzLXBsYWNlaG9sZGVyYCAoaWYgZGVmaW5lZClcblx0ICpcblx0ICogQHBhcmFtIHBhcmVudFJlZiBjb250YWluZXIgdG8gcG9zaXRpb24gcmVsYXRpdmUgdG9cblx0ICogQHBhcmFtIG1lbnVSZWYgbWVudSB0byBiZSBhcHBlbmRlZCB0byBib2R5XG5cdCAqIEBwYXJhbSBjbGFzc0xpc3QgYW55IGV4dHJhIGNsYXNzZXMgd2Ugc2hvdWxkIHdyYXAgdGhlIGNvbnRhaW5lciB3aXRoXG5cdCAqL1xuXHRhcHBlbmRUb0JvZHkocGFyZW50UmVmOiBIVE1MRWxlbWVudCwgbWVudVJlZjogSFRNTEVsZW1lbnQsIGNsYXNzTGlzdCk6IEhUTUxFbGVtZW50IHtcblx0XHQvLyBidWlsZCB0aGUgZHJvcGRvd24gbGlzdCBjb250YWluZXJcblx0XHRtZW51UmVmLnN0eWxlLmRpc3BsYXkgPSBcImJsb2NrXCI7XG5cdFx0Y29uc3QgZHJvcGRvd25XcmFwcGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcblx0XHRkcm9wZG93bldyYXBwZXIuY2xhc3NOYW1lID0gYGRyb3Bkb3duICR7Y2xhc3NMaXN0fWA7XG5cdFx0ZHJvcGRvd25XcmFwcGVyLnN0eWxlLndpZHRoID0gcGFyZW50UmVmLm9mZnNldFdpZHRoICsgXCJweFwiO1xuXHRcdGRyb3Bkb3duV3JhcHBlci5zdHlsZS5wb3NpdGlvbiA9IFwiYWJzb2x1dGVcIjtcblx0XHRkcm9wZG93bldyYXBwZXIuYXBwZW5kQ2hpbGQobWVudVJlZik7XG5cblx0XHQvLyBhcHBlbmQgaXQgdG8gdGhlIHBsYWNlaG9sZGVyXG5cdFx0aWYgKHRoaXMucGxhY2Vob2xkZXJTZXJ2aWNlLmhhc1BsYWNlaG9sZGVyUmVmKCkpIHtcblx0XHRcdHRoaXMucGxhY2Vob2xkZXJTZXJ2aWNlLmFwcGVuZEVsZW1lbnQoZHJvcGRvd25XcmFwcGVyKTtcblx0XHRcdC8vIG9yIGFwcGVuZCBpdCBkaXJlY3RseSB0byB0aGUgYm9keVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGRyb3Bkb3duV3JhcHBlcik7XG5cdFx0fVxuXG5cdFx0dGhpcy5tZW51SW5zdGFuY2UgPSBkcm9wZG93bldyYXBwZXI7XG5cblx0XHR0aGlzLmFuaW1hdGlvbkZyYW1lU3Vic2NyaXB0aW9uID0gdGhpcy5hbmltYXRpb25GcmFtZVNlcnZpY2UudGljay5zdWJzY3JpYmUoKCkgPT4ge1xuXHRcdFx0dGhpcy5wb3NpdGlvbkRyb3Bkb3duKHBhcmVudFJlZiwgZHJvcGRvd25XcmFwcGVyKTtcblx0XHR9KTtcblxuXHRcdC8vIHJ1biBvbmUgcG9zaXRpb24gaW4gc3luYywgc28gd2UncmUgbGVzcyBsaWtlbHkgdG8gaGF2ZSB0aGUgdmlldyBcImp1bXBcIiBhcyB3ZSBmb2N1c1xuXHRcdHRoaXMucG9zaXRpb25Ecm9wZG93bihwYXJlbnRSZWYsIGRyb3Bkb3duV3JhcHBlcik7XG5cblx0XHRyZXR1cm4gZHJvcGRvd25XcmFwcGVyO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlYXR0YWNoIHRoZSBkcm9wZG93biBtZW51IHRvIHRoZSBwYXJlbnQgY29udGFpbmVyXG5cdCAqIEBwYXJhbSBob3N0UmVmIGNvbnRhaW5lciB0byBhcHBlbmQgdG9cblx0ICovXG5cdGFwcGVuZFRvRHJvcGRvd24oaG9zdFJlZjogSFRNTEVsZW1lbnQpOiBIVE1MRWxlbWVudCB7XG5cdFx0Ly8gaWYgdGhlIGluc3RhbmNlIGlzIGFscmVhZHkgcmVtb3ZlZCBkb24ndCB0cnkgYW5kIHJlbW92ZSBpdCBhZ2FpblxuXHRcdGlmICghdGhpcy5tZW51SW5zdGFuY2UpIHsgcmV0dXJuOyB9XG5cdFx0Y29uc3QgaW5zdGFuY2UgPSB0aGlzLm1lbnVJbnN0YW5jZTtcblx0XHRjb25zdCBtZW51ID0gaW5zdGFuY2UuZmlyc3RFbGVtZW50Q2hpbGQgYXMgSFRNTEVsZW1lbnQ7XG5cdFx0Ly8gY2xlYW4gdXAgdGhlIGluc3RhbmNlXG5cdFx0dGhpcy5tZW51SW5zdGFuY2UgPSBudWxsO1xuXHRcdG1lbnUuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuXHRcdGhvc3RSZWYuYXBwZW5kQ2hpbGQobWVudSk7XG5cdFx0dGhpcy5hbmltYXRpb25GcmFtZVN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuXHRcdGlmICh0aGlzLnBsYWNlaG9sZGVyU2VydmljZS5oYXNQbGFjZWhvbGRlclJlZigpICYmIHRoaXMucGxhY2Vob2xkZXJTZXJ2aWNlLmhhc0VsZW1lbnQoaW5zdGFuY2UpKSB7XG5cdFx0XHR0aGlzLnBsYWNlaG9sZGVyU2VydmljZS5yZW1vdmVFbGVtZW50KGluc3RhbmNlKTtcblx0XHR9IGVsc2UgaWYgKGRvY3VtZW50LmJvZHkuY29udGFpbnMoaW5zdGFuY2UpKSB7XG5cdFx0XHRkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGluc3RhbmNlKTtcblx0XHR9XG5cdFx0cmV0dXJuIGluc3RhbmNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIHBvc2l0aW9uIGFuIG9wZW4gZHJvcGRvd24gcmVsYXRpdmUgdG8gdGhlIGdpdmVuIHBhcmVudFJlZlxuXHQgKi9cblx0dXBkYXRlUG9zaXRpb24ocGFyZW50UmVmKSB7XG5cdFx0dGhpcy5wb3NpdGlvbkRyb3Bkb3duKHBhcmVudFJlZiwgdGhpcy5tZW51SW5zdGFuY2UpO1xuXHR9XG5cblx0bmdPbkRlc3Ryb3koKSB7XG5cdFx0dGhpcy5hbmltYXRpb25GcmFtZVN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuXHR9XG5cblx0cHJvdGVjdGVkIHBvc2l0aW9uRHJvcGRvd24ocGFyZW50UmVmLCBtZW51UmVmKSB7XG5cdFx0aWYgKCFtZW51UmVmKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0bGV0IGxlZnRPZmZzZXQgPSAwO1xuXG5cdFx0Y29uc3QgYm94TWVudSA9IG1lbnVSZWYucXVlcnlTZWxlY3RvcihcIi5jZHMtLWxpc3QtYm94X19tZW51XCIpO1xuXG5cdFx0aWYgKGJveE1lbnUpIHtcblx0XHRcdC8vIElmIHRoZSBwYXJlbnRSZWYgYW5kIGJveE1lbnUgYXJlIGluIGEgZGlmZmVyZW50IGxlZnQgcG9zaXRpb24gcmVsYXRpdmUgdG8gdGhlXG5cdFx0XHQvLyB3aW5kb3csIHRoZSB0aGUgYm94TWVudSBwb3NpdGlvbiBoYXMgYWxyZWFkeSBiZWVuIGZsaXBwZWQgYW5kIGEgY2hlY2sgbmVlZHMgdG8gYmUgZG9uZVxuXHRcdFx0Ly8gdG8gc2VlIGlmIGl0IG5lZWRzIHRvIHN0YXkgZmxpcHBlZC5cblx0XHRcdGlmIChwYXJlbnRSZWYuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdCAhPT0gYm94TWVudS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0KSB7XG5cdFx0XHRcdC8vIFRoZSBnZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5yaWdodCBvZiB0aGUgYm94TWVudSBpZiBpdCB3ZXJlIGh5cG90aGV0aWNhbGx5IGZsaXBwZWRcblx0XHRcdFx0Ly8gYmFjayBpbnRvIHRoZSBvcmlnaW5hbCBwb3NpdGlvbiBiZWZvcmUgdGhlIGZsaXAuXG5cdFx0XHRcdGNvbnN0IHRlc3RCb3hNZW51UmlnaHRFZGdlUG9zID1cblx0XHRcdFx0XHRwYXJlbnRSZWYuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdCAtIGJveE1lbnUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdCArIGJveE1lbnUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkucmlnaHQ7XG5cblx0XHRcdFx0aWYgKHRlc3RCb3hNZW51UmlnaHRFZGdlUG9zID4gKHdpbmRvdy5pbm5lcldpZHRoIHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aCkpIHtcblx0XHRcdFx0XHRsZWZ0T2Zmc2V0ID0gcGFyZW50UmVmLm9mZnNldFdpZHRoIC0gYm94TWVudS5vZmZzZXRXaWR0aDtcblx0XHRcdFx0fVxuXHRcdFx0Ly8gSWYgaXQgaGFzIG5vdCBhbHJlYWR5IGJlZW4gZmxpcHBlZCwgY2hlY2sgaWYgaXQgaXMgbmVjZXNzYXJ5IHRvIGZsaXAsIGllLiBpZiB0aGVcblx0XHRcdC8vIGJveE1lbnUgaXMgb3V0c2lkZSBvZiB0aGUgcmlnaHQgdmlld1BvcnQuXG5cdFx0XHR9IGVsc2UgaWYgKGJveE1lbnUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkucmlnaHQgPiAod2luZG93LmlubmVyV2lkdGggfHwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudFdpZHRoKSkge1xuXHRcdFx0XHRsZWZ0T2Zmc2V0ID0gcGFyZW50UmVmLm9mZnNldFdpZHRoIC0gYm94TWVudS5vZmZzZXRXaWR0aDtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBJZiBjZHMtcGxhY2Vob2xkZXIgaGFzIGEgcGFyZW50IHdpdGggYSBwb3NpdGlvbihyZWxhdGl2ZXxmaXhlZHxhYnNvbHV0ZSkgYWNjb3VudCBmb3IgdGhlIHBhcmVudCBvZmZzZXRcblx0XHRjb25zdCBjbG9zZXN0TWVudVdpdGhQb3MgPSBjbG9zZXN0QXR0cihcInBvc2l0aW9uXCIsIFtcInJlbGF0aXZlXCIsIFwiZml4ZWRcIiwgXCJhYnNvbHV0ZVwiXSwgbWVudVJlZi5wYXJlbnRFbGVtZW50KTtcblx0XHRjb25zdCB0b3BQb3MgPSBjbG9zZXN0TWVudVdpdGhQb3MgPyBjbG9zZXN0TWVudVdpdGhQb3MuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wICogLTEgOiB0aGlzLm9mZnNldC50b3A7XG5cdFx0Y29uc3QgbGVmdFBvcyA9IGNsb3Nlc3RNZW51V2l0aFBvcyA/IGNsb3Nlc3RNZW51V2l0aFBvcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0ICogLTEgOiB0aGlzLm9mZnNldC5sZWZ0ICsgbGVmdE9mZnNldDtcblxuXHRcdGxldCBwb3MgPSBwb3NpdGlvbi5maW5kQWJzb2x1dGUocGFyZW50UmVmLCBtZW51UmVmLCBcImJvdHRvbVwiKTtcblx0XHRwb3MgPSBwb3NpdGlvbi5hZGRPZmZzZXQocG9zLCB0b3BQb3MsIGxlZnRQb3MpO1xuXG5cdFx0cG9zaXRpb24uc2V0RWxlbWVudChtZW51UmVmLCBwb3MpO1xuXHR9XG59XG4iXX0=