import {Component, EventEmitter, HostListener, Input, OnInit, Output, ViewChild} from '@angular/core'; @Component({ selector: 'wysiwyg-editor', templateUrl: './wysiwyg.component.html', styleUrls: ['./wysiwyg.component.scss'], }) export class WysiwygComponent implements OnInit { @ViewChild('editable') editable; @Input() readonly = false; @Input() set contents(val: string) { if ( this.currentContents !== val ) { this.currentContents = val; } } get contents(): string { return this.currentContents; } @Output() contentsChanged: EventEmitter = new EventEmitter(); public currentContents = ''; public isFocused = false; protected hadOneFocusOut = false; protected isEditOnly = false; public get editonly() { return this.isEditOnly; } @Input() public set editonly(val: boolean) { this.isEditOnly = val; if ( this.isEditOnly && !this.readonly ) { this.isFocused = true; } } public get displayContents() { return (this.contents || 'Double-click to edit...').replace(/ `${val}`); } public isDark() { return document.body.classList.contains('dark'); } ngOnInit() { } onFocusIn(event: MouseEvent) { console.log('on focus in', event); this.isFocused = !this.readonly; } @HostListener('document:keyup.escape', ['$event']) onFocusOut(event) { if ( this.isEditOnly ) { return; } if ( !this.hadOneFocusOut ) { this.hadOneFocusOut = true; setTimeout(() => { this.hadOneFocusOut = false; }, 500); } else { this.isFocused = false; this.hadOneFocusOut = false; } } documentCommand(cmd: string) { // Yes, technically this is deprecated, but it'll be poly-filled if necessary. Bite me. document.execCommand(cmd, false, ''); } onContentsChanged(contents: string) { const innerHTML = this.editable.nativeElement.innerHTML; if ( this.contents !== innerHTML ) { this.contents = innerHTML; this.contentsChanged.emit(innerHTML); } } @HostListener('document:keydown.tab', ['$event']) onIndent(event) { event.preventDefault(); this.documentCommand('indent'); } @HostListener('document:keydown.shift.tab', ['$event']) onOutdent(event) { event.preventDefault(); this.documentCommand('outdent'); } @HostListener('document:keydown.control.b', ['$event']) onBold(event) { event.preventDefault(); this.documentCommand('bold'); } @HostListener('document:keydown.control.i', ['$event']) onItalic(event) { event.preventDefault(); this.documentCommand('italic'); } @HostListener('document:keydown.control.u', ['$event']) onUnderline(event) { event.preventDefault(); this.documentCommand('underline'); } @HostListener('document:keydown.control.z', ['$event']) onUndo(event) { event.preventDefault(); this.documentCommand('undo'); } @HostListener('document:keydown.control.shift.z', ['$event']) onRedo(event) { event.preventDefault(); this.documentCommand('redo'); } }