UNPKG

ngx-tinymce

Version:
287 lines (280 loc) 9.21 kB
import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { Subject } from 'rxjs'; import { Injectable, Inject, Component, forwardRef, Input, ChangeDetectionStrategy, ChangeDetectorRef, TemplateRef, ViewEncapsulation, Output, EventEmitter, NgModule } from '@angular/core'; import { DOCUMENT, CommonModule } from '@angular/common'; class TinymceOptions { constructor() { /** 指定tinymce目录路径,默认:`./assets/tinymce/` */ this.baseURL = './assets/tinymce/'; /** 指定tinymce文件名,默认:`tinymce.min.js` */ this.fileName = 'tinymce.min.js'; } } class ScriptService { constructor(doc) { this.doc = doc; this.loaded = false; this.list = {}; this.emitter = new Subject(); } getChangeEmitter() { return this.emitter; } load(path) { if (this.loaded) { return this; } this.loaded = true; const promises = []; [path].forEach(script => promises.push(this.loadScript(script))); Promise.all(promises).then(res => { this.emitter.next(true); }); return this; } loadScript(path) { return new Promise((resolve, reject) => { if (this.list[path] === true) { resolve({ path: path, loaded: true, status: 'Loaded', }); return; } this.list[path] = true; const node = this.doc.createElement('script'); node.type = 'text/javascript'; node.src = path; node.charset = 'utf-8'; if (node.readyState) { // IE node.onreadystatechange = () => { if (node.readyState === 'loaded' || node.readyState === 'complete') { node.onreadystatechange = null; resolve({ path: path, loaded: true, status: 'Loaded', }); } }; } else { node.onload = () => { resolve({ path: path, loaded: true, status: 'Loaded', }); }; } node.onerror = (error) => resolve({ path: path, loaded: false, status: 'Loaded', }); this.doc.getElementsByTagName('head')[0].appendChild(node); }); } } ScriptService.decorators = [ { type: Injectable } ]; /** @nocollapse */ ScriptService.ctorParameters = () => [ { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] } ]; class TinymceComponent { constructor(defConfig, ss, cd) { this.defConfig = defConfig; this.ss = ss; this.cd = cd; this.load = true; this.id = `_tinymce-${Math.random().toString(36).substring(2)}`; this._disabled = false; /** 延迟初始化 */ this.delay = 0; this.ready = new EventEmitter(); } set disabled(value) { this._disabled = value; this.setDisabled(); } set loading(value) { if (value instanceof TemplateRef) { this._loading = null; this._loadingTpl = value; } else { this._loading = value; } } get instance() { return this._instance; } initDelay() { if (this.delay > 0) { setTimeout(() => this.init(), this.delay); } else { this.init(); } } init() { if (!window.tinymce) throw new Error('tinymce js文件加载失败'); const { defConfig, config, id } = this; if (this._instance) return; if (defConfig.baseURL) { let url = '' + defConfig.baseURL; if (url.endsWith('/')) url = url.substr(0, url.length - 1); tinymce.baseURL = url; } const userOptions = Object.assign({}, defConfig.config, config); const options = Object.assign({ selector: `#` + id, }, defConfig.config, config, { setup: (editor) => { this._instance = editor; editor.on('change keyup', () => { this.value = editor.getContent(); this.onChange(this.value); this.cd.detectChanges(); }); if (typeof userOptions.setup === 'function') { userOptions.setup(editor); } }, init_instance_callback: (editor) => { if (editor && this.value) editor.setContent(this.value); this.setDisabled(); if (typeof userOptions.init_instance_callback === 'function') { userOptions.init_instance_callback(editor); } this.ready.emit(this._instance); }, }); if (userOptions.auto_focus) { options.auto_focus = id; } tinymce.init(options); this.load = false; this.cd.detectChanges(); } destroy() { if (!this._instance) { return; } this._instance.off(); this._instance.remove('#' + this.id); this._instance = null; } setDisabled() { if (!this._instance) return; this._instance.setMode(this._disabled ? 'readonly' : 'design'); } ngAfterViewInit() { // 已经存在对象无须进入懒加载模式 if (window.tinymce) { this.initDelay(); return; } const { defConfig } = this; const baseURL = defConfig && defConfig.baseURL; const fileName = defConfig && defConfig.fileName; this.ss .load((baseURL || './assets/tinymce/') + (fileName || 'tinymce.min.js')) .getChangeEmitter() .subscribe(() => this.initDelay()); } ngOnChanges(changes) { if (this._instance && changes.config) { this.destroy(); this.initDelay(); } } ngOnDestroy() { this.destroy(); } // reuse-tab: http://ng-alain.com/components/reuse-tab#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F _onReuseInit() { this.destroy(); this.initDelay(); } writeValue(value) { // value should be NOT NULL this.value = value || ''; if (this._instance) { this._instance.setContent(this.value); } } registerOnChange(fn) { this.onChange = fn; } registerOnTouched(fn) { this.onTouched = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; this.setDisabled(); } } TinymceComponent.decorators = [ { type: Component, args: [{ selector: 'tinymce', template: "<textarea id=\"{{id}}\" [placeholder]=\"placeholder\" class=\"tinymce-selector\"></textarea>\n<div class=\"loading\" *ngIf=\"load\">\n <ng-container *ngIf=\"_loading; else _loadingTpl\">{{_loading}}</ng-container>\n</div>\n", encapsulation: ViewEncapsulation.None, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TinymceComponent), multi: true, }, ], changeDetection: ChangeDetectionStrategy.OnPush, styles: [`tinymce .tinymce-selector { display: none; }`] }] } ]; /** @nocollapse */ TinymceComponent.ctorParameters = () => [ { type: TinymceOptions }, { type: ScriptService }, { type: ChangeDetectorRef } ]; TinymceComponent.propDecorators = { config: [{ type: Input }], placeholder: [{ type: Input }], disabled: [{ type: Input }], loading: [{ type: Input }], delay: [{ type: Input }], ready: [{ type: Output }] }; class NgxTinymceModule { static forRoot(options) { return { ngModule: NgxTinymceModule, providers: [ ScriptService, { provide: TinymceOptions, useValue: options }, ], }; } } NgxTinymceModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule], declarations: [TinymceComponent], exports: [TinymceComponent], },] } ]; /** * Generated bundle index. Do not edit. */ export { ScriptService as ɵa, TinymceComponent, TinymceOptions, NgxTinymceModule }; //# sourceMappingURL=ngx-tinymce.js.map