UNPKG

smart-tooltip-angular

Version:

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

488 lines (481 loc) 24.5 kB
import { __decorate, __values } from 'tslib'; import { ɵɵdefineInjectable, Injectable, ElementRef, HostBinding, HostListener, Directive, NgModule } from '@angular/core'; var SmartTooltipAngularService = /** @class */ (function () { function SmartTooltipAngularService() { } SmartTooltipAngularService.ɵprov = ɵɵdefineInjectable({ factory: function SmartTooltipAngularService_Factory() { return new SmartTooltipAngularService(); }, token: SmartTooltipAngularService, providedIn: "root" }); SmartTooltipAngularService = __decorate([ Injectable({ providedIn: 'root' }) ], SmartTooltipAngularService); return SmartTooltipAngularService; }()); 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; }()); var SmartTooltipAngularModule = /** @class */ (function () { function SmartTooltipAngularModule() { var head = document.getElementsByTagName('head')[0]; var cs = document.createElement('style'); cs.type = 'text/css'; cs.innerHTML = "\n .smart-tooltip-container {\n position: relative;\n }\n\n .smart-tooltip {\n position: absolute;\n background-color: #333;\n border-radius: 5px;\n color: #eee;\n padding: 10px 12px;\n z-index: 100000;\n top: 50%;\n -webkit-transform: translate(-50%, -50%);\n transform: translate(-50%, -50%);\n left: 50%;\n visibility: collapse;\n /*transition: all .2s;*/\n opacity: 0;\n outline: none;\n }\n\n .smart-tooltip.left-t {\n -webkit-transform: none;\n transform: none;\n right: calc(100% + 5px);\n left: initial;\n top: initial;\n bottom: 5px;\n\n \n }\n\n .smart-tooltip.left-b {\n -webkit-transform: none;\n transform: none;\n right: calc(100% + 5px);\n left: initial;\n top: 5px;\n bottom: initial;\n }\n\n .smart-tooltip.left {\n right: calc(100% + 5px);\n left: initial;\n top: 50%;\n -webkit-transform: translateY(-50%);\n transform: translateY(-50%);\n }\n\n .smart-tooltip.right-b {\n -webkit-transform: none;\n transform: none;\n left: calc(100% + 5px);\n top: 5px;\n right: initial;\n bottom: initial; \n }\n\n .smart-tooltip.right-t {\n -webkit-transform: none;\n transform: none;\n /* display: none; */\n left: calc(100% + 5px);\n top: initial;\n bottom: 5px;\n }\n\n .smart-tooltip.right {\n left: calc(100% + 5px);\n top: 50%;\n bottom: initial;\n right: initial;\n -webkit-transform: translateY(-50%);\n transform: translateY(-50%);\n }\n\n .smart-tooltip.bottom-r {\n /* display: none; */\n top: calc(100% + 5px);\n bottom: initial;\n left: 5px;\n right:initial;\n transform: none;\n }\n .smart-tooltip.bottom-l {\n /* display: none; */\n top: calc(100% + 5px);\n bottom: initial;\n right: 5px;\n left:initial;\n transform: none;\n }\n .smart-tooltip.bottom {\n /* display: none; */\n top: calc(100% + 5px);\n bottom: initial;\n left: 50%;\n transform: translateX(-50%);\n }\n\n .smart-tooltip.top-r {\n /* display: none; */\n bottom: calc(100% + 5px);\n top: initial;\n left: 5px;\n right:initial;\n transform: none;\n }\n .smart-tooltip.top-l {\n /* display: none; */\n bottom: calc(100% + 5px);\n top: initial;\n right: 5px;\n left: initial;\n transform: none;\n }\n .smart-tooltip.top {\n /* display: none; */\n bottom: calc(100% + 5px);\n top: initial;\n left: 50%;\n transform: translateX(-50%);\n }\n\n .smart-tooltip-container .smart-tooltip.overlayed{\n \n transform: none;\n top:initial;\n right:initial;\n bottom:initial;\n left:initial;\n }\n "; head.appendChild(cs); } SmartTooltipAngularModule = __decorate([ NgModule({ declarations: [SmartTooltipAngularDirective], imports: [], exports: [SmartTooltipAngularDirective] }) ], SmartTooltipAngularModule); return SmartTooltipAngularModule; }()); /* * Public API Surface of smart-tooltip-angular */ /** * Generated bundle index. Do not edit. */ export { SmartTooltipAngularDirective, SmartTooltipAngularModule, SmartTooltipAngularService }; //# sourceMappingURL=smart-tooltip-angular.js.map