From fa0a08fc1bdc91ca304b45ba9c938cc8739baa9a Mon Sep 17 00:00:00 2001 From: cipchk Date: Tue, 27 Nov 2018 20:58:25 +0800 Subject: [PATCH 1/7] refactor(module:affix): refactor affix - the nzTarget support string value --- components/affix/affix.spec.ts | 15 ++- components/affix/doc/index.en-US.md | 2 +- components/affix/doc/index.zh-CN.md | 2 +- components/affix/nz-affix.component.ts | 139 +++++++++++++------------ 4 files changed, 83 insertions(+), 75 deletions(-) diff --git a/components/affix/affix.spec.ts b/components/affix/affix.spec.ts index f173e801fff..48828eaf120 100644 --- a/components/affix/affix.spec.ts +++ b/components/affix/affix.spec.ts @@ -288,6 +288,15 @@ describe('affix', () => { fixture.detectChanges(); expect(component.updatePosition).toHaveBeenCalled(); }); + + it('should be a string value', () => { + spyOn(component, 'updatePosition'); + expect(component.updatePosition).not.toHaveBeenCalled(); + fixture.detectChanges(); + context.fakeTarget = '#target'; + fixture.detectChanges(); + expect(component.updatePosition).toHaveBeenCalled(); + }); }); describe('(nzChange)', () => { @@ -486,14 +495,12 @@ describe('affix-extra', () => {
- `, - styleUrls: [ './style/index.less' ], - encapsulation: ViewEncapsulation.None + ` }) class TestAffixComponent { @ViewChild(NzAffixComponent) nzAffixComponent: NzAffixComponent; - fakeTarget: Element | Window = null; + fakeTarget: string | Element | Window = null; newOffset: {}; newOffsetBottom: {}; } diff --git a/components/affix/doc/index.en-US.md b/components/affix/doc/index.en-US.md index 8125b25ac3f..d0b11d41468 100755 --- a/components/affix/doc/index.en-US.md +++ b/components/affix/doc/index.en-US.md @@ -20,7 +20,7 @@ Please note that Affix should not cover other content on the page, especially wh | -------- | ----------- | ---- | ------- | | `[nzOffsetBottom]` | Pixels to offset from bottom when calculating position of scroll | number | - | | `[nzOffsetTop]` | Pixels to offset from top when calculating position of scroll | number | 0 | -| `[nzTarget]` | specifies the scrollable area dom node | `HTMLElement` | `window` | +| `[nzTarget]` | specifies the scrollable area dom node | `string, HTMLElement` | `window` | | `(nzChange)` | Callback for when affix state is changed | `EventEmitter` | - | **Note:** Children of `nz-affix` can not be `position: absolute`, but you can set `nz-affix` as `position: absolute`: diff --git a/components/affix/doc/index.zh-CN.md b/components/affix/doc/index.zh-CN.md index c1989e9ba8f..d01518a3862 100755 --- a/components/affix/doc/index.zh-CN.md +++ b/components/affix/doc/index.zh-CN.md @@ -21,7 +21,7 @@ title: Affix | --- | --- | --- | --- | | `[nzOffsetBottom]` | 距离窗口底部达到指定偏移量后触发 | number | | | `[nzOffsetTop]` | 距离窗口顶部达到指定偏移量后触发 | number | | -| `[nzTarget]` | 设置 `nz-affix` 需要监听其滚动事件的元素,值为一个返回对应 DOM 元素的函数 | `HTMLElement` | `window` | +| `[nzTarget]` | 设置 `nz-affix` 需要监听其滚动事件的元素,值为一个返回对应 DOM 元素的函数 | `string, HTMLElement` | `window` | | `(nzChange)` | 固定状态改变时触发的回调函数 | `EventEmitter` | 无 | **注意:**`nz-affix` 内的元素不要使用绝对定位,如需要绝对定位的效果,可以直接设置 `nz-affix` 为绝对定位: diff --git a/components/affix/nz-affix.component.ts b/components/affix/nz-affix.component.ts index c17e378f605..85a5416d104 100644 --- a/components/affix/nz-affix.component.ts +++ b/components/affix/nz-affix.component.ts @@ -1,10 +1,12 @@ // tslint:disable:no-any +import { DOCUMENT } from '@angular/common'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, + Inject, Input, OnDestroy, OnInit, @@ -30,9 +32,9 @@ import { throttleByAnimationFrameDecorator } from '../core/util/throttleByAnimat export class NzAffixComponent implements OnInit, OnDestroy { @Input() - set nzTarget(value: Element | Window) { + set nzTarget(value: string | Element | Window) { this.clearEventListeners(); - this._target = value || window; + this._target = typeof value === 'string' ? this.doc.querySelector(value) : value || window; this.setTargetEventListeners(); this.updatePosition({}); } @@ -60,7 +62,7 @@ export class NzAffixComponent implements OnInit, OnDestroy { @Output() readonly nzChange: EventEmitter = new EventEmitter(); - constructor(private scrollSrv: NzScrollService, private _el: ElementRef, private cd: ChangeDetectorRef) { + constructor(private scrollSrv: NzScrollService, private _el: ElementRef, @Inject(DOCUMENT) private doc: Document, private cd: ChangeDetectorRef) { } private timeout: any; @@ -109,7 +111,7 @@ export class NzAffixComponent implements OnInit, OnDestroy { const scrollTop = this.scrollSrv.getScroll(target, true); const scrollLeft = this.scrollSrv.getScroll(target, false); - const docElem = window.document.body; + const docElem = this.doc.body; const clientTop = docElem.clientTop || 0; const clientLeft = docElem.clientLeft || 0; @@ -121,6 +123,70 @@ export class NzAffixComponent implements OnInit, OnDestroy { }; } + private setTargetEventListeners(): void { + this.clearEventListeners(); + this.events.forEach((eventName: string) => { + this._target.addEventListener(eventName, this.updatePosition, false); + }); + } + + private clearEventListeners(): void { + this.events.forEach(eventName => { + this._target.removeEventListener(eventName, this.updatePosition, false); + }); + } + + private getTargetRect(target: Element | Window | null): ClientRect { + return target !== window ? + (target as HTMLElement).getBoundingClientRect() : + { top: 0, left: 0, bottom: 0 } as ClientRect; + } + + private genStyle(affixStyle: {}): string { + if (affixStyle == null) { + return ''; + } + return Object.keys(affixStyle).map(key => { + const val = affixStyle[ key ]; + return `${key}:${typeof val === 'string' ? val : val + 'px'}`; + }).join(';'); + } + + private setAffixStyle(e: any, affixStyle: {}): void { + const originalAffixStyle = this.affixStyle; + const isWindow = this._target === window; + if (e.type === 'scroll' && originalAffixStyle && affixStyle && isWindow) { + return; + } + if (shallowEqual(originalAffixStyle, affixStyle)) { + return; + } + + const fixed = !!affixStyle; + const wrapEl = this.wrap.nativeElement as HTMLElement; + wrapEl.style.cssText = this.genStyle(affixStyle); + this.affixStyle = affixStyle; + const cls = 'ant-affix'; + if (fixed) { + wrapEl.classList.add(cls); + } else { + wrapEl.classList.remove(cls); + } + + if ((affixStyle && !originalAffixStyle) || (!affixStyle && originalAffixStyle)) { + this.nzChange.emit(fixed); + } + } + + private setPlaceholderStyle(placeholderStyle: {}): void { + const originalPlaceholderStyle = this.placeholderStyle; + if (shallowEqual(placeholderStyle, originalPlaceholderStyle)) { + return; + } + (this._el.nativeElement as HTMLElement).style.cssText = this.genStyle(placeholderStyle); + this.placeholderStyle = placeholderStyle; + } + @throttleByAnimationFrameDecorator() updatePosition(e: any): void { const targetNode = this._target; @@ -187,69 +253,4 @@ export class NzAffixComponent implements OnInit, OnDestroy { this.setPlaceholderStyle(null); } } - - private setTargetEventListeners(): void { - this.clearEventListeners(); - this.events.forEach((eventName: string) => { - this._target.addEventListener(eventName, this.updatePosition, false); - }); - } - - private clearEventListeners(): void { - this.events.forEach(eventName => { - this._target.removeEventListener(eventName, this.updatePosition, false); - }); - } - - private getTargetRect(target: Element | Window | null): ClientRect { - return target !== window ? - (target as HTMLElement).getBoundingClientRect() : - { top: 0, left: 0, bottom: 0 } as ClientRect; - } - - private genStyle(affixStyle: {}): string { - if (affixStyle == null) { - return ''; - } - return Object.keys(affixStyle).map(key => { - const val = affixStyle[ key ]; - return `${key}:${typeof val === 'string' ? val : val + 'px'}`; - }).join(';'); - } - - private setAffixStyle(e: any, affixStyle: {}): void { - const originalAffixStyle = this.affixStyle; - const isWindow = this._target === window; - if (e.type === 'scroll' && originalAffixStyle && affixStyle && isWindow) { - return; - } - if (shallowEqual(originalAffixStyle, affixStyle)) { - return; - } - - const fixed = !!affixStyle; - const wrapEl = this.wrap.nativeElement as HTMLElement; - wrapEl.style.cssText = this.genStyle(affixStyle); - this.affixStyle = affixStyle; - const cls = 'ant-affix'; - if (fixed) { - wrapEl.classList.add(cls); - } else { - wrapEl.classList.remove(cls); - } - - if ((affixStyle && !originalAffixStyle) || (!affixStyle && originalAffixStyle)) { - this.nzChange.emit(fixed); - } - } - - private setPlaceholderStyle(placeholderStyle: {}): void { - const originalPlaceholderStyle = this.placeholderStyle; - if (shallowEqual(placeholderStyle, originalPlaceholderStyle)) { - return; - } - (this._el.nativeElement as HTMLElement).style.cssText = this.genStyle(placeholderStyle); - this.placeholderStyle = placeholderStyle; - } - } From 40d7d77c43ca8284239bf016a202d5a6047ed70f Mon Sep 17 00:00:00 2001 From: cipchk Date: Tue, 27 Nov 2018 21:10:26 +0800 Subject: [PATCH 2/7] fix: release --- components/affix/nz-affix.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/affix/nz-affix.component.ts b/components/affix/nz-affix.component.ts index 85a5416d104..15398f7218f 100644 --- a/components/affix/nz-affix.component.ts +++ b/components/affix/nz-affix.component.ts @@ -62,7 +62,7 @@ export class NzAffixComponent implements OnInit, OnDestroy { @Output() readonly nzChange: EventEmitter = new EventEmitter(); - constructor(private scrollSrv: NzScrollService, private _el: ElementRef, @Inject(DOCUMENT) private doc: Document, private cd: ChangeDetectorRef) { + constructor(private scrollSrv: NzScrollService, private _el: ElementRef, @Inject(DOCUMENT) private doc: any, private cd: ChangeDetectorRef) { } private timeout: any; From 54819d5ab7cba419c4a6f8fed9ee2bc908248d9e Mon Sep 17 00:00:00 2001 From: cipchk Date: Fri, 30 Nov 2018 14:52:33 +0800 Subject: [PATCH 3/7] style: removed no-any in first line --- components/affix/nz-affix.component.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/components/affix/nz-affix.component.ts b/components/affix/nz-affix.component.ts index 15398f7218f..7f5e2fc4e05 100644 --- a/components/affix/nz-affix.component.ts +++ b/components/affix/nz-affix.component.ts @@ -1,4 +1,3 @@ -// tslint:disable:no-any import { DOCUMENT } from '@angular/common'; import { ChangeDetectionStrategy, @@ -62,10 +61,11 @@ export class NzAffixComponent implements OnInit, OnDestroy { @Output() readonly nzChange: EventEmitter = new EventEmitter(); + // tslint:disable-next-line:no-any constructor(private scrollSrv: NzScrollService, private _el: ElementRef, @Inject(DOCUMENT) private doc: any, private cd: ChangeDetectorRef) { } - private timeout: any; + private timeout; private events = [ 'resize', 'scroll', @@ -75,8 +75,8 @@ export class NzAffixComponent implements OnInit, OnDestroy { 'pageshow', 'load' ]; - private affixStyle: any; - private placeholderStyle: any; + private affixStyle; + private placeholderStyle; @ViewChild('wrap') private wrap: ElementRef; @@ -96,6 +96,7 @@ export class NzAffixComponent implements OnInit, OnDestroy { ngOnDestroy(): void { this.clearEventListeners(); clearTimeout(this.timeout); + // tslint:disable-next-line:no-any (this.updatePosition as any).cancel(); } @@ -152,7 +153,7 @@ export class NzAffixComponent implements OnInit, OnDestroy { }).join(';'); } - private setAffixStyle(e: any, affixStyle: {}): void { + private setAffixStyle(e: Event, affixStyle: {}): void { const originalAffixStyle = this.affixStyle; const isWindow = this._target === window; if (e.type === 'scroll' && originalAffixStyle && affixStyle && isWindow) { @@ -188,6 +189,7 @@ export class NzAffixComponent implements OnInit, OnDestroy { } @throttleByAnimationFrameDecorator() + // tslint:disable-next-line:no-any updatePosition(e: any): void { const targetNode = this._target; // Backwards support From 067f8bfaa938b4558ae8544359e4ecb6c6231dc3 Mon Sep 17 00:00:00 2001 From: cipchk Date: Fri, 30 Nov 2018 14:54:40 +0800 Subject: [PATCH 4/7] fix: fix style --- components/affix/nz-affix.component.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/components/affix/nz-affix.component.ts b/components/affix/nz-affix.component.ts index 7f5e2fc4e05..655345efda2 100644 --- a/components/affix/nz-affix.component.ts +++ b/components/affix/nz-affix.component.ts @@ -10,7 +10,8 @@ import { OnDestroy, OnInit, Output, - ViewChild + ViewChild, + ViewEncapsulation } from '@angular/core'; import { NzScrollService } from '../core/scroll/nz-scroll.service'; @@ -22,11 +23,10 @@ import { throttleByAnimationFrameDecorator } from '../core/util/throttleByAnimat selector : 'nz-affix', templateUrl : './nz-affix.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - styles : [ - `:host { - display: block; - }` - ] + host : { + 'style' : 'display:block' + }, + encapsulation : ViewEncapsulation.None }) export class NzAffixComponent implements OnInit, OnDestroy { From 7cf4bb90be76d314d3281ca35148f985c4931cde Mon Sep 17 00:00:00 2001 From: cipchk Date: Fri, 30 Nov 2018 16:19:49 +0800 Subject: [PATCH 5/7] chore: fix test --- components/affix/affix.spec.ts | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/components/affix/affix.spec.ts b/components/affix/affix.spec.ts index 48828eaf120..6606e04b70f 100644 --- a/components/affix/affix.spec.ts +++ b/components/affix/affix.spec.ts @@ -44,6 +44,8 @@ describe('affix', () => { new Event('pageshow'), new Event('load') ]; + const height = 100; + const width = 100; beforeEach(fakeAsync(() => { TestBed.configureTestingModule({ @@ -109,13 +111,13 @@ describe('affix', () => { describe('when element gets shifted horizontally', () => { it('adjusts left position accordingly to maintain natural position', fakeAsync(() => { setupInitialState(); - componentObject.offsetTo(componentObject.elementRef(), { top: startOffset, left: 10, width: 100, height: 100 }); + componentObject.offsetTo(componentObject.elementRef(), { top: startOffset, left: 10, width, height }); emitScroll(window, defaultOffsetTop + startOffset + 1); expect(componentObject.wrap().offsetLeft).toBe(10); emitScroll(window, defaultOffsetTop + startOffset - 1); - componentObject.offsetTo(componentObject.elementRef(), { top: startOffset, left: 100, width: 100, height: 100 }); + componentObject.offsetTo(componentObject.elementRef(), { top: startOffset, left: 100, width, height }); emitScroll(window, defaultOffsetTop + startOffset + 1); expect(componentObject.wrap().offsetLeft).toBe(100); @@ -327,11 +329,12 @@ describe('affix', () => { })); }); - it('should adjust the width when resize', fakeAsync(() => { + it('should adjust placeholder width when resize', fakeAsync(() => { const offsetTop = 150; context.newOffset = offsetTop; setupInitialState({ offsetTop: offsetTop + 1 }); emitScroll(window, 2); + expect(componentObject.elementRef().style.width).toBe(`${width}px`); componentObject.offsetYTo(componentObject.elementRef(), offsetTop + 2); tick(20); fixture.detectChanges(); @@ -339,7 +342,7 @@ describe('affix', () => { tick(20); fixture.detectChanges(); - expect(componentObject.wrap().offsetTop).toBe(offsetTop); + expect(componentObject.elementRef().style.width).toBe(``); discardPeriodicTasks(); })); @@ -361,7 +364,7 @@ describe('affix', () => { } getOffset(el: Element): Offset { - return this.offsets[el.id] || { top: 10, left: 0, height: 100, width: 100 }; + return this.offsets[el.id] || { top: 10, left: 0, height, width }; } emitEvent(el: Element | Window, event: Event): void { @@ -377,8 +380,8 @@ describe('affix', () => { this.offsets[this.getKey(el)] = { top: offset.top, left: offset.left, - height: 100, - width: 100 + height, + width }; } @@ -388,8 +391,8 @@ describe('affix', () => { { top: offsetTop, left: 0, - height: 100, - width: 100 + height, + width } ); } From fcbde8d2a6db47f4698be0f966ff83a1f8a7454d Mon Sep 17 00:00:00 2001 From: cipchk Date: Fri, 30 Nov 2018 16:31:51 +0800 Subject: [PATCH 6/7] chore: fix display style in host --- components/affix/nz-affix.component.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/components/affix/nz-affix.component.ts b/components/affix/nz-affix.component.ts index 655345efda2..6aca7e495bf 100644 --- a/components/affix/nz-affix.component.ts +++ b/components/affix/nz-affix.component.ts @@ -23,9 +23,11 @@ import { throttleByAnimationFrameDecorator } from '../core/util/throttleByAnimat selector : 'nz-affix', templateUrl : './nz-affix.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - host : { - 'style' : 'display:block' - }, + styles : [ ` + :host { + display: block; + } + ` ], encapsulation : ViewEncapsulation.None }) export class NzAffixComponent implements OnInit, OnDestroy { From f5cd7b0525ebbcb440bffcbfeaf6b94cb3c0aa92 Mon Sep 17 00:00:00 2001 From: cipchk Date: Fri, 30 Nov 2018 16:44:42 +0800 Subject: [PATCH 7/7] chore: remove :host --- components/affix/nz-affix.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/affix/nz-affix.component.ts b/components/affix/nz-affix.component.ts index 6aca7e495bf..4b579cf62cc 100644 --- a/components/affix/nz-affix.component.ts +++ b/components/affix/nz-affix.component.ts @@ -24,7 +24,7 @@ import { throttleByAnimationFrameDecorator } from '../core/util/throttleByAnimat templateUrl : './nz-affix.component.html', changeDetection: ChangeDetectionStrategy.OnPush, styles : [ ` - :host { + nz-affix { display: block; } ` ],