lesson-title-config.component.ts 6.45 KB
import {
  Component,
  ElementRef,
  EventEmitter,
  Input,
  OnChanges,
  OnDestroy,
  OnInit,
  Output,
  ViewChild
} from '@angular/core';

@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',
    'ARBLI'
  ];

  colorList = [
    '#111111',
    '#ffffff',
    '#595959',
    '#0075c2',
    '#c61c1e',
    '#9cbc3a'
  ];
  MIN_FONT_SIZE = 1;
  MAX_FONT_SIZE = 7;
  isShowFontColorPane = false;
  isShowBGColorPane = false;
  fontSizeRange: number[];

  editorContent = '';


  __fontFamily = 'Arial';
  __fontColor = '';
  __fontSize = 3;

  loopCnt = 0;
  maxLoops = 20;
  groupIconsCount = {
    a: Array.from(Array(11).keys()),
    b: Array.from(Array(8).keys()),
    c: Array.from(Array(8).keys()),
  };
  prevIcons = [];
  prevType = '';
  @ViewChild('titleEl') titleEl: ElementRef;
  titleEW = null;

  @Input()
  titleObj = {
    type: 'a',
    content: '',
    icons: [],
    audio_url: ''
  };
  @Input()
  withIcon = true;

  @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 = {
        type: 'a',
        content: '',
        icons: [],
        audio_url: ''
      };
    } else {
      defObj = vars.titleObj.currentValue;
    }
    this.titleObj.icons = defObj.icons || [];
    this.titleObj.type = defObj.type || 'a';
    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 = {
        type: 'a',
        content: '',
        icons: [],
        audio_url: ''
      };
    }
    this.titleObj.icons = this.titleObj.icons || [];
    this.titleObj.type = this.titleObj.type || 'a';
    this.titleObj.content = this.titleObj.content || '';
    this.titleObj.audio_url = this.titleObj.audio_url || '';

    this.editorContent = `<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"/>
  </head>
  <body style="height:48px;overflow: hidden;margin: 0;padding: 0 .5rem;background: #FFF;line-height: 48px;">
  ${this.titleObj.content}
  </body>
  </html>`;
    this.titleEW = this.titleEl.nativeElement.contentWindow;
    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, '&amp;')
      .replace(/\</ig, '&lt;')
      .replace(/\>/ig, '&gt;')
      .replace(/\"/ig, '&quot;');
  }

  htmlDecode(text) {
    if (!text) {
      return '';
    }
    return text.replace(/\&amp\;/ig, '&')
      .replace(/\&lt\;/ig, '<')
      .replace(/\&gt\;/ig, '>')
      .replace(/\&quot\;/ig, '"');
  }


  ngOnDestroy(): void {

  }
  iconsChanges(val) {
    let a = this.titleObj.icons;
    let b = val;

    if (a.length > b.length) {
      const diff = a.filter(x => !b.includes(x));
      const ti = [...this.titleObj.icons];
      for (let i = 0; i < diff.length; i++) {
        const d = diff[i];
        const idx = ti.indexOf(d);
        ti.splice(idx, 1);
      }
      this.titleObj.icons = ti;
    } else {
      const diff = b.filter(x => !a.includes(x));
      this.titleObj.icons = [...this.titleObj.icons, ...diff];
    }

    this.shouldSave();
  }
  typeChange(val) {
    this.titleObj.icons = [];
    this.shouldSave();
  }
  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) {
    try {
      this.titleEW.focus();
      this.titleEW.document.execCommand(command, false, option);
      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.content = this.titleEW.document.body.innerHTML.trim();
    this.titleUpdated.emit(this.titleObj);
  }
}