Skip to content

Commit

Permalink
Merge pull request #216 from tabuckner/copy-method
Browse files Browse the repository at this point in the history
Allow for updating `copyResponse$` when calling `copyFromContent` directly in service.
  • Loading branch information
maxisam authored Nov 25, 2019
2 parents 9b0c737 + ae097f4 commit 785d2e2
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 17 deletions.
2 changes: 1 addition & 1 deletion projects/ngx-clipboard/src/lib/interface.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export interface IClipboardResponse {
isSuccess: boolean;
content?: string;
event: Event;
event?: Event;
successMessage?: string;
}

Expand Down
54 changes: 38 additions & 16 deletions projects/ngx-clipboard/src/lib/ngx-clipboard.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,33 @@ import { Observable, Subject } from 'rxjs';

import { ClipboardParams, IClipboardResponse } from './interface';

// The following code is heavily copy from https:/zenorocha/clipboard.js

/**
* The following code is heavily copied from https:/zenorocha/clipboard.js
*/
@Injectable({ providedIn: 'root' })
export class ClipboardService {
private tempTextArea: HTMLTextAreaElement | undefined;
private config: ClipboardParams = {};

private copySubject = new Subject<IClipboardResponse>();
public copyResponse$: Observable<IClipboardResponse> = this.copySubject.asObservable();
private tempTextArea: HTMLTextAreaElement | undefined;
private config: ClipboardParams = {};

constructor(@Inject(DOCUMENT) public document: any, @Optional() @Inject(WINDOW) private window: any) {}

public configure(config: ClipboardParams) {
this.config = config;
}

public copy(content: string): void {
if (!this.isSupported || !content) {
return this.pushCopyResponse({ isSuccess: false, content });
}
const copyResult = this.copyFromContent(content);
if (copyResult) {
return this.pushCopyResponse({ content, isSuccess: copyResult });
}
return this.pushCopyResponse({ isSuccess: false, content });
}

public get isSupported(): boolean {
return !!this.document.queryCommandSupported && !!this.document.queryCommandSupported('copy') && !!this.window;
}
Expand All @@ -36,7 +47,7 @@ export class ClipboardService {
}

/**
* copyFromInputElement
* Attempts to copy from an input `targetElm`
*/
public copyFromInputElement(targetElm: HTMLInputElement | HTMLTextAreaElement): boolean {
try {
Expand All @@ -49,8 +60,10 @@ export class ClipboardService {
}
}

// this is for IE11 return true even if copy fail
isCopySuccessInIE11() {
/**
* This is a hack for IE11 to return `true` even if copy fails.
*/
public isCopySuccessInIE11(): boolean {
const clipboardData = this.window['clipboardData'];
if (clipboardData && clipboardData.getData) {
if (!clipboardData.getData('Text')) {
Expand All @@ -64,7 +77,7 @@ export class ClipboardService {
* Creates a fake textarea element, sets its value from `text` property,
* and makes a selection on it.
*/
public copyFromContent(content: string, container: HTMLElement = this.document.body) {
public copyFromContent(content: string, container: HTMLElement = this.document.body): boolean {
// check if the temp textarea still belongs to the current container.
// In case we have multiple places using ngx-clipboard, one is in a modal using container but the other one is not.
if (this.tempTextArea && !container.contains(this.tempTextArea)) {
Expand All @@ -88,16 +101,20 @@ export class ClipboardService {
return toReturn;
}

// remove temporary textarea if any
public destroy(container: HTMLElement = this.document.body) {
/**
* Remove temporary textarea if any exists.
*/
public destroy(container: HTMLElement = this.document.body): void {
if (this.tempTextArea) {
container.removeChild(this.tempTextArea);
// removeChild doesn't remove the reference from memory
this.tempTextArea = undefined;
}
}

// select the target html input element
/**
* Select the target html input element.
*/
private selectTarget(inputElement: HTMLInputElement | HTMLTextAreaElement): number | undefined {
inputElement.select();
inputElement.setSelectionRange(0, inputElement.value.length);
Expand All @@ -107,14 +124,19 @@ export class ClipboardService {
private copyText(): boolean {
return this.document.execCommand('copy');
}
// Moves focus away from `target` and back to the trigger, removes current selection.
private clearSelection(inputElement: HTMLInputElement | HTMLTextAreaElement, window: Window) {

/**
* Moves focus away from `target` and back to the trigger, removes current selection.
*/
private clearSelection(inputElement: HTMLInputElement | HTMLTextAreaElement, window: Window): void {
// tslint:disable-next-line:no-unused-expression
inputElement && inputElement.focus();
window.getSelection().removeAllRanges();
}

// create a fake textarea for copy command
/**
* Creates a fake textarea for copy command.
*/
private createTempTextArea(doc: Document, window: Window): HTMLTextAreaElement {
const isRTL = doc.documentElement.getAttribute('dir') === 'rtl';
let ta: HTMLTextAreaElement;
Expand All @@ -139,7 +161,7 @@ export class ClipboardService {
* Pushes copy operation response to copySubject, to provide global access
* to the response.
*/
public pushCopyResponse(response: IClipboardResponse) {
public pushCopyResponse(response: IClipboardResponse): void {
this.copySubject.next(response);
}
}

0 comments on commit 785d2e2

Please sign in to comment.