UNPKG

@clr/angular

Version:

Angular components for Clarity

266 lines 34.9 kB
/* * Copyright (c) 2016-2023 VMware, Inc. All Rights Reserved. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ import { Subject } from 'rxjs'; export var Point; (function (Point) { Point[Point["RIGHT_CENTER"] = 0] = "RIGHT_CENTER"; Point[Point["RIGHT_TOP"] = 1] = "RIGHT_TOP"; Point[Point["RIGHT_BOTTOM"] = 2] = "RIGHT_BOTTOM"; Point[Point["TOP_CENTER"] = 3] = "TOP_CENTER"; Point[Point["TOP_RIGHT"] = 4] = "TOP_RIGHT"; Point[Point["TOP_LEFT"] = 5] = "TOP_LEFT"; Point[Point["BOTTOM_CENTER"] = 6] = "BOTTOM_CENTER"; Point[Point["BOTTOM_RIGHT"] = 7] = "BOTTOM_RIGHT"; Point[Point["BOTTOM_LEFT"] = 8] = "BOTTOM_LEFT"; Point[Point["LEFT_CENTER"] = 9] = "LEFT_CENTER"; Point[Point["LEFT_TOP"] = 10] = "LEFT_TOP"; Point[Point["LEFT_BOTTOM"] = 11] = "LEFT_BOTTOM"; })(Point || (Point = {})); const POSITION_RELATIVE = 'relative'; const POSITION_ABSOLUTE = 'absolute'; const POSITION_FIXED = 'fixed'; const OVERFLOW_SCROLL = 'scroll'; const OVERFLOW_AUTO = 'auto'; export class Popover { constructor(element) { this.element = element; this.boundOnScrollListener = this.emitScrollEvent.bind(this); /* * Containers up to the first positioned one will have an event on scroll */ this.scrollableElements = []; // Browsers don't agree with what to do if some of these are not specified, so we set them all to be safe. element.style.position = POSITION_ABSOLUTE; element.style.top = 0; element.style.bottom = 'auto'; element.style.left = 0; element.style.right = 'auto'; } // TODO: need a way to account for parameters that change dynamically (positioning). anchor(anchor, anchorAlign, popoverAlign, { offsetX = 0, offsetY = 0, useAnchorParent = false } = {}) { // TODO: we are assuming here that the popover is inside or next to the anchor. // We'd need to go up the popover tree too otherwise this.addScrollEventListeners(anchor); if (useAnchorParent) { anchor = anchor.parentNode; } // explicitly override anchor's style to static anchor.style.position = 'static'; const anchorRect = anchor.getBoundingClientRect(); const popoverRect = this.element.getBoundingClientRect(); // position of left top corner of anchor + the offset let leftDiff = anchorRect.left - popoverRect.left + offsetX; let topDiff = anchorRect.top - popoverRect.top + offsetY; // first, adjust positioning based on anchor's align point switch (anchorAlign) { case Point.LEFT_TOP: case Point.TOP_LEFT: break; case Point.TOP_CENTER: leftDiff += anchorRect.width / 2; break; case Point.TOP_RIGHT: leftDiff += anchorRect.width; break; case Point.RIGHT_TOP: leftDiff += anchorRect.width; break; case Point.LEFT_BOTTOM: topDiff += anchorRect.height; break; case Point.BOTTOM_LEFT: topDiff += anchorRect.height; break; case Point.BOTTOM_CENTER: topDiff += anchorRect.height; leftDiff += anchorRect.width / 2; break; case Point.BOTTOM_RIGHT: topDiff += anchorRect.height; leftDiff += anchorRect.width; break; case Point.RIGHT_BOTTOM: topDiff += anchorRect.height; leftDiff += anchorRect.width; break; case Point.LEFT_CENTER: topDiff += anchorRect.height / 2; break; case Point.RIGHT_CENTER: topDiff += anchorRect.height / 2; leftDiff += anchorRect.width; break; default: } // second, adjust positioning based on popover's align point switch (popoverAlign) { case Point.LEFT_TOP: case Point.TOP_LEFT: break; case Point.TOP_CENTER: leftDiff -= popoverRect.width / 2; break; case Point.TOP_RIGHT: leftDiff -= popoverRect.width; break; case Point.RIGHT_TOP: leftDiff -= popoverRect.width; break; case Point.LEFT_BOTTOM: topDiff -= popoverRect.height; break; case Point.BOTTOM_LEFT: topDiff -= popoverRect.height; break; case Point.BOTTOM_CENTER: topDiff -= popoverRect.height; leftDiff -= popoverRect.width / 2; break; case Point.BOTTOM_RIGHT: topDiff -= popoverRect.height; leftDiff -= popoverRect.width; break; case Point.RIGHT_BOTTOM: topDiff -= popoverRect.height; leftDiff -= popoverRect.width; break; case Point.LEFT_CENTER: topDiff -= popoverRect.height / 2; break; case Point.RIGHT_CENTER: topDiff -= popoverRect.height / 2; leftDiff -= popoverRect.width; break; default: } // Third, adjust with popover's margins based on the two align points. // Here, we make an assumption that popover is primarily positioned outside the // anchor with minor offset. Without this assumption, it's impossible to apply // the popover's margins in a predictable way. For example, assume that a popover // and its anchor are exactly the same size. if a popover is positioned inside the // anchor (which is technically possible), then it becomes impossible to know what to do // if the popover has a non-zero margin value all around (because applying the margin in // all four directions will result in no margin visually, which isn't what we want). // Therefore, our logic makes assumptions about margins of interest given the points, // and only covers the cases where popover is outside the anchor. const popoverComputedStyle = getComputedStyle(this.element); const marginLeft = parseInt(popoverComputedStyle.marginLeft, 10); const marginRight = parseInt(popoverComputedStyle.marginRight, 10); const marginTop = parseInt(popoverComputedStyle.marginTop, 10); const marginBottom = parseInt(popoverComputedStyle.marginBottom, 10); switch (anchorAlign) { case Point.LEFT_TOP: case Point.TOP_LEFT: case Point.TOP_RIGHT: case Point.RIGHT_TOP: if (popoverAlign === Point.BOTTOM_RIGHT || popoverAlign === Point.RIGHT_BOTTOM) { topDiff -= marginBottom; leftDiff -= marginRight; } if (popoverAlign === Point.BOTTOM_LEFT || popoverAlign === Point.LEFT_BOTTOM) { topDiff -= marginTop; leftDiff += marginLeft; } if (popoverAlign === Point.TOP_LEFT || popoverAlign === Point.LEFT_TOP) { topDiff += marginTop; leftDiff += marginLeft; } if (popoverAlign === Point.TOP_RIGHT || popoverAlign === Point.RIGHT_TOP) { topDiff += marginTop; leftDiff -= marginRight; } break; case Point.LEFT_BOTTOM: case Point.BOTTOM_LEFT: case Point.BOTTOM_RIGHT: case Point.RIGHT_BOTTOM: if (popoverAlign === Point.BOTTOM_LEFT || popoverAlign === Point.LEFT_BOTTOM) { topDiff -= marginBottom; leftDiff += marginLeft; } if (popoverAlign === Point.BOTTOM_RIGHT || popoverAlign === Point.RIGHT_BOTTOM) { topDiff -= marginBottom; leftDiff -= marginRight; } if (popoverAlign === Point.TOP_LEFT || popoverAlign === Point.LEFT_TOP) { topDiff += marginTop; leftDiff += marginLeft; } if (popoverAlign === Point.TOP_RIGHT || popoverAlign === Point.RIGHT_TOP) { topDiff += marginTop; leftDiff -= marginRight; } break; case Point.TOP_CENTER: topDiff -= marginBottom; leftDiff += marginLeft; leftDiff -= marginRight; break; case Point.BOTTOM_CENTER: topDiff += marginTop; leftDiff += marginLeft; leftDiff -= marginRight; break; case Point.LEFT_CENTER: topDiff += marginTop; topDiff -= marginBottom; leftDiff -= marginRight; break; case Point.RIGHT_CENTER: topDiff += marginTop; topDiff -= marginBottom; leftDiff += marginLeft; break; default: } this.element.style.transform = `translateX(${Math.round(leftDiff)}px) translateY(${Math.round(topDiff)}px)`; return this._scroll.asObservable(); } release() { this.element.style.transform = ''; this.removeScrollEventListeners(); } isPositioned(container) { const position = getComputedStyle(container).position; return position === POSITION_RELATIVE || position === POSITION_ABSOLUTE || position === POSITION_FIXED; } emitScrollEvent() { this._scroll.next(); } addScrollEventListeners(e) { this._scroll = new Subject(); const anchor = e; let current = e; while (current && current !== document) { if (this.scrolls(current)) { current.addEventListener('scroll', this.boundOnScrollListener); this.scrollableElements.push(current); } if (current !== anchor && this.isPositioned(current)) { break; } current = current.parentNode; } } removeScrollEventListeners() { for (const elem of this.scrollableElements) { elem.removeEventListener('scroll', this.boundOnScrollListener); } this.scrollableElements.length = 0; if (this._scroll) { this._scroll.complete(); delete this._scroll; } } scrolls(container) { const computedStyles = getComputedStyle(container); return (computedStyles.overflowX === OVERFLOW_SCROLL || computedStyles.overflowX === OVERFLOW_AUTO || computedStyles.overflowY === OVERFLOW_SCROLL || computedStyles.overflowY === OVERFLOW_AUTO); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9wb3Zlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXIvc3JjL3BvcG92ZXIvY29tbW9uL3BvcG92ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQVFILE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFHL0IsTUFBTSxDQUFOLElBQVksS0FhWDtBQWJELFdBQVksS0FBSztJQUNmLGlEQUFZLENBQUE7SUFDWiwyQ0FBUyxDQUFBO0lBQ1QsaURBQVksQ0FBQTtJQUNaLDZDQUFVLENBQUE7SUFDViwyQ0FBUyxDQUFBO0lBQ1QseUNBQVEsQ0FBQTtJQUNSLG1EQUFhLENBQUE7SUFDYixpREFBWSxDQUFBO0lBQ1osK0NBQVcsQ0FBQTtJQUNYLCtDQUFXLENBQUE7SUFDWCwwQ0FBUSxDQUFBO0lBQ1IsZ0RBQVcsQ0FBQTtBQUNiLENBQUMsRUFiVyxLQUFLLEtBQUwsS0FBSyxRQWFoQjtBQUVELE1BQU0saUJBQWlCLEdBQUcsVUFBVSxDQUFDO0FBQ3JDLE1BQU0saUJBQWlCLEdBQUcsVUFBVSxDQUFDO0FBQ3JDLE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQztBQUUvQixNQUFNLGVBQWUsR0FBRyxRQUFRLENBQUM7QUFDakMsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDO0FBRTdCLE1BQU0sT0FBTyxPQUFPO0lBU2xCLFlBQW9CLE9BQVk7UUFBWixZQUFPLEdBQVAsT0FBTyxDQUFLO1FBUHhCLDBCQUFxQixHQUFRLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXJFOztXQUVHO1FBQ0ssdUJBQWtCLEdBQWtCLEVBQUUsQ0FBQztRQUc3QywwR0FBMEc7UUFDMUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLEdBQUcsaUJBQWlCLENBQUM7UUFDM0MsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFD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Q0FBQyxPQUFPLEVBQUU7WUFDaEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN4QixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7U0FDckI7SUFDSCxDQUFDO0lBRU8sT0FBTyxDQUFDLFNBQWM7UUFDNUIsTUFBTSxjQUFjLEdBQUcsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDbkQsT0FBTyxDQUNMLGNBQWMsQ0FBQyxTQUFTLEtBQUssZUFBZTtZQUM1QyxjQUFjLENBQUMsU0FBUyxLQUFLLGFBQWE7WUFDMUMsY0FBYyxDQUFDLFNBQVMsS0FBSyxlQUFlO1lBQzVDLGNBQWMsQ0FBQyxTQUFTLEtBQUssYUFBYSxDQUMzQyxDQUFDO0lBQ0osQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoYykgMjAxNi0yMDIzIFZNd2FyZSwgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogVGhpcyBzb2Z0d2FyZSBpcyByZWxlYXNlZCB1bmRlciBNSVQgbGljZW5zZS5cbiAqIFRoZSBmdWxsIGxpY2Vuc2UgaW5mb3JtYXRpb24gY2FuIGJlIGZvdW5kIGluIExJQ0VOU0UgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgcHJvamVjdC5cbiAqL1xuXG4vKlxuICogRG8gTk9UIEFuZ3VsYXIgdGhpcyB1cC4gSXQgYXNzdW1lcyB3ZSdyZSBpbiB0aGUgRE9NLCBwbGF5cyB3aXRoIG5hdGl2ZSBlbGVtZW50cywgLi4uXG4gKiBJdCBjb3VsZCBwb3RlbnRpYWxseSBiZSB1c2VkIGFzIHBhcnQgb2YgQGNsci91aSBhcyBhIHZhbmlsbGEgSmF2YXNjcmlwdCBoZWxwZXIuXG4gKi9cblxuaW1wb3J0IHsgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBQb3BvdmVyT3B0aW9ucyB9IGZyb20gJy4vcG9wb3Zlci1vcHRpb25zLmludGVyZmFjZSc7XG5leHBvcnQgZW51bSBQb2ludCB7XG4gIFJJR0hUX0NFTlRFUixcbiAgUklHSFRfVE9QLFxuICBSSUdIVF9CT1RUT00sXG4gIFRPUF9DRU5URVIsXG4gIFRPUF9SSUdIVCxcbiAgVE9QX0xFRlQsXG4gIEJPVFRPTV9DRU5URVIsXG4gIEJPVFRPTV9SSUdIVCxcbiAgQk9UVE9NX0xFRlQsXG4gIExFRlRfQ0VOVEVSLFxuICBMRUZUX1RPUCxcbiAgTEVGVF9CT1RUT00sXG59XG5cbmNvbnN0IFBPU0lUSU9OX1JFTEFUSVZFID0gJ3JlbGF0aXZlJztcbmNvbnN0IFBPU0lUSU9OX0FCU09MVVRFID0gJ2Fic29sdXRlJztcbmNvbnN0IFBPU0lUSU9OX0ZJWEVEID0gJ2ZpeGVkJztcblxuY29uc3QgT1ZFUkZMT1dfU0NST0xMID0gJ3Njcm9sbCc7XG5jb25zdCBPVkVSRkxPV19BVVRPID0gJ2F1dG8nO1xuXG5leHBvcnQgY2xhc3MgUG9wb3ZlciB7XG4gIHByaXZhdGUgX3Njcm9sbDogU3ViamVjdDx2b2lkPjtcbiAgcHJpdmF0ZSBib3VuZE9uU2Nyb2xsTGlzdGVuZXI6IGFueSA9IHRoaXMuZW1pdFNjcm9sbEV2ZW50LmJpbmQodGhpcyk7XG5cbiAgLypcbiAgICogQ29udGFpbmVycyB1cCB0byB0aGUgZmlyc3QgcG9zaXRpb25lZCBvbmUgd2lsbCBoYXZlIGFuIGV2ZW50IG9uIHNjcm9sbFxuICAgKi9cbiAgcHJpdmF0ZSBzY3JvbGxhYmxlRWxlbWVudHM6IEhUTUxFbGVtZW50W10gPSBbXTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGVsZW1lbnQ6IGFueSkge1xuICAgIC8vIEJyb3dzZXJzIGRvbid0IGFncmVlIHdpdGggd2hhdCB0byBkbyBpZiBzb21lIG9mIHRoZXNlIGFyZSBub3Qgc3BlY2lmaWVkLCBzbyB3ZSBzZXQgdGhlbSBhbGwgdG8gYmUgc2FmZS5cbiAgICBlbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gUE9TSVRJT05fQUJTT0xVVEU7XG4gICAgZWxlbWVudC5zdHlsZS50b3AgPSAwO1xuICAgIGVsZW1lbnQuc3R5bGUuYm90dG9tID0gJ2F1dG8nO1xuICAgIGVsZW1lbnQuc3R5bGUubGVmdCA9IDA7XG4gICAgZWxlbWVudC5zdHlsZS5yaWdodCA9ICdhdXRvJztcbiAgfVxuXG4gIC8vIFRPRE86IG5lZWQgYSB3YXkgdG8gYWNjb3VudCBmb3IgcGFyYW1ldGVycyB0aGF0IGNoYW5nZSBkeW5hbWljYWxseSAocG9zaXRpb25pbmcpLlxuICBhbmNob3IoXG4gICAgYW5jaG9yOiBhbnksXG4gICAgYW5jaG9yQWxpZ246IFBvaW50LFxuICAgIHBvcG92ZXJBbGlnbjogUG9pbnQsXG4gICAgeyBvZmZzZXRYID0gMCwgb2Zmc2V0WSA9IDAsIHVzZUFuY2hvclBhcmVudCA9IGZhbHNlIH06IFBvcG92ZXJPcHRpb25zID0ge31cbiAgKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICAvLyBUT0RPOiB3ZSBhcmUgYXNzdW1pbmcgaGVyZSB0aGF0IHRoZSBwb3BvdmVyIGlzIGluc2lkZSBvciBuZXh0IHRvIHRoZSBhbmNob3IuXG4gICAgLy8gV2UnZCBuZWVkIHRvIGdvIHVwIHRoZSBwb3BvdmVyIHRyZWUgdG9vIG90aGVyd2lzZVxuXG4gICAgdGhpcy5hZGRTY3JvbGxFdmVudExpc3RlbmVycyhhbmNob3IpO1xuICAgIGlmICh1c2VBbmNob3JQYXJlbnQpIHtcbiAgICAgIGFuY2hvciA9IGFuY2hvci5wYXJlbnROb2RlO1xuICAgIH1cbiAgICAvLyBleHBsaWNpdGx5IG92ZXJyaWRlIGFuY2hvcidzIHN0eWxlIHRvIHN0YXRpY1xuICAgIGFuY2hvci5zdHlsZS5wb3NpdGlvbiA9ICdzdGF0aWMnO1xuXG4gICAgY29uc3QgYW5jaG9yUmVjdCA9IGFuY2hvci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBjb25zdCBwb3BvdmVyUmVjdCA9IHRoaXMuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgIC8vIHBvc2l0aW9uIG9mIGxlZnQgdG9wIGNvcm5lciBvZiBhbmNob3IgKyB0aGUgb2Zmc2V0XG4gICAgbGV0IGxlZnREaWZmOiBudW1iZXIgPSBhbmNob3JSZWN0LmxlZnQgLSBwb3BvdmVyUmVjdC5sZWZ0ICsgb2Zmc2V0WDtcbiAgICBsZXQgdG9wRGlmZjogbnVtYmVyID0gYW5jaG9yUmVjdC50b3AgLSBwb3BvdmVyUmVjdC50b3AgKyBvZmZzZXRZO1xuXG4gICAgLy8gZmlyc3QsIGFkanVzdCBwb3NpdGlvbmluZyBiYXNlZCBvbiBhbmNob3IncyBhbGlnbiBwb2ludFxuICAgIHN3aXRjaCAoYW5jaG9yQWxpZ24pIHtcbiAgICAgIGNhc2UgUG9pbnQuTEVGVF9UT1A6XG4gICAgICBjYXNlIFBvaW50LlRPUF9MRUZUOlxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUG9pbnQuVE9QX0NFTlRFUjpcbiAgICAgICAgbGVmdERpZmYgKz0gYW5jaG9yUmVjdC53aWR0aCAvIDI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQb2ludC5UT1BfUklHSFQ6XG4gICAgICAgIGxlZnREaWZmICs9IGFuY2hvclJlY3Qud2lkdGg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQb2ludC5SSUdIVF9UT1A6XG4gICAgICAgIGxlZnREaWZmICs9IGFuY2hvclJlY3Qud2lkdGg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQb2ludC5MRUZUX0JPVFRPTTpcbiAgICAgICAgdG9wRGlmZiArPSBhbmNob3JSZWN0LmhlaWdodDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFBvaW50LkJPVFRPTV9MRUZUOlxuICAgICAgICB0b3BEaWZmICs9IGFuY2hvclJlY3QuaGVpZ2h0O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUG9pbnQuQk9UVE9NX0NFTlRFUjpcbiAgICAgICAgdG9wRGlmZiArPSBhbmNob3JSZWN0LmhlaWdodDtcbiAgICAgICAgbGVmdERpZmYgKz0gYW5jaG9yUmVjdC53aWR0aCAvIDI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQb2ludC5CT1RUT01fUklHSFQ6XG4gICAgICAgIHRvcERpZmYgKz0gYW5jaG9yUmVjdC5oZWlnaHQ7XG4gICAgICAgIGxlZnREaWZmICs9IGFuY2hvclJlY3Qud2lkdGg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQb2ludC5SSUdIVF9CT1RUT006XG4gICAgICAgIHRvcERpZmYgKz0gYW5jaG9yUmVjdC5oZWlnaHQ7XG4gICAgICAgIGxlZnREaWZmICs9IGFuY2hvclJlY3Qud2lkdGg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQb2ludC5MRUZUX0NFTlRFUjpcbiAgICAgICAgdG9wRGlmZiArPSBhbmNob3JSZWN0LmhlaWdodCAvIDI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQb2ludC5SSUdIVF9DRU5URVI6XG4gICAgICAgIHRvcERpZmYgKz0gYW5jaG9yUmVjdC5oZWlnaHQgLyAyO1xuICAgICAgICBsZWZ0RGlmZiArPSBhbmNob3JSZWN0LndpZHRoO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgfVxuXG4gICAgLy8gc2Vjb25kLCBhZGp1c3QgcG9zaXRpb25pbmcgYmFzZWQgb24gcG9wb3ZlcidzIGFsaWduIHBvaW50XG4gICAgc3dpdGNoIChwb3BvdmVyQWxpZ24pIHtcbiAgICAgIGNhc2UgUG9pbnQuTEVGVF9UT1A6XG4gICAgICBjYXNlIFBvaW50LlRPUF9MRUZUOlxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUG9pbnQuVE9QX0NFTlRFUjpcbiAgICAgICAgbGVmdERpZmYgLT0gcG9wb3ZlclJlY3Qud2lkdGggLyAyO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUG9pbnQuVE9QX1JJR0hUOlxuICAgICAgICBsZWZ0RGlmZiAtPSBwb3BvdmVyUmVjdC53aWR0aDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFBvaW50LlJJR0hUX1RPUDpcbiAgICAgICAgbGVmdERpZmYgLT0gcG9wb3ZlclJlY3Qud2lkdGg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQb2ludC5MRUZUX0JPVFRPTTpcbiAgICAgICAgdG9wRGlmZiAtPSBwb3BvdmVyUmVjdC5oZWlnaHQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQb2ludC5CT1RUT01fTEVGVDpcbiAgICAgICAgdG9wRGlmZiAtPSBwb3BvdmVyUmVjdC5oZWlnaHQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQb2ludC5CT1RUT01fQ0VOVEVSOlxuICAgICAgICB0b3BEaWZmIC09IHBvcG92ZXJSZWN0LmhlaWdodDtcbiAgICAgICAgbGVmdERpZmYgLT0gcG9wb3ZlclJlY3Qud2lkdGggLyAyO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUG9pbnQuQk9UVE9NX1JJR0hUOlxuICAgICAgICB0b3BEaWZmIC09IHBvcG92ZXJSZWN0LmhlaWdodDtcbiAgICAgICAgbGVmdERpZmYgLT0gcG9wb3ZlclJlY3Qud2lkdGg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQb2ludC5SSUdIVF9CT1RUT006XG4gICAgICAgIHRvcERpZmYgLT0gcG9wb3ZlclJlY3QuaGVpZ2h0O1xuICAgICAgICBsZWZ0RGlmZiAtPSBwb3BvdmVyUmVjdC53aWR0aDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFBvaW50LkxFRlRfQ0VOVEVSOlxuICAgICAgICB0b3BEaWZmIC09IHBvcG92ZXJSZWN0LmhlaWdodCAvIDI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQb2ludC5SSUdIVF9DRU5URVI6XG4gICAgICAgIHRvcERpZmYgLT0gcG9wb3ZlclJlY3QuaGVpZ2h0IC8gMjtcbiAgICAgICAgbGVmdERpZmYgLT0gcG9wb3ZlclJlY3Qud2lkdGg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICB9XG5cbiAgICAvLyBUaGlyZCwgYWRqdXN0IHdpdGggcG9wb3ZlcidzIG1hcmdpbnMgYmFzZWQgb24gdGhlIHR3byBhbGlnbiBwb2ludHMuXG4gICAgLy8gSGVyZSwgd2UgbWFrZSBhbiBhc3N1bXB0aW9uIHRoYXQgcG9wb3ZlciBpcyBwcmltYXJpbHkgcG9zaXRpb25lZCBvdXRzaWRlIHRoZVxuICAgIC8vIGFuY2hvciB3aXRoIG1pbm9yIG9mZnNldC4gV2l0aG91dCB0aGlzIGFzc3VtcHRpb24sIGl0J3MgaW1wb3NzaWJsZSB0byBhcHBseVxuICAgIC8vIHRoZSBwb3BvdmVyJ3MgbWFyZ2lucyBpbiBhIHByZWRpY3RhYmxlIHdheS4gRm9yIGV4YW1wbGUsIGFzc3VtZSB0aGF0IGEgcG9wb3ZlclxuICAgIC8vIGFuZCBpdHMgYW5jaG9yIGFyZSBleGFjdGx5IHRoZSBzYW1lIHNpemUuIGlmIGEgcG9wb3ZlciBpcyBwb3NpdGlvbmVkIGluc2lkZSB0aGVcbiAgICAvLyBhbmNob3IgKHdoaWNoIGlzIHRlY2huaWNhbGx5IHBvc3NpYmxlKSwgdGhlbiBpdCBiZWNvbWVzIGltcG9zc2libGUgdG8ga25vdyB3aGF0IHRvIGRvXG4gICAgLy8gaWYgdGhlIHBvcG92ZXIgaGFzIGEgbm9uLXplcm8gbWFyZ2luIHZhbHVlIGFsbCBhcm91bmQgKGJlY2F1c2UgYXBwbHlpbmcgdGhlIG1hcmdpbiBpblxuICAgIC8vIGFsbCBmb3VyIGRpcmVjdGlvbnMgd2lsbCByZXN1bHQgaW4gbm8gbWFyZ2luIHZpc3VhbGx5LCB3aGljaCBpc24ndCB3aGF0IHdlIHdhbnQpLlxuICAgIC8vIFRoZXJlZm9yZSwgb3VyIGxvZ2ljIG1ha2VzIGFzc3VtcHRpb25zIGFib3V0IG1hcmdpbnMgb2YgaW50ZXJlc3QgZ2l2ZW4gdGhlIHBvaW50cyxcbiAgICAvLyBhbmQgb25seSBjb3ZlcnMgdGhlIGNhc2VzIHdoZXJlIHBvcG92ZXIgaXMgb3V0c2lkZSB0aGUgYW5jaG9yLlxuXG4gICAgY29uc3QgcG9wb3ZlckNvbXB1dGVkU3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlKHRoaXMuZWxlbWVudCk7XG4gICAgY29uc3QgbWFyZ2luTGVmdCA9IHBhcnNlSW50KHBvcG92ZXJDb21wdXRlZFN0eWxlLm1hcmdpbkxlZnQsIDEwKTtcbiAgICBjb25zdCBtYXJnaW5SaWdodCA9IHBhcnNlSW50KHBvcG92ZXJDb21wdXRlZFN0eWxlLm1hcmdpblJpZ2h0LCAxMCk7XG4gICAgY29uc3QgbWFyZ2luVG9wID0gcGFyc2VJbnQocG9wb3ZlckNvbXB1dGVkU3R5bGUubWFyZ2luVG9wLCAxMCk7XG4gICAgY29uc3QgbWFyZ2luQm90dG9tID0gcGFyc2VJbnQocG9wb3ZlckNvbXB1dGVkU3R5bGUubWFyZ2luQm90dG9tLCAxMCk7XG5cbiAgICBzd2l0Y2ggKGFuY2hvckFsaWduKSB7XG4gICAgICBjYXNlIFBvaW50LkxFRlRfVE9QOlxuICAgICAgY2FzZSBQb2ludC5UT1BfTEVGVDpcbiAgICAgIGNhc2UgUG9pbnQuVE9QX1JJR0hUOlxuICAgICAgY2FzZSBQb2ludC5SSUdIVF9UT1A6XG4gICAgICAgIGlmIChwb3BvdmVyQWxpZ24gPT09IFBvaW50LkJPVFRPTV9SSUdIVCB8fCBwb3BvdmVyQWxpZ24gPT09IFBvaW50LlJJR0hUX0JPVFRPTSkge1xuICAgICAgICAgIHRvcERpZmYgLT0gbWFyZ2luQm90dG9tO1xuICAgICAgICAgIGxlZnREaWZmIC09IG1hcmdpblJpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIGlmIChwb3BvdmVyQWxpZ24gPT09IFBvaW50LkJPVFRPTV9MRUZUIHx8IHBvcG92ZXJBbGlnbiA9PT0gUG9pbnQuTEVGVF9CT1RUT00pIHtcbiAgICAgICAgICB0b3BEaWZmIC09IG1hcmdpblRvcDtcbiAgICAgICAgICBsZWZ0RGlmZiArPSBtYXJnaW5MZWZ0O1xuICAgICAgICB9XG4gICAgICAgIGlmIChwb3BvdmVyQWxpZ24gPT09IFBvaW50LlRPUF9MRUZUIHx8IHBvcG92ZXJBbGlnbiA9PT0gUG9pbnQuTEVGVF9UT1ApIHtcbiAgICAgICAgICB0b3BEaWZmICs9IG1hcmdpblRvcDtcbiAgICAgICAgICBsZWZ0RGlmZiArPSBtYXJnaW5MZWZ0O1xuICAgICAgICB9XG4gICAgICAgIGlmIChwb3BvdmVyQWxpZ24gPT09IFBvaW50LlRPUF9SSUdIVCB8fCBwb3BvdmVyQWxpZ24gPT09IFBvaW50LlJJR0hUX1RPUCkge1xuICAgICAgICAgIHRvcERpZmYgKz0gbWFyZ2luVG9wO1xuICAgICAgICAgIGxlZnREaWZmIC09IG1hcmdpblJpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQb2ludC5MRUZUX0JPVFRPTTpcbiAgICAgIGNhc2UgUG9pbnQuQk9UVE9NX0xFRlQ6XG4gICAgICBjYXNlIFBvaW50LkJPVFRPTV9SSUdIVDpcbiAgICAgIGNhc2UgUG9pbnQuUklHSFRfQk9UVE9NOlxuICAgICAgICBpZiAocG9wb3ZlckFsaWduID09PSBQb2ludC5CT1RUT01fTEVGVCB8fCBwb3BvdmVyQWxpZ24gPT09IFBvaW50LkxFRlRfQk9UVE9NKSB7XG4gICAgICAgICAgdG9wRGlmZiAtPSBtYXJnaW5Cb3R0b207XG4gICAgICAgICAgbGVmdERpZmYgKz0gbWFyZ2luTGVmdDtcbiAgICAgICAgfVxuICAgICAgICBpZiAocG9wb3ZlckFsaWduID09PSBQb2ludC5CT1RUT01fUklHSFQgfHwgcG9wb3ZlckFsaWduID09PSBQb2ludC5SSUdIVF9CT1RUT00pIHtcbiAgICAgICAgICB0b3BEaWZmIC09IG1hcmdpbkJvdHRvbTtcbiAgICAgICAgICBsZWZ0RGlmZiAtPSBtYXJnaW5SaWdodDtcbiAgICAgICAgfVxuICAgICAgICBpZiAocG9wb3ZlckFsaWduID09PSBQb2ludC5UT1BfTEVGVCB8fCBwb3BvdmVyQWxpZ24gPT09IFBvaW50LkxFRlRfVE9QKSB7XG4gICAgICAgICAgdG9wRGlmZiArPSBtYXJnaW5Ub3A7XG4gICAgICAgICAgbGVmdERpZmYgKz0gbWFyZ2luTGVmdDtcbiAgICAgICAgfVxuICAgICAgICBpZiAocG9wb3ZlckFsaWduID09PSBQb2ludC5UT1BfUklHSFQgfHwgcG9wb3ZlckFsaWduID09PSBQb2ludC5SSUdIVF9UT1ApIHtcbiAgICAgICAgICB0b3BEaWZmICs9IG1hcmdpblRvcDtcbiAgICAgICAgICBsZWZ0RGlmZiAtPSBtYXJnaW5SaWdodDtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUG9pbnQuVE9QX0NFTlRFUjpcbiAgICAgICAgdG9wRGlmZiAtPSBtYXJnaW5Cb3R0b207XG4gICAgICAgIGxlZnREaWZmICs9IG1hcmdpbkxlZnQ7XG4gICAgICAgIGxlZnREaWZmIC09IG1hcmdpblJpZ2h0O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUG9pbnQuQk9UVE9NX0NFTlRFUjpcbiAgICAgICAgdG9wRGlmZiArPSBtYXJnaW5Ub3A7XG4gICAgICAgIGxlZnREaWZmICs9IG1hcmdpbkxlZnQ7XG4gICAgICAgIGxlZnREaWZmIC09IG1hcmdpblJpZ2h0O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUG9pbnQuTEVGVF9DRU5URVI6XG4gICAgICAgIHRvcERpZmYgKz0gbWFyZ2luVG9wO1xuICAgICAgICB0b3BEaWZmIC09IG1hcmdpbkJvdHRvbTtcbiAgICAgICAgbGVmdERpZmYgLT0gbWFyZ2luUmlnaHQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQb2ludC5SSUdIVF9DRU5URVI6XG4gICAgICAgIHRvcERpZmYgKz0gbWFyZ2luVG9wO1xuICAgICAgICB0b3BEaWZmIC09IG1hcmdpbkJvdHRvbTtcbiAgICAgICAgbGVmdERpZmYgKz0gbWFyZ2luTGVmdDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgIH1cblxuICAgIHRoaXMuZWxlbWVudC5zdHlsZS50cmFuc2Zvcm0gPSBgdHJhbnNsYXRlWCgke01hdGgucm91bmQobGVmdERpZmYpfXB4KSB0cmFuc2xhdGVZKCR7TWF0aC5yb3VuZCh0b3BEaWZmKX1weClgO1xuICAgIHJldHVybiB0aGlzLl9zY3JvbGwuYXNPYnNlcnZhYmxlKCk7XG4gIH1cblxuICByZWxlYXNlKCkge1xuICAgIHRoaXMuZWxlbWVudC5zdHlsZS50cmFuc2Zvcm0gPSAnJztcbiAgICB0aGlzLnJlbW92ZVNjcm9sbEV2ZW50TGlzdGVuZXJzKCk7XG4gIH1cblxuICBwcml2YXRlIGlzUG9zaXRpb25lZChjb250YWluZXI6IGFueSkge1xuICAgIGNvbnN0IHBvc2l0aW9uID0gZ2V0Q29tcHV0ZWRTdHlsZShjb250YWluZXIpLnBvc2l0aW9uO1xuICAgIHJldHVybiBwb3NpdGlvbiA9PT0gUE9TSVRJT05fUkVMQVRJVkUgfHwgcG9zaXRpb24gPT09IFBPU0lUSU9OX0FCU09MVVRFIHx8IHBvc2l0aW9uID09PSBQT1NJVElPTl9GSVhFRDtcbiAgfVxuXG4gIHByaXZhdGUgZW1pdFNjcm9sbEV2ZW50KCkge1xuICAgIHRoaXMuX3Njcm9sbC5uZXh0KCk7XG4gIH1cblxuICBwcml2YXRlIGFkZFNjcm9sbEV2ZW50TGlzdGVuZXJzKGU6IGFueSkge1xuICAgIHRoaXMuX3Njcm9sbCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gICAgY29uc3QgYW5jaG9yOiBhbnkgPSBlO1xuICAgIGxldCBjdXJyZW50OiBhbnkgPSBlO1xuICAgIHdoaWxlIChjdXJyZW50ICYmIGN1cnJlbnQgIT09IGRvY3VtZW50KSB7XG4gICAgICBpZiAodGhpcy5zY3JvbGxzKGN1cnJlbnQpKSB7XG4gICAgICAgIGN1cnJlbnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5ib3VuZE9uU2Nyb2xsTGlzdGVuZXIpO1xuICAgICAgICB0aGlzLnNjcm9sbGFibGVFbGVtZW50cy5wdXNoKGN1cnJlbnQpO1xuICAgICAgfVxuICAgICAgaWYgKGN1cnJlbnQgIT09IGFuY2hvciAmJiB0aGlzLmlzUG9zaXRpb25lZChjdXJyZW50KSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGN1cnJlbnQgPSBjdXJyZW50LnBhcmVudE5vZGU7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZW1vdmVTY3JvbGxFdmVudExpc3RlbmVycygpIHtcbiAgICBmb3IgKGNvbnN0IGVsZW0gb2YgdGhpcy5zY3JvbGxhYmxlRWxlbWVudHMpIHtcbiAgICAgIGVsZW0ucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5ib3VuZE9uU2Nyb2xsTGlzdGVuZXIpO1xuICAgIH1cbiAgICB0aGlzLnNjcm9sbGFibGVFbGVtZW50cy5sZW5ndGggPSAwO1xuICAgIGlmICh0aGlzLl9zY3JvbGwpIHtcbiAgICAgIHRoaXMuX3Njcm9sbC5jb21wbGV0ZSgpO1xuICAgICAgZGVsZXRlIHRoaXMuX3Njcm9sbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNjcm9sbHMoY29udGFpbmVyOiBhbnkpOiBib29sZWFuIHtcbiAgICBjb25zdCBjb21wdXRlZFN0eWxlcyA9IGdldENvbXB1dGVkU3R5bGUoY29udGFpbmVyKTtcbiAgICByZXR1cm4gKFxuICAgICAgY29tcHV0ZWRTdHlsZXMub3ZlcmZsb3dYID09PSBPVkVSRkxPV19TQ1JPTEwgfHxcbiAgICAgIGNvbXB1dGVkU3R5bGVzLm92ZXJmbG93WCA9PT0gT1ZFUkZMT1dfQVVUTyB8fFxuICAgICAgY29tcHV0ZWRTdHlsZXMub3ZlcmZsb3dZID09PSBPVkVSRkxPV19TQ1JPTEwgfHxcbiAgICAgIGNvbXB1dGVkU3R5bGVzLm92ZXJmbG93WSA9PT0gT1ZFUkZMT1dfQVVUT1xuICAgICk7XG4gIH1cbn1cbiJdfQ==