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
JavaScript
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