UNPKG

@dllcn/ngx-clipboard

Version:
340 lines (331 loc) 11 kB
import { WINDOW } from 'ngx-window-token'; import { Subject } from 'rxjs'; import { DOCUMENT, CommonModule } from '@angular/common'; import { Inject, Injectable, Optional, Directive, TemplateRef, ViewContainerRef, EventEmitter, HostListener, Input, Output, NgModule, defineInjectable, inject } from '@angular/core'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // The following code is heavily copy from https://github.com/zenorocha/clipboard.js class ClipboardService { /** * @param {?} document * @param {?} window */ constructor(document, window) { this.document = document; this.window = window; this.copySubject = new Subject(); this.copyResponse$ = this.copySubject.asObservable(); } /** * @return {?} */ get isSupported() { return !!this.document.queryCommandSupported && !!this.document.queryCommandSupported('copy') && !!this.window; } /** * @param {?} element * @return {?} */ isTargetValid(element) { if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) { if (element.hasAttribute('disabled')) { throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute'); } return true; } throw new Error('Target should be input or textarea'); } /** * copyFromInputElement * @param {?} targetElm * @return {?} */ copyFromInputElement(targetElm) { try { this.selectTarget(targetElm); /** @type {?} */ const re = this.copyText(); this.clearSelection(targetElm, this.window); return re && this.isCopySuccessInIE11(); } catch (error) { return false; } } // this is for IE11 return true even if copy fail /** * @return {?} */ isCopySuccessInIE11() { /** @type {?} */ const clipboardData = this.window['clipboardData']; if (clipboardData && clipboardData.getData) { if (!clipboardData.getData('Text')) { return false; } } return true; } /** * Creates a fake textarea element, sets its value from `text` property, * and makes a selection on it. * @param {?} content * @param {?=} container * @return {?} */ copyFromContent(content, container = this.window.document.body) { // 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)) { this.destroy(this.tempTextArea.parentElement); } if (!this.tempTextArea) { this.tempTextArea = this.createTempTextArea(this.document, this.window); try { container.appendChild(this.tempTextArea); } catch (error) { throw new Error('Container should be a Dom element'); } } this.tempTextArea.value = content; return this.copyFromInputElement(this.tempTextArea); } // remove temporary textarea if any /** * @param {?=} container * @return {?} */ destroy(container = this.window.document.body) { if (this.tempTextArea) { container.removeChild(this.tempTextArea); // removeChild doesn't remove the reference from memory this.tempTextArea = undefined; } } // select the target html input element /** * @private * @param {?} inputElement * @return {?} */ selectTarget(inputElement) { inputElement.select(); inputElement.setSelectionRange(0, inputElement.value.length); return inputElement.value.length; } /** * @private * @return {?} */ copyText() { return this.document.execCommand('copy'); } // Moves focus away from `target` and back to the trigger, removes current selection. /** * @private * @param {?} inputElement * @param {?} window * @return {?} */ clearSelection(inputElement, window) { // tslint:disable-next-line:no-unused-expression inputElement && inputElement.focus(); window.getSelection().removeAllRanges(); } // create a fake textarea for copy command /** * @private * @param {?} doc * @param {?} window * @return {?} */ createTempTextArea(doc, window) { /** @type {?} */ const isRTL = doc.documentElement.getAttribute('dir') === 'rtl'; /** @type {?} */ let ta; ta = doc.createElement('textarea'); // Prevent zooming on iOS ta.style.fontSize = '12pt'; // Reset box model ta.style.border = '0'; ta.style.padding = '0'; ta.style.margin = '0'; // Move element out of screen horizontally ta.style.position = 'absolute'; ta.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position vertically /** @type {?} */ const yPosition = window.pageYOffset || doc.documentElement.scrollTop; ta.style.top = yPosition + 'px'; ta.setAttribute('readonly', ''); return ta; } /** * Pushes copy operation response to copySubject, to provide global access * to the response. * @param {?} response * @return {?} */ pushCopyReponse(response) { this.copySubject.next(response); } } ClipboardService.decorators = [ { type: Injectable, args: [{ providedIn: 'root' },] } ]; /** @nocollapse */ ClipboardService.ctorParameters = () => [ { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [WINDOW,] }] } ]; /** @nocollapse */ ClipboardService.ngInjectableDef = defineInjectable({ factory: function ClipboardService_Factory() { return new ClipboardService(inject(DOCUMENT), inject(WINDOW, 8)); }, token: ClipboardService, providedIn: "root" }); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class ClipboardDirective { /** * @param {?} clipboardSrv */ constructor(clipboardSrv) { this.clipboardSrv = clipboardSrv; this.cbOnSuccess = new EventEmitter(); this.cbOnError = new EventEmitter(); } // tslint:disable-next-line:no-empty /** * @return {?} */ ngOnInit() { } /** * @return {?} */ ngOnDestroy() { this.clipboardSrv.destroy(this.container); } /** * @param {?} event * @return {?} */ onClick(event) { if (!this.clipboardSrv.isSupported) { this.handleResult(false, undefined, event); } else if (this.targetElm && this.clipboardSrv.isTargetValid(this.targetElm)) { this.handleResult(this.clipboardSrv.copyFromInputElement(this.targetElm), this.targetElm.value, event); } else if (this.cbContent) { this.handleResult(this.clipboardSrv.copyFromContent(this.cbContent, this.container), this.cbContent, event); } } /** * Fires an event based on the copy operation result. * @private * @param {?} succeeded * @param {?} copiedContent * @param {?} event * @return {?} */ handleResult(succeeded, copiedContent, event) { /** @type {?} */ let response = { isSuccess: succeeded, event }; if (succeeded) { response = Object.assign(response, { content: copiedContent, successMessage: this.cbSuccessMsg }); this.cbOnSuccess.emit(response); } else { this.cbOnError.emit(response); } this.clipboardSrv.pushCopyReponse(response); } } ClipboardDirective.decorators = [ { type: Directive, args: [{ selector: '[ngxClipboard]' },] } ]; /** @nocollapse */ ClipboardDirective.ctorParameters = () => [ { type: ClipboardService } ]; ClipboardDirective.propDecorators = { targetElm: [{ type: Input, args: ['ngxClipboard',] }], container: [{ type: Input }], cbContent: [{ type: Input }], cbSuccessMsg: [{ type: Input }], cbOnSuccess: [{ type: Output }], cbOnError: [{ type: Output }], onClick: [{ type: HostListener, args: ['click', ['$event.target'],] }] }; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class ClipboardIfSupportedDirective { /** * @param {?} _clipboardService * @param {?} _viewContainerRef * @param {?} _templateRef */ constructor(_clipboardService, _viewContainerRef, _templateRef) { this._clipboardService = _clipboardService; this._viewContainerRef = _viewContainerRef; this._templateRef = _templateRef; } /** * @return {?} */ ngOnInit() { if (this._clipboardService.isSupported) { this._viewContainerRef.createEmbeddedView(this._templateRef); } } } ClipboardIfSupportedDirective.decorators = [ { type: Directive, args: [{ selector: '[ngxClipboardIfSupported]' },] } ]; /** @nocollapse */ ClipboardIfSupportedDirective.ctorParameters = () => [ { type: ClipboardService }, { type: ViewContainerRef }, { type: TemplateRef } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class ClipboardModule { } ClipboardModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule], declarations: [ClipboardDirective, ClipboardIfSupportedDirective], exports: [ClipboardDirective, ClipboardIfSupportedDirective] },] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ export { ClipboardService, ClipboardDirective, ClipboardModule, ClipboardIfSupportedDirective }; //# sourceMappingURL=dllcn-ngx-clipboard.js.map