UNPKG

@edugouvfr/ngx-dsfr-ext

Version:

NgxDsfrExt est une extension au package @edugouvfr/ngx-dsfr (portage Angular des éléments DSFR)

168 lines 25.7 kB
import { afterNextRender, Directive, ElementRef, EventEmitter, inject, Input, input, Output, Renderer2, } from '@angular/core'; import { DropdownUtils } from './dropdown.utils'; import * as i0 from "@angular/core"; export class DsfrDropdownPositionDirective { /** * Ajoute l'élément dropdown et le repositionne * /!\ ne pas utiliser un effect() : le cycle de rendu est différent entre angular 17 et angular 19, * le composant ne sera pas encore ajouté dans le DOM en angular 19. */ constructor() { this.autoWidth = false; /** Emission après attachement de la dropdown au parentContainer en appendTo */ this.appendDropdown = new EventEmitter(); this.comboBox = input.required(); this.dropdownRef = inject((ElementRef)); this._renderer = inject(Renderer2); afterNextRender(() => { if (this.dropdownRef) { if (this.parentContainer) { this.appendElement(this.dropdownRef.nativeElement); } this.setPosition(this.dropdownRef.nativeElement); this.appendDropdown.emit(); } }); } /** A la destruction du composant, supprimer l'élément listbox si il a été ajouté au parent ou body (appendTo) */ ngOnDestroy() { if (this.parentContainer && this.dropdownRef) { this.destroyOverlayDropdown(); } } setPosition(dropdownElement) { const viewport = DropdownUtils.getViewport(); const comboBox = this.comboBox(); //box container to attach to if (dropdownElement) { const top = this.calcPositionY(dropdownElement, comboBox, viewport.height); this._renderer.setStyle(dropdownElement, 'top', top); if (this.autoWidth || this.parentContainer) { const left = this.calcPositionX(dropdownElement, comboBox, viewport.width); this._renderer.setStyle(dropdownElement, 'left', left); } } } /** * Calcul de la position verticale de la dropdown * - selon la place disponible (en dessous / au dessus) * - en valeur absolue selon le container parent (si appendTo) * @param dropdown dropdown a positionner * @param comboBox container auquel rattacher la dropdown visuellement * @param viewportHeight * @returns nouvelle position en string (px/auto) */ calcPositionY(dropdown, comboBox, viewportHeight) { let top = 'auto'; const dropdownHeight = dropdown.offsetHeight; // hauteur de mon dropdownElement // ELEMENTOUTERHEIGHT const comboBoxOffset = comboBox.getBoundingClientRect(); // position de ma box container (ex. select) const windowScrollTop = DropdownUtils.getWindowScrollTop(); // si position de ma box container + hauteur de ma box container + hauteur de mon dropdownElement inférieur a hauteur disponible const canDisplayBelow = comboBoxOffset.top + comboBox.offsetHeight + dropdownHeight < viewportHeight; let calcPos = 0; if (this.parentContainer) { // calcul de la position si appendTo en fonction du container passé en parametre calcPos = this.computeTopPositionRelative(comboBox, this.parentContainer); top = `${calcPos}px`; } if (!canDisplayBelow) { // si il n'y a pas assez de place pour afficher au-dessus, on laisse en dessous par défaut const candisplayAbove = comboBoxOffset.top + windowScrollTop - dropdownHeight > 0; // TODO FIX BETTER -- fix pour la hauteur de l'input qui n'est pas la bonne a cause de l'ensemble combobox let diff = 0; let input = comboBox.querySelector('.fr-input'); if (input) { diff = comboBox.offsetHeight - input.getBoundingClientRect().height; } // ---------------------- if (candisplayAbove) { // calcul de la position en fonction de appendTo (container to attach) calcPos = this.parentContainer ? calcPos + diff - dropdownHeight - comboBox.offsetHeight : -dropdownHeight + diff; top = `${calcPos}px`; // afficher au dessus du combobox } } return top; } /** * Calcul de la position horizontale de la dropdown * - selon la place disponible (décalage à gauche éventuel) * - en valeur absolue selon le container parent (si appendTo) * @param dropdown dropdown a positionner * @param comboBox container auquel rattacher la dropdown visuellement * @param viewportWidth * @returns nouvelle position en string (px/auto) */ calcPositionX(dropdown, comboBox, viewportWidth) { const elementOuterWidth = dropdown.offsetWidth; const comboBoxOffset = comboBox.getBoundingClientRect(); // position de ma box container (ex. select) if (this.autoWidth) { if (comboBoxOffset.left + elementOuterWidth > viewportWidth) { return this.parentContainer ? Math.max(0, comboBoxOffset.left + comboBox.offsetWidth - elementOuterWidth) + 'px' : comboBox.offsetWidth - elementOuterWidth + 'px'; } } if (this.parentContainer && DropdownUtils.isBodyOrFixedElement(this.parentContainer)) { // decalage a droite en cas de body return comboBox.getBoundingClientRect().left + 'px'; } else if (this.parentContainer && comboBox.offsetLeft > 0) { return comboBox.offsetLeft + 'px'; } return 'auto'; } /** * Compute top position relative to parent element (top position, margin/padding, scroll inside parent) * @param element element to move relatively * @param parentElement parent container * @returns new top position */ computeTopPositionRelative(element, parentElement) { if (DropdownUtils.isBodyOrFixedElement(parentElement)) { return (element.getBoundingClientRect().top + element.offsetHeight + (parentElement.tagName === 'BODY' ? window.scrollY : 0)); } return (element.getBoundingClientRect().top + element.offsetHeight + parentElement.scrollTop - parentElement.getBoundingClientRect().top); } /** * Ajouter l'element dropdown directement au body ou container spécifié dans le cas de appendTo * Permet d'afficher la dropdown "en dehors" d'un container visuel type modale ou accordéon (pas de scroll) * @param element dropdown */ appendElement(element) { const box = this.comboBox(); this._renderer.setStyle(element, 'width', `${box.offsetWidth}px`); this._renderer.setStyle(element, 'top', `0px`); // obligatoire pour positionner correctement l'element ensuite // Attach element to new parent this._renderer.appendChild(this.parentContainer, element); } /** Suppression de la liste rattachée au container appendTo */ destroyOverlayDropdown() { if (this.dropdownRef.nativeElement?.parentElement === this.parentContainer) { this._renderer.removeChild(this.parentContainer, this.dropdownRef.nativeElement); } if (this._unlistenFn) this._unlistenFn(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DsfrDropdownPositionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.13", type: DsfrDropdownPositionDirective, isStandalone: true, selector: "[dsfrxDropdown]", inputs: { autoWidth: { classPropertyName: "autoWidth", publicName: "autoWidth", isSignal: false, isRequired: false, transformFunction: null }, parentContainer: { classPropertyName: "parentContainer", publicName: "parentContainer", isSignal: false, isRequired: false, transformFunction: null }, comboBox: { classPropertyName: "comboBox", publicName: "comboBox", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { appendDropdown: "appendDropdown" }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DsfrDropdownPositionDirective, decorators: [{ type: Directive, args: [{ selector: '[dsfrxDropdown]', standalone: true, }] }], ctorParameters: () => [], propDecorators: { autoWidth: [{ type: Input }], parentContainer: [{ type: Input }], appendDropdown: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJvcGRvd24tcG9zaXRpb24uZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWRzZnItZXh0L3NyYy9saWIvc2hhcmVkL2NvbXBvbmVudHMvZHJvcGRvd24tY29udGFpbmVyL2Ryb3Bkb3duLXBvc2l0aW9uLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsZUFBZSxFQUNmLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLE1BQU0sRUFDTixLQUFLLEVBQ0wsS0FBSyxFQUdMLE1BQU0sRUFDTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGtCQUFrQixDQUFDOztBQU1qRCxNQUFNLE9BQU8sNkJBQTZCO0lBY3hDOzs7O09BSUc7SUFDSDtRQWxCUyxjQUFTLEdBQVksS0FBSyxDQUFDO1FBSXBDLCtFQUErRTtRQUNyRSxtQkFBYyxHQUF1QixJQUFJLFlBQVksRUFBRSxDQUFDO1FBRWxFLGFBQVEsR0FBNkIsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBRXJDLGdCQUFXLEdBQUcsTUFBTSxDQUFDLENBQUEsVUFBdUIsQ0FBQSxDQUFDLENBQUM7UUFDOUMsY0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQVM3QyxlQUFlLENBQUMsR0FBRyxFQUFFO1lBQ25CLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNyQixJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztvQkFDekIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUNyRCxDQUFDO2dCQUVELElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsQ0FBQztnQkFDakQsSUFBSSxDQUFDLGNBQWMs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LFdBQVcsQ0FBQyxJQUFJLENBQUMsZUFBZSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDbkYsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLFdBQVc7WUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDM0MsQ0FBQzsrR0FwTFUsNkJBQTZCO21HQUE3Qiw2QkFBNkI7OzRGQUE3Qiw2QkFBNkI7a0JBSnpDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLGlCQUFpQjtvQkFDM0IsVUFBVSxFQUFFLElBQUk7aUJBQ2pCO3dEQUVVLFNBQVM7c0JBQWpCLEtBQUs7Z0JBR0csZUFBZTtzQkFBdkIsS0FBSztnQkFFSSxjQUFjO3NCQUF2QixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgYWZ0ZXJOZXh0UmVuZGVyLFxuICBEaXJlY3RpdmUsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgaW5qZWN0LFxuICBJbnB1dCxcbiAgaW5wdXQsXG4gIElucHV0U2lnbmFsLFxuICBPbkRlc3Ryb3ksXG4gIE91dHB1dCxcbiAgUmVuZGVyZXIyLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERyb3Bkb3duVXRpbHMgfSBmcm9tICcuL2Ryb3Bkb3duLnV0aWxzJztcblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW2RzZnJ4RHJvcGRvd25dJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbn0pXG5leHBvcnQgY2xhc3MgRHNmckRyb3Bkb3duUG9zaXRpb25EaXJlY3RpdmUgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBASW5wdXQoKSBhdXRvV2lkdGg6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKiogRWxlbWVudCBhdXF1ZWwgbGUgZHJvcGRvd24gZXN0IHByb2dyYW1tYXRpcXVlbWVudCBhdHRhY2jDqSBlbiBjYXMgZGUgYXBwZW5kVG8gKCdib2R5JyBvdSAgY29udGFpbmVyIHJlbGF0aWYpICovXG4gIEBJbnB1dCgpIHBhcmVudENvbnRhaW5lcjogSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gIC8qKiBFbWlzc2lvbiBhcHLDqHMgYXR0YWNoZW1lbnQgZGUgbGEgZHJvcGRvd24gYXUgcGFyZW50Q29udGFpbmVyIGVuIGFwcGVuZFRvICovXG4gIEBPdXRwdXQoKSBhcHBlbmREcm9wZG93bjogRXZlbnRFbWl0dGVyPHZvaWQ+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIGNvbWJvQm94OiBJbnB1dFNpZ25hbDxIVE1MRWxlbWVudD4gPSBpbnB1dC5yZXF1aXJlZCgpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgZHJvcGRvd25SZWYgPSBpbmplY3QoRWxlbWVudFJlZjxIVE1MRWxlbWVudD4pO1xuICBwcml2YXRlIHJlYWRvbmx5IF9yZW5kZXJlciA9IGluamVjdChSZW5kZXJlcjIpO1xuICBwcml2YXRlIHJlYWRvbmx5IF91bmxpc3RlbkZuOiBGdW5jdGlvbjtcblxuICAvKipcbiAgICogQWpvdXRlIGwnw6lsw6ltZW50IGRyb3Bkb3duIGV0IGxlIHJlcG9zaXRpb25uZVxuICAgKiAvIVxcIG5lIHBhcyB1dGlsaXNlciB1biBlZmZlY3QoKSA6IGxlIGN5Y2xlIGRlIHJlbmR1IGVzdCBkaWZmw6lyZW50IGVudHJlIGFuZ3VsYXIgMTcgZXQgYW5ndWxhciAxOSxcbiAgICogbGUgY29tcG9zYW50IG5lIHNlcmEgcGFzIGVuY29yZSBham91dMOpIGRhbnMgbGUgRE9NIGVuIGFuZ3VsYXIgMTkuXG4gICAqL1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBhZnRlck5leHRSZW5kZXIoKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuZHJvcGRvd25SZWYpIHtcbiAgICAgICAgaWYgKHRoaXMucGFyZW50Q29udGFpbmVyKSB7XG4gICAgICAgICAgdGhpcy5hcHBlbmRFbGVtZW50KHRoaXMuZHJvcGRvd25SZWYubmF0aXZlRWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnNldFBvc2l0aW9uKHRoaXMuZHJvcGRvd25SZWYubmF0aXZlRWxlbWVudCk7XG4gICAgICAgIHRoaXMuYXBwZW5kRHJvcGRvd24uZW1pdCgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqIEEgbGEgZGVzdHJ1Y3Rpb24gZHUgY29tcG9zYW50LCBzdXBwcmltZXIgbCfDqWzDqW1lbnQgbGlzdGJveCBzaSBpbCBhIMOpdMOpIGFqb3V0w6kgYXUgcGFyZW50IG91IGJvZHkgKGFwcGVuZFRvKSAqL1xuICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucGFyZW50Q29udGFpbmVyICYmIHRoaXMuZHJvcGRvd25SZWYpIHtcbiAgICAgIHRoaXMuZGVzdHJveU92ZXJsYXlEcm9wZG93bigpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc2V0UG9zaXRpb24oZHJvcGRvd25FbGVtZW50OiBIVE1MRWxlbWVudCkge1xuICAgIGNvbnN0IHZpZXdwb3J0OiB7IHdpZHRoOiBudW1iZXI7IGhlaWdodDogbnVtYmVyIH0gPSBEcm9wZG93blV0aWxzLmdldFZpZXdwb3J0KCk7XG4gICAgY29uc3QgY29tYm9Cb3g6IEhUTUxFbGVtZW50ID0gdGhpcy5jb21ib0JveCgpOyAvL2JveCBjb250YWluZXIgdG8gYXR0YWNoIHRvXG5cbiAgICBpZiAoZHJvcGRvd25FbGVtZW50KSB7XG4gICAgICBjb25zdCB0b3A6IHN0cmluZyA9IHRoaXMuY2FsY1Bvc2l0aW9uWShkcm9wZG93bkVsZW1lbnQsIGNvbWJvQm94LCB2aWV3cG9ydC5oZWlnaHQpO1xuICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0U3R5bGUoZHJvcGRvd25FbGVtZW50LCAndG9wJywgdG9wKTtcblxuICAgICAgaWYgKHRoaXMuYXV0b1dpZHRoIHx8IHRoaXMucGFyZW50Q29udGFpbmVyKSB7XG4gICAgICAgIGNvbnN0IGxlZnQ6IHN0cmluZyA9IHRoaXMuY2FsY1Bvc2l0aW9uWChkcm9wZG93bkVsZW1lbnQsIGNvbWJvQm94LCB2aWV3cG9ydC53aWR0aCk7XG4gICAgICAgIHRoaXMuX3JlbmRlcmVyLnNldFN0eWxlKGRyb3Bkb3duRWxlbWVudCwgJ2xlZnQnLCBsZWZ0KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsIGRlIGxhIHBvc2l0aW9uIHZlcnRpY2FsZSBkZSBsYSBkcm9wZG93blxuICAgKiAtIHNlbG9uIGxhIHBsYWNlIGRpc3BvbmlibGUgKGVuIGRlc3NvdXMgLyBhdSBkZXNzdXMpXG4gICAqIC0gZW4gdmFsZXVyIGFic29sdWUgc2Vsb24gbGUgY29udGFpbmVyIHBhcmVudCAoc2kgYXBwZW5kVG8pXG4gICAqIEBwYXJhbSBkcm9wZG93biBkcm9wZG93biBhIHBvc2l0aW9ubmVyXG4gICAqIEBwYXJhbSBjb21ib0JveCBjb250YWluZXIgYXVxdWVsIHJhdHRhY2hlciBsYSBkcm9wZG93biB2aXN1ZWxsZW1lbnRcbiAgICogQHBhcmFtIHZpZXdwb3J0SGVpZ2h0XG4gICAqIEByZXR1cm5zIG5vdXZlbGxlIHBvc2l0aW9uIGVuIHN0cmluZyAocHgvYXV0bylcbiAgICovXG4gIHByaXZhdGUgY2FsY1Bvc2l0aW9uWShkcm9wZG93bjogSFRNTEVsZW1lbnQsIGNvbWJvQm94OiBIVE1MRWxlbWVudCwgdmlld3BvcnRIZWlnaHQ6IG51bWJlcik6IHN0cmluZyB7XG4gICAgbGV0IHRvcDogc3RyaW5nID0gJ2F1dG8nO1xuXG4gICAgY29uc3QgZHJvcGRvd25IZWlnaHQgPSBkcm9wZG93bi5vZmZzZXRIZWlnaHQ7IC8vIGhhdXRldXIgZGUgbW9uIGRyb3Bkb3duRWxlbWVudCAvLyBFTEVNRU5UT1VURVJIRUlHSFRcbiAgICBjb25zdCBjb21ib0JveE9mZnNldCA9IGNvbWJvQm94LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyAvLyBwb3NpdGlvbiBkZSBtYSBib3ggY29udGFpbmVyIChleC4gc2VsZWN0KVxuICAgIGNvbnN0IHdpbmRvd1Njcm9sbFRvcCA9IERyb3Bkb3duVXRpbHMuZ2V0V2luZG93U2Nyb2xsVG9wKCk7XG5cbiAgICAvLyBzaSBwb3NpdGlvbiBkZSBtYSBib3ggY29udGFpbmVyICsgaGF1dGV1ciBkZSBtYSBib3ggY29udGFpbmVyICsgaGF1dGV1ciBkZSBtb24gZHJvcGRvd25FbGVtZW50IGluZsOpcmlldXIgYSBoYXV0ZXVyIGRpc3BvbmlibGVcbiAgICBjb25zdCBjYW5EaXNwbGF5QmVsb3c6IGJvb2xlYW4gPSBjb21ib0JveE9mZnNldC50b3AgKyBjb21ib0JveC5vZmZzZXRIZWlnaHQgKyBkcm9wZG93bkhlaWdodCA8IHZpZXdwb3J0SGVpZ2h0O1xuICAgIGxldCBjYWxjUG9zOiBudW1iZXIgPSAwO1xuXG4gICAgaWYgKHRoaXMucGFyZW50Q29udGFpbmVyKSB7XG4gICAgICAvLyBjYWxjdWwgZGUgbGEgcG9zaXRpb24gc2kgYXBwZW5kVG8gZW4gZm9uY3Rpb24gZHUgY29udGFpbmVyIHBhc3PDqSBlbiBwYXJhbWV0cmVcbiAgICAgIGNhbGNQb3MgPSB0aGlzLmNvbXB1dGVUb3BQb3NpdGlvblJlbGF0aXZlKGNvbWJvQm94LCB0aGlzLnBhcmVudENvbnRhaW5lcik7XG4gICAgICB0b3AgPSBgJHtjYWxjUG9zfXB4YDtcbiAgICB9XG5cbiAgICBpZiAoIWNhbkRpc3BsYXlCZWxvdykge1xuICAgICAgLy8gc2kgaWwgbid5IGEgcGFzIGFzc2V6IGRlIHBsYWNlIHBvdXIgYWZmaWNoZXIgYXUtZGVzc3VzLCBvbiBsYWlzc2UgZW4gZGVzc291cyBwYXIgZMOpZmF1dFxuICAgICAgY29uc3QgY2FuZGlzcGxheUFib3ZlID0gY29tYm9Cb3hPZmZzZXQudG9wICsgd2luZG93U2Nyb2xsVG9wIC0gZHJvcGRvd25IZWlnaHQgPiAwO1xuXG4gICAgICAvLyBUT0RPIEZJWCBCRVRURVIgLS0gZml4IHBvdXIgbGEgaGF1dGV1ciBkZSBsJ2lucHV0IHF1aSBuJ2VzdCBwYXMgbGEgYm9ubmUgYSBjYXVzZSBkZSBsJ2Vuc2VtYmxlIGNvbWJvYm94XG4gICAgICBsZXQgZGlmZiA9IDA7XG4gICAgICBsZXQgaW5wdXQgPSBjb21ib0JveC5xdWVyeVNlbGVjdG9yKCcuZnItaW5wdXQnKTtcbiAgICAgIGlmIChpbnB1dCkge1xuICAgICAgICBkaWZmID0gY29tYm9Cb3gub2Zmc2V0SGVpZ2h0IC0gaW5wdXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0O1xuICAgICAgfVxuICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gICAgICBpZiAoY2FuZGlzcGxheUFib3ZlKSB7XG4gICAgICAgIC8vIGNhbGN1bCBkZSBsYSBwb3NpdGlvbiBlbiBmb25jdGlvbiBkZSBhcHBlbmRUbyAoY29udGFpbmVyIHRvIGF0dGFjaClcbiAgICAgICAgY2FsY1BvcyA9IHRoaXMucGFyZW50Q29udGFpbmVyXG4gICAgICAgICAgPyBjYWxjUG9zICsgZGlmZiAtIGRyb3Bkb3duSGVpZ2h0IC0gY29tYm9Cb3gub2Zmc2V0SGVpZ2h0XG4gICAgICAgICAgOiAtZHJvcGRvd25IZWlnaHQgKyBkaWZmO1xuICAgICAgICB0b3AgPSBgJHtjYWxjUG9zfXB4YDsgLy8gYWZmaWNoZXIgYXUgZGVzc3VzIGR1IGNvbWJvYm94XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRvcDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWwgZGUgbGEgcG9zaXRpb24gaG9yaXpvbnRhbGUgZGUgbGEgZHJvcGRvd25cbiAgICogLSBzZWxvbiBsYSBwbGFjZSBkaXNwb25pYmxlIChkw6ljYWxhZ2Ugw6AgZ2F1Y2hlIMOpdmVudHVlbClcbiAgICogLSBlbiB2YWxldXIgYWJzb2x1ZSBzZWxvbiBsZSBjb250YWluZXIgcGFyZW50IChzaSBhcHBlbmRUbylcbiAgICogQHBhcmFtIGRyb3Bkb3duIGRyb3Bkb3duIGEgcG9zaXRpb25uZXJcbiAgICogQHBhcmFtIGNvbWJvQm94IGNvbnRhaW5lciBhdXF1ZWwgcmF0dGFjaGVyIGxhIGRyb3Bkb3duIHZpc3VlbGxlbWVudFxuICAgKiBAcGFyYW0gdmlld3BvcnRXaWR0aFxuICAgKiBAcmV0dXJucyBub3V2ZWxsZSBwb3NpdGlvbiBlbiBzdHJpbmcgKHB4L2F1dG8pXG4gICAqL1xuICBwcml2YXRlIGNhbGNQb3NpdGlvblgoZHJvcGRvd246IEhUTUxFbGVtZW50LCBjb21ib0JveDogSFRNTEVsZW1lbnQsIHZpZXdwb3J0V2lkdGg6IG51bWJlcik6IHN0cmluZyB7XG4gICAgY29uc3QgZWxlbWVudE91dGVyV2lkdGggPSBkcm9wZG93bi5vZmZzZXRXaWR0aDtcbiAgICBjb25zdCBjb21ib0JveE9mZnNldCA9IGNvbWJvQm94LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyAvLyBwb3NpdGlvbiBkZSBtYSBib3ggY29udGFpbmVyIChleC4gc2VsZWN0KVxuXG4gICAgaWYgKHRoaXMuYXV0b1dpZHRoKSB7XG4gICAgICBpZiAoY29tYm9Cb3hPZmZzZXQubGVmdCArIGVsZW1lbnRPdXRlcldpZHRoID4gdmlld3BvcnRXaWR0aCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wYXJlbnRDb250YWluZXJcbiAgICAgICAgICA/IE1hdGgubWF4KDAsIGNvbWJvQm94T2Zmc2V0LmxlZnQgKyBjb21ib0JveC5vZmZzZXRXaWR0aCAtIGVsZW1lbnRPdXRlcldpZHRoKSArICdweCdcbiAgICAgICAgICA6IGNvbWJvQm94Lm9mZnNldFdpZHRoIC0gZWxlbWVudE91dGVyV2lkdGggKyAncHgnO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLnBhcmVudENvbnRhaW5lciAmJiBEcm9wZG93blV0aWxzLmlzQm9keU9yRml4ZWRFbGVtZW50KHRoaXMucGFyZW50Q29udGFpbmVyKSkge1xuICAgICAgLy8gZGVjYWxhZ2UgYSBkcm9pdGUgZW4gY2FzIGRlIGJvZHlcbiAgICAgIHJldHVybiBjb21ib0JveC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0ICsgJ3B4JztcbiAgICB9IGVsc2UgaWYgKHRoaXMucGFyZW50Q29udGFpbmVyICYmIGNvbWJvQm94Lm9mZnNldExlZnQgPiAwKSB7XG4gICAgICByZXR1cm4gY29tYm9Cb3gub2Zmc2V0TGVmdCArICdweCc7XG4gICAgfVxuXG4gICAgcmV0dXJuICdhdXRvJztcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wdXRlIHRvcCBwb3NpdGlvbiByZWxhdGl2ZSB0byBwYXJlbnQgZWxlbWVudCAodG9wIHBvc2l0aW9uLCBtYXJnaW4vcGFkZGluZywgc2Nyb2xsIGluc2lkZSBwYXJlbnQpXG4gICAqIEBwYXJhbSBlbGVtZW50IGVsZW1lbnQgdG8gbW92ZSByZWxhdGl2ZWx5XG4gICAqIEBwYXJhbSBwYXJlbnRFbGVtZW50IHBhcmVudCBjb250YWluZXJcbiAgICogQHJldHVybnMgbmV3IHRvcCBwb3NpdGlvblxuICAgKi9cbiAgcHJpdmF0ZSBjb21wdXRlVG9wUG9zaXRpb25SZWxhdGl2ZShlbGVtZW50OiBIVE1MRWxlbWVudCwgcGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiBudW1iZXIge1xuICAgIGlmIChEcm9wZG93blV0aWxzLmlzQm9keU9yRml4ZWRFbGVtZW50KHBhcmVudEVsZW1lbnQpKSB7XG4gICAgICByZXR1cm4gKFxuICAgICAgICBlbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcCArXG4gICAgICAgIGVsZW1lbnQub2Zmc2V0SGVpZ2h0ICtcbiAgICAgICAgKHBhcmVudEVsZW1lbnQudGFnTmFtZSA9PT0gJ0JPRFknID8gd2luZG93LnNjcm9sbFkgOiAwKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gKFxuICAgICAgZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3AgK1xuICAgICAgZWxlbWVudC5vZmZzZXRIZWlnaHQgK1xuICAgICAgcGFyZW50RWxlbWVudC5zY3JvbGxUb3AgLVxuICAgICAgcGFyZW50RWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3BcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEFqb3V0ZXIgbCdlbGVtZW50IGRyb3Bkb3duIGRpcmVjdGVtZW50IGF1IGJvZHkgb3UgY29udGFpbmVyIHNww6ljaWZpw6kgZGFucyBsZSBjYXMgZGUgYXBwZW5kVG9cbiAgICogUGVybWV0IGQnYWZmaWNoZXIgbGEgZHJvcGRvd24gXCJlbiBkZWhvcnNcIiBkJ3VuIGNvbnRhaW5lciB2aXN1ZWwgdHlwZSBtb2RhbGUgb3UgYWNjb3Jkw6lvbiAocGFzIGRlIHNjcm9sbClcbiAgICogQHBhcmFtIGVsZW1lbnQgZHJvcGRvd25cbiAgICovXG4gIHByaXZhdGUgYXBwZW5kRWxlbWVudChlbGVtZW50OiBIVE1MRWxlbWVudCk6IHZvaWQge1xuICAgIGNvbnN0IGJveCA9IHRoaXMuY29tYm9Cb3goKSBhcyBIVE1MRWxlbWVudDtcblxuICAgIHRoaXMuX3JlbmRlcmVyLnNldFN0eWxlKGVsZW1lbnQsICd3aWR0aCcsIGAke2JveC5vZmZzZXRXaWR0aH1weGApO1xuICAgIHRoaXMuX3JlbmRlcmVyLnNldFN0eWxlKGVsZW1lbnQsICd0b3AnLCBgMHB4YCk7IC8vIG9ibGlnYXRvaXJlIHBvdXIgcG9zaXRpb25uZXIgY29ycmVjdGVtZW50IGwnZWxlbWVudCBlbnN1aXRlXG5cbiAgICAvLyBBdHRhY2ggZWxlbWVudCB0byBuZXcgcGFyZW50XG4gICAgdGhpcy5fcmVuZGVyZXIuYXBwZW5kQ2hpbGQodGhpcy5wYXJlbnRDb250YWluZXIsIGVsZW1lbnQpO1xuICB9XG5cbiAgLyoqIFN1cHByZXNzaW9uIGRlIGxhIGxpc3RlIHJhdHRhY2jDqWUgYXUgY29udGFpbmVyIGFwcGVuZFRvICovXG4gIHByaXZhdGUgZGVzdHJveU92ZXJsYXlEcm9wZG93bigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kcm9wZG93blJlZi5uYXRpdmVFbGVtZW50Py5wYXJlbnRFbGVtZW50ID09PSB0aGlzLnBhcmVudENvbnRhaW5lcikge1xuICAgICAgdGhpcy5fcmVuZGVyZXIucmVtb3ZlQ2hpbGQodGhpcy5wYXJlbnRDb250YWluZXIsIHRoaXMuZHJvcGRvd25SZWYubmF0aXZlRWxlbWVudCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX3VubGlzdGVuRm4pIHRoaXMuX3VubGlzdGVuRm4oKTtcbiAgfVxufVxuIl19