From 552dea87a572ee8c93526a0ccb9b78d5842ebf51 Mon Sep 17 00:00:00 2001 From: Dmitry Efimenko Date: Wed, 26 Jun 2019 15:12:01 -0700 Subject: [PATCH 1/3] feat: added option cleanUpAfterCopy closes #196 --- .gitignore | 1 + .vscode/settings.json | 3 + README.md | 12 + package.json | 1 + .../ngx-clipboard/src/lib/injection-tokens.ts | 5 + projects/ngx-clipboard/src/lib/interface.ts | 12 +- .../src/lib/ngx-clipboard.directive.spec.ts | 342 ++++++++++-------- .../src/lib/ngx-clipboard.module.ts | 22 +- .../src/lib/ngx-clipboard.service.spec.ts | 3 +- .../src/lib/ngx-clipboard.service.ts | 28 +- projects/ngx-clipboard/src/public_api.ts | 1 + 11 files changed, 258 insertions(+), 172 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 projects/ngx-clipboard/src/lib/injection-tokens.ts diff --git a/.gitignore b/.gitignore index 721e90e..dbb7516 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ node_modules !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json +!.vscode/settings.json # misc /.sass-cache diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0623957 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.tabSize": 4 +} diff --git a/README.md b/README.md index 5655446..13c2adb 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,18 @@ export class ClipboardResponseService { _Special thanks to @surajpoddar16 for implementing this feature_ +### Clean up temporary textarea used by this module after each copy to clipboard +This library creates a textarea element at the root of the body for its internal use. By default it only destroys it when the directive is destroyed. If you'd like it to be destroyed after each copy to clipboard, provide root level module configuration like this: +```ts +import { ClipboardModule } from 'ngx-clipboard'; +... +imports: [ + ClipboardModule.forRoot({ cleanUpAfterCopy: true }), +] +``` + +Special thanks to [@DmitryEfimenko](https://github.com/DmitryEfimenko) for implementing this feature + ## Example [stackblitz.com](https://stackblitz.com/github/maxisam/ngx-clipboard) diff --git a/package.json b/package.json index 651e392..079f8ea 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "start": "ng serve", "build": "ng build ngx-clipboard --prod && npm run build-copy", "test": "ng test ngx-clipboard", + "test:watch": "ng test ngx-clipboard --watch", "lint": "ng lint ngx-clipboard", "publish:lib": "yarn publish ./dist/lib", "publish:lib:next": "yarn publish ./dist/lib --tag next", diff --git a/projects/ngx-clipboard/src/lib/injection-tokens.ts b/projects/ngx-clipboard/src/lib/injection-tokens.ts new file mode 100644 index 0000000..d350f88 --- /dev/null +++ b/projects/ngx-clipboard/src/lib/injection-tokens.ts @@ -0,0 +1,5 @@ +import { InjectionToken } from '@angular/core'; + +import { ClipboardParams } from './interface'; + +export const CLIPBOARD_ROOT_OPTIONS = new InjectionToken('CLIPBOARD_ROOT_OPTIONS'); diff --git a/projects/ngx-clipboard/src/lib/interface.ts b/projects/ngx-clipboard/src/lib/interface.ts index 8d7e2bd..175f1ec 100644 --- a/projects/ngx-clipboard/src/lib/interface.ts +++ b/projects/ngx-clipboard/src/lib/interface.ts @@ -1,6 +1,10 @@ export interface IClipboardResponse { - isSuccess: boolean; - content?: string; - event: Event; - successMessage?: string; + isSuccess: boolean; + content?: string; + event: Event; + successMessage?: string; +} + +export interface ClipboardParams { + cleanUpAfterCopy?: boolean; } diff --git a/projects/ngx-clipboard/src/lib/ngx-clipboard.directive.spec.ts b/projects/ngx-clipboard/src/lib/ngx-clipboard.directive.spec.ts index b49851b..4ff990f 100644 --- a/projects/ngx-clipboard/src/lib/ngx-clipboard.directive.spec.ts +++ b/projects/ngx-clipboard/src/lib/ngx-clipboard.directive.spec.ts @@ -4,9 +4,10 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { FormsModule } from '@angular/forms'; import { BrowserModule } from '@angular/platform-browser'; +import { CLIPBOARD_ROOT_OPTIONS } from './injection-tokens'; +import { ClipboardParams, IClipboardResponse } from './interface'; import { ClipboardModule } from './ngx-clipboard.module'; import { ClipboardService } from './ngx-clipboard.service'; -import { IClipboardResponse } from './interface'; /* * Shell component with property 'text' that will be used with our tests @@ -33,185 +34,216 @@ function createTestComponent(template: string): ComponentFixture { - beforeEach(() => { - TestBed.configureTestingModule({ - declarations: [TestClipboardComponent], - imports: [BrowserModule, ClipboardModule, FormsModule] - }); - }); - - describe('copy when cbContent is set', () => { - let template: string; - let fixture: ComponentFixture; - let clipboardService: ClipboardService; - let spy: jasmine.Spy; - let button: HTMLButtonElement; + describe('GIVEN: no root configuration', () => { beforeEach(() => { - template = ``; - fixture = createTestComponent(template); - clipboardService = fixture.debugElement.injector.get(ClipboardService); - // Setup spy on the `copyText` method, somehow document.execCommand('copy') doesn't work in Karma - spy = spyOn(clipboardService, 'copyText' as keyof (ClipboardService)); - fixture.detectChanges(); - button = fixture.debugElement.nativeElement.querySelector('button'); + TestBed.configureTestingModule({ + declarations: [TestClipboardComponent], + imports: [BrowserModule, ClipboardModule, FormsModule], + providers: [ClipboardService] + }); }); - it('should fire cbOnError if environment does not support copy', async(() => { - spy = spyOn(clipboardService, 'isSupported'); - spy.and.returnValue(false); - button.click(); - fixture.whenStable().then(() => { - expect(fixture.componentInstance.isCopied).toBeFalsy(); + describe('copy when cbContent is set', () => { + let template: string; + let fixture: ComponentFixture; + let clipboardService: ClipboardService; + let spy: jasmine.Spy; + let button: HTMLButtonElement; + beforeEach(() => { + template = ``; + fixture = createTestComponent(template); + clipboardService = fixture.debugElement.injector.get(ClipboardService); + // Setup spy on the `copyText` method, somehow document.execCommand('copy') doesn't work in Karma + spy = spyOn(clipboardService, 'copyText' as keyof (ClipboardService)); + fixture.detectChanges(); + button = fixture.debugElement.nativeElement.querySelector('button'); }); - })); - it('should fire cbOnSuccess after copy successfully', async(() => { - spy.and.returnValue(true); - button.click(); - fixture.whenStable().then(() => { - expect(fixture.componentInstance.isCopied).toBeTruthy(); - }); - })); + it('should fire cbOnError if environment does not support copy', async(() => { + spy = spyOn(clipboardService, 'isSupported'); + spy.and.returnValue(false); + button.click(); + fixture.whenStable().then(() => { + expect(fixture.componentInstance.isCopied).toBeFalsy(); + }); + })); + + it('should fire cbOnSuccess after copy successfully', async(() => { + spy.and.returnValue(true); + button.click(); + fixture.whenStable().then(() => { + expect(fixture.componentInstance.isCopied).toBeTruthy(); + }); + })); + + it('should fire cbOnError after copy fail', async(() => { + button.click(); + fixture.whenStable().then(() => { + expect(fixture.componentInstance.isCopied).toBeFalsy(); + }); + })); + + it('should create a textarea in dom, and remove it after calling destroy', async(() => { + const doc = fixture.debugElement.injector.get(DOCUMENT); + expect(doc.querySelector('textarea')).toBeFalsy(); + button.click(); + fixture.whenStable().then(() => { + expect(doc.querySelector('textarea')).toBeTruthy(); + clipboardService.destroy(doc.body); + expect(doc.querySelector('textarea')).toBeFalsy(); + }); + })); + + it('should push copy response to copySubject', async(() => { + button.click(); + const component = fixture.componentInstance; + clipboardService.copyResponse$.subscribe((res: IClipboardResponse) => { + expect(res).toBeDefined(); + expect(res.isSuccess).toEqual(true); + expect(res.content).toEqual(component.text); + expect(res.successMessage).toEqual(component.copySuccessMsg); + expect(res.event).toBeDefined(); + }); + })); + }); - it('should fire cbOnError after copy fail', async(() => { - button.click(); - fixture.whenStable().then(() => { - expect(fixture.componentInstance.isCopied).toBeFalsy(); + describe('copy when cbContent and container is set', () => { + let template: string; + let fixture: ComponentFixture; + let clipboardService: ClipboardService; + let spy: jasmine.Spy; + let button: HTMLButtonElement; + beforeEach(() => { + template = `
`; + fixture = createTestComponent(template); + clipboardService = fixture.debugElement.injector.get(ClipboardService); + // Setup spy on the `copyText` method, somehow document.execCommand('copy') doesn't work in Karma + spy = spyOn(clipboardService, 'copyText' as keyof (ClipboardService)); + fixture.detectChanges(); + button = fixture.debugElement.nativeElement.querySelector('button'); }); - })); - it('should create a textarea in dom, and remove it after calling destroy', async(() => { - const doc = fixture.debugElement.injector.get(DOCUMENT); - expect(doc.querySelector('textarea')).toBeFalsy(); - button.click(); - fixture.whenStable().then(() => { - expect(doc.querySelector('textarea')).toBeTruthy(); - clipboardService.destroy(doc.body); + it('should create a textarea in dom, and remove it after calling destroy', async(() => { + const doc = fixture.debugElement.injector.get(DOCUMENT); expect(doc.querySelector('textarea')).toBeFalsy(); - }); - })); + button.click(); + fixture.whenStable().then(() => { + const ta = doc.querySelector('textarea'); + expect(ta).toBeTruthy(); + expect(ta.parentElement.className).toBe('container'); + clipboardService.destroy(ta.parentElement); + expect(doc.querySelector('textarea')).toBeFalsy(); + }); + })); + }); - it('should push copy response to copySubject', async(() => { - button.click(); - const component = fixture.componentInstance; - clipboardService.copyResponse$.subscribe((res: IClipboardResponse) => { - expect(res).toBeDefined(); - expect(res.isSuccess).toEqual(true); - expect(res.content).toEqual(component.text); - expect(res.successMessage).toEqual(component.copySuccessMsg); - expect(res.event).toBeDefined(); + describe('copy when using copyFromContent directly', () => { + let template: string; + let fixture: ComponentFixture; + let clipboardService: ClipboardService; + let spy: jasmine.Spy; + let button: HTMLButtonElement; + beforeEach(() => { + template = `
`; + fixture = createTestComponent(template); + clipboardService = fixture.debugElement.injector.get(ClipboardService); + // Setup spy on the `copyText` method, somehow document.execCommand('copy') doesn't work in Karma + spy = spyOn(clipboardService, 'copyText' as keyof (ClipboardService)); + fixture.detectChanges(); + button = fixture.debugElement.nativeElement.querySelector('button'); }); - })); - }); - describe('copy when cbContent and container is set', () => { - let template: string; - let fixture: ComponentFixture; - let clipboardService: ClipboardService; - let spy: jasmine.Spy; - let button: HTMLButtonElement; - beforeEach(() => { - template = `
`; - fixture = createTestComponent(template); - clipboardService = fixture.debugElement.injector.get(ClipboardService); - // Setup spy on the `copyText` method, somehow document.execCommand('copy') doesn't work in Karma - spy = spyOn(clipboardService, 'copyText' as keyof (ClipboardService)); - fixture.detectChanges(); - button = fixture.debugElement.nativeElement.querySelector('button'); + it('should create a textarea in dom with parent as body, and remove it after calling destroy', async(() => { + const doc = fixture.debugElement.injector.get(DOCUMENT); + expect(doc.querySelector('textarea')).toBeFalsy(); + clipboardService.copyFromContent('test content'); + fixture.whenStable().then(() => { + const ta = doc.querySelector('textarea'); + expect(ta).toBeTruthy(); + expect(ta.parentElement.nodeName).toBe('BODY'); + clipboardService.destroy(ta.parentElement); + expect(doc.querySelector('textarea')).toBeFalsy(); + }); + })); }); - it('should create a textarea in dom, and remove it after calling destroy', async(() => { - const doc = fixture.debugElement.injector.get(DOCUMENT); - expect(doc.querySelector('textarea')).toBeFalsy(); - button.click(); - fixture.whenStable().then(() => { - const ta = doc.querySelector('textarea'); - expect(ta).toBeTruthy(); - expect(ta.parentElement.className).toBe('container'); - clipboardService.destroy(ta.parentElement); - expect(doc.querySelector('textarea')).toBeFalsy(); + describe('copy when target is set', () => { + let template: string; + let fixture: ComponentFixture; + let clipboardService: ClipboardService; + let spy: jasmine.Spy; + let button: HTMLButtonElement; + let input: HTMLInputElement; + beforeEach(() => { + template = ` + `; + fixture = createTestComponent(template); + clipboardService = fixture.debugElement.injector.get(ClipboardService); + // Setup spy on the `copyText` method, somehow document.execCommand('copy') doesn't work in Karma + spy = spyOn(clipboardService, 'copyText' as keyof (ClipboardService)); + fixture.detectChanges(); + button = fixture.debugElement.nativeElement.querySelector('button'); + input = fixture.debugElement.nativeElement.querySelector('input'); + // input 'new test' + input.value = 'new test'; + input.dispatchEvent(new Event('input')); }); - })); - }); - describe('copy when using copyFromContent directly', () => { - let template: string; - let fixture: ComponentFixture; - let clipboardService: ClipboardService; - let spy: jasmine.Spy; - let button: HTMLButtonElement; - beforeEach(() => { - template = `
`; - fixture = createTestComponent(template); - clipboardService = fixture.debugElement.injector.get(ClipboardService); - // Setup spy on the `copyText` method, somehow document.execCommand('copy') doesn't work in Karma - spy = spyOn(clipboardService, 'copyText' as keyof (ClipboardService)); - fixture.detectChanges(); - button = fixture.debugElement.nativeElement.querySelector('button'); + it('should fire cbOnSuccess after copy successfully', async(() => { + spy.and.returnValue(true); + fixture.detectChanges(); + // button click to trigger copy + button.click(); + fixture.whenStable().then(() => { + expect(fixture.componentInstance.isCopied).toBeTruthy(); + }); + })); + + it('should fire cbOnError if environment does not support copy', async(() => { + spy = spyOn(clipboardService, 'isSupported'); + spy.and.returnValue(false); + button.click(); + fixture.whenStable().then(() => { + expect(fixture.componentInstance.isCopied).toBeFalsy(); + }); + })); + + it('should fire cbOnError after copy fail', async(() => { + spy.and.returnValue(false); + fixture.detectChanges(); + // button click to trigger copy + button.click(); + fixture.whenStable().then(() => { + expect(fixture.componentInstance.isCopied).toBeFalsy(); + }); + })); }); - - it('should create a textarea in dom with parent as body, and remove it after calling destroy', async(() => { - const doc = fixture.debugElement.injector.get(DOCUMENT); - expect(doc.querySelector('textarea')).toBeFalsy(); - clipboardService.copyFromContent('test content'); - fixture.whenStable().then(() => { - const ta = doc.querySelector('textarea'); - expect(ta).toBeTruthy(); - expect(ta.parentElement.nodeName).toBe('BODY'); - clipboardService.destroy(ta.parentElement); - expect(doc.querySelector('textarea')).toBeFalsy(); - }); - })); }); - describe('copy when target is set', () => { - let template: string; + describe('GIVEN with root configuration', () => { let fixture: ComponentFixture; let clipboardService: ClipboardService; - let spy: jasmine.Spy; - let button: HTMLButtonElement; - let input: HTMLInputElement; - beforeEach(() => { - template = ` - `; - fixture = createTestComponent(template); - clipboardService = fixture.debugElement.injector.get(ClipboardService); - // Setup spy on the `copyText` method, somehow document.execCommand('copy') doesn't work in Karma - spy = spyOn(clipboardService, 'copyText' as keyof (ClipboardService)); - fixture.detectChanges(); - button = fixture.debugElement.nativeElement.querySelector('button'); - input = fixture.debugElement.nativeElement.querySelector('input'); - // input 'new test' - input.value = 'new test'; - input.dispatchEvent(new Event('input')); - }); - - it('should fire cbOnSuccess after copy successfully', async(() => { - spy.and.returnValue(true); - fixture.detectChanges(); - // button click to trigger copy - button.click(); - fixture.whenStable().then(() => { - expect(fixture.componentInstance.isCopied).toBeTruthy(); - }); - })); + let doc: Document; - it('should fire cbOnError if environment does not support copy', async(() => { - spy = spyOn(clipboardService, 'isSupported'); - spy.and.returnValue(false); - button.click(); - fixture.whenStable().then(() => { - expect(fixture.componentInstance.isCopied).toBeFalsy(); + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TestClipboardComponent], + imports: [BrowserModule, ClipboardModule, FormsModule], + providers: [ + ClipboardService, + { provide: CLIPBOARD_ROOT_OPTIONS, useValue: { cleanUpAfterCopy: true } } + ] }); - })); + fixture = createTestComponent(`
`); + clipboardService = TestBed.get(ClipboardService); + doc = TestBed.get(DOCUMENT); + }); - it('should fire cbOnError after copy fail', async(() => { - spy.and.returnValue(false); - fixture.detectChanges(); - // button click to trigger copy - button.click(); + it('should clean up temp textarea after copying automatically', async(() => { + clipboardService.copyFromContent('test content'); fixture.whenStable().then(() => { - expect(fixture.componentInstance.isCopied).toBeFalsy(); + const ta = doc.querySelector('textarea'); + expect(ta).toBeFalsy(); }); })); }); diff --git a/projects/ngx-clipboard/src/lib/ngx-clipboard.module.ts b/projects/ngx-clipboard/src/lib/ngx-clipboard.module.ts index 3d5fc58..3abbb49 100644 --- a/projects/ngx-clipboard/src/lib/ngx-clipboard.module.ts +++ b/projects/ngx-clipboard/src/lib/ngx-clipboard.module.ts @@ -1,12 +1,26 @@ import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; +import { ModuleWithProviders, NgModule } from '@angular/core'; -import { ClipboardDirective } from './ngx-clipboard.directive'; +import { CLIPBOARD_ROOT_OPTIONS } from './injection-tokens'; +import { ClipboardParams } from './interface'; import { ClipboardIfSupportedDirective } from './ngx-clipboard-if-supported.directive'; +import { ClipboardDirective } from './ngx-clipboard.directive'; +import { ClipboardService } from './ngx-clipboard.service'; @NgModule({ imports: [CommonModule], declarations: [ClipboardDirective, ClipboardIfSupportedDirective], - exports: [ClipboardDirective, ClipboardIfSupportedDirective] + exports: [ClipboardDirective, ClipboardIfSupportedDirective], + providers: [ClipboardService] }) -export class ClipboardModule {} +export class ClipboardModule { + static forRoot(params: ClipboardParams): ModuleWithProviders { + return { + ngModule: ClipboardModule, + providers: [ + ClipboardService, + { provide: CLIPBOARD_ROOT_OPTIONS, useValue: params } + ] + }; + } +} diff --git a/projects/ngx-clipboard/src/lib/ngx-clipboard.service.spec.ts b/projects/ngx-clipboard/src/lib/ngx-clipboard.service.spec.ts index 2f61227..cbd8564 100644 --- a/projects/ngx-clipboard/src/lib/ngx-clipboard.service.spec.ts +++ b/projects/ngx-clipboard/src/lib/ngx-clipboard.service.spec.ts @@ -6,7 +6,8 @@ import { ClipboardService } from './ngx-clipboard.service'; describe('Service: Clipboard', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [BrowserModule] + imports: [BrowserModule], + providers: [ClipboardService] }); }); diff --git a/projects/ngx-clipboard/src/lib/ngx-clipboard.service.ts b/projects/ngx-clipboard/src/lib/ngx-clipboard.service.ts index 0685ec0..c61ed74 100644 --- a/projects/ngx-clipboard/src/lib/ngx-clipboard.service.ts +++ b/projects/ngx-clipboard/src/lib/ngx-clipboard.service.ts @@ -1,13 +1,15 @@ - -import { Inject, Injectable, Optional } from '@angular/core'; import { DOCUMENT } from '@angular/common'; +import { Inject, Injectable, Optional } from '@angular/core'; import { WINDOW } from 'ngx-window-token'; -import { Subject, Observable } from 'rxjs'; -import { IClipboardResponse } from './interface'; +import { Observable, Subject } from 'rxjs'; + +import { CLIPBOARD_ROOT_OPTIONS } from './injection-tokens'; +import { ClipboardParams, IClipboardResponse } from './interface'; + // The following code is heavily copy from https://github.com/zenorocha/clipboard.js -@Injectable({ providedIn: 'root' }) +@Injectable() export class ClipboardService { private tempTextArea: HTMLTextAreaElement | undefined; @@ -16,8 +18,13 @@ export class ClipboardService { constructor( @Inject(DOCUMENT) public document: any, - @Optional() @Inject(WINDOW) private window: any - ) {} + @Optional() @Inject(WINDOW) private window: any, + @Optional() @Inject(CLIPBOARD_ROOT_OPTIONS) private rootOptions: ClipboardParams + ) { + if (!this.rootOptions) { + this.rootOptions = {}; + } + } public get isSupported(): boolean { return !!this.document.queryCommandSupported && !!this.document.queryCommandSupported('copy') && !!this.window; @@ -78,7 +85,12 @@ export class ClipboardService { } } this.tempTextArea.value = content; - return this.copyFromInputElement(this.tempTextArea); + + const toReturn = this.copyFromInputElement(this.tempTextArea); + if (this.rootOptions.cleanUpAfterCopy) { + this.destroy(this.tempTextArea.parentElement); + } + return toReturn; } // remove temporary textarea if any diff --git a/projects/ngx-clipboard/src/public_api.ts b/projects/ngx-clipboard/src/public_api.ts index 4b7650f..db8eb76 100644 --- a/projects/ngx-clipboard/src/public_api.ts +++ b/projects/ngx-clipboard/src/public_api.ts @@ -7,3 +7,4 @@ export * from './lib/ngx-clipboard.directive'; export * from './lib/ngx-clipboard.module'; export * from './lib/ngx-clipboard-if-supported.directive'; export * from './lib/interface'; +export * from './lib/injection-tokens'; From 97d62703586f6145e53ee821412d4e0f1ab0e49c Mon Sep 17 00:00:00 2001 From: Dmitry Efimenko Date: Fri, 28 Jun 2019 16:47:52 -0700 Subject: [PATCH 2/3] fix: remove settings.json --- .gitignore | 2 +- .vscode/settings.json | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index dbb7516..fef82d4 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,7 @@ node_modules !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json -!.vscode/settings.json + # misc /.sass-cache diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 0623957..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "editor.tabSize": 4 -} From 0228fa868372f92176c7a1eeac79edf870e901c8 Mon Sep 17 00:00:00 2001 From: Dmitry Efimenko Date: Fri, 28 Jun 2019 16:47:52 -0700 Subject: [PATCH 3/3] fix: provide config via service method --- .../ngx-clipboard/src/lib/injection-tokens.ts | 5 --- projects/ngx-clipboard/src/lib/interface.ts | 3 -- .../src/lib/ngx-clipboard.directive.spec.ts | 41 +++++-------------- .../src/lib/ngx-clipboard.module.ts | 20 ++------- .../src/lib/ngx-clipboard.service.spec.ts | 3 +- .../src/lib/ngx-clipboard.service.ts | 19 ++++----- projects/ngx-clipboard/src/public_api.ts | 1 - 7 files changed, 22 insertions(+), 70 deletions(-) delete mode 100644 projects/ngx-clipboard/src/lib/injection-tokens.ts diff --git a/projects/ngx-clipboard/src/lib/injection-tokens.ts b/projects/ngx-clipboard/src/lib/injection-tokens.ts deleted file mode 100644 index d350f88..0000000 --- a/projects/ngx-clipboard/src/lib/injection-tokens.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { InjectionToken } from '@angular/core'; - -import { ClipboardParams } from './interface'; - -export const CLIPBOARD_ROOT_OPTIONS = new InjectionToken('CLIPBOARD_ROOT_OPTIONS'); diff --git a/projects/ngx-clipboard/src/lib/interface.ts b/projects/ngx-clipboard/src/lib/interface.ts index e8afb71..175f1ec 100644 --- a/projects/ngx-clipboard/src/lib/interface.ts +++ b/projects/ngx-clipboard/src/lib/interface.ts @@ -3,11 +3,8 @@ export interface IClipboardResponse { content?: string; event: Event; successMessage?: string; -<<<<<<< HEAD } export interface ClipboardParams { cleanUpAfterCopy?: boolean; -======= ->>>>>>> upstream/master } diff --git a/projects/ngx-clipboard/src/lib/ngx-clipboard.directive.spec.ts b/projects/ngx-clipboard/src/lib/ngx-clipboard.directive.spec.ts index d5af261..b1e3600 100644 --- a/projects/ngx-clipboard/src/lib/ngx-clipboard.directive.spec.ts +++ b/projects/ngx-clipboard/src/lib/ngx-clipboard.directive.spec.ts @@ -4,8 +4,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { FormsModule } from '@angular/forms'; import { BrowserModule } from '@angular/platform-browser'; -import { CLIPBOARD_ROOT_OPTIONS } from './injection-tokens'; -import { ClipboardParams, IClipboardResponse } from './interface'; +import { IClipboardResponse } from './interface'; import { ClipboardModule } from './ngx-clipboard.module'; import { ClipboardService } from './ngx-clipboard.service'; @@ -96,6 +95,16 @@ describe('Directive: clipboard', () => { }); })); + it('given the configuration it should clean up temp textarea after copying automatically', async(() => { + const doc = fixture.debugElement.injector.get(DOCUMENT); + clipboardService.configure({ cleanUpAfterCopy: true }); + clipboardService.copyFromContent('test content'); + fixture.whenStable().then(() => { + const ta = doc.querySelector('textarea'); + expect(ta).toBeFalsy(); + }); + })); + it('should push copy response to copySubject', async(() => { button.click(); const component = fixture.componentInstance; @@ -221,32 +230,4 @@ describe('Directive: clipboard', () => { })); }); }); - - describe('GIVEN with root configuration', () => { - let fixture: ComponentFixture; - let clipboardService: ClipboardService; - let doc: Document; - - beforeEach(() => { - TestBed.configureTestingModule({ - declarations: [TestClipboardComponent], - imports: [BrowserModule, ClipboardModule, FormsModule], - providers: [ - ClipboardService, - { provide: CLIPBOARD_ROOT_OPTIONS, useValue: { cleanUpAfterCopy: true } } - ] - }); - fixture = createTestComponent(`
`); - clipboardService = TestBed.get(ClipboardService); - doc = TestBed.get(DOCUMENT); - }); - - it('should clean up temp textarea after copying automatically', async(() => { - clipboardService.copyFromContent('test content'); - fixture.whenStable().then(() => { - const ta = doc.querySelector('textarea'); - expect(ta).toBeFalsy(); - }); - })); - }); }); diff --git a/projects/ngx-clipboard/src/lib/ngx-clipboard.module.ts b/projects/ngx-clipboard/src/lib/ngx-clipboard.module.ts index 3abbb49..148b5d6 100644 --- a/projects/ngx-clipboard/src/lib/ngx-clipboard.module.ts +++ b/projects/ngx-clipboard/src/lib/ngx-clipboard.module.ts @@ -1,26 +1,12 @@ import { CommonModule } from '@angular/common'; -import { ModuleWithProviders, NgModule } from '@angular/core'; +import { NgModule } from '@angular/core'; -import { CLIPBOARD_ROOT_OPTIONS } from './injection-tokens'; -import { ClipboardParams } from './interface'; import { ClipboardIfSupportedDirective } from './ngx-clipboard-if-supported.directive'; import { ClipboardDirective } from './ngx-clipboard.directive'; -import { ClipboardService } from './ngx-clipboard.service'; @NgModule({ imports: [CommonModule], declarations: [ClipboardDirective, ClipboardIfSupportedDirective], - exports: [ClipboardDirective, ClipboardIfSupportedDirective], - providers: [ClipboardService] + exports: [ClipboardDirective, ClipboardIfSupportedDirective] }) -export class ClipboardModule { - static forRoot(params: ClipboardParams): ModuleWithProviders { - return { - ngModule: ClipboardModule, - providers: [ - ClipboardService, - { provide: CLIPBOARD_ROOT_OPTIONS, useValue: params } - ] - }; - } -} +export class ClipboardModule {} diff --git a/projects/ngx-clipboard/src/lib/ngx-clipboard.service.spec.ts b/projects/ngx-clipboard/src/lib/ngx-clipboard.service.spec.ts index 4f80673..3af182e 100644 --- a/projects/ngx-clipboard/src/lib/ngx-clipboard.service.spec.ts +++ b/projects/ngx-clipboard/src/lib/ngx-clipboard.service.spec.ts @@ -6,8 +6,7 @@ import { ClipboardService } from './ngx-clipboard.service'; describe('Service: Clipboard', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [BrowserModule], - providers: [ClipboardService] + imports: [BrowserModule] }); }); diff --git a/projects/ngx-clipboard/src/lib/ngx-clipboard.service.ts b/projects/ngx-clipboard/src/lib/ngx-clipboard.service.ts index c61ed74..1fe8614 100644 --- a/projects/ngx-clipboard/src/lib/ngx-clipboard.service.ts +++ b/projects/ngx-clipboard/src/lib/ngx-clipboard.service.ts @@ -3,27 +3,22 @@ import { Inject, Injectable, Optional } from '@angular/core'; import { WINDOW } from 'ngx-window-token'; import { Observable, Subject } from 'rxjs'; -import { CLIPBOARD_ROOT_OPTIONS } from './injection-tokens'; import { ClipboardParams, IClipboardResponse } from './interface'; - // The following code is heavily copy from https://github.com/zenorocha/clipboard.js -@Injectable() +@Injectable({ providedIn: 'root' }) export class ClipboardService { private tempTextArea: HTMLTextAreaElement | undefined; + private config: ClipboardParams = {}; private copySubject = new Subject(); public copyResponse$: Observable = this.copySubject.asObservable(); - constructor( - @Inject(DOCUMENT) public document: any, - @Optional() @Inject(WINDOW) private window: any, - @Optional() @Inject(CLIPBOARD_ROOT_OPTIONS) private rootOptions: ClipboardParams - ) { - if (!this.rootOptions) { - this.rootOptions = {}; - } + constructor(@Inject(DOCUMENT) public document: any, @Optional() @Inject(WINDOW) private window: any) {} + + public configure(config: ClipboardParams) { + this.config = config; } public get isSupported(): boolean { @@ -87,7 +82,7 @@ export class ClipboardService { this.tempTextArea.value = content; const toReturn = this.copyFromInputElement(this.tempTextArea); - if (this.rootOptions.cleanUpAfterCopy) { + if (this.config.cleanUpAfterCopy) { this.destroy(this.tempTextArea.parentElement); } return toReturn; diff --git a/projects/ngx-clipboard/src/public_api.ts b/projects/ngx-clipboard/src/public_api.ts index db8eb76..4b7650f 100644 --- a/projects/ngx-clipboard/src/public_api.ts +++ b/projects/ngx-clipboard/src/public_api.ts @@ -7,4 +7,3 @@ export * from './lib/ngx-clipboard.directive'; export * from './lib/ngx-clipboard.module'; export * from './lib/ngx-clipboard-if-supported.directive'; export * from './lib/interface'; -export * from './lib/injection-tokens';