import { TextareaWordcountDirective } from './textarea-wordcount.directive'; import { NgControl } from '@angular/forms'; import { Directive, ElementRef, Renderer2, Injector, OnInit, Input, AfterViewInit, OnDestroy, OnChanges, SimpleChanges, Optional } from '@angular/core'; import { EventManager } from '@angular/platform-browser'; import { MessagerService } from '@farris/ui-messager'; @Directive({ selector: '[textarea-zoom]', }) export class TextareaZoomDirective implements OnInit, AfterViewInit, OnDestroy, OnChanges { @Input('textarea-zoom') useZoom = true; @Input() dialogWidth = 500; @Input() dialogHeight = 400; @Input() fullscreen = false; @Input() title = ''; @Input() value = ''; onMouseEnter = null; onMouseLeave = null; onClick = null; altEnterHandler = null; zoomButtonElement = null; private messagerService: MessagerService; private eventManager: EventManager; private ngControl: NgControl; constructor(private el: ElementRef, private render: Renderer2, private injector: Injector, @Optional() private wordCountRef: TextareaWordcountDirective ) { this.messagerService = this.injector.get(MessagerService); this.eventManager = this.injector.get(EventManager); } ngOnInit() { this.ngControl = this.injector.get(NgControl, null); } ngOnChanges(changes: SimpleChanges) { if (changes.useZoom && !changes.useZoom.isFirstChange()) { if (this.useZoom) { this.createZoomButton(); } else { this.destroy(); } } } ngAfterViewInit() { if (this.useZoom) { this.createZoomButton(); } } ngOnDestroy() { this.destroy(); } private destroy() { if (this.onMouseEnter) { this.onMouseEnter(); } if (this.onMouseLeave) { this.onMouseLeave(); } if (this.onClick) { this.onClick(); } if (this.altEnterHandler) { this.altEnterHandler(); } if (this.zoomButtonElement) { this.zoomButtonElement.remove(); } } private bindEventHandler() { this.altEnterHandler = this.eventManager.addEventListener(this.el.nativeElement, 'keydown.alt.enter', (event: KeyboardEvent) => { const target = (event.target as any); const val = target.value + '\n'; target.value = val; event.preventDefault(); event.stopPropagation(); return false; }); } private createZoombarID() { const tagName = this.el.nativeElement.tagName; if (this.ngControl) { const ctrlName = this.ngControl.name; return `${tagName}_ZOOMBAR_${ctrlName}`; } else { if (this.el.nativeElement.id) { return `${tagName}_ZOOMBAR_${this.el.nativeElement.id}`; } } return ''; } private createZoomButton() { const zoomSPAN = this.render.createElement('span'); zoomSPAN.className = 'f-icon modal_maximize textarea-zoom'; zoomSPAN.title = '点击后弹出进行编辑'; const id = this.createZoombarID(); if (id) { zoomSPAN.id = id; } this.render.setStyle(zoomSPAN, 'position', 'absolute'); this.render.setStyle(zoomSPAN, 'top', '2px'); this.render.setStyle(zoomSPAN, 'right', '2px'); this.render.setStyle(zoomSPAN, 'cursor', 'pointer'); this.el.nativeElement.after(zoomSPAN); this.zoomButtonElement = zoomSPAN; this.onMouseEnter = this.render.listen(zoomSPAN, 'mouseenter', () => { this.render.setStyle(zoomSPAN, 'fontSize', '22px'); }); this.onMouseLeave = this.render.listen(zoomSPAN, 'mouseleave', () => { this.render.setStyle(zoomSPAN, 'fontSize', '1rem'); }); this.onClick = this.render.listen(zoomSPAN, 'click', () => { this.zoomTextarea(); }); } private zoomTextarea() { const opts: any = { width: this.dialogWidth || 500, height: this.dialogHeight || 400, showFontSize: true, saveSize: true // 启用个性化存储,localStorage }; if (window.localStorage) { const key = this.messagerService.getKeyString(); const val = localStorage.getItem(key); if (val) { const lastSetting = JSON.parse(val); opts.fontSize = lastSetting.fontSize || 18; opts.width = lastSetting.width || opts.width; opts.height = lastSetting.height || opts.height; } } const tagName = this.el.nativeElement.tagName; let showText = this.el.nativeElement.value; if (this.ngControl) { showText = this.ngControl.value; } else { showText = this.el.nativeElement.value; } showText = this.value || showText; if (tagName === 'FARRIS-TEXT' || this.el.nativeElement.readOnly || this.el.nativeElement.disabled) { opts.readonly = true; opts.showOkButton = false; this.messagerService.prompt2(this.title, showText, opts).subscribe(); } else { opts.maxLength = this.el.nativeElement.maxLength; opts.enableWordCount = this.wordCountRef ? this.wordCountRef.useWordCount : false; opts.countType = this.wordCountRef ? this.wordCountRef.countType : 'length'; this.messagerService.prompt2(this.title, showText, opts).subscribe(v => { if (typeof v === 'boolean' && !v) { return; } else { this.ngControl.control.setValue(v); if (this.wordCountRef) { this.wordCountRef.updateWordsCount(); } } }); } } }