UNPKG

ckeditor4-angular

Version:

Official CKEditor 4 component for Angular.

419 lines (412 loc) 18.7 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common'), require('@angular/forms'), require('ckeditor4-integrations-common')) : typeof define === 'function' && define.amd ? define('ckeditor4-angular', ['exports', '@angular/core', '@angular/common', '@angular/forms', 'ckeditor4-integrations-common'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["ckeditor4-angular"] = {}, global.ng.core, global.ng.common, global.ng.forms, global.ckeditor4IntegrationsCommon)); })(this, (function (exports, core, common, forms, ckeditor4IntegrationsCommon) { 'use strict'; /** * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved. * For licensing, see LICENSE.md. */ var CKEditorComponent = /** @class */ (function () { function CKEditorComponent(elementRef, ngZone) { this.elementRef = elementRef; this.ngZone = ngZone; /** * CKEditor 4 script url address. Script will be loaded only if CKEDITOR namespace is missing. * * Defaults to 'https://cdn.ckeditor.com/4.19.1/standard-all/ckeditor.js' */ this.editorUrl = 'https://cdn.ckeditor.com/4.19.1/standard-all/ckeditor.js'; /** * Tag name of the editor component. * * The default tag is `textarea`. */ this.tagName = 'textarea'; /** * The type of the editor interface. * * By default editor interface will be initialized as `classic` editor. * You can also choose to create an editor with `inline` interface type instead. * * See https://ckeditor.com/docs/ckeditor4/latest/guide/dev_uitypes.html * and https://ckeditor.com/docs/ckeditor4/latest/examples/fixedui.html * to learn more. */ this.type = "classic" /* CLASSIC */; /** * Fired when the CKEDITOR https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html namespace * is loaded. It only triggers once, no matter how many CKEditor 4 components are initialised. * Can be used for convenient changes in the namespace, e.g. for adding external plugins. */ this.namespaceLoaded = new core.EventEmitter(); /** * Fires when the editor is ready. It corresponds with the `editor#instanceReady` * https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-instanceReady * event. */ this.ready = new core.EventEmitter(); /** * Fires when the editor data is loaded, e.g. after calling setData() * https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-setData * editor's method. It corresponds with the `editor#dataReady` * https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-dataReady event. */ this.dataReady = new core.EventEmitter(); /** * Fires when the content of the editor has changed. It corresponds with the `editor#change` * https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-change * event. For performance reasons this event may be called even when data didn't really changed. * Please note that this event will only be fired when `undo` plugin is loaded. If you need to * listen for editor changes (e.g. for two-way data binding), use `dataChange` event instead. */ this.change = new core.EventEmitter(); /** * Fires when the content of the editor has changed. In contrast to `change` - only emits when * data really changed thus can be successfully used with `[data]` and two way `[(data)]` binding. * * See more: https://angular.io/guide/template-syntax#two-way-binding--- */ this.dataChange = new core.EventEmitter(); /** * Fires when the native dragStart event occurs. It corresponds with the `editor#dragstart` * https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-dragstart * event. */ this.dragStart = new core.EventEmitter(); /** * Fires when the native dragEnd event occurs. It corresponds with the `editor#dragend` * https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-dragend * event. */ this.dragEnd = new core.EventEmitter(); /** * Fires when the native drop event occurs. It corresponds with the `editor#drop` * https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-drop * event. */ this.drop = new core.EventEmitter(); /** * Fires when the file loader response is received. It corresponds with the `editor#fileUploadResponse` * https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-fileUploadResponse * event. */ this.fileUploadResponse = new core.EventEmitter(); /** * Fires when the file loader should send XHR. It corresponds with the `editor#fileUploadRequest` * https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-fileUploadRequest * event. */ this.fileUploadRequest = new core.EventEmitter(); /** * Fires when the editing area of the editor is focused. It corresponds with the `editor#focus` * https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-focus * event. */ this.focus = new core.EventEmitter(); /** * Fires after the user initiated a paste action, but before the data is inserted. * It corresponds with the `editor#paste` * https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-paste * event. */ this.paste = new core.EventEmitter(); /** * Fires after the `paste` event if content was modified. It corresponds with the `editor#afterPaste` * https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-afterPaste * event. */ this.afterPaste = new core.EventEmitter(); /** * Fires when the editing view of the editor is blurred. It corresponds with the `editor#blur` * https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-blur * event. */ this.blur = new core.EventEmitter(); /** * If the component is read–only before the editor instance is created, it remembers that state, * so the editor can become read–only once it is ready. */ this._readOnly = null; this._data = null; this._destroyed = false; } Object.defineProperty(CKEditorComponent.prototype, "data", { get: function () { return this._data; }, /** * Keeps track of the editor'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: function (data) { if (data === this._data) { return; } if (this.instance) { this.instance.setData(data); // Data may be changed by ACF. this._data = this.instance.getData(); return; } this._data = data; }, enumerable: false, configurable: true }); Object.defineProperty(CKEditorComponent.prototype, "readOnly", { get: function () { if (this.instance) { return this.instance.readOnly; } return this._readOnly; }, /** * When set to `true`, the editor becomes read-only. * * See https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-readOnly * to learn more. */ set: function (isReadOnly) { if (this.instance) { this.instance.setReadOnly(isReadOnly); return; } // Delay setting read-only state until editor initialization. this._readOnly = isReadOnly; }, enumerable: false, configurable: true }); CKEditorComponent.prototype.ngAfterViewInit = function () { var _this = this; ckeditor4IntegrationsCommon.getEditorNamespace(this.editorUrl, function (namespace) { _this.namespaceLoaded.emit(namespace); }).then(function () { // 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.createEditor.bind(_this)); }).catch(window.console.error); }; CKEditorComponent.prototype.ngOnDestroy = function () { var _this = this; this._destroyed = true; this.ngZone.runOutsideAngular(function () { if (_this.instance) { _this.instance.destroy(); _this.instance = null; } }); }; CKEditorComponent.prototype.writeValue = function (value) { this.data = value; }; CKEditorComponent.prototype.registerOnChange = function (callback) { this.onChange = callback; }; CKEditorComponent.prototype.registerOnTouched = function (callback) { this.onTouched = callback; }; CKEditorComponent.prototype.createEditor = function () { var _this = this; var _a, _b; var element = document.createElement(this.tagName); this.elementRef.nativeElement.appendChild(element); var userInstanceReadyCallback = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.on) === null || _b === void 0 ? void 0 : _b.instanceReady; var defaultConfig = { delayIfDetached: true }; var config = Object.assign(Object.assign({}, defaultConfig), this.config); if (typeof config.on === 'undefined') { config.on = {}; } config.on.instanceReady = function (evt) { var editor = evt.editor; _this.instance = editor; // Read only state may change during instance initialization. _this.readOnly = _this._readOnly !== null ? _this._readOnly : _this.instance.readOnly; _this.subscribe(_this.instance); var undo = editor.undoManager; if (_this.data !== null) { undo && undo.lock(); editor.setData(_this.data, { callback: function () { // Locking undoManager prevents 'change' event. // Trigger it manually to updated bound data. if (_this.data !== editor.getData()) { undo ? editor.fire('change') : editor.fire('dataReady'); } undo && undo.unlock(); _this.ngZone.run(function () { if (typeof userInstanceReadyCallback === 'function') { userInstanceReadyCallback(evt); } _this.ready.emit(evt); }); } }); } else { _this.ngZone.run(function () { if (typeof userInstanceReadyCallback === 'function') { userInstanceReadyCallback(evt); } _this.ready.emit(evt); }); } }; if (this.type === "inline" /* INLINE */) { CKEDITOR.inline(element, config); } else { CKEDITOR.replace(element, config); } }; CKEditorComponent.prototype.subscribe = function (editor) { var _this = this; editor.on('focus', function (evt) { _this.ngZone.run(function () { _this.focus.emit(evt); }); }); editor.on('paste', function (evt) { _this.ngZone.run(function () { _this.paste.emit(evt); }); }); editor.on('afterPaste', function (evt) { _this.ngZone.run(function () { _this.afterPaste.emit(evt); }); }); editor.on('dragend', function (evt) { _this.ngZone.run(function () { _this.dragEnd.emit(evt); }); }); editor.on('dragstart', function (evt) { _this.ngZone.run(function () { _this.dragStart.emit(evt); }); }); editor.on('drop', function (evt) { _this.ngZone.run(function () { _this.drop.emit(evt); }); }); editor.on('fileUploadRequest', function (evt) { _this.ngZone.run(function () { _this.fileUploadRequest.emit(evt); }); }); editor.on('fileUploadResponse', function (evt) { _this.ngZone.run(function () { _this.fileUploadResponse.emit(evt); }); }); editor.on('blur', function (evt) { _this.ngZone.run(function () { if (_this.onTouched) { _this.onTouched(); } _this.blur.emit(evt); }); }); editor.on('dataReady', this.propagateChange, this); if (this.instance.undoManager) { editor.on('change', this.propagateChange, this); } // If 'undo' plugin is not loaded, listen to 'selectionCheck' event instead. (#54). else { editor.on('selectionCheck', this.propagateChange, this); } }; CKEditorComponent.prototype.propagateChange = function (event) { var _this = this; this.ngZone.run(function () { var newData = _this.instance.getData(); if (event.name === 'change') { _this.change.emit(event); } else if (event.name === 'dataReady') { _this.dataReady.emit(event); } if (newData === _this.data) { return; } _this._data = newData; _this.dataChange.emit(newData); if (_this.onChange) { _this.onChange(newData); } }); }; return CKEditorComponent; }()); CKEditorComponent.decorators = [ { type: core.Component, args: [{ selector: 'ckeditor', template: '<ng-template></ng-template>', providers: [ { provide: forms.NG_VALUE_ACCESSOR, useExisting: core.forwardRef(function () { return CKEditorComponent; }), multi: true, } ] },] } ]; CKEditorComponent.ctorParameters = function () { return [ { type: core.ElementRef }, { type: core.NgZone } ]; }; CKEditorComponent.propDecorators = { config: [{ type: core.Input }], editorUrl: [{ type: core.Input }], tagName: [{ type: core.Input }], type: [{ type: core.Input }], data: [{ type: core.Input }], readOnly: [{ type: core.Input }], namespaceLoaded: [{ type: core.Output }], ready: [{ type: core.Output }], dataReady: [{ type: core.Output }], change: [{ type: core.Output }], dataChange: [{ type: core.Output }], dragStart: [{ type: core.Output }], dragEnd: [{ type: core.Output }], drop: [{ type: core.Output }], fileUploadResponse: [{ type: core.Output }], fileUploadRequest: [{ type: core.Output }], focus: [{ type: core.Output }], paste: [{ type: core.Output }], afterPaste: [{ type: core.Output }], blur: [{ type: core.Output }] }; /** * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved. * For licensing, see LICENSE.md. */ var CKEditorModule = /** @class */ (function () { function CKEditorModule() { } return CKEditorModule; }()); CKEditorModule.decorators = [ { type: core.NgModule, args: [{ imports: [forms.FormsModule, common.CommonModule], declarations: [CKEditorComponent], exports: [CKEditorComponent] },] } ]; /** * Generated bundle index. Do not edit. */ exports.CKEditorComponent = CKEditorComponent; exports.CKEditorModule = CKEditorModule; Object.defineProperty(exports, '__esModule', { value: true }); })); //# sourceMappingURL=ckeditor4-angular.umd.js.map