UNPKG

smart-tooltip-angular

Version:

A package that allows you tooltip to show intelligently base on where it is

447 lines 58.4 kB
import { __decorate, __values } from "tslib"; import { OnInit, Directive, HostBinding, HostListener, ElementRef } from '@angular/core'; var SmartTooltipAngularDirective = /** @class */ (function () { function SmartTooltipAngularDirective(elementRef) { this.elementRef = elementRef; this.classes = ["right", "right-t", "right-b", "left", "left-t", "left-b", "bottom", "bottom-r", "bottom-l", "top", "top-r", "top-l"]; this.offSetValue = 5; var tooltipContainer = elementRef.nativeElement; tooltipContainer.classList.add("smart-tooltip-container"); } SmartTooltipAngularDirective.prototype.mouseEnter = function () { //Run the code on click if the element doesn't have the clicktoshow class if (!this.elementRef.nativeElement.classList.contains("clicktoshow")) { this.myfunc(this.elementRef); } }; SmartTooltipAngularDirective.prototype.click = function () { //Run the code on click if the element has the clicktoshow class if (this.elementRef.nativeElement.classList.contains("clicktoshow")) { //Get access to the tooltip element var tooltip = this.elementRef.nativeElement.querySelector(".smart-tooltip"); //Add the stick class to allow the element to stay when it's clicked tooltip.classList.add("stick"); this.myfunc(this.elementRef); } }; SmartTooltipAngularDirective.prototype.mouseLeave = function () { this.mouseLeft(this.elementRef); }; SmartTooltipAngularDirective.prototype.ngOnInit = function () { var _this = this; var tooltipContainer = this.elementRef.nativeElement; var tooltip = tooltipContainer.querySelector(".smart-tooltip"); //Assign tabIndex to allow element to be focusable if (tooltip) { tooltip.tabIndex = 1; tooltip.addEventListener("blur", function (event) { _this.toolTipBlured(event.target); }); tooltip.addEventListener("mouseleave", function (event) { _this.tooltipMouseLeft(event.target); }); tooltip.addEventListener("mouseenter", function (event) { _this.tooltipMouseEnter(event.target); }); } }; SmartTooltipAngularDirective.prototype.toolTipBlured = function (tooltip) { //console.log("toolTipBlured"); if (this.removeOverlayClass(tooltip)) { var tooltipRect = tooltip.getBoundingClientRect(); //Reset Inline Styles tooltip.style.position = ""; tooltip.style.top = ""; tooltip.style.left = ""; tooltip.style.bottom = ""; tooltip.style.right = ""; tooltip.classList.add("overlay"); } tooltip.style.visibility = "collapse"; tooltip.style.opacity = "0"; tooltip.style.display = "none"; }; SmartTooltipAngularDirective.prototype.myfunc = function (elementRef) { clearTimeout(this.mouseLeftTimeOut); var root = this; var btn = elementRef.nativeElement; if (!btn) return; //var body = document.querySelector("body"); var tooltip = btn.querySelector(".smart-tooltip"); if (!tooltip) return; tooltip.style.visibility = "visible"; tooltip.style.opacity = "1"; tooltip.style.display = "block"; var tooltipclient = tooltip.getBoundingClientRect(); var btnclient = btn.getBoundingClientRect(); //var bodyclient = body.getClientRects()[0]; var windowWidth = window.innerWidth; var windowHeight = window.innerHeight; var spaces = { left: btnclient.left > tooltipclient.width, right: (windowWidth - btnclient.right) > tooltipclient.width, top: btnclient.top > tooltipclient.height, bottom: (windowHeight - btnclient.bottom) > tooltipclient.height, getSpace: function (key) { var stayClass = root.getStayClass(tooltip); // debugger; if (stayClass) { if (stayClass == key) return true; else return false; } return this[key]; } }; this.removeTooltipClass(tooltip); if (spaces.getSpace("left")) { var topHalf = (btnclient.bottom - (btnclient.height / 2)); var bottomHalf = windowHeight - topHalf; var halfTooltip = (tooltipclient.height / 2); var isContainerBigger = btnclient.height >= tooltipclient.height; if (isContainerBigger || ((topHalf > halfTooltip) && (bottomHalf > halfTooltip))) { if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "left")) { tooltip.classList.add('left'); } } else if (topHalf <= halfTooltip) { if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "left-b")) { tooltip.classList.add('left-b'); } } else if (bottomHalf <= halfTooltip) { if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "left-t")) { tooltip.classList.add('left-t'); } } } else if (spaces.getSpace("right")) { var topHalf = (btnclient.bottom - (btnclient.height / 2)); var bottomHalf = windowHeight - topHalf; var halfTooltip = (tooltipclient.height / 2); var isContainerBigger = btnclient.height >= tooltipclient.height; if (isContainerBigger || ((topHalf > halfTooltip) && (bottomHalf > halfTooltip))) { if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "right")) { tooltip.classList.add('right'); } } else if (topHalf <= halfTooltip) { if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "right-b")) { tooltip.classList.add('right-b'); } } else if (bottomHalf <= halfTooltip) { if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "right-t")) { tooltip.classList.add('right-t'); } } } else if (spaces.getSpace("top")) { var leftHalf = (btnclient.right - (btnclient.width / 2)); var rightHalf = windowWidth - leftHalf; var halfTooltip = (tooltipclient.width / 2); var isContainerBigger = btnclient.width >= tooltipclient.width; if (isContainerBigger || ((leftHalf > halfTooltip) && (rightHalf > halfTooltip))) { if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "top")) { tooltip.classList.add('top'); } } else if (leftHalf <= halfTooltip) { if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "top-r")) { tooltip.classList.add('top-r'); } } else if (rightHalf <= halfTooltip) { if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "top-l")) { tooltip.classList.add('top-l'); } } } else if (spaces.getSpace("bottom")) { // debugger; var leftHalf = (btnclient.right - (btnclient.width / 2)); var rightHalf = windowWidth - leftHalf; var halfTooltip = (tooltipclient.width / 2); var isContainerBigger = btnclient.width >= tooltipclient.width; if (isContainerBigger || ((leftHalf > halfTooltip) && (rightHalf > halfTooltip))) { if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "bottom")) { tooltip.classList.add('bottom'); } } else if (leftHalf <= halfTooltip) { if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "bottom-r")) { tooltip.classList.add('bottom-r'); } } else if (rightHalf <= halfTooltip) { if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "bottom-l")) { tooltip.classList.add('bottom-l'); } } } else { // debugger; if (!this.manipulateOverlayIfPresent(btnclient, tooltip, "bottom")) { tooltip.classList.add('bottom'); } } }; SmartTooltipAngularDirective.prototype.removeTooltipClass = function (tooltip) { var _this = this; var classList = tooltip.classList; classList.forEach(function (element) { if (_this.classes.includes(element)) { classList.remove(element); } }); }; SmartTooltipAngularDirective.prototype.getStayClass = function (tooltip) { var classList = tooltip.classList; var stayPosition; classList.forEach(function (element) { if (element.includes("stay-")) { stayPosition = element.split("-")[1]; } }); return stayPosition; }; SmartTooltipAngularDirective.prototype.mouseLeft = function (elementRef) { var _this = this; // console.log("mouseLeft"); var btn = elementRef.nativeElement; if (!btn) return; var tooltip = btn.querySelector(".smart-tooltip"); if (!tooltip) return; var stickyTime = this.getStickyTime(tooltip); if (!isNaN(stickyTime)) { this.mouseLeftTimeOut = setTimeout(function () { if (tooltip.classList.contains("hovered")) return; if (_this.removeOverlayClass(tooltip)) { var tooltipRect = tooltip.getBoundingClientRect(); //Reset Inline Styles tooltip.style.position = ""; tooltip.style.top = ""; tooltip.style.left = ""; tooltip.style.bottom = ""; tooltip.style.right = ""; tooltip.classList.add("overlay"); } //Make sure its not visible after mouse has left tooltip.style.visibility = "collapse"; tooltip.style.opacity = "0"; tooltip.style.display = "none"; }, stickyTime); } else { tooltip.focus(); } }; SmartTooltipAngularDirective.prototype.removeOverlayClass = function (tooltip) { var hasOverlay = false; if (tooltip.classList.contains("overlayed")) { hasOverlay = true; tooltip.classList.remove("overlayed"); } return hasOverlay; }; SmartTooltipAngularDirective.prototype.removeOverlayMarkClass = function (tooltip) { var hasOverlay = false; if (tooltip.classList.contains("overlay")) { hasOverlay = true; tooltip.classList.remove("overlay"); } return hasOverlay; }; /** * Calculate the position of the tooltip based on the fixed position of the container * @param {DOMClientRect} btnclient The Rectangle that defines the button element * @param {string} tooltipPostion The position the tooltip should be displayed */ SmartTooltipAngularDirective.prototype.getOverlayCoordinates = function (btnclient, tooltipclient, tooltipPostion) { // let body:any = document.querySelector("body"); // let bodyclient = body.getClientRects()[0]; var windowWidth = window.innerWidth; var windowHeight = window.innerHeight; if (tooltipPostion.includes("right")) { var overlayCoordinates = { left: btnclient.right + this.offSetValue, top: (btnclient.top + (btnclient.height / 2)) - (tooltipclient.height / 2), props: ["left", "top"] }; if (tooltipPostion == "right-t") { overlayCoordinates.bottom = windowHeight - btnclient.bottom; overlayCoordinates.props = ["left", "bottom"]; } else if (tooltipPostion == "right-b") { overlayCoordinates.top = btnclient.top + this.offSetValue; } return overlayCoordinates; } else if (tooltipPostion.includes("left")) { var overlayCoordinates = { right: (windowWidth - btnclient.left) + this.offSetValue, top: (btnclient.top + (btnclient.height / 2)) - (tooltipclient.height / 2), props: ["right", "top"] }; if (tooltipPostion == "left-t") { overlayCoordinates.bottom = windowHeight - btnclient.bottom; overlayCoordinates.props = ["right", "bottom"]; } else if (tooltipPostion == "left-b") { overlayCoordinates.top = btnclient.top + this.offSetValue; } return overlayCoordinates; } else if (tooltipPostion.includes("top")) { var overlayCoordinates = { left: (btnclient.right - (btnclient.width / 2)) - (tooltipclient.width / 2), bottom: (windowHeight - btnclient.top) + this.offSetValue, props: ["left", "bottom"] }; if (tooltipPostion == "top-l") { overlayCoordinates.right = (windowWidth - btnclient.right) + this.offSetValue; overlayCoordinates.props = ["right", "bottom"]; } else if (tooltipPostion == "top-r") { overlayCoordinates.left = btnclient.left + this.offSetValue; } return overlayCoordinates; } else if (tooltipPostion.includes("bottom")) { var overlayCoordinates = { left: (btnclient.right - (btnclient.width / 2)) - (tooltipclient.width / 2), top: btnclient.bottom + this.offSetValue, props: ["left", "top"] }; if (tooltipPostion == "bottom-l") { overlayCoordinates.right = (windowWidth - btnclient.right) + this.offSetValue; overlayCoordinates.props = ["right", "top"]; } else if (tooltipPostion == "bottom-r") { overlayCoordinates.left = btnclient.left + this.offSetValue; } return overlayCoordinates; } }; /** * Checks for overlay class and manipulate it * @param {any} tooltip the tooltip element * @param {string} position the string that show which side the tooltip is */ SmartTooltipAngularDirective.prototype.manipulateOverlayIfPresent = function (btnBClientRect, tooltip, tooltipPosition) { var e_1, _a; //removeOverlayMarkClass checks for the presence of the overlay mark i.e //overlay .. remove it and add the overlayed class which has the css declarations //debugger; if (this.removeOverlayMarkClass(tooltip)) { // debugger; //Get the overlay coordinates var overlayCoordinates = this.getOverlayCoordinates(btnBClientRect, tooltip.getBoundingClientRect(), tooltipPosition); //Get the set properties base the tooltip position based on the tooltipPosition //Overlay styles to tooltip control tooltip.style.position = "fixed"; try { for (var _b = __values(overlayCoordinates.props), _c = _b.next(); !_c.done; _c = _b.next()) { var prop = _c.value; tooltip.style[prop] = overlayCoordinates[prop] + "px"; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } //Add the actual overlayed class which resets old styles tooltip.classList.add("overlayed"); return true; } return false; }; /** * Get the sticky time on the tooltip or returns zero if none is found * @param {HtmlElement} tooltip The tooltip element */ SmartTooltipAngularDirective.prototype.getStickyTime = function (tooltip) { var e_2, _a; try { try { for (var _b = __values(tooltip.classList), _c = _b.next(); !_c.done; _c = _b.next()) { var item = _c.value; if (item.includes("stick")) { if (item.includes("-")) { var numberstring = item.split("-")[1]; return +numberstring; } else { return Number.NaN; } } } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_2) throw e_2.error; } } } catch (_d) { return 0; } //return zero if tooltip doesn't have a sticky class return 0; }; SmartTooltipAngularDirective.prototype.tooltipMouseLeft = function (tooltip) { //console.log("tooltipMouseLeft"); if (tooltip.classList.contains('hovered')) { if (!isNaN(this.getStickyTime(tooltip))) { tooltip.classList.add("stayonhover"); tooltip.classList.remove('hovered'); //console.log("blured"); //tooltip.blur(); } } }; SmartTooltipAngularDirective.prototype.tooltipMouseEnter = function (tooltip) { //console.log("tooltipMouseEnter"); if (tooltip.classList.contains('stayonhover')) { if (!isNaN(this.getStickyTime(tooltip))) { tooltip.classList.remove("stayonhover"); tooltip.classList.add('hovered'); //tooltip.focus(); } } }; SmartTooltipAngularDirective.ctorParameters = function () { return [ { type: ElementRef } ]; }; __decorate([ HostBinding("style.position") ], SmartTooltipAngularDirective.prototype, "position", void 0); __decorate([ HostListener("mouseenter") ], SmartTooltipAngularDirective.prototype, "mouseEnter", null); __decorate([ HostListener("click") ], SmartTooltipAngularDirective.prototype, "click", null); __decorate([ HostListener("mouseleave") ], SmartTooltipAngularDirective.prototype, "mouseLeave", null); SmartTooltipAngularDirective = __decorate([ Directive({ selector: '[smart-tooltip-container]', }) ], SmartTooltipAngularDirective); return SmartTooltipAngularDirective; }()); export { SmartTooltipAngularDirective }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnQtdG9vbHRpcC1hbmd1bGFyLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL3NtYXJ0LXRvb2x0aXAtYW5ndWxhci8iLCJzb3VyY2VzIjpbImxpYi9zbWFydC10b29sdGlwLWFuZ3VsYXIuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQU96RjtJQWlDRSxzQ0FBb0IsVUFBc0I7UUFBdEIsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQS9CMUMsWUFBTyxHQUFHLENBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUVqSSxnQkFBVyxHQUFHLENBQUMsQ0FBQztRQThCZCxJQUFJLGdCQUFnQixHQUFHLFVBQVUsQ0FBQyxhQUFhLENBQUM7UUFDaEQsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUExQjJCLGlEQUFVLEdBQVY7UUFDMUIseUVBQXlFO1FBQ3pFLElBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxFQUFDO1lBQ2xFLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1NBQzlCO0lBQ0gsQ0FBQztJQUVzQiw0Q0FBSyxHQUFMO1FBQ3JCLGdFQUFnRTtRQUNoRSxJQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLEVBQUM7WUFDakUsbUNBQW1DO1lBQ25DLElBQUks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LENBQUM7Z0JBQ3hDLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUNqQyxrQkFBa0I7YUFDbkI7U0FDRjtJQUNILENBQUM7O2dCQXRjK0IsVUFBVTs7SUF6Qlg7UUFBOUIsV0FBVyxDQUFDLGdCQUFnQixDQUFDO2tFQUFVO0lBRVo7UUFBM0IsWUFBWSxDQUFDLFlBQVksQ0FBQztrRUFLMUI7SUFFc0I7UUFBdEIsWUFBWSxDQUFDLE9BQU8sQ0FBQzs2REFVckI7SUFFMkI7UUFBM0IsWUFBWSxDQUFDLFlBQVksQ0FBQztrRUFFMUI7SUEvQlUsNEJBQTRCO1FBSnhDLFNBQVMsQ0FBQztZQUNULFFBQVEsRUFBRSwyQkFBMkI7U0FFdEMsQ0FBQztPQUNXLDRCQUE0QixDQXlleEM7SUFBRCxtQ0FBQztDQUFBLEFBemVELElBeWVDO1NBemVZLDRCQUE0QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9uSW5pdCwgRGlyZWN0aXZlLCBIb3N0QmluZGluZywgSG9zdExpc3RlbmVyLCBFbGVtZW50UmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBlbGVtZW50IH0gZnJvbSAncHJvdHJhY3Rvcic7XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tzbWFydC10b29sdGlwLWNvbnRhaW5lcl0nLFxuXG59KVxuZXhwb3J0IGNsYXNzIFNtYXJ0VG9vbHRpcEFuZ3VsYXJEaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQge1xuXG4gIGNsYXNzZXMgPSBbXCJyaWdodFwiLCBcInJpZ2h0LXRcIiwgXCJyaWdodC1iXCIsIFwibGVmdFwiLCBcImxlZnQtdFwiLCBcImxlZnQtYlwiLCBcImJvdHRvbVwiLCBcImJvdHRvbS1yXCIsIFwiYm90dG9tLWxcIiwgXCJ0b3BcIiwgXCJ0b3AtclwiLCBcInRvcC1sXCJdO1xuXG4gIG9mZlNldFZhbHVlID0gNTtcblxuICBtb3VzZUxlZnRUaW1lT3V0O1xuXG4gIEBIb3N0QmluZGluZyhcInN0eWxlLnBvc2l0aW9uXCIpIHBvc2l0aW9uO1xuXG4gIEBIb3N0TGlzdGVuZXIoXCJtb3VzZWVudGVyXCIpIG1vdXNlRW50ZXIoKSB7XG4gICAgLy9SdW4gdGhlIGNvZGUgb24gY2xpY2sgaWYgdGhlIGVsZW1lbnQgZG9lc24ndCBoYXZlIHRoZSBjbGlja3Rvc2hvdyBjbGFzc1xuICAgIGlmKCF0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoXCJjbGlja3Rvc2hvd1wiKSl7XG4gICAgICB0aGlzLm15ZnVuYyh0aGlzLmVsZW1lbnRSZWYpO1xuICAgIH1cbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoXCJjbGlja1wiKSBjbGljaygpIHtcbiAgICAvL1J1biB0aGUgY29kZSBvbiBjbGljayBpZiB0aGUgZWxlbWVudCBoYXMgdGhlIGNsaWNrdG9zaG93IGNsYXNzXG4gICAgaWYodGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKFwiY2xpY2t0b3Nob3dcIikpe1xuICAgICAgLy9HZXQgYWNjZXNzIHRvIHRoZSB0b29sdGlwIGVsZW1lbnRcbiAgICAgIGxldCB0b29sdGlwID0gdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcihcIi5zbWFydC10b29sdGlwXCIpO1xuICAgICAgLy9BZGQgdGhlIHN0aWNrIGNsYXNzIHRvIGFsbG93IHRoZSBlbGVtZW50IHRvIHN0YXkgd2hlbiBpdCdzIGNsaWNrZWRcbiAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZChcInN0aWNrXCIpO1xuXG4gICAgICB0aGlzLm15ZnVuYyh0aGlzLmVsZW1lbnRSZWYpO1xuICAgIH1cbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoXCJtb3VzZWxlYXZlXCIpIG1vdXNlTGVhdmUoKSB7XG4gICAgdGhpcy5tb3VzZUxlZnQodGhpcy5lbGVtZW50UmVmKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZikge1xuICAgIGxldCB0b29sdGlwQ29udGFpbmVyID0gZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xuICAgIHRvb2x0aXBDb250YWluZXIuY2xhc3NMaXN0LmFkZChcInNtYXJ0LXRvb2x0aXAtY29udGFpbmVyXCIpO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgbGV0IHRvb2x0aXBDb250YWluZXIgPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcbiAgICBsZXQgdG9vbHRpcCA9IHRvb2x0aXBDb250YWluZXIucXVlcnlTZWxlY3RvcihcIi5zbWFydC10b29sdGlwXCIpO1xuICAgIC8vQXNzaWduIHRhYkluZGV4IHRvIGFsbG93IGVsZW1lbnQgdG8gYmUgZm9jdXNhYmxlXG4gICAgaWYgKHRvb2x0aXApIHtcbiAgICAgIHRvb2x0aXAudGFiSW5kZXggPSAxO1xuXG4gICAgICB0b29sdGlwLmFkZEV2ZW50TGlzdGVuZXIoXCJibHVyXCIsIChldmVudCkgPT4ge1xuICAgICAgICB0aGlzLnRvb2xUaXBCbHVyZWQoZXZlbnQudGFyZ2V0KTtcbiAgICAgIH0pO1xuXG4gICAgICB0b29sdGlwLmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZWxlYXZlXCIsIChldmVudCkgPT4ge1xuICAgICAgICB0aGlzLnRvb2x0aXBNb3VzZUxlZnQoZXZlbnQudGFyZ2V0KVxuICAgICAgfSk7XG5cbiAgICAgIHRvb2x0aXAuYWRkRXZlbnRMaXN0ZW5lcihcIm1vdXNlZW50ZXJcIiwgKGV2ZW50KSA9PiB7XG4gICAgICAgIHRoaXMudG9vbHRpcE1vdXNlRW50ZXIoZXZlbnQudGFyZ2V0KTtcbiAgICAgIH0pO1xuXG4gICAgfVxuICB9XG5cblxuICB0b29sVGlwQmx1cmVkKHRvb2x0aXApIHtcbiAgICAvL2NvbnNvbGUubG9nKFwidG9vbFRpcEJsdXJlZFwiKTtcbiAgICBpZiAodGhpcy5yZW1vdmVPdmVybGF5Q2xhc3ModG9vbHRpcCkpIHtcblxuICAgICAgbGV0IHRvb2x0aXBSZWN0ID0gdG9vbHRpcC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgICAgLy9SZXNldCBJbmxpbmUgU3R5bGVzXG4gICAgICB0b29sdGlwLnN0eWxlLnBvc2l0aW9uID0gXCJcIjtcbiAgICAgIHRvb2x0aXAuc3R5bGUudG9wID0gXCJcIjtcbiAgICAgIHRvb2x0aXAuc3R5bGUubGVmdCA9IFwiXCI7XG4gICAgICB0b29sdGlwLnN0eWxlLmJvdHRvbSA9IFwiXCI7XG4gICAgICB0b29sdGlwLnN0eWxlLnJpZ2h0ID0gXCJcIjtcblxuICAgICAgdG9vbHRpcC5jbGFzc0xpc3QuYWRkKFwib3ZlcmxheVwiKTtcbiAgICB9XG5cbiAgICB0b29sdGlwLnN0eWxlLnZpc2liaWxpdHkgPSBcImNvbGxhcHNlXCJcbiAgICB0b29sdGlwLnN0eWxlLm9wYWNpdHkgPSBcIjBcIjtcbiAgICB0b29sdGlwLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcblxuICB9XG5cblxuICBteWZ1bmMoZWxlbWVudFJlZjogRWxlbWVudFJlZikge1xuICAgIGNsZWFyVGltZW91dCh0aGlzLm1vdXNlTGVmdFRpbWVPdXQpO1xuICAgIGxldCByb290ID0gdGhpcztcblxuICAgIGxldCBidG4gPSBlbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgaWYgKCFidG4pIHJldHVybjtcbiAgICAvL3ZhciBib2R5ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcImJvZHlcIik7XG5cbiAgICBsZXQgdG9vbHRpcCA9IGJ0bi5xdWVyeVNlbGVjdG9yKFwiLnNtYXJ0LXRvb2x0aXBcIik7XG5cbiAgICBpZiAoIXRvb2x0aXApIHJldHVybjtcblxuICAgIHRvb2x0aXAuc3R5bGUudmlzaWJpbGl0eSA9IFwidmlzaWJsZVwiO1xuICAgIHRvb2x0aXAuc3R5bGUub3BhY2l0eSA9IFwiMVwiO1xuICAgIHRvb2x0aXAuc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcblxuICAgIHZhciB0b29sdGlwY2xpZW50ID0gdG9vbHRpcC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB2YXIgYnRuY2xpZW50ID0gYnRuLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIC8vdmFyIGJvZHljbGllbnQgPSBib2R5LmdldENsaWVudFJlY3RzKClbMF07XG5cbiAgICBsZXQgd2luZG93V2lkdGggPSB3aW5kb3cuaW5uZXJXaWR0aDtcbiAgICBsZXQgd2luZG93SGVpZ2h0ID0gd2luZG93LmlubmVySGVpZ2h0O1xuXG4gICAgdmFyIHNwYWNlcyA9IHtcbiAgICAgIGxlZnQ6IGJ0bmNsaWVudC5sZWZ0ID4gdG9vbHRpcGNsaWVudC53aWR0aCxcbiAgICAgIHJpZ2h0OiAod2luZG93V2lkdGggLSBidG5jbGllbnQucmlnaHQpID4gdG9vbHRpcGNsaWVudC53aWR0aCxcbiAgICAgIHRvcDogYnRuY2xpZW50LnRvcCA+IHRvb2x0aXBjbGllbnQuaGVpZ2h0LFxuICAgICAgYm90dG9tOiAod2luZG93SGVpZ2h0IC0gYnRuY2xpZW50LmJvdHRvbSkgPiB0b29sdGlwY2xpZW50LmhlaWdodCxcbiAgICAgIGdldFNwYWNlOiBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIGxldCBzdGF5Q2xhc3MgPSByb290LmdldFN0YXlDbGFzcyh0b29sdGlwKTtcbiAgICAgICAgLy8gZGVidWdnZXI7XG4gICAgICAgIGlmIChzdGF5Q2xhc3MpIHtcbiAgICAgICAgICBpZiAoc3RheUNsYXNzID09IGtleSlcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpc1trZXldO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMucmVtb3ZlVG9vbHRpcENsYXNzKHRvb2x0aXApO1xuXG4gICAgaWYgKHNwYWNlcy5nZXRTcGFjZShcImxlZnRcIikpIHtcblxuICAgICAgbGV0IHRvcEhhbGYgPSAoYnRuY2xpZW50LmJvdHRvbSAtIChidG5jbGllbnQuaGVpZ2h0IC8gMikpO1xuICAgICAgbGV0IGJvdHRvbUhhbGYgPSB3aW5kb3dIZWlnaHQgLSB0b3BIYWxmO1xuICAgICAgbGV0IGhhbGZUb29sdGlwID0gKHRvb2x0aXBjbGllbnQuaGVpZ2h0IC8gMik7XG5cbiAgICAgIGxldCBpc0NvbnRhaW5lckJpZ2dlciA9IGJ0bmNsaWVudC5oZWlnaHQgPj0gdG9vbHRpcGNsaWVudC5oZWlnaHQ7XG5cbiAgICAgIGlmIChpc0NvbnRhaW5lckJpZ2dlciB8fCAoKHRvcEhhbGYgPiBoYWxmVG9vbHRpcCkgJiYgKGJvdHRvbUhhbGYgPiBoYWxmVG9vbHRpcCkpKSB7XG4gICAgICAgIGlmICghdGhpcy5tYW5pcHVsYXRlT3ZlcmxheUlmUHJlc2VudChidG5jbGllbnQsIHRvb2x0aXAsIFwibGVmdFwiKSkge1xuICAgICAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZCgnbGVmdCcpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHRvcEhhbGYgPD0gaGFsZlRvb2x0aXApIHtcbiAgICAgICAgaWYgKCF0aGlzLm1hbmlwdWxhdGVPdmVybGF5SWZQcmVzZW50KGJ0bmNsaWVudCwgdG9vbHRpcCwgXCJsZWZ0LWJcIikpIHtcbiAgICAgICAgICB0b29sdGlwLmNsYXNzTGlzdC5hZGQoJ2xlZnQtYicpO1xuICAgICAgICB9XG5cbiAgICAgIH0gZWxzZSBpZiAoYm90dG9tSGFsZiA8PSBoYWxmVG9vbHRpcCkge1xuICAgICAgICBpZiAoIXRoaXMubWFuaXB1bGF0ZU92ZXJsYXlJZlByZXNlbnQoYnRuY2xpZW50LCB0b29sdGlwLCBcImxlZnQtdFwiKSkge1xuICAgICAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZCgnbGVmdC10Jyk7XG4gICAgICAgIH1cblxuICAgICAgfVxuXG4gICAgfSBlbHNlIGlmIChzcGFjZXMuZ2V0U3BhY2UoXCJyaWdodFwiKSkge1xuXG4gICAgICBsZXQgdG9wSGFsZiA9IChidG5jbGllbnQuYm90dG9tIC0gKGJ0bmNsaWVudC5oZWlnaHQgLyAyKSk7XG4gICAgICBsZXQgYm90dG9tSGFsZiA9IHdpbmRvd0hlaWdodCAtIHRvcEhhbGY7XG4gICAgICBsZXQgaGFsZlRvb2x0aXAgPSAodG9vbHRpcGNsaWVudC5oZWlnaHQgLyAyKTtcblxuICAgICAgbGV0IGlzQ29udGFpbmVyQmlnZ2VyID0gYnRuY2xpZW50LmhlaWdodCA+PSB0b29sdGlwY2xpZW50LmhlaWdodDtcblxuICAgICAgaWYgKGlzQ29udGFpbmVyQmlnZ2VyIHx8ICgodG9wSGFsZiA+IGhhbGZUb29sdGlwKSAmJiAoYm90dG9tSGFsZiA+IGhhbGZUb29sdGlwKSkpIHtcbiAgICAgICAgaWYgKCF0aGlzLm1hbmlwdWxhdGVPdmVybGF5SWZQcmVzZW50KGJ0bmNsaWVudCwgdG9vbHRpcCwgXCJyaWdodFwiKSkge1xuICAgICAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZCgncmlnaHQnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0b3BIYWxmIDw9IGhhbGZUb29sdGlwKSB7XG4gICAgICAgIGlmICghdGhpcy5tYW5pcHVsYXRlT3ZlcmxheUlmUHJlc2VudChidG5jbGllbnQsIHRvb2x0aXAsIFwicmlnaHQtYlwiKSkge1xuICAgICAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZCgncmlnaHQtYicpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGJvdHRvbUhhbGYgPD0gaGFsZlRvb2x0aXApIHtcbiAgICAgICAgaWYgKCF0aGlzLm1hbmlwdWxhdGVPdmVybGF5SWZQcmVzZW50KGJ0bmNsaWVudCwgdG9vbHRpcCwgXCJyaWdodC10XCIpKSB7XG4gICAgICAgICAgdG9vbHRpcC5jbGFzc0xpc3QuYWRkKCdyaWdodC10Jyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgIH0gZWxzZSBpZiAoc3BhY2VzLmdldFNwYWNlKFwidG9wXCIpKSB7XG5cbiAgICAgIGxldCBsZWZ0SGFsZiA9IChidG5jbGllbnQucmlnaHQgLSAoYnRuY2xpZW50LndpZHRoIC8gMikpO1xuICAgICAgbGV0IHJpZ2h0SGFsZiA9IHdpbmRvd1dpZHRoIC0gbGVmdEhhbGY7XG4gICAgICBsZXQgaGFsZlRvb2x0aXAgPSAodG9vbHRpcGNsaWVudC53aWR0aCAvIDIpO1xuXG4gICAgICBsZXQgaXNDb250YWluZXJCaWdnZXIgPSBidG5jbGllbnQud2lkdGggPj0gdG9vbHRpcGNsaWVudC53aWR0aDtcblxuICAgICAgaWYgKGlzQ29udGFpbmVyQmlnZ2VyIHx8ICgobGVmdEhhbGYgPiBoYWxmVG9vbHRpcCkgJiYgKHJpZ2h0SGFsZiA+IGhhbGZUb29sdGlwKSkpIHtcbiAgICAgICAgaWYgKCF0aGlzLm1hbmlwdWxhdGVPdmVybGF5SWZQcmVzZW50KGJ0bmNsaWVudCwgdG9vbHRpcCwgXCJ0b3BcIikpIHtcbiAgICAgICAgICB0b29sdGlwLmNsYXNzTGlzdC5hZGQoJ3RvcCcpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGxlZnRIYWxmIDw9IGhhbGZUb29sdGlwKSB7XG4gICAgICAgIGlmICghdGhpcy5tYW5pcHVsYXRlT3ZlcmxheUlmUHJlc2VudChidG5jbGllbnQsIHRvb2x0aXAsIFwidG9wLXJcIikpIHtcbiAgICAgICAgICB0b29sdGlwLmNsYXNzTGlzdC5hZGQoJ3RvcC1yJyk7XG4gICAgICAgIH1cblxuICAgICAgfSBlbHNlIGlmIChyaWdodEhhbGYgPD0gaGFsZlRvb2x0aXApIHtcbiAgICAgICAgaWYgKCF0aGlzLm1hbmlwdWxhdGVPdmVybGF5SWZQcmVzZW50KGJ0bmNsaWVudCwgdG9vbHRpcCwgXCJ0b3AtbFwiKSkge1xuICAgICAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZCgndG9wLWwnKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgfSBlbHNlIGlmIChzcGFjZXMuZ2V0U3BhY2UoXCJib3R0b21cIikpIHtcbiAgICAgIC8vIGRlYnVnZ2VyO1xuICAgICAgbGV0IGxlZnRIYWxmID0gKGJ0bmNsaWVudC5yaWdodCAtIChidG5jbGllbnQud2lkdGggLyAyKSk7XG4gICAgICBsZXQgcmlnaHRIYWxmID0gd2luZG93V2lkdGggLSBsZWZ0SGFsZjtcbiAgICAgIGxldCBoYWxmVG9vbHRpcCA9ICh0b29sdGlwY2xpZW50LndpZHRoIC8gMik7XG5cbiAgICAgIGxldCBpc0NvbnRhaW5lckJpZ2dlciA9IGJ0bmNsaWVudC53aWR0aCA+PSB0b29sdGlwY2xpZW50LndpZHRoO1xuXG5cblxuICAgICAgaWYgKGlzQ29udGFpbmVyQmlnZ2VyIHx8ICgobGVmdEhhbGYgPiBoYWxmVG9vbHRpcCkgJiYgKHJpZ2h0SGFsZiA+IGhhbGZUb29sdGlwKSkpIHtcbiAgICAgICAgaWYgKCF0aGlzLm1hbmlwdWxhdGVPdmVybGF5SWZQcmVzZW50KGJ0bmNsaWVudCwgdG9vbHRpcCwgXCJib3R0b21cIikpIHtcbiAgICAgICAgICB0b29sdGlwLmNsYXNzTGlzdC5hZGQoJ2JvdHRvbScpO1xuICAgICAgICB9XG5cbiAgICAgIH0gZWxzZSBpZiAobGVmdEhhbGYgPD0gaGFsZlRvb2x0aXApIHtcbiAgICAgICAgaWYgKCF0aGlzLm1hbmlwdWxhdGVPdmVybGF5SWZQcmVzZW50KGJ0bmNsaWVudCwgdG9vbHRpcCwgXCJib3R0b20tclwiKSkge1xuICAgICAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZCgnYm90dG9tLXInKTtcbiAgICAgICAgfVxuXG4gICAgICB9IGVsc2UgaWYgKHJpZ2h0SGFsZiA8PSBoYWxmVG9vbHRpcCkge1xuICAgICAgICBpZiAoIXRoaXMubWFuaXB1bGF0ZU92ZXJsYXlJZlByZXNlbnQoYnRuY2xpZW50LCB0b29sdGlwLCBcImJvdHRvbS1sXCIpKSB7XG4gICAgICAgICAgdG9vbHRpcC5jbGFzc0xpc3QuYWRkKCdib3R0b20tbCcpO1xuICAgICAgICB9XG4gICAgICB9XG5cblxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBkZWJ1Z2dlcjtcbiAgICAgIGlmICghdGhpcy5tYW5pcHVsYXRlT3ZlcmxheUlmUHJlc2VudChidG5jbGllbnQsIHRvb2x0aXAsIFwiYm90dG9tXCIpKSB7XG4gICAgICAgIHRvb2x0aXAuY2xhc3NMaXN0LmFkZCgnYm90dG9tJyk7XG4gICAgICB9XG4gICAgfVxuXG4gIH1cblxuICByZW1vdmVUb29sdGlwQ2xhc3ModG9vbHRpcCkge1xuICAgIGxldCBjbGFzc0xpc3QgPSB0b29sdGlwLmNsYXNzTGlzdDtcbiAgICBjbGFzc0xpc3QuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgIGlmICh0aGlzLmNsYXNzZXMuaW5jbHVkZXMoZWxlbWVudCkpIHtcbiAgICAgICAgY2xhc3NMaXN0LnJlbW92ZShlbGVtZW50KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGdldFN0YXlDbGFzcyh0b29sdGlwKSB7XG4gICAgdmFyIGNsYXNzTGlzdCA9IHRvb2x0aXAuY2xhc3NMaXN0O1xuICAgIGxldCBzdGF5UG9zaXRpb247XG4gICAgY2xhc3NMaXN0LmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICBpZiAoZWxlbWVudC5pbmNsdWRlcyhgc3RheS1gKSkge1xuICAgICAgICBzdGF5UG9zaXRpb24gPSBlbGVtZW50LnNwbGl0KFwiLVwiKVsxXTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiBzdGF5UG9zaXRpb247XG4gIH1cblxuXG4gIG1vdXNlTGVmdChlbGVtZW50UmVmOiBFbGVtZW50UmVmKSB7XG4gICAvLyBjb25zb2xlLmxvZyhcIm1vdXNlTGVmdFwiKTtcbiAgICBsZXQgYnRuID0gZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xuICAgIGlmICghYnRuKSByZXR1cm47XG5cbiAgICBsZXQgdG9vbHRpcCA9IGJ0bi5xdWVyeVNlbGVjdG9yKFwiLnNtYXJ0LXRvb2x0aXBcIik7XG5cbiAgICBpZiAoIXRvb2x0aXApIHJldHVybjtcblxuXG4gICAgdmFyIHN0aWNreVRpbWUgPSB0aGlzLmdldFN0aWNreVRpbWUodG9vbHRpcCk7XG5cbiAgICBcblxuICAgIGlmICghaXNOYU4oc3RpY2t5VGltZSkpIHtcbiAgICAgIHRoaXMubW91c2VMZWZ0VGltZU91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuXG4gICAgICAgIGlmICh0b29sdGlwLmNsYXNzTGlzdC5jb250YWlucyhcImhvdmVyZWRcIikpXG4gICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGlmICh0aGlzLnJlbW92ZU92ZXJsYXlDbGFzcyh0b29sdGlwKSkge1xuXG4gICAgICAgICAgbGV0IHRvb2x0aXBSZWN0ID0gdG9vbHRpcC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuXG4gICAgICAgICAgLy9SZXNldCBJbmxpbmUgU3R5bGVzXG4gICAgICAgICAgdG9vbHRpcC5zdHlsZS5wb3NpdGlvbiA9IFwiXCI7XG4gICAgICAgICAgdG9vbHRpcC5zdHlsZS50b3AgPSBcIlwiO1xuICAgICAgICAgIHRvb2x0aXAuc3R5bGUubGVmdCA9IFwiXCI7XG4gICAgICAgICAgdG9vbHRpcC5zdHlsZS5ib3R0b20gPSBcIlwiO1xuICAgICAgICAgIHRvb2x0aXAuc3R5bGUucmlna