Skip to content

Commit

Permalink
feat(module:typography): support nzSuffix property (#4629)
Browse files Browse the repository at this point in the history
* feat(module:typography): support `nzSuffix` property

close #4620

* test(module:typography): add the suffix test

* test(module:typography): add the suffix test

* fix(module:typography): fix the template
  • Loading branch information
hsuanxyz authored Feb 26, 2020
1 parent c53c0f2 commit ca02a07
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 21 deletions.
14 changes: 9 additions & 5 deletions components/core/util/text-measure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ export function measure(
rows: number,
contentNodes: Node[],
fixedContent: HTMLElement[],
ellipsisStr: string
ellipsisStr: string,
suffixStr: string = ''
): { contentNodes: Node[]; text: string; ellipsis: boolean } {
if (!ellipsisContainer) {
ellipsisContainer = document.createElement('div');
Expand Down Expand Up @@ -94,6 +95,7 @@ export function measure(
const contentList = mergeChildren(contentNodes);
const container = document.createElement('div');
const contentContainer = document.createElement('span');
const suffixContainer = document.createTextNode(suffixStr);
const fixedContainer = document.createElement('span');

// Add styles in container
Expand All @@ -104,6 +106,9 @@ export function measure(
contentList.forEach(n => {
contentContainer.appendChild(n);
});

contentContainer.appendChild(suffixContainer);

fixedContent.forEach(node => {
fixedContainer.appendChild(node.cloneNode(true));
});
Expand Down Expand Up @@ -137,7 +142,7 @@ export function measure(
// Create origin content holder
const ellipsisContentHolder = document.createElement('span');
ellipsisContainer.appendChild(ellipsisContentHolder);
const ellipsisTextNode = document.createTextNode(ellipsisStr);
const ellipsisTextNode = document.createTextNode(ellipsisStr + suffixStr);
ellipsisContentHolder.appendChild(ellipsisTextNode);

fixedNodes.forEach(childNode => {
Expand All @@ -158,16 +163,15 @@ export function measure(
lastSuccessLoc: number = 0
): MeasureResult {
const midLoc = Math.floor((startLoc + endLoc) / 2);
const currentText = fullText.slice(0, midLoc);
textNode.textContent = currentText;
textNode.textContent = fullText.slice(0, midLoc);

if (startLoc >= endLoc - 1) {
// Loop when step is small
for (let step = endLoc; step >= startLoc; step -= 1) {
const currentStepText = fullText.slice(0, step);
textNode.textContent = currentStepText;

if (inRange()) {
if (inRange() || !currentStepText) {
return step === fullText.length
? {
finished: false,
Expand Down
3 changes: 2 additions & 1 deletion components/typography/demo/module
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { NzTypographyModule } from 'ng-zorro-antd/typography';
import { NzDividerModule } from 'ng-zorro-antd/divider';
import { NzSliderModule } from 'ng-zorro-antd/slider';

export const moduleList = [ NzTypographyModule, NzDividerModule ];
export const moduleList = [ NzTypographyModule, NzDividerModule, NzSliderModule ];
14 changes: 14 additions & 0 deletions components/typography/demo/suffix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
order: 6
title:
zh-CN: 后缀
en-US: suffix
---

## zh-CN

添加后缀的省略。

## en-US

add suffix ellipsis support.
17 changes: 17 additions & 0 deletions components/typography/demo/suffix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Component } from '@angular/core';

@Component({
selector: 'nz-demo-typography-suffix',
template: `
<nz-slider [(ngModel)]="rows" [nzMax]="10" [nzMin]="1"></nz-slider>
<p nz-paragraph nzEllipsis nzExpandable [attr.title]="content + suffix" [nzEllipsisRows]="rows" [nzSuffix]="suffix">
{{ content }}
</p>
`
})
export class NzDemoTypographySuffixComponent {
content =
'To be, or not to be, that is a question: Whether it is nobler in the mind to suffer. The slings and arrows of outrageous fortune';
suffix = '--William Shakespeare';
rows = 1;
}
1 change: 1 addition & 0 deletions components/typography/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Basic text writing, including headings, body text, lists, and more.
| `[nzCopyable]` | Can copy, require use `[nzContent]` | `boolean` | `false` ||
| `[nzEditable]` | Editable, require use `[nzContent]` | `boolean` | `false` ||
| `[nzEllipsis]` | Display ellipsis when overflow, require use `[nzContent]` when dynamic content | `boolean` | `false` ||
| `[nzSuffix]` | The text suffix when used `nzEllipsis` | `string` | - ||
| `[nzCopyText]` | Customize the copy text | `string` | - ||
| `[nzDisabled]` | Disable content | `boolean` | `false` ||
| `[nzExpandable]` | Expandable when ellipsis | `boolean` | `false` ||
Expand Down
3 changes: 2 additions & 1 deletion components/typography/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ cols: 1
| --- | --- | --- | --- | --- |
| `[nzContent]` | 组件内容 | `string` | - |
| `[nzCopyable]` | 是否可拷贝,需要配合 `[nzContent]` 使用 | `boolean` | `false` |
| `[nzEditable]` | 是否可编辑,是否可拷贝,需要配合 `[nzContent]` 使用 | `boolean` | `false` |
| `[nzEditable]` | 是否可编辑,需要配合 `[nzContent]` 使用 | `boolean` | `false` |
| `[nzEllipsis]` | 自动溢出省略,动态内容时需要配合 `[nzContent]` 使用 | `boolean` | `false` |
| `[nzExpandable]` | 自动溢出省略时是否可展开 | `boolean` | `false` |
| `[nzSuffix]` | 自动溢出省略时的文本后缀 | `string` | - |
| `[nzCopyText]` | 自定义被拷贝的文本 | `string` | - |
| `[nzDisabled]` | 禁用文本 | `boolean` | `false` |
| `[nzEllipsisRows]` | 自动溢出省略时省略行数 | `number` | `1` ||
Expand Down
11 changes: 8 additions & 3 deletions components/typography/nz-typography.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@
</ng-template>

<ng-container *ngIf="!editing">
<ng-container *ngIf="expanded || (!nzExpandable && nzEllipsisRows === 1) || canCssEllipsis">
<ng-container
*ngIf="expanded || (!nzExpandable && !nzSuffix && nzEllipsisRows === 1) || canCssEllipsis"
>
<ng-template
[ngTemplateOutlet]="contentTemplate"
[ngTemplateOutletContext]="{ content: nzContent }"
></ng-template>
</ng-container>
<ng-container *ngIf="nzEllipsis && !expanded && (nzEllipsisRows > 1 || nzExpandable)">
<span #ellipsisContainer></span>
<ng-container
*ngIf="(nzEllipsis && !expanded && (nzEllipsisRows > 1 || nzExpandable)) || nzSuffix"
>
<span #ellipsisContainer *ngIf="!expanded"></span>
<ng-container *ngIf="isEllipsis">{{ ellipsisStr }}</ng-container>
<ng-container *ngIf="nzSuffix">{{ nzSuffix }}</ng-container>
<a
#expandable
*ngIf="nzExpandable && isEllipsis"
Expand Down
49 changes: 41 additions & 8 deletions components/typography/nz-typography.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import { Platform } from '@angular/cdk/platform';
import { DOCUMENT } from '@angular/common';
import {
AfterViewInit,
ChangeDetectionStrategy,
Expand All @@ -15,6 +16,7 @@ import {
ElementRef,
EmbeddedViewRef,
EventEmitter,
Inject,
Input,
OnChanges,
OnDestroy,
Expand Down Expand Up @@ -48,6 +50,7 @@ import { NzTextCopyComponent } from './nz-text-copy.component';
import { NzTextEditComponent } from './nz-text-edit.component';

const NZ_CONFIG_COMPONENT_NAME = 'typography';
const EXPAND_ELEMENT_CLASSNAME = 'ant-typography-expand';

@Component({
selector: `
Expand Down Expand Up @@ -85,6 +88,7 @@ export class NzTypographyComponent implements OnInit, AfterViewInit, OnDestroy,
@Input() @WithConfig(NZ_CONFIG_COMPONENT_NAME, 1) @InputNumber() nzEllipsisRows: number;
@Input() nzType: 'secondary' | 'warning' | 'danger' | undefined;
@Input() nzCopyText: string | undefined;
@Input() nzSuffix: string | undefined;
@Output() readonly nzContentChange = new EventEmitter<string>();
@Output() readonly nzCopy = new EventEmitter<string>();
@Output() readonly nzExpandChange = new EventEmitter<void>();
Expand All @@ -97,10 +101,12 @@ export class NzTypographyComponent implements OnInit, AfterViewInit, OnDestroy,

// tslint:disable-next-line:no-any
locale: any = {};
document: Document;
expandableBtnElementCache: HTMLElement | null = null;
editing = false;
ellipsisText: string | undefined;
cssEllipsis: boolean = false;
isEllipsis: boolean = false;
isEllipsis: boolean = true;
expanded: boolean = false;
ellipsisStr = '...';

Expand All @@ -124,8 +130,11 @@ export class NzTypographyComponent implements OnInit, AfterViewInit, OnDestroy,
private renderer: Renderer2,
private platform: Platform,
private i18n: NzI18nService,
@Inject(DOCUMENT) document: any, // tslint:disable-line no-any
private nzDomEventService: NzDomEventService
) {}
) {
this.document = document;
}

onTextCopy(text: string): void {
this.nzCopy.emit(text);
Expand All @@ -144,12 +153,13 @@ export class NzTypographyComponent implements OnInit, AfterViewInit, OnDestroy,
}

onExpand(): void {
this.isEllipsis = false;
this.expanded = true;
this.nzExpandChange.emit();
}

canUseCSSEllipsis(): boolean {
if (this.nzEditable || this.nzCopyable || this.nzExpandable) {
if (this.nzEditable || this.nzCopyable || this.nzExpandable || this.nzSuffix) {
return false;
}
if (this.nzEllipsisRows === 1) {
Expand Down Expand Up @@ -187,14 +197,18 @@ export class NzTypographyComponent implements OnInit, AfterViewInit, OnDestroy,
return;
}
const { viewRef, removeView } = this.getOriginContentViewRef();
const fixedNodes = [this.textCopyRef, this.textEditRef, this.expandableBtn].filter(e => e && e.nativeElement).map(e => e.nativeElement);

const fixedNodes = [this.textCopyRef, this.textEditRef].filter(e => e && e.nativeElement).map(e => e.nativeElement);
const expandableBtnElement = this.getExpandableBtnElement();
if (expandableBtnElement) {
fixedNodes.push(expandableBtnElement);
}
const { contentNodes, text, ellipsis } = measure(
this.host.nativeElement,
this.nzEllipsisRows,
viewRef.rootNodes,
fixedNodes,
this.ellipsisStr
this.ellipsisStr,
this.nzSuffix
);

removeView();
Expand All @@ -211,6 +225,24 @@ export class NzTypographyComponent implements OnInit, AfterViewInit, OnDestroy,
this.cdr.markForCheck();
}

// Need to create the element for calculation size before view init
private getExpandableBtnElement(): HTMLElement | null {
if (this.nzExpandable) {
const expandText = this.locale ? this.locale.expand : '';
const cache = this.expandableBtnElementCache;
if (!cache || cache.innerText === expandText) {
const el = this.document.createElement('a');
el.className = EXPAND_ELEMENT_CLASSNAME;
el.innerText = expandText;
this.expandableBtnElementCache = el;
}
return this.expandableBtnElementCache;
} else {
this.expandableBtnElementCache = null;
return null;
}
}

private renderAndSubscribeWindowResize(): void {
if (this.platform.isBrowser) {
this.windowResizeSubscription.unsubscribe();
Expand Down Expand Up @@ -239,8 +271,8 @@ export class NzTypographyComponent implements OnInit, AfterViewInit, OnDestroy,
}

ngOnChanges(changes: SimpleChanges): void {
const { nzCopyable, nzEditable, nzExpandable, nzEllipsis, nzContent, nzEllipsisRows } = changes;
if (nzCopyable || nzEditable || nzExpandable || nzEllipsis || nzContent || nzEllipsisRows) {
const { nzCopyable, nzEditable, nzExpandable, nzEllipsis, nzContent, nzEllipsisRows, nzSuffix } = changes;
if (nzCopyable || nzEditable || nzExpandable || nzEllipsis || nzContent || nzEllipsisRows || nzSuffix) {
if (this.nzEllipsis) {
if (this.expanded) {
this.windowResizeSubscription.unsubscribe();
Expand All @@ -254,6 +286,7 @@ export class NzTypographyComponent implements OnInit, AfterViewInit, OnDestroy,
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
this.expandableBtnElementCache = null;
this.windowResizeSubscription.unsubscribe();
}
}
45 changes: 42 additions & 3 deletions components/typography/nz-typography.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,7 @@ describe('typography', () => {
viewport.reset();
}));

// TODO Uncaught RangeError: Maximum call stack size exceeded thrown
xit('should resize work', fakeAsync(() => {
it('should resize work', fakeAsync(() => {
testComponent.expandable = true;
viewport.set(400, 1000);
dispatchFakeEvent(window, 'resize');
Expand Down Expand Up @@ -295,6 +294,45 @@ describe('typography', () => {
});
viewport.reset();
}));

it('should suffix work', fakeAsync(() => {
testComponent.expandable = true;
testComponent.suffix = 'The suffix.';

{
viewport.set(8000, 1000);
dispatchFakeEvent(window, 'resize');
fixture.detectChanges();
tick(32);
fixture.detectChanges();
const el = componentElement.querySelector('.dynamic') as HTMLParagraphElement;
expect(el.innerText.endsWith('The suffix.')).toBe(true);
expect(el.innerText.includes('...')).toBe(false);
}

{
viewport.set(800, 1000);
dispatchFakeEvent(window, 'resize');
fixture.detectChanges();
tick(32);
fixture.detectChanges();
const el = componentElement.querySelector('.dynamic') as HTMLParagraphElement;
expect(el.innerText.includes('The suffix.')).toBe(true);
expect(el.innerText.includes('...')).toBe(true);
testComponent.expandable = false;
fixture.detectChanges();
tick(32);
fixture.detectChanges();
expect(el.innerText.endsWith('The suffix.')).toBe(true);
expect(el.innerText.includes('...')).toBe(true);
}

viewport.reset();
dispatchFakeEvent(window, 'resize');
fixture.detectChanges();
tick(32);
fixture.detectChanges();
}));
});
});

Expand Down Expand Up @@ -368,6 +406,7 @@ export class NzTestTypographyEditComponent {
[nzEllipsisRows]="2"
(nzExpandChange)="onExpand()"
[nzContent]="str"
[nzSuffix]="suffix"
class="dynamic"
></p>
`,
Expand All @@ -382,7 +421,7 @@ export class NzTestTypographyEditComponent {
export class NzTestTypographyEllipsisComponent {
expandable = false;
onExpand = jasmine.createSpy('expand callback');

suffix: string | null = null;
@ViewChild(NzTypographyComponent, { static: false }) nzTypographyComponent: NzTypographyComponent;
str = new Array(5).fill('Ant Design, a design language for background applications, is refined by Ant UED Team.').join('');
}

0 comments on commit ca02a07

Please sign in to comment.