UNPKG

ngx-quill

Version:

An angular (>= v2) component for the easy use of the QuillJS richt text editor.

617 lines (609 loc) 21.4 kB
import { isPlatformServer, DOCUMENT } from '@angular/common'; import { DomSanitizer } from '@angular/platform-browser'; import { InjectionToken, Component, ElementRef, EventEmitter, forwardRef, Inject, Input, NgZone, Output, PLATFORM_ID, Renderer2, SecurityContext, ViewEncapsulation, NgModule } from '@angular/core'; import { NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var defaultModules = { toolbar: [ ['bold', 'italic', 'underline', 'strike'], ['blockquote', 'code-block'], [{ header: 1 }, { header: 2 }], [{ list: 'ordered' }, { list: 'bullet' }], [{ script: 'sub' }, { script: 'super' }], [{ indent: '-1' }, { indent: '+1' }], [{ direction: 'rtl' }], [{ size: ['small', false, 'large', 'huge'] }], [{ header: [1, 2, 3, 4, 5, 6, false] }], [ { color: [] }, { background: [] } ], [{ font: [] }], [{ align: [] }], ['clean'], ['link', 'image', 'video'] // link and image, video ] }; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var QUILL_CONFIG_TOKEN = new InjectionToken('config'); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // tslint:disable-next-line:variable-name /** @type {?} */ var Quill = null; var QuillEditorComponent = /** @class */ (function () { function QuillEditorComponent(elementRef, domSanitizer, doc, platformId, renderer, zone, config) { var _this = this; this.elementRef = elementRef; this.domSanitizer = domSanitizer; this.doc = doc; this.platformId = platformId; this.renderer = renderer; this.zone = zone; this.config = config; this.format = 'html'; this.required = false; this.customToolbarPosition = 'top'; this.sanitize = false; this.style = null; this.strict = true; this.customOptions = []; this.onEditorCreated = new EventEmitter(); this.onContentChanged = new EventEmitter(); this.onSelectionChanged = new EventEmitter(); this.disabled = false; // used to store initial value before ViewInit this.valueGetter = (/** * @param {?} quillEditor * @param {?} editorElement * @return {?} */ function (quillEditor, editorElement) { /** @type {?} */ var html = editorElement.children[0].innerHTML; if (html === '<p><br></p>' || html === '<div><br><div>') { html = null; } /** @type {?} */ var modelValue = html; if (_this.format === 'text') { modelValue = quillEditor.getText(); } else if (_this.format === 'object') { modelValue = quillEditor.getContents(); } else if (_this.format === 'json') { try { modelValue = JSON.stringify(quillEditor.getContents()); } catch (e) { modelValue = quillEditor.getText(); } } return modelValue; }); this.valueSetter = (/** * @param {?} quillEditor * @param {?} value * @return {?} */ function (quillEditor, value) { if (_this.format === 'html') { if (_this.sanitize) { value = _this.domSanitizer.sanitize(SecurityContext.HTML, value); } return quillEditor.clipboard.convert(value); } else if (_this.format === 'json') { try { return JSON.parse(value); } catch (e) { return [{ insert: value }]; } } return value; }); this.selectionChangeHandler = (/** * @param {?} range * @param {?} oldRange * @param {?} source * @return {?} */ function (range, oldRange, source) { _this.zone.run((/** * @return {?} */ function () { _this.onSelectionChanged.emit({ editor: _this.quillEditor, oldRange: oldRange, range: range, source: source }); if (!range && _this.onModelTouched) { _this.onModelTouched(); } })); }); this.textChangeHandler = (/** * @param {?} delta * @param {?} oldDelta * @param {?} source * @return {?} */ function (delta, oldDelta, source) { // only emit changes emitted by user interactions // only emit changes emitted by user interactions /** @type {?} */ var text = _this.quillEditor.getText(); /** @type {?} */ var content = _this.quillEditor.getContents(); /** @type {?} */ var html = (/** @type {?} */ (_this.editorElem)).children[0].innerHTML; if (html === '<p><br></p>' || html === '<div><br><div>') { html = null; } _this.zone.run((/** * @return {?} */ function () { /** @type {?} */ var trackChanges = _this.trackChanges || _this.config.trackChanges; if ((source === Quill.sources.USER || trackChanges && trackChanges === 'all') && _this.onModelChange) { _this.onModelChange(_this.valueGetter(_this.quillEditor, (/** @type {?} */ (_this.editorElem)))); } _this.onContentChanged.emit({ content: content, delta: delta, editor: _this.quillEditor, html: html, oldDelta: oldDelta, source: source, text: text }); })); }); } // tslint:disable-next-line:no-empty // tslint:disable-next-line:no-empty /** * @param {?=} _modelValue * @return {?} */ QuillEditorComponent.prototype.onModelChange = // tslint:disable-next-line:no-empty /** * @param {?=} _modelValue * @return {?} */ function (_modelValue) { }; // tslint:disable-next-line:no-empty // tslint:disable-next-line:no-empty /** * @return {?} */ QuillEditorComponent.prototype.onModelTouched = // tslint:disable-next-line:no-empty /** * @return {?} */ function () { }; /** * @return {?} */ QuillEditorComponent.prototype.ngAfterViewInit = /** * @return {?} */ function () { var _this = this; if (isPlatformServer(this.platformId)) { return; } if (!Quill) { Quill = require('quill'); } if (this.customToolbarPosition === 'top') { this.elementRef.nativeElement.insertAdjacentHTML('beforeend', '<div quill-editor-element></div>'); } else { this.elementRef.nativeElement.insertAdjacentHTML('afterbegin', '<div quill-editor-element></div>'); } this.editorElem = this.elementRef.nativeElement.querySelector('[quill-editor-element]'); /** @type {?} */ var toolbarElem = this.elementRef.nativeElement.querySelector('[quill-editor-toolbar]'); /** @type {?} */ var modules = this.modules || (this.config.modules || defaultModules); if (modules.toolbar === undefined) { modules.toolbar = defaultModules.toolbar; } /** @type {?} */ var placeholder = this.placeholder !== undefined ? this.placeholder : this.config.placeholder; if (placeholder === undefined) { placeholder = 'Insert text here ...'; } if (toolbarElem) { // tslint:disable-next-line:no-string-literal modules['toolbar'] = toolbarElem; } if (this.style) { Object.keys(this.style).forEach((/** * @param {?} key * @return {?} */ function (key) { _this.renderer.setStyle(_this.editorElem, key, _this.style[key]); })); } this.customOptions.forEach((/** * @param {?} customOption * @return {?} */ function (customOption) { /** @type {?} */ var newCustomOption = Quill.import(customOption.import); newCustomOption.whitelist = customOption.whitelist; Quill.register(newCustomOption, true); })); /** @type {?} */ var bounds = this.bounds && this.bounds === 'self' ? this.editorElem : this.bounds; if (!bounds) { bounds = this.config.bounds ? this.config.bounds : this.doc.body; } /** @type {?} */ var debug = this.debug; if (!debug && debug !== false && this.config.debug) { debug = this.config.debug; } /** @type {?} */ var readOnly = this.readOnly; if (!readOnly && this.readOnly !== false) { readOnly = this.config.readOnly !== undefined ? this.config.readOnly : false; } /** @type {?} */ var scrollingContainer = this.scrollingContainer; if (!scrollingContainer && this.scrollingContainer !== null) { scrollingContainer = this.config.scrollingContainer === null || this.config.scrollingContainer ? this.config.scrollingContainer : null; } /** @type {?} */ var formats = this.formats; if (!formats && formats === undefined) { formats = this.config.formats || this.config.formats === null ? this.config.formats : undefined; } this.quillEditor = new Quill(this.editorElem, { bounds: bounds, debug: debug, formats: formats, modules: modules, placeholder: placeholder, readOnly: readOnly, scrollingContainer: scrollingContainer, strict: this.strict, theme: this.theme || (this.config.theme ? this.config.theme : 'snow') }); if (this.content) { if (this.format === 'object') { this.quillEditor.setContents(this.content, 'silent'); } else if (this.format === 'text') { this.quillEditor.setText(this.content, 'silent'); } else if (this.format === 'json') { try { this.quillEditor.setContents(JSON.parse(this.content), 'silent'); } catch (e) { this.quillEditor.setText(this.content, 'silent'); } } else { if (this.sanitize) { this.content = this.domSanitizer.sanitize(SecurityContext.HTML, this.content); } /** @type {?} */ var contents = this.quillEditor.clipboard.convert(this.content); this.quillEditor.setContents(contents, 'silent'); } this.quillEditor.history.clear(); } // initialize disabled status based on this.disabled as default value this.setDisabledState(); this.onEditorCreated.emit(this.quillEditor); // mark model as touched if editor lost focus this.quillEditor.on('selection-change', this.selectionChangeHandler); // update model if text changes this.quillEditor.on('text-change', this.textChangeHandler); }; /** * @return {?} */ QuillEditorComponent.prototype.ngOnDestroy = /** * @return {?} */ function () { if (this.quillEditor) { this.quillEditor.off('selection-change', this.selectionChangeHandler); this.quillEditor.off('text-change', this.textChangeHandler); } }; /** * @param {?} changes * @return {?} */ QuillEditorComponent.prototype.ngOnChanges = /** * @param {?} changes * @return {?} */ function (changes) { var _this = this; if (!this.quillEditor) { return; } // tslint:disable:no-string-literal if (changes['readOnly']) { this.quillEditor.enable(!changes['readOnly'].currentValue); } if (changes['placeholder']) { this.quillEditor.root.dataset.placeholder = changes['placeholder'].currentValue; } if (changes['style']) { /** @type {?} */ var currentStyling = changes['style'].currentValue; /** @type {?} */ var previousStyling = changes['style'].previousValue; if (previousStyling) { Object.keys(previousStyling).forEach((/** * @param {?} key * @return {?} */ function (key) { _this.renderer.removeStyle(_this.editorElem, key); })); } if (currentStyling) { Object.keys(currentStyling).forEach((/** * @param {?} key * @return {?} */ function (key) { _this.renderer.setStyle(_this.editorElem, key, _this.style[key]); })); } } // tslint:enable:no-string-literal }; /** * @param {?} currentValue * @return {?} */ QuillEditorComponent.prototype.writeValue = /** * @param {?} currentValue * @return {?} */ function (currentValue) { this.content = currentValue; if (this.quillEditor) { if (currentValue) { if (this.format === 'text') { this.quillEditor.setText(currentValue); } else { this.quillEditor.setContents(this.valueSetter(this.quillEditor, this.content)); } return; } this.quillEditor.setText(''); } }; /** * @param {?=} isDisabled * @return {?} */ QuillEditorComponent.prototype.setDisabledState = /** * @param {?=} isDisabled * @return {?} */ function (isDisabled) { if (isDisabled === void 0) { isDisabled = this.disabled; } // store initial value to set appropriate disabled status after ViewInit this.disabled = isDisabled; if (this.quillEditor) { if (isDisabled) { this.quillEditor.disable(); this.renderer.setAttribute(this.elementRef.nativeElement, 'disabled', 'disabled'); } else { if (!this.readOnly) { this.quillEditor.enable(); } this.renderer.removeAttribute(this.elementRef.nativeElement, 'disabled'); } } }; /** * @param {?} fn * @return {?} */ QuillEditorComponent.prototype.registerOnChange = /** * @param {?} fn * @return {?} */ function (fn) { this.onModelChange = fn; }; /** * @param {?} fn * @return {?} */ QuillEditorComponent.prototype.registerOnTouched = /** * @param {?} fn * @return {?} */ function (fn) { this.onModelTouched = fn; }; /** * @return {?} */ QuillEditorComponent.prototype.validate = /** * @return {?} */ function () { if (!this.quillEditor) { return null; } /** @type {?} */ var err = {}; /** @type {?} */ var valid = true; /** @type {?} */ var textLength = this.quillEditor.getText().trim().length; if (this.minLength && textLength && textLength < this.minLength) { err.minLengthError = { given: textLength, minLength: this.minLength }; valid = false; } if (this.maxLength && textLength > this.maxLength) { err.maxLengthError = { given: textLength, maxLength: this.maxLength }; valid = false; } if (this.required && !textLength) { err.requiredError = { empty: true }; valid = false; } return valid ? null : err; }; QuillEditorComponent.decorators = [ { type: Component, args: [{ encapsulation: ViewEncapsulation.None, providers: [ { multi: true, provide: NG_VALUE_ACCESSOR, useExisting: forwardRef((/** * @return {?} */ function () { return QuillEditorComponent; })) }, { multi: true, provide: NG_VALIDATORS, useExisting: forwardRef((/** * @return {?} */ function () { return QuillEditorComponent; })) } ], selector: 'quill-editor', template: "\n <ng-content select=\"[quill-editor-toolbar]\"></ng-content>\n" }] } ]; /** @nocollapse */ QuillEditorComponent.ctorParameters = function () { return [ { type: ElementRef }, { type: DomSanitizer }, { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }, { type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] }, { type: Renderer2 }, { type: NgZone }, { type: undefined, decorators: [{ type: Inject, args: [QUILL_CONFIG_TOKEN,] }] } ]; }; QuillEditorComponent.propDecorators = { format: [{ type: Input }], theme: [{ type: Input }], modules: [{ type: Input }], debug: [{ type: Input }], readOnly: [{ type: Input }], placeholder: [{ type: Input }], maxLength: [{ type: Input }], minLength: [{ type: Input }], required: [{ type: Input }], formats: [{ type: Input }], customToolbarPosition: [{ type: Input }], sanitize: [{ type: Input }], style: [{ type: Input }], strict: [{ type: Input }], scrollingContainer: [{ type: Input }], bounds: [{ type: Input }], customOptions: [{ type: Input }], trackChanges: [{ type: Input }], onEditorCreated: [{ type: Output }], onContentChanged: [{ type: Output }], onSelectionChanged: [{ type: Output }], valueGetter: [{ type: Input }], valueSetter: [{ type: Input }] }; return QuillEditorComponent; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ var ɵ0 = { modules: defaultModules }; var QuillModule = /** @class */ (function () { function QuillModule() { } /** * @param {?=} config * @return {?} */ QuillModule.forRoot = /** * @param {?=} config * @return {?} */ function (config) { return { ngModule: QuillModule, providers: [ { provide: QUILL_CONFIG_TOKEN, // tslint:disable-next-line:only-arrow-functions useValue: config || { modules: defaultModules } } ] }; }; QuillModule.decorators = [ { type: NgModule, args: [{ declarations: [ QuillEditorComponent ], exports: [QuillEditorComponent], imports: [], providers: [ { provide: QUILL_CONFIG_TOKEN, useValue: ɵ0 } ] },] } ]; return QuillModule; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ export { QuillModule, QuillEditorComponent, QUILL_CONFIG_TOKEN, defaultModules as ɵa }; //# sourceMappingURL=ngx-quill.js.map