@joniras/ngx-editor2
Version:
WYSIWYG Editor for Angular 8+
1,090 lines (1,056 loc) • 93.3 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common'), require('@angular/forms'), require('ngx-bootstrap/popover'), require('@angular/common/http'), require('rxjs'), require('@fortawesome/free-solid-svg-icons'), require('@fortawesome/free-regular-svg-icons'), require('@fortawesome/free-brands-svg-icons'), require('@fortawesome/angular-fontawesome')) :
typeof define === 'function' && define.amd ? define('@joniras/ngx-editor2', ['exports', '@angular/core', '@angular/common', '@angular/forms', 'ngx-bootstrap/popover', '@angular/common/http', 'rxjs', '@fortawesome/free-solid-svg-icons', '@fortawesome/free-regular-svg-icons', '@fortawesome/free-brands-svg-icons', '@fortawesome/angular-fontawesome'], factory) :
(global = global || self, factory((global.joniras = global.joniras || {}, global.joniras['ngx-editor2'] = {}), global.ng.core, global.ng.common, global.ng.forms, global.popover, global.ng.common.http, global.rxjs, global.freeSolidSvgIcons, global.freeRegularSvgIcons, global.freeBrandsSvgIcons, global.angularFontawesome));
}(this, (function (exports, core, common, forms, popover, http, rxjs, freeSolidSvgIcons, freeRegularSvgIcons, freeBrandsSvgIcons, angularFontawesome) { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
function __decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
function __param(paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
}
function __metadata(metadataKey, metadataValue) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
}
function __awaiter(thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
function __exportStar(m, exports) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
function __values(o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m) return m.call(o);
return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
}
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
}
function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++)
ar = ar.concat(__read(arguments[i]));
return ar;
}
function __spreadArrays() {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
function __await(v) {
return this instanceof __await ? (this.v = v, this) : new __await(v);
}
function __asyncGenerator(thisArg, _arguments, generator) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
}
function __asyncDelegator(o) {
var i, p;
return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
}
function __asyncValues(o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
}
function __makeTemplateObject(cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
};
function __importStar(mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result.default = mod;
return result;
}
function __importDefault(mod) {
return (mod && mod.__esModule) ? mod : { default: mod };
}
/**
* enable or disable toolbar based on configuration
*
* @param value toolbar item
* @param toolbar toolbar configuration object
*/
function canEnableToolbarOptions(value, toolbar) {
if (value) {
if (toolbar['length'] === 0) {
return true;
}
else {
var found = toolbar.filter(function (array) {
return array.indexOf(value) !== -1;
});
return !!found.length;
}
}
else {
return false;
}
}
/**
* set editor configuration
*
* @param value configuration via [config] propertyify
* @param ngxTextEditorConfig default editor configuration
* @param input direct configuration inputs via directives
*/
function getEditorConfiguration(value, ngxTextEditorConfig, input) {
for (var i in ngxTextEditorConfig) {
if (i) {
if (input[i] !== undefined) {
value[i] = input[i];
}
if (!value.hasOwnProperty(i)) {
value[i] = ngxTextEditorConfig[i];
}
}
}
return value;
}
/**
* return vertical if the element is the resizer property is set to basic
*
* @param resizer type of resizer, either basic or stack
*/
function canResize(resizer) {
if (resizer === 'basic') {
return 'vertical';
}
return false;
}
/**
* save selection when the editor is focussed out
*/
function saveSelection() {
if (window.getSelection) {
var sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
return sel.getRangeAt(0);
}
}
else if (document.getSelection && document.createRange) {
return document.createRange();
}
return null;
}
/**
* restore selection when the editor is focussed in
*
* @param range saved selection when the editor is focussed out
*/
function restoreSelection(range) {
if (range) {
if (window.getSelection) {
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
return true;
}
else if (document.getSelection && range.select) {
range.select();
return true;
}
}
else {
return false;
}
}
var Utils = /*#__PURE__*/Object.freeze({
__proto__: null,
canEnableToolbarOptions: canEnableToolbarOptions,
getEditorConfiguration: getEditorConfiguration,
canResize: canResize,
saveSelection: saveSelection,
restoreSelection: restoreSelection
});
var CommandExecutorService = /** @class */ (function () {
/**
*
* @param _http HTTP Client for making http requests
*/
function CommandExecutorService(_http) {
this._http = _http;
/** saves the selection from the editor when focused out */
this.savedSelection = undefined;
}
/**
* executes command from the toolbar
*
* @param command command to be executed
*/
CommandExecutorService.prototype.execute = function (command) {
if (!this.savedSelection && command !== 'enableObjectResizing') {
throw new Error('Range out of Editor');
}
if (command === 'enableObjectResizing') {
document.execCommand('enableObjectResizing', true);
}
if (command === 'blockquote') {
document.execCommand('formatBlock', false, 'blockquote');
}
if (command === 'removeBlockquote') {
document.execCommand('formatBlock', false, 'div');
}
if (command === 'h1') {
document.execCommand('formatBlock', false, 'h1');
}
if (command === 'h2') {
document.execCommand('formatBlock', false, 'h2');
}
if (command === 'h3') {
document.execCommand('formatBlock', false, 'h3');
}
if (command === 'clear') {
document.execCommand('formatBlock', false, 'div');
}
document.execCommand(command, false, null);
};
/**
* inserts image in the editor
*
* @param imageURI url of the image to be inserted
*/
CommandExecutorService.prototype.insertImage = function (imageURI) {
if (this.savedSelection) {
if (imageURI) {
var restored = restoreSelection(this.savedSelection);
if (restored) {
var img = document.createElement('img');
img.src = imageURI;
img.style.width = 'auto';
var inserted = this.insertHtml(img.outerHTML);
if (!inserted) {
throw new Error('Invalid URL');
}
}
}
}
else {
throw new Error('Range out of the editor');
}
};
/**
* inserts image in the editor
*
* @param videParams url of the image to be inserted
*/
CommandExecutorService.prototype.insertVideo = function (videParams) {
if (this.savedSelection) {
if (videParams) {
var restored = restoreSelection(this.savedSelection);
if (restored) {
if (this.isYoutubeLink(videParams.videoUrl)) {
var youtubeURL = '<iframe width="' + videParams.width + '" height="' + videParams.height + '"'
+ 'src="' + videParams.videoUrl + '"></iframe>';
this.insertHtml(youtubeURL);
}
else if (this.checkTagSupportInBrowser('video')) {
if (this.isValidURL(videParams.videoUrl)) {
var videoSrc = '<video width="' + videParams.width + '" height="' + videParams.height + '"'
+ ' controls="true"><source src="' + videParams.videoUrl + '"></video>';
this.insertHtml(videoSrc);
}
else {
throw new Error('Invalid video URL');
}
}
else {
throw new Error('Unable to insert video');
}
}
}
}
else {
throw new Error('Range out of the editor');
}
};
/**
* checks the input url is a valid youtube URL or not
*
* @param url Youtue URL
*/
CommandExecutorService.prototype.isYoutubeLink = function (url) {
var ytRegExp = /^(http(s)?:\/\/)?((w){3}.)?youtu(be|.be)?(\.com)?\/.+/;
return ytRegExp.test(url);
};
/**
* check whether the string is a valid url or not
* @param url url
*/
CommandExecutorService.prototype.isValidURL = function (url) {
var urlRegExp = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
return urlRegExp.test(url);
};
/**
* uploads image to the server
*
* @param file file that has to be uploaded
* @param endPoint enpoint to which the image has to be uploaded
*/
CommandExecutorService.prototype.uploadImage = function (file, endPoint) {
if (!endPoint) {
throw new Error('Image Endpoint isn`t provided or invalid');
}
var formData = new FormData();
if (file) {
formData.append('file', file);
var req = new http.HttpRequest('POST', endPoint, formData, {
reportProgress: true
});
return this._http.request(req);
}
else {
throw new Error('Invalid Image');
}
};
/**
* inserts link in the editor
*
* @param params parameters that holds the information for the link
*/
CommandExecutorService.prototype.createLink = function (params) {
if (this.savedSelection) {
/**
* check whether the saved selection contains a range or plain selection
*/
if (params.urlNewTab) {
var newUrl = '<a href="' + params.urlLink + '" target="_blank">' + params.urlText + '</a>';
if (document.getSelection().type !== 'Range') {
var restored = restoreSelection(this.savedSelection);
if (restored) {
this.insertHtml(newUrl);
}
}
else {
throw new Error('Only new links can be inserted. You cannot edit URL`s');
}
}
else {
var restored = restoreSelection(this.savedSelection);
if (restored) {
document.execCommand('createLink', false, params.urlLink);
}
}
}
else {
throw new Error('Range out of the editor');
}
};
/**
* insert color either font or background
*
* @param color color to be inserted
* @param where where the color has to be inserted either text/background
*/
CommandExecutorService.prototype.insertColor = function (color, where) {
if (this.savedSelection) {
var restored = restoreSelection(this.savedSelection);
if (restored && this.checkSelection()) {
if (where === 'textColor') {
document.execCommand('foreColor', false, color);
}
else {
document.execCommand('hiliteColor', false, color);
}
}
}
else {
throw new Error('Range out of the editor');
}
};
/**
* set font size for text
*
* @param fontSize font-size to be set
*/
CommandExecutorService.prototype.setFontSize = function (fontSize) {
if (this.savedSelection && this.checkSelection()) {
var deletedValue = this.deleteAndGetElement();
if (deletedValue) {
var restored = restoreSelection(this.savedSelection);
if (restored) {
if (this.isNumeric(fontSize)) {
var fontPx = '<span style="font-size: ' + fontSize + 'px;">' + deletedValue + '</span>';
this.insertHtml(fontPx);
}
else {
var fontPx = '<span style="font-size: ' + fontSize + ';">' + deletedValue + '</span>';
this.insertHtml(fontPx);
}
}
}
}
else {
throw new Error('Range out of the editor');
}
};
/**
* set font name/family for text
*
* @param fontName font-family to be set
*/
CommandExecutorService.prototype.setFontName = function (fontName) {
if (this.savedSelection && this.checkSelection()) {
var deletedValue = this.deleteAndGetElement();
if (deletedValue) {
var restored = restoreSelection(this.savedSelection);
if (restored) {
if (this.isNumeric(fontName)) {
var fontFamily = '<span style="font-family: ' + fontName + 'px;">' + deletedValue + '</span>';
this.insertHtml(fontFamily);
}
else {
var fontFamily = '<span style="font-family: ' + fontName + ';">' + deletedValue + '</span>';
this.insertHtml(fontFamily);
}
}
}
}
else {
throw new Error('Range out of the editor');
}
};
/** insert HTML */
CommandExecutorService.prototype.insertHtml = function (html) {
var isHTMLInserted = document.execCommand('insertHTML', false, html);
if (!isHTMLInserted) {
throw new Error('Unable to perform the operation');
}
return isHTMLInserted;
};
/**
* check whether the value is a number or string
* if number return true
* else return false
*/
CommandExecutorService.prototype.isNumeric = function (value) {
return /^-{0,1}\d+$/.test(value);
};
/** delete the text at selected range and return the value */
CommandExecutorService.prototype.deleteAndGetElement = function () {
var slectedText;
if (this.savedSelection) {
slectedText = this.savedSelection.toString();
this.savedSelection.deleteContents();
return slectedText;
}
return false;
};
/** check any slection is made or not */
CommandExecutorService.prototype.checkSelection = function () {
var slectedText = this.savedSelection.toString();
if (slectedText.length === 0) {
throw new Error('No Selection Made');
}
return true;
};
/**
* check tag is supported by browser or not
*
* @param tag HTML tag
*/
CommandExecutorService.prototype.checkTagSupportInBrowser = function (tag) {
return !(document.createElement(tag) instanceof HTMLUnknownElement);
};
CommandExecutorService.ctorParameters = function () { return [
{ type: http.HttpClient }
]; };
CommandExecutorService = __decorate([
core.Injectable()
], CommandExecutorService);
return CommandExecutorService;
}());
/** time in which the message has to be cleared */
var DURATION = 7000;
var MessageService = /** @class */ (function () {
function MessageService() {
/** variable to hold the user message */
this.message = new rxjs.Subject();
}
/** returns the message sent by the editor */
MessageService.prototype.getMessage = function () {
return this.message.asObservable();
};
/**
* sends message to the editor
*
* @param message message to be sent
*/
MessageService.prototype.sendMessage = function (message) {
this.message.next(message);
this.clearMessageIn(DURATION);
};
/**
* a short interval to clear message
*
* @param milliseconds time in seconds in which the message has to be cleared
*/
MessageService.prototype.clearMessageIn = function (milliseconds) {
var _this = this;
setTimeout(function () {
_this.message.next(undefined);
}, milliseconds);
};
MessageService = __decorate([
core.Injectable()
], MessageService);
return MessageService;
}());
/**
* toolbar default configuration
*/
var ngxTextEditorConfig = {
editable: true,
spellcheck: true,
height: 'auto',
minHeight: '0',
width: 'auto',
minWidth: '0',
translate: 'yes',
enableToolbar: true,
showToolbar: true,
placeholder: 'Enter text here...',
imageEndPoint: '',
toolbar: [
['h1', 'h2', 'h3', 'bold', 'italic', 'underline', 'strikeThrough', 'superscript', 'subscript'],
['fontName', 'fontSize', 'color'],
['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull', 'indent', 'outdent'],
['cut', 'copy', 'delete', 'removeFormat', 'undo', 'redo'],
['paragraph', 'blockquote', 'removeBlockquote', 'horizontalLine', 'orderedList', 'unorderedList'],
['link', 'unlink', 'image', 'video']
],
toolbarTitle: {
'bold': 'Bold',
'italic': 'Italic',
'underline': 'Underline',
'strikeThrough': 'strikeThrough',
'superscript': 'Superscript',
'subscript': 'Subscript',
'fontName': 'Font Family',
'fontSize': 'Font Size',
'color': 'Color Picker',
'justifyLeft': 'Justify Left',
'justifyCenter': 'Justify Center',
'justifyRight': 'Justify Right',
'justifyFull': 'Justify Full',
'indent': 'Indent',
'outdent': 'Outdent',
'cut': 'Cut',
'copy': 'Copy',
'delete': 'Delete',
'removeFormat': 'Clear Formatting',
'undo': 'Undo',
'redo': 'Redo',
'paragraph': 'Paragraph',
'blockquote': 'Blockquote',
'removeBlockquote': 'Remove Blockquote',
'horizontalLine': 'Horizontal Line',
'orderedList': 'Ordered List',
'unorderedList': 'Color Picker',
'link': 'Insert Link',
'URLInput': 'URL',
'urlTextInput': 'Text',
'urlNewTab': 'Open in new tab',
'linkSubmit': 'Submit',
'unlink': 'Unlink',
'image': 'Insert Image',
'chooseImage': 'Choose Image',
'uploadingimage': 'Uploading Image',
'imageURLInput': 'URL',
'imageSubmit': 'Submit',
'video': 'Insert Video',
'videoURLInput': 'URL',
'height': 'height (px)',
'width': 'width (px)',
'heightwidth': 'Height/Width',
'videoSubmit': 'Submit',
'textColor': 'Text',
'backgroundColor': 'Background',
'hexInput': 'Hex Color',
'hexSubmit': 'Submit',
'fontSubmit': 'Submit',
'example': 'Ex:'
}
};
var NgxTextEditorComponent = /** @class */ (function () {
/**
* @param _messageService service to send message to the editor message component
* @param _commandExecutor executes command from the toolbar
* @param _renderer access and manipulate the dom element
*/
function NgxTextEditorComponent(_messageService, _commandExecutor, _renderer) {
this._messageService = _messageService;
this._commandExecutor = _commandExecutor;
this._renderer = _renderer;
/**
* The editor can be resized vertically.
*
* `basic` resizer enables the html5 reszier. Check here https://www.w3schools.com/cssref/css3_pr_resize.asp
*
* `stack` resizer enable a resizer that looks like as if in https://stackoverflow.com
*/
this.resizer = 'stack';
/**
* The config property is a JSON object
*
* All avaibale inputs inputs can be provided in the configuration as JSON
* inputs provided directly are considered as top priority
*/
this.config = ngxTextEditorConfig;
/** emits `blur` event when focused out from the textarea */
this.blur = new core.EventEmitter();
/** emits `focus` event when focused in to the textarea */
this.focus = new core.EventEmitter();
/** emits `uploadImage` event when image is selected */
this.uploadImage = new core.EventEmitter();
this.Utils = Utils;
}
NgxTextEditorComponent_1 = NgxTextEditorComponent;
/**
* events
*/
NgxTextEditorComponent.prototype.onTextAreaFocus = function () {
this.focus.emit('focus');
};
/** focus the text area when the editor is focussed */
NgxTextEditorComponent.prototype.onEditorFocus = function () {
this.textArea.nativeElement.focus();
};
/**
* Executed from the contentEditable section while the input property changes
* @param innerHTML html string from contentEditable
*/
NgxTextEditorComponent.prototype.onContentChange = function (innerHTML) {
if (typeof this.onChange === 'function') {
this.onChange(innerHTML);
this.togglePlaceholder(innerHTML);
}
};
NgxTextEditorComponent.prototype.onTextAreaBlur = function () {
/** save selection if focussed out */
this._commandExecutor.savedSelection = saveSelection();
if (typeof this.onTouched === 'function') {
this.onTouched();
}
this.blur.emit('blur');
};
/**
* Executed when the image from the disc is selected
* @param image uploaded file object
*/
NgxTextEditorComponent.prototype.onUploadImage = function (image) {
this.uploadImage.emit(image);
};
/**
* resizing text area
*
* @param offsetY vertical height of the eidtable portion of the editor
*/
NgxTextEditorComponent.prototype.resizeTextArea = function (offsetY) {
var newHeight = parseInt(this.height, 10);
newHeight += offsetY;
this.height = newHeight + 'px';
this.textArea.nativeElement.style.height = this.height;
};
/**
* editor actions, i.e., executes command from toolbar
*
* @param commandName name of the command to be executed
*/
NgxTextEditorComponent.prototype.executeCommand = function (commandName) {
try {
this._commandExecutor.execute(commandName);
}
catch (error) {
this._messageService.sendMessage(error.message);
}
};
/**
* Write a new value to the element.
*
* @param value value to be executed when there is a change in contenteditable
*/
NgxTextEditorComponent.prototype.writeValue = function (value) {
this.togglePlaceholder(value);
if (value === null || value === undefined || value === '' || value === '<br>') {
value = null;
}
this.refreshView(value);
};
/**
* Set the function to be called
* when the control receives a change event.
*
* @param fn a function
*/
NgxTextEditorComponent.prototype.registerOnChange = function (fn) {
this.onChange = fn;
};
/**
* Set the function to be called
* when the control receives a touch event.
*
* @param fn a function
*/
NgxTextEditorComponent.prototype.registerOnTouched = function (fn) {
this.onTouched = fn;
};
/**
* refresh view/HTML of the editor
*
* @param value html string from the editor
*/
NgxTextEditorComponent.prototype.refreshView = function (value) {
var normalizedValue = value === null ? '' : value;
this._renderer.setProperty(this.textArea.nativeElement, 'innerHTML', normalizedValue);
};
/**
* toggles placeholder based on input string
*
* @param value A HTML string from the editor
*/
NgxTextEditorComponent.prototype.togglePlaceholder = function (value) {
if (!value || value === '<br>' || value === '') {
this._renderer.addClass(this.ngxWrapper.nativeElement, 'show-placeholder');
}
else {
this._renderer.removeClass(this.ngxWrapper.nativeElement, 'show-placeholder');
}
};
/**
* returns a json containing input params
*/
NgxTextEditorComponent.prototype.getCollectiveParams = function () {
return {
editable: this.editable,
spellcheck: this.spellcheck,
placeholder: this.placeholder,
translate: this.translate,
height: this.height,
minHeight: this.minHeight,
width: this.width,
minWidth: this.minWidth,
enableToolbar: this.enableToolbar,
showToolbar: this.showToolbar,
imageEndPoint: this.imageEndPoint,
toolbar: this.toolbar
};
};
NgxTextEditorComponent.prototype.ngOnInit = function () {
/**
* set configuration
*/
this.config = this.Utils.getEditorConfiguration(this.config, ngxTextEditorConfig, this.getCollectiveParams());
this.height = this.height || this.textArea.nativeElement.offsetHeight;
this.executeCommand('enableObjectResizing');
};
var NgxTextEditorComponent_1;
NgxTextEditorComponent.ctorParameters = function () { return [
{ type: MessageService },
{ type: CommandExecutorService },
{ type: core.Renderer2 }
]; };
__decorate([
core.Input()
], NgxTextEditorComponent.prototype, "editable", void 0);
__decorate([
core.Input()
], NgxTextEditorComponent.prototype, "spellcheck", void 0);
__decorate([
core.Input()
], NgxTextEditorComponent.prototype, "placeholder", void 0);
__decorate([
core.Input()
], NgxTextEditorComponent.prototype, "translate", void 0);
__decorate([
core.Input()
], NgxTextEditorComponent.prototype, "height", void 0);
__decorate([
core.Input()
], NgxTextEditorComponent.prototype, "minHeight", void 0);
__decorate([
core.Input()
], NgxTextEditorComponent.prototype, "width", void 0);
__decorate([
core.Input()
], NgxTextEditorComponent.prototype, "minWidth", void 0);
__decorate([
core.Input()
], NgxTextEditorComponent.prototype, "toolbar", void 0);
__decorate([
core.Input()
], NgxTextEditorComponent.prototype, "resizer", void 0);
__decorate([
core.Input()
], NgxTextEditorComponent.prototype, "config", void 0);
__decorate([
core.Input()
], NgxTextEditorComponent.prototype, "showToolbar", void 0);
__decorate([
core.Input()
], NgxTextEditorComponent.prototype, "enableToolbar", void 0);
__decorate([
core.Input()
], NgxTextEditorComponent.prototype, "imageEndPoint", void 0);
__decorate([
core.Output()
], NgxTextEditorComponent.prototype, "blur", void 0);
__decorate([
core.Output()
], NgxTextEditorComponent.prototype, "focus", void 0);
__decorate([
core.Output()
], NgxTextEditorComponent.prototype, "uploadImage", void 0);
__decorate([
core.ViewChild('ngxTextArea', { static: true })
], NgxTextEditorComponent.prototype, "textArea", void 0);
__decorate([
core.ViewChild('ngxWrapper', { static: true })
], NgxTextEditorComponent.prototype, "ngxWrapper", void 0);
NgxTextEditorComponent = NgxTextEditorComponent_1 = __decorate([
core.Component({
selector: 'ngx-text-editor',
template: "<div class=\"ngx-text-editor\"\r\n id=\"ngxTextEditor\"\r\n [style.width]=\"config['width']\"\r\n [style.minWidth]=\"config['minWidth']\"\r\n tabindex=\"0\"\r\n (focus)=\"onEditorFocus()\">\r\n\r\n <ngx-text-editor-toolbar [config]=\"config\"\r\n (execute)=\"executeCommand($event)\"\r\n (uploadImage)=\"onUploadImage($event)\"></ngx-text-editor-toolbar>\r\n\r\n <!-- text area -->\r\n <div #ngxWrapper\r\n class=\"ngx-wrapper\">\r\n <div #ngxTextArea\r\n class=\"ngx-text-editor-textarea\"\r\n [attr.contenteditable]=\"config['editable']\"\r\n (input)=\"onContentChange($event.target.innerHTML)\"\r\n [attr.translate]=\"config['translate']\"\r\n [attr.spellcheck]=\"config['spellcheck']\"\r\n [style.height]=\"config['height']\"\r\n [style.minHeight]=\"config['minHeight']\"\r\n [style.resize]=\"Utils?.canResize(resizer)\"\r\n (focus)=\"onTextAreaFocus()\"\r\n (blur)=\"onTextAreaBlur()\"></div>\r\n\r\n <span class=\"ngx-text-editor-placeholder\">\r\n {{ placeholder || config['placeholder'] }}\r\n </span>\r\n </div>\r\n\r\n <ngx-text-editor-message></ngx-text-editor-message>\r\n\r\n <ngx-grippie *ngIf=\"resizer === 'stack'\"></ngx-grippie>\r\n</div>\r\n",
providers: [{
provide: forms.NG_VALUE_ACCESSOR,
useExisting: core.forwardRef(function () { return NgxTextEditorComponent_1; }),
multi: true
}],
styles: [".ngx-text-editor{position:relative}.ngx-text-editor ::ng-deep [contenteditable=true]:empty:before{content:attr(placeholder);display:block;color:#868e96;opacity:1}.ngx-text-editor .ngx-wrapper{position:relative}.ngx-text-editor .ngx-wrapper .ngx-text-editor-textarea{min-height:5rem;padding:.5rem .8rem 1rem;border:1px solid #ddd;background-color:transparent;overflow-x:hidden;overflow-y:auto;z-index:2;position:relative}.ngx-text-editor .ngx-wrapper .ngx-text-editor-textarea.focus,.ngx-text-editor .ngx-wrapper .ngx-text-editor-textarea:focus{outline:0}.ngx-text-editor .ngx-wrapper .ngx-text-editor-textarea ::ng-deep blockquote{margin-left:1rem;border-left:.2em solid #dfe2e5;padding-left:.5rem}.ngx-text-editor .ngx-wrapper .ngx-text-editor-textarea::before{content:normal!important}.ngx-text-editor .ngx-wrapper ::ng-deep p{margin-bottom:0}.ngx-text-editor .ngx-wrapper .ngx-text-editor-placeholder{display:none;position:absolute;top:0;padding:.5rem .8rem 1rem .9rem;z-index:1;color:#6c757d;opacity:1}.ngx-text-editor .ngx-wrapper.show-placeholder .ngx-text-editor-placeholder{display:block}"]
})
], NgxTextEditorComponent);
return NgxTextEditorComponent;
}());
var NgxGrippieComponent = /** @class */ (function () {
/**
* Constructor
*
* @param _editorComponent Editor component
*/
function NgxGrippieComponent(_editorComponent) {
this._editorComponent = _editorComponent;
/** previous value befor resizing the editor */
this.oldY = 0;
/** set to true on mousedown event */
this.grabber = false;
}
/**
*
* @param event Mouseevent
*
* Update the height of the editor when the grabber is dragged
*/
NgxGrippieComponent.prototype.onMouseMove = function (event) {
if (!this.grabber) {
return;
}
this._editorComponent.resizeTextArea(event.clientY - this.oldY);
this.oldY = event.clientY;
};
/**
*
* @param event Mouseevent
*
* set the grabber to false on mouse up action
*/
NgxGrippieComponent.prototype.onMouseUp = function (event) {
this.grabber = false;
};
NgxGrippieComponent.prototype.onResize = function (event, resizer) {
this.grabber = true;
this.oldY = event.clientY;
event.preventDefault();
};
NgxGrippieComponent.ctorParameters = function () { return [
{ type: NgxTextEditorComponent }
]; };
__decorate([
core.HostListener('document:mousemove', ['$event'])
], NgxGrippieComponent.prototype, "onMouseMove", null);
__decorate([
core.HostListener('document:mouseup', ['$event'])
], NgxGrippieComponent.prototype, "onMouseUp", null);
__decorate([
core.HostListener('mousedown', ['$event'])
], NgxGrippieComponent.prototype, "onResize", null);
NgxGrippieComponent = __decorate([
core.Component({
selector: 'ngx-grippie',
template: "<div class=\"ngx-text-editor-grippie\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" style=\"isolation:isolate\" viewBox=\"651.6 235 26 5\"\r\n width=\"26\" height=\"5\">\r\n <g id=\"sprites\">\r\n <path d=\" M 651.6 235 L 653.6 235 L 653.6 237 L 651.6 237 M 654.6 238 L 656.6 238 L 656.6 240 L 654.6 240 M 660.6 238 L 662.6 238 L 662.6 240 L 660.6 240 M 666.6 238 L 668.6 238 L 668.6 240 L 666.6 240 M 672.6 238 L 674.6 238 L 674.6 240 L 672.6 240 M 657.6 235 L 659.6 235 L 659.6 237 L 657.6 237 M 663.6 235 L 665.6 235 L 665.6 237 L 663.6 237 M 669.6 235 L 671.6 235 L 671.6 237 L 669.6 237 M 675.6 235 L 677.6 235 L 677.6 237 L 675.6 237\"\r\n fill=\"rgb(147,153,159)\" />\r\n </g>\r\n </svg>\r\n</div>\r\n",
styles: [".ngx-text-editor-grippie{height:9px;background-color:#f1f1f1;position:relative;text-align:center;cursor:s-resize;border:1px solid #ddd;border-top:transparent}.ngx-text-editor-grippie svg{position:absolute;top:1.5px;width:50%;right:25%}"]
})
], NgxGrippieComponent);
return NgxGrippieComponent;
}());
var NgxTextEditorMessageComponent = /** @class */ (function () {
/**
* @param _messageService service to send message to the editor
*/
function NgxTextEditorMessageComponent(_messageService) {
var _this = this;
this._messageService = _messageService;
/** property that holds the message to be displayed on the editor */
this.ngxMessage = undefined;
this._messageService.getMessage().subscribe(function (message) { return _this.ngxMessage = message; });
}
/**
* clears editor message
*/
NgxTextEditorMessageComponent.prototype.clearMessage = function () {
this.ngxMessage = undefined;
};
NgxTextEditorMessageComponent.ctorParameters = function () { return [
{ type: MessageService }
]; };
NgxTextEditorMessageComponent = __decorate([
core.Component({
selector: 'ngx-text-editor-message',
template: "<div class=\"ngx-text-editor-message\" *ngIf=\"ngxMessage\" (dblclick)=\"clearMessage()\">\r\n {{ ngxMessage }}\r\n</div>\r\n",
styles: [".ngx-text-editor-message{font-size:80%;background-color:#f1f1f1;border:1px solid #ddd;border-top:transparent;padding:0 .5rem .1rem;transition:.5s ease-in}"]
})
], NgxTextEditorMessageComponent);
return NgxTextEditorMessageComponent;
}());
var NgxTextEditorToolbarComponent = /** @class */ (function () {
function NgxTextEditorToolbarComponent(_popOverConfig, _formBuilder, _messageService, _commandExecutorService) {
this._popOverConfig = _popOverConfig;
this._formBuilder = _formBuilder;
this._messageService = _messageService;
this._commandExecutorService = _commandExecutorService;
/** set to false when image is being uploaded */
this.uploadComplete = true;
/** upload percentage */
this.updloadPercentage = 0;
/** set to true when the image is being uploaded */
this.isUploading = false;
/** which tab to active for color insertion */
this.selectedColorTab = 'textColor';
/** font family name */
this.fontName = '';
/** font size */
this.fontSize = '';
/** hex color code */
this.hexColor = '';
/** show/hide image uploader */
this.isImageUploader = false;
this.wasH1Pressed = false;
/** Icons for the Toolbar */
this.icons = {
heading: freeSolidSvgIcons.faHeading,
bold: freeSolidSvgIcons.faBold,
italic: freeSolidSvgIcons.faItalic,
underline: freeSolidSvgIcons.faUnderline,
strikethrough: freeSolidSvgIcons.faStrikethrough,
superscript: freeSolidSvgIcons.faSuperscript,
subscript: freeSolidSvgIcons.faSubscript,