diff options
Diffstat (limited to 'src/angular/multiline-ellipsis')
3 files changed, 89 insertions, 0 deletions
diff --git a/src/angular/multiline-ellipsis/multiline-ellipsis.component.html.ts b/src/angular/multiline-ellipsis/multiline-ellipsis.component.html.ts new file mode 100644 index 0000000..ecaeb42 --- /dev/null +++ b/src/angular/multiline-ellipsis/multiline-ellipsis.component.html.ts @@ -0,0 +1,8 @@ +export const template = ` +<div class="multiline-ellipsis-container" [ngClass]="className" [ngStyle]="stylesContainer" #multilineEllipsisContainer> + <div class="multiline-ellipsis-content" [ngStyle]="stylesContent" #multilineEllipsisContent> + <ng-content></ng-content> + <div class="multiline-ellipsis-dots" [ngStyle]="stylesDots"></div> + </div> +</div> +`; diff --git a/src/angular/multiline-ellipsis/multiline-ellipsis.component.ts b/src/angular/multiline-ellipsis/multiline-ellipsis.component.ts new file mode 100644 index 0000000..bc7f805 --- /dev/null +++ b/src/angular/multiline-ellipsis/multiline-ellipsis.component.ts @@ -0,0 +1,70 @@ +import { Component, OnChanges, AfterViewChecked, ViewChild, ElementRef, Input, Output, SimpleChanges, EventEmitter } from "@angular/core"; +import { template } from './multiline-ellipsis.component.html'; + +declare const window: any; + +@Component({ + selector: 'multiline-ellipsis', + template: template +}) + +export class MultilineEllipsisComponent implements OnChanges, AfterViewChecked { + + @Input() public lines: number; + @Input() public lineHeight: string; + @Input() public className: string; + @Output() public hasEllipsisChanged: EventEmitter<boolean>; + + @ViewChild('multilineEllipsisContainer') public elmContainer: ElementRef; + @ViewChild('multilineEllipsisContent') public elmContent: ElementRef; + + public stylesContainer: { [key: string]: string }; + public stylesContent: { [key: string]: string }; + public stylesDots: { [key: string]: string }; + + private hasEllipsis: boolean; + + public constructor() { + this.hasEllipsisChanged = new EventEmitter<boolean>(); + } + + public ngOnChanges(changes: SimpleChanges) { + this.prepareStyles() + } + + public ngAfterViewChecked() { + const hasEllipsis = (this.elmContainer.nativeElement.offsetHeight < this.elmContent.nativeElement.offsetHeight); + if (hasEllipsis !== this.hasEllipsis) { + this.hasEllipsis = hasEllipsis; + setTimeout(() => { + this.hasEllipsisChanged.emit(this.hasEllipsis); + }); + } + } + + private prepareStyles() { + const lineHeight = this.lineHeight || this.getLineHeight(); + this.stylesContainer = { + 'max-height': `calc(${this.lines} * ${lineHeight})` + }; + this.stylesContent = { + 'max-height': `calc(${this.lines + 1} * ${lineHeight})` + }; + this.stylesDots = { + 'top': `calc(${2 * this.lines} * ${lineHeight} - 100%)` + }; + } + + private getLineHeight() { + let lineHeight: number = parseFloat(window.getComputedStyle(this.elmContainer.nativeElement)['line-height']); + if (!lineHeight) { + const oneLetterElm = window.document.createElement('div'); + oneLetterElm.innerText = '.'; + this.elmContainer.nativeElement.append(oneLetterElm); + lineHeight = oneLetterElm.clientHeight; + this.elmContainer.nativeElement.removeChild(oneLetterElm); + } + return `${lineHeight}px`; + } + +} diff --git a/src/angular/multiline-ellipsis/multiline-ellipsis.module.ts b/src/angular/multiline-ellipsis/multiline-ellipsis.module.ts new file mode 100644 index 0000000..24ed7b3 --- /dev/null +++ b/src/angular/multiline-ellipsis/multiline-ellipsis.module.ts @@ -0,0 +1,11 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {MultilineEllipsisComponent} from './multiline-ellipsis.component'; + +@NgModule({ + declarations: [MultilineEllipsisComponent], + imports: [CommonModule], + exports: [MultilineEllipsisComponent], + entryComponents: [MultilineEllipsisComponent] +}) +export class MultilineEllipsisModule {} |