UNPKG

raonkeditor-angular

Version:

Angular component for RAON K Editor.

400 lines (394 loc) 15.3 kB
import { EventEmitter, Component, forwardRef, ElementRef, NgZone, Input, Output, NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms'; import { getRaonwizComponentNamespace } from 'raonwiz-integrations-common'; /** * @license Copyright (c) 2003-2022, RAONWIZ DevTeam. All rights reserved. */ class RaonkEditorComponent { constructor(elementRef, ngZone) { this.elementRef = elementRef; this.ngZone = ngZone; /** * The id of the component */ this.id = ""; /** * The component type */ this.componentType = 'RAONKEDITOR'; /** * RAON K Editor script url address. Script will be loaded only if RAONKEDITOR namespace is missing. */ this.componentUrl = '/raonkeditor/js/raonkeditor.js'; /** * Tag name of the component. * * The default tag is `div`. */ this.tagName = 'div'; /** * The runtimes of the component interface. */ this.runtimes = "html5" /* HTML5 */; /** * Fired when the component namespace * is loaded. It only triggers once, no matter how many components are initialised. */ this.namespaceLoaded = new EventEmitter(); this.change = new EventEmitter(); /** * event. */ this.creationComplete = new EventEmitter(); this.afterChangeMode = new EventEmitter(); this.onError = new EventEmitter(); this.onLanguageDefinition = new EventEmitter(); this.afterPopupShow = new EventEmitter(); this.agentInstall = new EventEmitter(); this.beforeInsertUrl = new EventEmitter(); this.mouse = new EventEmitter(); this.command = new EventEmitter(); this.key = new EventEmitter(); this.resized = new EventEmitter(); this.documentEditComplete = new EventEmitter(); this.pasteImage = new EventEmitter(); this.wordCount = new EventEmitter(); this.beforePaste = new EventEmitter(); this.customAction = new EventEmitter(); this.fullScreen = new EventEmitter(); this.setComplete = new EventEmitter(); this.setInsertComplete = new EventEmitter(); this.closeInstallPopup = new EventEmitter(); this.setForbiddenWordComplete = new EventEmitter(); this.drag = new EventEmitter(); this.focus = new EventEmitter(); this.dialogLoaded = new EventEmitter(); this.beforeInsertHyperlink = new EventEmitter(); /** * If the component is view-mode before the component instance is created, it remembers that state, * so the component can become view-mode once it is ready. */ this._readOnly = null; this._viewMode = null; this._data = null; this._destroyed = false; } /** * Keeps track of the component's data. * * It's also decorated as an input which is useful when not using the ngModel. * * See https://angular.io/api/forms/NgModel to learn more. */ set data(data) { console.log("this.id: " + this.id + ", data : " + data); if (data === this._data) { return; } if (this.instance) { RAONKEDITOR.SetHtmlContents(data, this.id); return; } this._data = data; } get data() { return this._data; } /** * When set to `true`, the editor becomes readonly mode. */ set readOnly(isReadOnly) { if (this.instance) { RAONKEDITOR.SetReadOnly(isReadOnly, '', this.id); return; } // Delay setting mode this._readOnly = isReadOnly; } get readOnly() { if (this.instance) { return RAONKEDITOR.GetEditorByName(this.id)._BODY.contentEditable; } return this._readOnly; } /** * When set to `true`, the editor becomes view mode. */ set viewMode(isViewMode) { if (this.instance) { RAONKEDITOR.SetEditorMode(isViewMode ? 'view' : 'edit', this.id); return; } // Delay setting mode this._viewMode = isViewMode; } get viewMode() { if (this.instance) { let retValue; switch (RAONKEDITOR.GetEditorByName(this.id)._config.mode.toLowerCase()) { case 'edit': retValue = false; break; default: retValue = true; break; } return retValue; } return this._viewMode; } ngAfterViewInit() { getRaonwizComponentNamespace(this.componentType, this.componentUrl, namespace => { this.namespaceLoaded.emit(namespace); }).then((namespace) => { // Check if component instance was destroyed before `ngAfterViewInit` call (#110). // Here, `this.instance` is still not initialized and so additional flag is needed. if (this._destroyed) { return; } this.ngZone.runOutsideAngular(this.createComponent.bind(this, namespace)); }).catch(window.console.error); } ngOnDestroy() { this._destroyed = true; this.ngZone.runOutsideAngular(() => { if (this.instance) { if (RAONKEDITOR._ExternalComponentMap.has(this.id)) { RAONKEDITOR._ExternalComponentMap.delete(this.id); } if (RAONKEDITOR._ExternalEventRetValueMap.has(this.id)) { RAONKEDITOR._ExternalEventRetValueMap.delete(this.id); } RAONKEDITOR.Destroy(this.id, false); this.instance = null; } }); } writeValue(value) { this.data = value; } registerOnChange(callback) { this.onChange = callback; } registerOnTouched(callback) { this.onTouched = callback; } getComponentUniqueName() { return "raonkeditor_" + Math.random() .toString(36) .replace(/[^a-z]+/g, '') .substr(0, 5); } createComponent(namespace) { let _uniqueName = this.getComponentUniqueName(); (typeof this.id === 'undefined') && (this.id = _uniqueName); const element = document.createElement(this.tagName); element.id = "componentHolder_" + _uniqueName; this.elementRef.nativeElement.appendChild(element); // view state may change during instance initialization. (this._viewMode !== null) && (this.viewMode = this._viewMode); // default config let _compConfig = { Id: this.id, EditorHolder: element.id, Runtimes: this.runtimes, Mode: this._viewMode ? 'view' : 'edit', ReturnEventKeyboard: '1', ReturnEventFocus: '1', ReturnEventCommand: '1', Event: this.subscribe() }; _compConfig = namespace.util.objectExtend(true, this.config, _compConfig); // for event callback (typeof namespace._ExternalComponentMap === 'undefined') && (namespace._ExternalComponentMap = new Map()); namespace._ExternalComponentMap.set(this.id, this); (typeof namespace._ExternalEventRetValueMap === 'undefined') && (namespace._ExternalEventRetValueMap = new Map()); var _componentObject = new RAONKEditor(_compConfig); _componentObject.name = element.id; this.instance = _componentObject; } subscribe() { let _configEvent = {}; const ComponentEvents = [ 'CreationComplete', 'AfterChangeMode', 'OnError', 'OnLanguageDefinition', 'AfterPopupShow', 'AgentInstall', 'BeforeInsertUrl', 'Mouse', 'Command', 'Key', 'Resized', 'DocumentEditComplete', 'PasteImage', 'WordCount', 'BeforePaste', 'CustomAction', 'FullScreen', 'SetComplete', 'SetInsertComplete', 'CloseInstallPopup', 'SetForbiddenWordComplete', 'Drag', 'Focus', 'DialogLoaded', 'BeforeInsertHyperlink' ]; ComponentEvents.forEach(function (evtName) { _configEvent[evtName] = (componentName, paramObj) => { // Set default value switch (evtName) { case 'BeforePaste': RAONKEDITOR._ExternalEventRetValueMap.set(componentName, paramObj.strHtml); break; case 'BeforeInsertUrl': RAONKEDITOR._ExternalEventRetValueMap.set(componentName, paramObj.strUrl); break; case 'BeforeInsertHyperlink': RAONKEDITOR._ExternalEventRetValueMap.set(componentName, paramObj); // url break; } if (RAONKEDITOR._ExternalComponentMap.has(componentName)) { let _this = RAONKEDITOR._ExternalComponentMap.get(componentName); _this.ngZone.run(() => { switch (evtName) { case 'Focus': if (_this.onTouched) { _this.onTouched(); } break; case 'Command': _this.propagateChange(evtName, { componentName: componentName, paramObj: paramObj }); break; case 'Key': if (paramObj.strEventName === 'keyup') { _this.propagateChange(evtName, { componentName: componentName, paramObj: paramObj }); } break; case 'CreationComplete': if (_this.data && typeof _this.data !== 'undefined' && _this.data !== '') { RAONKEDITOR.SetHtmlContents(_this.data, _this.id); } // Data may be changed by content filtering. _this._data = RAONKEDITOR.GetEditorByName(_this.id)._BODY.innerHTML; break; case 'SetComplete': // Data may be changed by content filtering. _this._data = RAONKEDITOR.GetEditorByName(_this.id)._BODY.innerHTML; break; } _this[_this.capitalize(evtName)].emit({ componentName: componentName, paramObj: paramObj }); }); } // return event let _retValue = ""; switch (evtName) { case 'BeforePaste': case 'BeforeInsertUrl': case 'BeforeInsertHyperlink': if (RAONKEDITOR._ExternalEventRetValueMap.has(componentName)) { _retValue = RAONKEDITOR._ExternalEventRetValueMap.get(componentName); RAONKEDITOR._ExternalEventRetValueMap.delete(componentName); // Initialization return _retValue; } break; } }; }); return _configEvent; } capitalize(str) { return str.charAt(0).toLowerCase() + str.slice(1); } propagateChange(eventName, eventParams) { this.ngZone.run(() => { const newData = RAONKEDITOR.GetEditorByName(this.id)._BODY.innerHTML; this.change.emit(eventParams); if (newData === this.data) { return; } this._data = newData; if (this.onChange) { this.onChange(newData); } }); } } RaonkEditorComponent.decorators = [ { type: Component, args: [{ selector: 'RaonkEditor', template: '<ng-template></ng-template>', providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => RaonkEditorComponent), multi: true, } ] },] } ]; RaonkEditorComponent.ctorParameters = () => [ { type: ElementRef }, { type: NgZone } ]; RaonkEditorComponent.propDecorators = { id: [{ type: Input }], config: [{ type: Input }], componentType: [{ type: Input }], componentUrl: [{ type: Input }], tagName: [{ type: Input }], runtimes: [{ type: Input }], data: [{ type: Input }], readOnly: [{ type: Input }], viewMode: [{ type: Input }], namespaceLoaded: [{ type: Output }], change: [{ type: Output }], creationComplete: [{ type: Output }], afterChangeMode: [{ type: Output }], onError: [{ type: Output }], onLanguageDefinition: [{ type: Output }], afterPopupShow: [{ type: Output }], agentInstall: [{ type: Output }], beforeInsertUrl: [{ type: Output }], mouse: [{ type: Output }], command: [{ type: Output }], key: [{ type: Output }], resized: [{ type: Output }], documentEditComplete: [{ type: Output }], pasteImage: [{ type: Output }], wordCount: [{ type: Output }], beforePaste: [{ type: Output }], customAction: [{ type: Output }], fullScreen: [{ type: Output }], setComplete: [{ type: Output }], setInsertComplete: [{ type: Output }], closeInstallPopup: [{ type: Output }], setForbiddenWordComplete: [{ type: Output }], drag: [{ type: Output }], focus: [{ type: Output }], dialogLoaded: [{ type: Output }], beforeInsertHyperlink: [{ type: Output }] }; /** * @license Copyright (c) 2003-2022, RAONWIZ DevTean. All rights reserved. */ /** * @license Copyright (c) 2003-2022, RAONWIZ DevTeam. All rights reserved. */ class RaonkEditorModule { } RaonkEditorModule.decorators = [ { type: NgModule, args: [{ imports: [FormsModule, CommonModule], declarations: [RaonkEditorComponent], exports: [RaonkEditorComponent] },] } ]; /** * Generated bundle index. Do not edit. */ export { RaonkEditorComponent, RaonkEditorModule }; //# sourceMappingURL=raonkeditor-angular.js.map