Skip to content
Snippets Groups Projects
Commit 0ccaed8d authored by OZGCloud's avatar OZGCloud
Browse files

Merge pull request 'OZG-7047 Improve code quality' (#842) from OZG-7047-tooltip into master

parents 1dcd6114 f78e6641
Branches
Tags
No related merge requests found
...@@ -51,7 +51,7 @@ describe('TooltipDirective', () => { ...@@ -51,7 +51,7 @@ describe('TooltipDirective', () => {
describe('createTooltip', () => { describe('createTooltip', () => {
beforeEach(() => { beforeEach(() => {
directive.viewContainerRef.createComponent = jest.fn().mockReturnValue({ location: { nativeElement: {} } }); directive.viewContainerRef.createComponent = jest.fn().mockReturnValue({ location: { nativeElement: {} } });
directive.setDescribedBy = jest.fn(); directive.setAriaDescribedBy = jest.fn();
directive.setTooltipProperties = jest.fn(); directive.setTooltipProperties = jest.fn();
}); });
...@@ -67,10 +67,10 @@ describe('TooltipDirective', () => { ...@@ -67,10 +67,10 @@ describe('TooltipDirective', () => {
expect(directive.elementRef.nativeElement.appendChild).toHaveBeenCalled(); expect(directive.elementRef.nativeElement.appendChild).toHaveBeenCalled();
}); });
it('should set aria described by attribute to parent', () => { it('should set aria-describedby attribute to parent', () => {
directive.createTooltip(); directive.createTooltip();
expect(directive.setDescribedBy).toHaveBeenCalled(); expect(directive.setAriaDescribedBy).toHaveBeenCalled();
}); });
it('should set tooltip properties', () => { it('should set tooltip properties', () => {
...@@ -136,7 +136,7 @@ describe('TooltipDirective', () => { ...@@ -136,7 +136,7 @@ describe('TooltipDirective', () => {
}); });
}); });
describe('setDescribedBy', () => { describe('setAriaDescribedBy', () => {
beforeEach(() => { beforeEach(() => {
directive.getFocusableElement = jest.fn(); directive.getFocusableElement = jest.fn();
directive.renderer.setAttribute = jest.fn(); directive.renderer.setAttribute = jest.fn();
...@@ -144,31 +144,31 @@ describe('TooltipDirective', () => { ...@@ -144,31 +144,31 @@ describe('TooltipDirective', () => {
}); });
it('should check if parent element focusable', () => { it('should check if parent element focusable', () => {
directive.setDescribedBy(); directive.setAriaDescribedBy();
expect(directive.interactivityChecker.isFocusable).toHaveBeenCalled(); expect(directive.interactivityChecker.isFocusable).toHaveBeenCalled();
}); });
it('should get focusable element if parent not focusable', () => { it('should get focusable element if parent not focusable', () => {
directive.setDescribedBy(); directive.setAriaDescribedBy();
expect(directive.getFocusableElement).toHaveBeenCalled(); expect(directive.getFocusableElement).toHaveBeenCalled();
}); });
it('should set describedby attribute', () => { it('should set aria-describedby attribute', () => {
directive.setDescribedBy(); directive.setAriaDescribedBy();
expect(directive.renderer.setAttribute).toHaveBeenCalled(); expect(directive.renderer.setAttribute).toHaveBeenCalled();
}); });
}); });
describe('removeDescribedBy', () => { describe('removeAriaDescribedBy', () => {
beforeEach(() => { beforeEach(() => {
directive.renderer.removeAttribute = jest.fn(); directive.renderer.removeAttribute = jest.fn();
}); });
it('should remove describedby attribute', () => { it('should remove aria-describedby attribute', () => {
directive.removeDescribedBy(); directive.removeAriaDescribedBy();
expect(directive.renderer.removeAttribute).toHaveBeenCalled(); expect(directive.renderer.removeAttribute).toHaveBeenCalled();
}); });
...@@ -197,7 +197,7 @@ describe('TooltipDirective', () => { ...@@ -197,7 +197,7 @@ describe('TooltipDirective', () => {
describe('destroy', () => { describe('destroy', () => {
beforeEach(() => { beforeEach(() => {
directive.componentRef = mockComponentRef; directive.componentRef = mockComponentRef;
directive.removeDescribedBy = jest.fn(); directive.removeAriaDescribedBy = jest.fn();
}); });
it('should set component ref to null', () => { it('should set component ref to null', () => {
...@@ -206,10 +206,10 @@ describe('TooltipDirective', () => { ...@@ -206,10 +206,10 @@ describe('TooltipDirective', () => {
expect(directive.componentRef).toBeNull(); expect(directive.componentRef).toBeNull();
}); });
it('should remove describedby attribute', () => { it('should remove aria-describedby attribute', () => {
directive.destroy(); directive.destroy();
expect(directive.removeDescribedBy).toHaveBeenCalled(); expect(directive.removeAriaDescribedBy).toHaveBeenCalled();
}); });
it('should set focusable element to null', () => { it('should set focusable element to null', () => {
......
import { isEscapeKey } from '@alfa-client/tech-shared'; import { isEscapeKey, isNotNull } from '@alfa-client/tech-shared';
import { InteractivityChecker } from '@angular/cdk/a11y'; import { InteractivityChecker } from '@angular/cdk/a11y';
import { import {
ComponentRef, ComponentRef,
...@@ -11,9 +11,11 @@ import { ...@@ -11,9 +11,11 @@ import {
Renderer2, Renderer2,
ViewContainerRef, ViewContainerRef,
} from '@angular/core'; } from '@angular/core';
import { uniqueId } from 'lodash-es'; import { isNull, uniqueId } from 'lodash-es';
import { TooltipComponent } from './tooltip.component'; import { TooltipComponent } from './tooltip.component';
const OUTLINE_INDENT = 4; // Outline offset (2) + outline width (2)
@Directive({ @Directive({
selector: '[tooltip]', selector: '[tooltip]',
standalone: true, standalone: true,
...@@ -37,15 +39,17 @@ export class TooltipDirective implements OnDestroy { ...@@ -37,15 +39,17 @@ export class TooltipDirective implements OnDestroy {
@HostListener('mouseenter') @HostListener('mouseenter')
@HostListener('focusin') @HostListener('focusin')
createTooltip(): void { createTooltip(): void {
if (this.componentRef === null) { if (isNotNull(this.componentRef)) {
return;
}
const nativeElement: HTMLElement = this.elementRef.nativeElement; const nativeElement: HTMLElement = this.elementRef.nativeElement;
const attachedToFocused: boolean = nativeElement.contains(document.activeElement); const attachedToFocused: boolean = nativeElement.contains(document.activeElement);
this.componentRef = this.viewContainerRef.createComponent(TooltipComponent); this.componentRef = this.viewContainerRef.createComponent(TooltipComponent);
nativeElement.appendChild(this.componentRef.location.nativeElement); nativeElement.appendChild(this.componentRef.location.nativeElement);
this.setDescribedBy(); this.setAriaDescribedBy();
this.setTooltipProperties(attachedToFocused); this.setTooltipProperties(attachedToFocused);
} }
}
@HostListener('mouseleave') @HostListener('mouseleave')
@HostListener('window:scroll') @HostListener('window:scroll')
...@@ -62,16 +66,18 @@ export class TooltipDirective implements OnDestroy { ...@@ -62,16 +66,18 @@ export class TooltipDirective implements OnDestroy {
} }
setTooltipProperties(attachedToFocused = false): void { setTooltipProperties(attachedToFocused = false): void {
if (this.componentRef !== null) { if (isNull(this.componentRef)) {
return;
}
const { left, right, bottom } = this.elementRef.nativeElement.getBoundingClientRect(); const { left, right, bottom } = this.elementRef.nativeElement.getBoundingClientRect();
this.componentRef.instance.left = (right + left) / 2; this.componentRef.instance.left = (right + left) / 2;
this.componentRef.instance.top = attachedToFocused ? bottom + 4 : bottom; this.componentRef.instance.top = attachedToFocused ? bottom + OUTLINE_INDENT : bottom;
this.componentRef.instance.text = this.tooltip; this.componentRef.instance.text = this.tooltip;
this.componentRef.instance.id = this.tooltipId; this.componentRef.instance.id = this.tooltipId;
} }
}
setDescribedBy(): void { setAriaDescribedBy(): void {
const nativeElement: HTMLElement = this.elementRef.nativeElement; const nativeElement: HTMLElement = this.elementRef.nativeElement;
this.tooltipId = uniqueId('tooltip'); this.tooltipId = uniqueId('tooltip');
this.focusableElement = this.focusableElement =
...@@ -79,7 +85,7 @@ export class TooltipDirective implements OnDestroy { ...@@ -79,7 +85,7 @@ export class TooltipDirective implements OnDestroy {
this.renderer.setAttribute(this.focusableElement, 'aria-describedby', this.tooltipId); this.renderer.setAttribute(this.focusableElement, 'aria-describedby', this.tooltipId);
} }
removeDescribedBy(): void { removeAriaDescribedBy(): void {
this.renderer.removeAttribute(this.focusableElement, 'aria-describedby'); this.renderer.removeAttribute(this.focusableElement, 'aria-describedby');
} }
...@@ -88,11 +94,13 @@ export class TooltipDirective implements OnDestroy { ...@@ -88,11 +94,13 @@ export class TooltipDirective implements OnDestroy {
} }
destroy(): void { destroy(): void {
if (this.componentRef !== null) { if (isNull(this.componentRef)) {
return;
}
this.componentRef.destroy(); this.componentRef.destroy();
this.componentRef = null; this.componentRef = null;
this.removeDescribedBy(); this.removeAriaDescribedBy();
this.focusableElement = null; this.focusableElement = null;
} }
} }
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment