1 | import { DOCUMENT, CommonModule } from '@angular/common';
|
2 | import { ɵɵdefineInjectable, ɵɵinject, Injectable, Inject, Optional, EventEmitter, Directive, Input, Output, HostListener, ViewContainerRef, TemplateRef, NgModule } from '@angular/core';
|
3 | import { WINDOW } from 'ngx-window-token';
|
4 | import { Subject } from 'rxjs';
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | class ClipboardService {
|
10 | constructor(document, window) {
|
11 | this.document = document;
|
12 | this.window = window;
|
13 | this.copySubject = new Subject();
|
14 | this.copyResponse$ = this.copySubject.asObservable();
|
15 | this.config = {};
|
16 | }
|
17 | configure(config) {
|
18 | this.config = config;
|
19 | }
|
20 | copy(content) {
|
21 | if (!this.isSupported || !content) {
|
22 | return this.pushCopyResponse({ isSuccess: false, content });
|
23 | }
|
24 | const copyResult = this.copyFromContent(content);
|
25 | if (copyResult) {
|
26 | return this.pushCopyResponse({ content, isSuccess: copyResult });
|
27 | }
|
28 | return this.pushCopyResponse({ isSuccess: false, content });
|
29 | }
|
30 | get isSupported() {
|
31 | return !!this.document.queryCommandSupported && !!this.document.queryCommandSupported('copy') && !!this.window;
|
32 | }
|
33 | isTargetValid(element) {
|
34 | if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
|
35 | if (element.hasAttribute('disabled')) {
|
36 | throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');
|
37 | }
|
38 | return true;
|
39 | }
|
40 | throw new Error('Target should be input or textarea');
|
41 | }
|
42 | |
43 |
|
44 |
|
45 | copyFromInputElement(targetElm, isFocus = true) {
|
46 | try {
|
47 | this.selectTarget(targetElm);
|
48 | const re = this.copyText();
|
49 | this.clearSelection(isFocus ? targetElm : undefined, this.window);
|
50 | return re && this.isCopySuccessInIE11();
|
51 | }
|
52 | catch (error) {
|
53 | return false;
|
54 | }
|
55 | }
|
56 | |
57 |
|
58 |
|
59 | isCopySuccessInIE11() {
|
60 | const clipboardData = this.window['clipboardData'];
|
61 | if (clipboardData && clipboardData.getData) {
|
62 | if (!clipboardData.getData('Text')) {
|
63 | return false;
|
64 | }
|
65 | }
|
66 | return true;
|
67 | }
|
68 | |
69 |
|
70 |
|
71 |
|
72 | copyFromContent(content, container = this.document.body) {
|
73 |
|
74 |
|
75 | if (this.tempTextArea && !container.contains(this.tempTextArea)) {
|
76 | this.destroy(this.tempTextArea.parentElement || undefined);
|
77 | }
|
78 | if (!this.tempTextArea) {
|
79 | this.tempTextArea = this.createTempTextArea(this.document, this.window);
|
80 | try {
|
81 | container.appendChild(this.tempTextArea);
|
82 | }
|
83 | catch (error) {
|
84 | throw new Error('Container should be a Dom element');
|
85 | }
|
86 | }
|
87 | this.tempTextArea.value = content;
|
88 | const toReturn = this.copyFromInputElement(this.tempTextArea, false);
|
89 | if (this.config.cleanUpAfterCopy) {
|
90 | this.destroy(this.tempTextArea.parentElement || undefined);
|
91 | }
|
92 | return toReturn;
|
93 | }
|
94 | |
95 |
|
96 |
|
97 | destroy(container = this.document.body) {
|
98 | if (this.tempTextArea) {
|
99 | container.removeChild(this.tempTextArea);
|
100 |
|
101 | this.tempTextArea = undefined;
|
102 | }
|
103 | }
|
104 | |
105 |
|
106 |
|
107 | selectTarget(inputElement) {
|
108 | inputElement.select();
|
109 | inputElement.setSelectionRange(0, inputElement.value.length);
|
110 | return inputElement.value.length;
|
111 | }
|
112 | copyText() {
|
113 | return this.document.execCommand('copy');
|
114 | }
|
115 | |
116 |
|
117 |
|
118 | clearSelection(inputElement, window) {
|
119 | var _a;
|
120 | inputElement && inputElement.focus();
|
121 | (_a = window.getSelection()) === null || _a === void 0 ? void 0 : _a.removeAllRanges();
|
122 | }
|
123 | |
124 |
|
125 |
|
126 | createTempTextArea(doc, window) {
|
127 | const isRTL = doc.documentElement.getAttribute('dir') === 'rtl';
|
128 | let ta;
|
129 | ta = doc.createElement('textarea');
|
130 |
|
131 | ta.style.fontSize = '12pt';
|
132 |
|
133 | ta.style.border = '0';
|
134 | ta.style.padding = '0';
|
135 | ta.style.margin = '0';
|
136 |
|
137 | ta.style.position = 'absolute';
|
138 | ta.style[isRTL ? 'right' : 'left'] = '-9999px';
|
139 |
|
140 | const yPosition = window.pageYOffset || doc.documentElement.scrollTop;
|
141 | ta.style.top = yPosition + 'px';
|
142 | ta.setAttribute('readonly', '');
|
143 | return ta;
|
144 | }
|
145 | |
146 |
|
147 |
|
148 |
|
149 | pushCopyResponse(response) {
|
150 | this.copySubject.next(response);
|
151 | }
|
152 | |
153 |
|
154 |
|
155 | pushCopyReponse(response) {
|
156 | this.pushCopyResponse(response);
|
157 | }
|
158 | }
|
159 | ClipboardService.ɵprov = ɵɵdefineInjectable({ factory: function ClipboardService_Factory() { return new ClipboardService(ɵɵinject(DOCUMENT), ɵɵinject(WINDOW, 8)); }, token: ClipboardService, providedIn: "root" });
|
160 | ClipboardService.decorators = [
|
161 | { type: Injectable, args: [{ providedIn: 'root' },] }
|
162 | ];
|
163 | ClipboardService.ctorParameters = () => [
|
164 | { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] },
|
165 | { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [WINDOW,] }] }
|
166 | ];
|
167 |
|
168 | class ClipboardDirective {
|
169 | constructor(clipboardSrv) {
|
170 | this.clipboardSrv = clipboardSrv;
|
171 | this.cbOnSuccess = new EventEmitter();
|
172 | this.cbOnError = new EventEmitter();
|
173 | }
|
174 |
|
175 | ngOnInit() { }
|
176 | ngOnDestroy() {
|
177 | this.clipboardSrv.destroy(this.container);
|
178 | }
|
179 | onClick(event) {
|
180 | if (!this.clipboardSrv.isSupported) {
|
181 | this.handleResult(false, undefined, event);
|
182 | }
|
183 | else if (this.targetElm && this.clipboardSrv.isTargetValid(this.targetElm)) {
|
184 | this.handleResult(this.clipboardSrv.copyFromInputElement(this.targetElm), this.targetElm.value, event);
|
185 | }
|
186 | else if (this.cbContent) {
|
187 | this.handleResult(this.clipboardSrv.copyFromContent(this.cbContent, this.container), this.cbContent, event);
|
188 | }
|
189 | }
|
190 | |
191 |
|
192 |
|
193 |
|
194 | handleResult(succeeded, copiedContent, event) {
|
195 | let response = {
|
196 | isSuccess: succeeded,
|
197 | event
|
198 | };
|
199 | if (succeeded) {
|
200 | response = Object.assign(response, {
|
201 | content: copiedContent,
|
202 | successMessage: this.cbSuccessMsg
|
203 | });
|
204 | this.cbOnSuccess.emit(response);
|
205 | }
|
206 | else {
|
207 | this.cbOnError.emit(response);
|
208 | }
|
209 | this.clipboardSrv.pushCopyResponse(response);
|
210 | }
|
211 | }
|
212 | ClipboardDirective.decorators = [
|
213 | { type: Directive, args: [{
|
214 | selector: '[ngxClipboard]'
|
215 | },] }
|
216 | ];
|
217 | ClipboardDirective.ctorParameters = () => [
|
218 | { type: ClipboardService }
|
219 | ];
|
220 | ClipboardDirective.propDecorators = {
|
221 | targetElm: [{ type: Input, args: ['ngxClipboard',] }],
|
222 | container: [{ type: Input }],
|
223 | cbContent: [{ type: Input }],
|
224 | cbSuccessMsg: [{ type: Input }],
|
225 | cbOnSuccess: [{ type: Output }],
|
226 | cbOnError: [{ type: Output }],
|
227 | onClick: [{ type: HostListener, args: ['click', ['$event.target'],] }]
|
228 | };
|
229 |
|
230 | class ClipboardIfSupportedDirective {
|
231 | constructor(_clipboardService, _viewContainerRef, _templateRef) {
|
232 | this._clipboardService = _clipboardService;
|
233 | this._viewContainerRef = _viewContainerRef;
|
234 | this._templateRef = _templateRef;
|
235 | }
|
236 | ngOnInit() {
|
237 | if (this._clipboardService.isSupported) {
|
238 | this._viewContainerRef.createEmbeddedView(this._templateRef);
|
239 | }
|
240 | }
|
241 | }
|
242 | ClipboardIfSupportedDirective.decorators = [
|
243 | { type: Directive, args: [{
|
244 | selector: '[ngxClipboardIfSupported]'
|
245 | },] }
|
246 | ];
|
247 | ClipboardIfSupportedDirective.ctorParameters = () => [
|
248 | { type: ClipboardService },
|
249 | { type: ViewContainerRef },
|
250 | { type: TemplateRef }
|
251 | ];
|
252 |
|
253 | class ClipboardModule {
|
254 | }
|
255 | ClipboardModule.decorators = [
|
256 | { type: NgModule, args: [{
|
257 | imports: [CommonModule],
|
258 | declarations: [ClipboardDirective, ClipboardIfSupportedDirective],
|
259 | exports: [ClipboardDirective, ClipboardIfSupportedDirective]
|
260 | },] }
|
261 | ];
|
262 |
|
263 |
|
264 |
|
265 |
|
266 |
|
267 |
|
268 |
|
269 |
|
270 |
|
271 | export { ClipboardDirective, ClipboardIfSupportedDirective, ClipboardModule, ClipboardService };
|
272 |
|