projects/i-components/src/lib/components/tooltip-service/tooltip-service.component.ts
ToolTip Service holder component
changeDetection | ChangeDetectionStrategy.OnPush |
selector | wm-tooltip-service |
styleUrls | ./tooltip-service.component.scss |
templateUrl | ./tooltip-service.component.html |
Properties |
|
Methods |
|
Inputs |
HostBindings |
Accessors |
constructor(elementRef: ElementRef, injector: Injector, cd: ChangeDetectorRef)
|
||||||||||||
Creates an instance of ToolTipServiceComponent.
Parameters :
|
model | |
Type : ToolTipModel
|
|
Input model property |
style.left |
Type : string
|
Default value : 'calc(50% - 11em)'
|
Binding to locate the message on left |
style.top |
Type : string
|
Default value : 'calc(50% - 11em)'
|
Binding to locate the message on top |
Private adjustPositionByMouse |
adjustPositionByMouse(targetLeft: number, targetTop: number, thisRect: DOMRect)
|
Adjust the position to not leave the limits of the screen when the position is handled by mouse position
Returns :
{ targetLeft: number; targetTop: number; }
|
Private adjustPositionHorizontally |
adjustPositionHorizontally(targetLeft: number, targetTop: number, thisRect: DOMRect)
|
Adjust the position to not leave the limits of the screen when the position is handled to the left or to the right
Returns :
{ targetLeft: number; targetTop: number; }
|
Private adjustPositionVertically |
adjustPositionVertically(targetLeft: number, targetTop: number, thisRect: DOMRect)
|
Adjust the position to not leave the limits of the screen when the position is handled to the top or to the bottom
Returns :
{ targetLeft: number; targetTop: number; }
|
assignInjector |
assignInjector()
|
Creates a new custom injector.
Returns :
void
|
Private calculatePosition |
calculatePosition()
|
Calculates the position to be rendered
Returns :
void
|
ngAfterViewInit |
ngAfterViewInit()
|
Angular lifecycle
Returns :
void
|
ngOnInit |
ngOnInit()
|
Angular lifecycle
Returns :
void
|
customInjector |
Type : Injector
|
Static custom injector to render dynamic components. |
left |
Type : string
|
Default value : 'calc(50% - 11em)'
|
Decorators :
@HostBinding('style.left')
|
Binding to locate the message on left |
model |
Type : ToolTipModel
|
Decorators :
@Input()
|
Input model property |
Public mousePosition |
Type : DOMRect
|
Default value : null
|
Position of the mouse at the moment of requesting the tooltip service to be displayed |
Public ownerTargetRect |
Type : DOMRect
|
Default value : null
|
Owner element to use as anchor |
Public placement |
Type : PlacementMode
|
Default value : PlacementMode.Mouse
|
Placement to display the tooltip |
top |
Type : string
|
Default value : 'calc(50% - 11em)'
|
Decorators :
@HostBinding('style.top')
|
Binding to locate the message on top |
itemToRender |
getitemToRender()
|
Gets the content that should be rendered
Returns :
any
|
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
HostBinding,
Injector,
Input,
OnInit,
} from '@angular/core';
import { ToolTipModel, PlacementMode } from '@mobilize/wms-framework';
import { Utils } from '../../utils/utilities';
/**
* ToolTip Service holder component
*
* @export
* @class ToolTipServiceComponent
*/
@Component({
selector: 'wm-tooltip-service',
templateUrl: './tooltip-service.component.html',
styleUrls: ['./tooltip-service.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ToolTipServiceComponent implements OnInit, AfterViewInit {
/**
* Owner element to use as anchor
*
* @type {DOMRect}
* @memberof ToolTipServiceComponent
*/
public ownerTargetRect: DOMRect = null;
/**
* Position of the mouse at the moment of requesting the tooltip service to be displayed
*
* @type {DOMRect}
* @memberof ToolTipServiceComponent
*/
public mousePosition: DOMRect = null;
/**
* Placement to display the tooltip
*
* @type {PlacementMode}
* @memberof ToolTipServiceComponent
*/
public placement: PlacementMode = PlacementMode.Mouse;
/**
* Static custom injector to render dynamic components.
*
* @type {Injector}
* @memberof ToolTipServiceComponent
*/
customInjector: Injector;
/**
* Binding to locate the message on top
*
* @memberof ToolTipServiceComponent
*/
@HostBinding('style.top') top = 'calc(50% - 11em)';
/**
* Binding to locate the message on left
*
* @memberof ToolTipServiceComponent
*/
@HostBinding('style.left') left = 'calc(50% - 11em)';
/**
* Input model property
*
* @type {ToolTipModel}
* @memberof ToolTipServiceComponent
*/
@Input()
model: ToolTipModel;
/**
* Creates an instance of ToolTipServiceComponent.
* @param {ElementRef} elementRef
* @memberof ToolTipServiceComponent
*/
constructor(
private elementRef: ElementRef,
private injector: Injector,
private cd: ChangeDetectorRef
) {}
/**
* Angular lifecycle
*
* @memberof ToolTipServiceComponent
*/
ngOnInit(): void {
this.assignInjector();
}
/**
* Angular lifecycle
*
* @memberof ToolTipServiceComponent
*/
ngAfterViewInit(): void {
this.calculatePosition();
this.cd.markForCheck();
}
/**
* Calculates the position to be rendered
*
* @private
* @memberof ToolTipServiceComponent
*/
private calculatePosition(): void {
const thisRect: DOMRect =
this.elementRef?.nativeElement?.getBoundingClientRect();
if (!!this.ownerTargetRect && !!this.mousePosition && !!thisRect) {
//By default lets use the mouse position
let targetLeft: number = this.mousePosition.right + 15;
let targetTop: number = this.mousePosition.bottom + 15;
switch (this.placement) {
case PlacementMode.Left:
targetLeft = this.ownerTargetRect.left - thisRect.width - 1;
targetTop = this.ownerTargetRect.top;
break;
case PlacementMode.Right:
targetLeft = this.ownerTargetRect.right + 1;
targetTop = this.ownerTargetRect.top;
break;
case PlacementMode.Top:
targetLeft = this.ownerTargetRect.left;
targetTop = this.ownerTargetRect.top - thisRect.height - 1;
break;
case PlacementMode.Bottom:
targetLeft = this.ownerTargetRect.left;
targetTop = this.ownerTargetRect.bottom + 1;
break;
}
//Corrections when the mouse position is used are different
if (this.placement == PlacementMode.Mouse) {
({ targetLeft, targetTop } = this.adjustPositionByMouse(
targetLeft,
targetTop,
thisRect
));
} else if (
this.placement == PlacementMode.Left ||
this.placement == PlacementMode.Right
) {
({ targetLeft, targetTop } = this.adjustPositionHorizontally(
targetLeft,
targetTop,
thisRect
));
} else {
({ targetLeft, targetTop } = this.adjustPositionVertically(
targetLeft,
targetTop,
thisRect
));
}
this.top = targetTop + 'px';
this.left = targetLeft + 'px';
}
}
/**
* Adjust the position to not leave the limits of the screen when the position is handled by mouse position
*
* @private
* @param {number} targetLeft
* @param {number} targetTop
* @param {DOMRect} thisRect
* @return {*}
* @memberof ToolTipServiceComponent
*/
private adjustPositionByMouse(
targetLeft: number,
targetTop: number,
thisRect: DOMRect
) {
const missingRight = window.innerWidth - (targetLeft + thisRect.width);
if (missingRight < 0) {
targetLeft += missingRight;
}
const missingBottom = window.innerHeight - (targetTop + thisRect.height);
if (missingBottom < 0) {
targetTop += missingBottom;
}
return { targetLeft, targetTop };
}
/**
* Adjust the position to not leave the limits of the screen when the position is handled to the left or to the right
*
* @private
* @param {number} targetLeft
* @param {number} targetTop
* @param {DOMRect} thisRect
* @return {*}
* @memberof ToolTipServiceComponent
*/
private adjustPositionHorizontally(
targetLeft: number,
targetTop: number,
thisRect: DOMRect
) {
//Message will be hidden on the right and there is enough room on the left then we move it to the left
if (
targetLeft + thisRect.width > window.innerWidth &&
this.ownerTargetRect.left - thisRect.width - 1 > 0
) {
targetLeft = this.ownerTargetRect.left - thisRect.width - 1;
}
//Message will be hidden on the left and there is enough room on the right then we move it to the right
if (
targetLeft < 0 &&
this.ownerTargetRect.right + thisRect.width + 1 < window.innerWidth
) {
targetLeft = this.ownerTargetRect.right + 1;
}
//Message will be hidden on the top so we just adjust to the 0 position
if (targetTop < 0) {
targetTop = 0;
}
//Messsage will be hidden at the bottom so we just adjust to above the bottom
const missingBottom = window.innerHeight - (targetTop + thisRect.height);
if (missingBottom < 0) {
targetTop += missingBottom;
}
return { targetLeft, targetTop };
}
/**
* Adjust the position to not leave the limits of the screen when the position is handled to the top or to the bottom
*
* @private
* @param {number} targetLeft
* @param {number} targetTop
* @param {DOMRect} thisRect
* @return {*}
* @memberof ToolTipServiceComponent
*/
private adjustPositionVertically(
targetLeft: number,
targetTop: number,
thisRect: DOMRect
) {
//Message will be hidden on the right so we just adjust it to the right edge
const missingRight = window.innerWidth - (targetLeft + thisRect.width);
if (missingRight < 0) {
targetLeft += missingRight;
}
//Message will be hidden on the left so we just adjust it to the left edge
if (targetLeft < 0) {
targetLeft = 0;
}
//Message will be hidden on the top and there is enough room on the bottom then we move it to the bottom
if (
targetTop < 0 &&
this.ownerTargetRect.bottom + thisRect.height + 1 < window.innerHeight
) {
targetTop = this.ownerTargetRect.bottom + 1;
}
//Messsage will be hidden at the bottom and there is enough room on the top then we move it to the top
if (
targetTop + thisRect.height > window.innerHeight &&
this.ownerTargetRect.top - thisRect.height - 1 > 0
) {
targetTop = this.ownerTargetRect.top - thisRect.height - 1;
}
return { targetLeft, targetTop };
}
/**
* Creates a new custom injector.
*
* @memberof ToolTipServiceComponent
*/
assignInjector(): void {
this.customInjector = Utils.createInjectorForDynamicComponent(
this.model,
this.injector
);
}
/**
* Gets the content that should be rendered
*
* @readonly
* @memberof ToolTipServiceComponent
*/
get itemToRender(): any {
if (!this.model) return undefined;
return { component: Utils.resolveComponentType(this.model) };
}
}
<div class="tooltip-container">
<ng-container *ngIf="itemToRender">
<ng-container
*ngComponentOutlet="itemToRender.component; injector: customInjector"
></ng-container>
</ng-container>
</div>
./tooltip-service.component.scss
@import '../../scss/variables';
:host {
position: fixed;
box-shadow: 1px 1px #888888;
height: auto;
width: auto;
z-index: $tooltip-z-index;
}