import { Component, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; const editorTpl = `<html lang="en"><head><meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"/> <style> @font-face{ font-family: 'BRLNSDB'; src: url("../../../assets/font/BRLNSDB.TTF") ; } @font-face{ font-family: 'BRLNSB'; src: url("../../../assets/font/BRLNSB.TTF") ; } @font-face{ font-family: 'BRLNSR'; src: url("../../../assets/font/BRLNSR.TTF") ; } @font-face{ font-family: 'GOTHIC'; src: url("../../../assets/font/GOTHIC.TTF") ; } @font-face{ font-family: 'GOTHICB'; src: url("../../../assets/font/GOTHICB.TTF") ; } @font-face{ font-family: 'GOTHICBI'; src: url("../../../assets/font/GOTHICBI.TTF") ; } @font-face{ font-family: 'GOTHICI'; src: url("../../../assets/font/GOTHICI.TTF") ; } @font-face{ font-family: 'MMTextBook'; src: url("../../../assets/font/MMTextBook.otf") ; } @font-face{ font-family: 'MMTextBook-Bold'; src: url("../../../assets/font/MMTextBook-Bold.otf") ; } @font-face{ font-family: 'MMTextBook-BoldItalic'; src: url("../../../assets/font/MMTextBook-BoldItalic.otf") ; } @font-face{ font-family: 'MMTextBook-Italic'; src: url("../../../assets/font/MMTextBook-Italic.otf") ; } html, body{ /*font-size: 30px;*/ } body{ height:48px; overflow: hidden; margin: 0; padding: 0 .5rem; font-family: 'BRLNSB, BRLNSDB, BRLNSR, GOTHIC, GOTHICB, MMTextBook'; background: #FFF; line-height: 48px; } </style> </head> <body>{{content}}</body> </html>`; @Component({ selector: 'app-lesson-title-config', templateUrl: './lesson-title-config.component.html', styleUrls: ['./lesson-title-config.component.scss'] }) export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy, OnChanges { fontFamilyList = [ 'Arial', 'BRLNSB', 'BRLNSDB', 'BRLNSR', 'GOTHIC', 'GOTHICB', // "GOTHICBI", // "GOTHICI", 'MMTextBook', // "MMTextBook-Bold", // "MMTextBook-Italic", // "MMTextBook-BoldItalic", ]; colorList = [ '#000000', '#ffffff', '#595959', '#0075c2', '#c61c1e', '#9cbc3a', '#008000', '#FF0000', '#D2691E', ]; MIN_FONT_SIZE = 1; MAX_FONT_SIZE = 7; isShowFontColorPane = false; isShowBGColorPane = false; fontSizeRange = [ // {name: '1号', value: 9}, // {name: '2号', value: 13}, // {name: '3号', value: 16}, // {name: '4号', value: 18}, // {name: '5号', value: 24}, // {name: '6号', value: 32}, ]; editorContent = ''; __fontFamily = 'Arial'; __fontColor = ''; __fontSize = 3; loopCnt = 0; maxLoops = 20; @ViewChild('titleEl', {static: true}) titleEl: ElementRef; titleEW = null; @Input() titleObj = { content: '', audio_url: '' }; @Output() titleUpdated = new EventEmitter(); constructor() { this.fontSizeRange = []; for (let i = this.MIN_FONT_SIZE; i <= this.MAX_FONT_SIZE; ++i) { this.fontSizeRange.push(i); } this.__fontSize = 3; this.__fontColor = this.colorList[0]; } ngOnChanges(vars) { if (!vars.titleObj.previousValue) {// 初始化,内容是空 return; } let defObj = this.titleObj; if (!vars.titleObj.currentValue) { defObj = { content: '', audio_url: '' }; } else { defObj = vars.titleObj.currentValue; } this.titleObj.content = defObj.content || ''; this.titleObj.audio_url = defObj.audio_url || ''; this.titleEW.document.body.innerHTML = this.titleObj.content; } ngOnInit() { if (!this.titleObj) { this.titleObj = { content: '', audio_url: '' }; } this.titleObj.content = this.titleObj.content || ''; this.titleObj.audio_url = this.titleObj.audio_url || ''; this.editorContent = editorTpl.replace('{{content}}', this.titleObj.content) ; this.titleEW = this.titleEl.nativeElement.contentWindow; console.log('this.titleEW', this.titleEW); const tdoc = this.titleEW.document; tdoc.designMode = 'on'; tdoc.open('text/html', 'replace'); tdoc.write(this.editorContent); tdoc.close(); tdoc.addEventListener('keypress', this.keyPress, true); tdoc.addEventListener('blur', () => { if (this.titleObj.content === this.titleEW.document.body.innerHTML.trim()) { return; } this.shouldSave(); }, true); } htmlEncode(text) { if (!text) { return ''; } return text.replace(/\&/ig, '&') .replace(/\</ig, '<') .replace(/\>/ig, '>') .replace(/\"/ig, '"'); } htmlDecode(text) { if (!text) { return ''; } return text.replace(/\&\;/ig, '&') .replace(/\<\;/ig, '<') .replace(/\>\;/ig, '>') .replace(/\"\;/ig, '"'); } ngOnDestroy(): void { } keyPress(evt) { try { if (evt.charCode === 13) { evt.preventDefault(); evt.stopPropagation(); return; } if (evt.ctrlKey) { const key = String.fromCharCode(evt.charCode).toLowerCase(); let cmd = ''; switch (key) { case 'b': cmd = 'bold'; break; case 'i': cmd = 'italic'; break; case 'u': cmd = 'underline'; break; } if (cmd) { this.execEditorCommand(cmd); // stop the event bubble evt.preventDefault(); evt.stopPropagation(); } } } catch (e) { console.log(1, e); alert(e); } } execEditorCommand(command, option?: any) { console.log('sssss'); try { this.titleEW.focus(); const result = this.titleEW.document.execCommand(command, false, option); console.log(result); this.loopCnt = 0; return false; } catch (e) { alert(e); if (this.loopCnt < this.maxLoops) { setTimeout(() => { this.execEditorCommand(command, option); }, 100); this.loopCnt += 1; } else { alert('Error executing command.'); } } } onSelectColor(color) { this.execEditorCommand('forecolor', color); this.__fontColor = color; } onChangeFontColor(val) { this.execEditorCommand('forecolor', this.__fontColor); } onChangeFontFamily(font) { this.execEditorCommand('fontName', font); } onChangeFontSize(size?: any) { if (size) { size += this.__fontSize; } else { size = this.__fontSize; } size = Math.max(this.MIN_FONT_SIZE, size); size = Math.min(this.MAX_FONT_SIZE, size); this.execEditorCommand('fontsize', size); } onChangeBold() { this.execEditorCommand('bold'); } onChangeItalic() { this.execEditorCommand('italic'); } onChangeUnderline() { this.execEditorCommand('underline'); } onChangeStrikethrough() { this.execEditorCommand('strikethrough'); } titleAudioUploaded(res) { this.titleObj.audio_url = res.url; this.titleUpdated.emit(this.titleObj); } shouldSave = () => { console.log('title shouldSave', this.titleObj); this.titleObj.content = this.titleEW.document.body.innerHTML.trim(); this.titleUpdated.emit(this.titleObj); } }