@syncfusion/ej2-richtexteditor
Version:
Essential JS 2 RichTextEditor component
1,020 lines (1,013 loc) • 180 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
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);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(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);
};
var __decorate = (this && this.__decorate) || function (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;
};
import { Component, EventHandler, Complex, Browser, addClass, detach, updateCSSText, isNullOrUndefined } from '@syncfusion/ej2-base';
import { Property, NotifyPropertyChanges, formatUnit, L10n, closest } from '@syncfusion/ej2-base';
import { setStyleAttribute, Event, removeClass, print as printWindow, attributes } from '@syncfusion/ej2-base';
import { isNullOrUndefined as isNOU, compile, append, extend, debounce } from '@syncfusion/ej2-base';
import { Touch as EJ2Touch } from '@syncfusion/ej2-base';
import { getScrollableParent } from '@syncfusion/ej2-popups';
import * as events from '../base/constant';
import * as EVENTS from './../../common/constant';
import * as classes from '../base/classes';
import { Render } from '../renderer/render';
import { ViewSource } from '../renderer/view-source';
import { executeGroup } from './interface';
import { ServiceLocator } from '../services/service-locator';
import { RendererFactory } from '../services/renderer-factory';
import { RenderType } from './enum';
import { ExecCommandCallBack } from '../actions/execute-command-callback';
import { KeyboardEvents } from '../actions/keyboard';
import { ToolbarSettings, ImageSettings, AudioSettings, VideoSettings, QuickToolbarSettings, FontFamily, FontSize, Format, NumberFormatList, BulletFormatList, FormatPainterSettings, ImportWord, ExportWord, ExportPdf, CodeBlockSettings, LineHeight } from '../../models/toolbar-settings';
import { EmojiSettings } from '../../models/emoji-settings';
import { FileManagerSettings } from '../models/fileManager-settings';
import { TableSettings, PasteCleanupSettings } from '../../models/toolbar-settings';
import { FontColor, BackgroundColor } from '../../models/toolbar-settings';
import { IFrameSettings } from '../../models/iframe-settings';
import { InlineMode } from '../../models/inline-mode';
import { defaultLocale } from '../models/default-locale';
import { setAttributes } from '../actions/html-attributes';
import { FullScreen } from '../actions/full-screen';
import { EnterKeyAction } from '../actions/enter-key';
import * as CONSTANT from '../../common/constant';
import { dispatchEvent, getEditValue, decode, isEditableValueEmpty, getDefaultValue } from '../base/util';
import { cleanHTMLString, scrollToCursor, getStructuredHtml, isIDevice, alignmentHtml, openPrintWindow } from '../../common/util';
import { DialogRenderer } from '../renderer/dialog-renderer';
import { SlashMenuSettings } from '../../models/slash-menu-settings';
import { mentionRestrictKeys } from '../../common/config';
import { CustomUserAgentData } from '../../common/user-agent';
import { cleanupInternalElements, removeSelectionClassStates, resetContentEditableElements } from '../../common/util';
import { NodeSelection } from '../../selection/index';
import { DialogType } from '../../common/enum';
import { AIAssistantSettings } from '../models/ai-assistant-settings';
import { DEFAULT_AI_COMMANDS } from '../models/items';
import { PopupUploader } from '../renderer/popup-uploader-renderer';
/**
* Represents the Rich Text Editor component.
* ```html
* <textarea id="rte"></textarea>
* <script>
* var rteObj = new RichTextEditor();
* rteObj.appendTo("#rte");
* </script>
* ```
*/
var RichTextEditor = /** @class */ (function (_super) {
__extends(RichTextEditor, _super);
function RichTextEditor(options, element) {
var _this = _super.call(this, options, element) || this;
_this.hasContentChanged = false;
_this.isPlainPaste = false;
_this.needsID = true;
_this.isCopyAll = false;
_this.isSelecting = false;
_this.isSelectionStartInRTE = false;
_this.isRTEFocused = false;
return _this;
}
/**
* To provide the array of modules needed for component rendering
*
* @returns {ModuleDeclaration[]} - specifies the declaration.
* @hidden
*/
RichTextEditor.prototype.requiredModules = function () {
var modules = [];
if (this.toolbarSettings.enable) {
modules.push({ member: 'toolbar', args: [this, this.serviceLocator] });
if (this.quickToolbarSettings.enable) {
modules.push({ member: 'quickToolbar', args: [this, this.serviceLocator] });
}
}
if (this.editorMode === 'HTML' && this.slashMenuSettings.enable) {
modules.push({ member: 'slashMenu', args: [this, this.serviceLocator] });
}
if (this.showCharCount) {
modules.push({ member: 'count', args: [this, this.serviceLocator] });
}
if (this.editorMode === 'Markdown') {
modules.push({ member: 'markdownEditor', args: [this, this.serviceLocator] });
}
modules.push({
member: 'link',
args: [this, this.serviceLocator]
});
modules.push({
member: 'table',
args: [this, this.serviceLocator]
});
modules.push({
member: 'image',
args: [this, this.serviceLocator]
});
if (this.editorMode === 'HTML') {
modules.push({
member: 'audio',
args: [this, this.serviceLocator]
});
modules.push({
member: 'video',
args: [this, this.serviceLocator]
});
modules.push({ member: 'htmlEditor', args: [this, this.serviceLocator] });
modules.push({ member: 'pasteCleanup', args: [this, this.serviceLocator] });
modules.push({ member: 'importExport', args: [this, this.serviceLocator] });
modules.push({
member: 'formatPainter',
args: [this]
});
modules.push({
member: 'emojiPicker',
args: [this, this.serviceLocator]
});
modules.push({
member: 'codeBlock',
args: [this, this.serviceLocator]
});
if (this.enableClipboardCleanup) {
modules.push({ member: 'clipBoardCleanup', args: [this] });
}
if (this.enableMarkdownAutoFormat) {
modules.push({
member: 'autoFormat',
args: [this]
});
}
modules.push({
member: 'aiAssistant',
args: [this, this.serviceLocator]
});
}
if (this.fileManagerSettings.enable) {
modules.push({ member: 'fileManager', args: [this, this.serviceLocator] });
}
if (this.enableResize) {
modules.push({ member: 'resize', args: [this] });
}
return modules;
};
RichTextEditor.prototype.updateEnable = function () {
if (this.enabled) {
removeClass([this.element], classes.CLS_DISABLED);
this.element.setAttribute('aria-disabled', 'false');
if (!isNOU(this.htmlAttributes.tabindex)) {
this.inputElement.setAttribute('tabindex', this.htmlAttributes.tabindex);
}
else {
this.inputElement.setAttribute('tabindex', '0');
}
}
else {
if (this.getToolbar()) {
removeClass(this.getToolbar().querySelectorAll('.' + classes.CLS_ACTIVE), classes.CLS_ACTIVE);
removeClass([this.getToolbar().parentElement], [classes.CLS_TB_FLOAT]);
}
addClass([this.element], classes.CLS_DISABLED);
this.element.tabIndex = -1;
this.element.setAttribute('aria-disabled', 'true');
this.inputElement.setAttribute('tabindex', '-1');
}
};
/**
* setEnable method
*
* @returns {void}
* @hidden
*/
RichTextEditor.prototype.setEnable = function () {
this.updateEnable();
// eslint-disable-next-line
(this.enabled) ? this.eventInitializer() : this.unWireEvents();
};
RichTextEditor.prototype.initializeValue = function () {
this.isFocusOut = false;
this.isRTE = false;
this.isToolbarClipboardAction = false;
this.isBlur = true;
this.defaultResetValue = null;
this.isResizeInitialized = false;
};
/**
* For internal use only - Initialize the event handler;
*
* @returns {void}
* @hidden
* @private
*/
RichTextEditor.prototype.preRender = function () {
this.initializeValue();
this.clickPoints = { clientX: 0, clientY: 0 };
this.initialValue = this.value;
this.serviceLocator = new ServiceLocator;
this.initializeServices();
this.setContainer();
this.persistData();
setStyleAttribute(this.element, { 'width': formatUnit(this.width) });
attributes(this.element, { role: 'application', 'aria-label': 'Rich Text Editor' });
this.beforeRenderClassValue = this.element.getAttribute('class');
};
RichTextEditor.prototype.persistData = function () {
if (this.enablePersistence && this.originalElement.tagName === 'TEXTAREA') {
this.element.id = this.originalElement.id + '_wrapper';
var data = window.localStorage.getItem(this.getModuleName() + this.element.id);
if (!(isNOU(data) || (data === ''))) {
this.setProperties(JSON.parse(data), true);
}
}
};
RichTextEditor.prototype.setContainer = function () {
this.originalElement = this.element.cloneNode(true);
if (this.value === null || this.valueTemplate !== null) {
this.setValue();
}
if (this.element.hasAttribute('tabindex')) {
this.htmlAttributes = { 'tabindex': this.element.getAttribute('tabindex') };
this.element.removeAttribute('tabindex');
}
this.element.innerHTML = '';
var invalidAttr = ['class', 'style', 'id', 'ejs-for'];
var htmlAttr = {};
for (var a = 0; a < this.element.attributes.length; a++) {
if (invalidAttr.indexOf(this.element.attributes[a].name) === -1 &&
!(/^data-val/.test(this.element.attributes[a].name))) { // data-val for asp.net core data annotation validation.
htmlAttr[this.element.attributes[a].name] = this.element.getAttribute(this.element.attributes[a].name);
}
}
extend(htmlAttr, this.htmlAttributes, htmlAttr);
this.setProperties({ htmlAttributes: htmlAttr }, true);
if (!isNOU(this.htmlAttributes.id)) {
this.element.id = this.htmlAttributes.id;
}
this.internalID = this.element.id;
if (this.element.tagName === 'TEXTAREA') {
var rteOuterWrapper = this.createElement('div', {
className: this.element.getAttribute('class')
});
this.element.innerHTML = '';
this.element.parentElement.insertBefore(rteOuterWrapper, this.element);
this.valueContainer = this.element;
removeClass([this.valueContainer], this.element.getAttribute('class').split(' '));
this.element = rteOuterWrapper;
}
else {
this.valueContainer = this.createElement('textarea', {
id: this.getID() + '-value',
attrs: { 'aria-labelledby': this.getID() }
});
}
this.valueContainer.name = this.getID();
addClass([this.valueContainer], classes.CLS_RTE_HIDDEN);
if (!isNOU(this.cssClass)) {
var currentClassList = this.cssClass.split(' ');
for (var i = 0; i < currentClassList.length; i++) {
addClass([this.valueContainer], currentClassList[i]);
}
}
this.rootContainer = this.createElement('div', { className: classes.CLS_RTE_CONTAINER, attrs: { 'role': 'presentation' } });
this.element.appendChild(this.rootContainer);
this.rootContainer.appendChild(this.valueContainer);
};
/**
* getPersistData method
*
* @returns {void}
* @hidden
*/
RichTextEditor.prototype.getPersistData = function () {
return this.addOnPersist(['value']);
};
/**
* Focuses the Rich Text Editor component.
*
* @returns {void}
* @public
*/
RichTextEditor.prototype.focusIn = function () {
if (this.enabled) {
this.inputElement.focus();
this.focusHandler({});
this.notify(events.toolbarRefresh, {});
}
};
/**
* Blurs the Rich Text Editor component, removing focus.
*
* @returns {void}
* @public
*/
RichTextEditor.prototype.focusOut = function () {
if (this.enabled) {
this.inputElement.blur();
this.blurHandler({});
}
};
/**
* Selects all content within the RichTextEditor.
*
* @returns {void}
* @public
*/
RichTextEditor.prototype.selectAll = function () {
this.notify(events.selectAll, {});
};
/**
* Selects a specific content range or element.
*
* @param {Range} range - Specify the range you want to select within the content.
* This method is used to select a particular sentence, word, or the entire document.
*
* @returns {void}
* @public
*/
RichTextEditor.prototype.selectRange = function (range) {
this.notify(events.selectRange, { range: range });
};
/**
* Retrieves the HTML markup from the currently selected content in RichTextEditor.
*
* @returns {string} - Returns the HTML string of selected content.
* @public
*/
RichTextEditor.prototype.getSelection = function () {
var str = '';
this.notify(events.getSelectedHtml, {
callBack: function (txt) {
str = txt;
}
});
return str;
};
/**
* Displays the emoji picker. If coordinates are provided, it positions the picker at those locations.
*
* @param {number} x - The x-axis position for the emoji picker.
* @param {number} y - The y-axis position for the emoji picker.
* @returns {void}
* @public
*/
RichTextEditor.prototype.showEmojiPicker = function (x, y) {
if (this.readonly) {
return;
}
this.notify(events.emojiPicker, { x: x, y: y });
};
/**
* Executes a specified command within the rich text editor, optionally utilizing additional parameters to tailor execution.
*
* @returns {void}
* @param {CommandName} commandName - The name of the command to be executed, such as 'importWord', 'insertHTML', and others.
* @param {string | HTMLElement | ILinkCommandsArgs | IImageCommandsArgs | ITableCommandsArgs | FormatPainterSettingsModel | IAudioCommandsArgs | IVideoCommandsArgs} value
* - An optional parameter that supplies the necessary value relevant to the command. This could be a string, an HTMLElement, or specific argument types like ILinkCommandsArgs, etc., contingent on the command requirements.
* @param {ExecuteCommandOption} option - Specifies additional options for executing the command, such as enabling features like undo functionality.
* @public
*/
RichTextEditor.prototype.executeCommand = function (commandName, value, option) {
if (commandName === 'importWord') {
var importContainer = this.createElement('div');
importContainer.innerHTML = value;
var tableElement = importContainer.querySelectorAll('table:not(.e-rte-table):not(.e-rte-paste-table)');
for (var i = 0; i < tableElement.length; i++) {
tableElement[i].classList.add('e-rte-paste-table');
}
value = importContainer.innerHTML;
importContainer.remove();
commandName = 'insertHTML';
}
value = this.htmlPurifier(commandName, value);
var internalValue;
if (this.editorMode === 'HTML') {
var range = this.getRange();
if (this.iframeSettings.enable) {
this.formatter.editorManager.nodeSelection.Clear(this.element.ownerDocument);
}
var toFocus = (this.iframeSettings.enable &&
range.startContainer === this.inputElement) ? true : !this.inputElement.contains(range.startContainer);
if (this.iframeSettings.enable) {
toFocus = true;
}
if (toFocus) {
this.focusIn();
}
}
var tool = executeGroup["" + commandName];
if (option && option.undo) {
if (option.undo && this.formatter.getUndoRedoStack().length === 0) {
this.formatter.saveData();
}
}
if (this.maxLength !== -1 && !isNOU(tool.command)) {
var currentInsertContentLength = 0;
if (tool.command === 'Links') {
currentInsertContentLength = value.text.length === 0 ?
value.url.length : value.text.length;
}
if (tool.command === 'Images' || tool.command === 'Table' || tool.command === 'Files') {
currentInsertContentLength = 1;
}
if (tool.command === 'InsertHTML') {
if (!isNOU(value)) {
var tempElem = this.createElement('div');
tempElem.innerHTML = value;
currentInsertContentLength = tempElem.textContent.length;
}
else if (!isNOU(tool.value) && (tool.value === '<hr/>' || tool.value === '<br/>')) {
currentInsertContentLength = 1;
}
}
if (tool.command === 'InsertText') {
currentInsertContentLength = value.length;
}
var currentLength = this.getText().trim().replace(/(\r\n|\n|\r|\t)/gm, '').replace(/\u200B/g, '').length;
var selectionLength = this.getSelection().length;
var totalLength = (currentLength - selectionLength) + currentInsertContentLength;
if (!(this.maxLength === -1 || totalLength <= this.maxLength)) {
return;
}
}
internalValue = value;
if (tool.command === 'FormatPainter') {
if (!isNOU(value)) {
this.formatPainterSettings = value;
}
internalValue = {
formatPainterAction: tool.value
};
}
if (tool.command === 'lineHeight') {
internalValue = { selectedValue: (value ? value : tool.value) };
}
if (tool.command === 'CodeBlock' && !isNOU(value)) {
value.action = 'createCodeBlock';
}
if ((tool.subCommand === 'NumberFormatList' || tool.subCommand === 'BulletFormatList')) {
internalValue = { listStyle: value, type: tool.subCommand };
}
this.formatter.editorManager.execCommand(tool.command, tool.subCommand ? tool.subCommand : (internalValue ? internalValue : tool.value), null, null, (internalValue ? internalValue : tool.value), (internalValue ? internalValue : (tool.value === 'UL' || tool.value === 'OL') ? null : tool.value), null, this.enterKey);
scrollToCursor(this.contentModule.getDocument(), this.inputElement);
if (option && option.undo) {
this.formatter.saveData();
this.formatter.enableUndo(this);
}
this.setPlaceHolder();
this.notify(events.contentChanged, {});
};
RichTextEditor.prototype.htmlPurifier = function (command, value) {
if (this.editorMode === 'HTML') {
switch (command) {
case 'insertHTML':
if (this.enableHtmlSanitizer) {
if (typeof value === 'string') {
value = value.replace(/&(times|divide|ne)/g, '&amp;$1');
value = this.htmlEditorModule.sanitizeHelper(value);
}
else {
value = this.htmlEditorModule.sanitizeHelper(value.outerHTML);
}
}
break;
case 'insertTable':
if (isNOU(value.width)) {
value.width = {
minWidth: this.tableSettings.minWidth,
maxWidth: this.tableSettings.maxWidth, width: this.tableSettings.width
};
}
break;
case 'insertImage': {
var temp = this.createElement('img', {
attrs: {
src: value.url
}
});
var imageValue = temp.outerHTML;
if (this.enableHtmlSanitizer) {
imageValue = this.htmlEditorModule.sanitizeHelper(temp.outerHTML);
}
var url = (imageValue !== '' && (this.createElement('div', {
innerHTML: imageValue
}).firstElementChild).getAttribute('src')) || null;
url = !isNOU(url) ? url : '';
value.url = url;
if (isNOU(value.width)) {
value.width = {
minWidth: this.insertImageSettings.minWidth,
maxWidth: this.insertImageSettings.maxWidth, width: this.insertImageSettings.width
};
}
if (isNOU(value.height)) {
value.height = {
minHeight: this.insertImageSettings.minHeight,
maxHeight: this.insertImageSettings.maxHeight, height: this.insertImageSettings.height
};
}
break;
}
case 'insertAudio': {
var wrapTemp = this.createElement('audio', {
attrs: {
controls: ''
}
});
var temp = this.createElement('source', {
attrs: {
src: value.url,
type: value.url && value.url.split('.').length > 0
? 'audio/' + value.url.split('.')[value.url.split('.').length - 1] : ''
}
});
wrapTemp.appendChild(temp);
var audioValue = wrapTemp.outerHTML;
if (this.enableHtmlSanitizer) {
audioValue = this.htmlEditorModule.sanitizeHelper(wrapTemp.outerHTML);
}
var url = (audioValue !== '' && (this.createElement('div', {
innerHTML: audioValue
}).firstElementChild.firstElementChild).getAttribute('src')) || null;
url = !isNOU(url) ? url : '';
value.url = url;
break;
}
case 'insertVideo': {
var wrapTemp = this.createElement('video', {
attrs: {
controls: ''
}
});
var temp = this.createElement('source', {
attrs: {
src: value.url,
type: value.url && value.url.split('.').length > 0
? 'video/' + value.url.split('.')[value.url.split('.').length - 1] : ''
}
});
wrapTemp.appendChild(temp);
var audioValue = wrapTemp.outerHTML;
if (this.enableHtmlSanitizer) {
audioValue = this.htmlEditorModule.sanitizeHelper(temp.outerHTML);
}
var url = (audioValue !== '' && (this.createElement('div', {
innerHTML: audioValue
}).firstElementChild).getAttribute('src')) || null;
url = !isNOU(url) ? url : '';
value.url = url;
if (isNOU(value.width)) {
value.width = {
minWidth: this.insertVideoSettings.minWidth,
maxWidth: this.insertVideoSettings.maxWidth, width: this.insertVideoSettings.width
};
}
if (isNOU(value.height)) {
value.height = {
minHeight: this.insertVideoSettings.minHeight,
maxHeight: this.insertVideoSettings.maxHeight, height: this.insertVideoSettings.height
};
}
break;
}
case 'createLink': {
var tempNode = this.createElement('a', {
attrs: {
href: value.url
}
});
var linkValue = tempNode.outerHTML;
if (this.enableHtmlSanitizer) {
linkValue = this.htmlEditorModule.sanitizeHelper(tempNode.outerHTML);
}
var href = (linkValue !== '' && (this.createElement('div', {
innerHTML: linkValue
}).firstElementChild).getAttribute('href')) || null;
href = !isNOU(href) ? href : '';
value.url = href;
break;
}
}
}
return value;
};
RichTextEditor.prototype.encode = function (value) {
var divNode = this.createElement('div');
divNode.innerText = value.trim();
// eslint-disable-next-line
return divNode.innerHTML.replace(/<br\s*[\/]?>/gi, '\n');
};
/**
* For internal use only - To Initialize the component rendering.
*
* @returns {void}
* @private
*/
RichTextEditor.prototype.render = function () {
this.setProperties({ value: this.replaceEntities(this.value) }, true);
if (this.value && !this.valueTemplate) {
this.setProperties({ value: this.serializeValue(this.value) }, true);
}
this.value = (!(this.editorMode === 'Markdown') && !isNOU(this.value)) ? this.addAnchorAriaLabel(this.value) : this.value;
this.renderModule = new Render(this, this.serviceLocator);
this.sourceCodeModule = new ViewSource(this, this.serviceLocator);
this.notify(events.initialLoad, {});
this.trigger(events.load);
this.RTERender();
// eslint-disable-next-line
var execCommandCallBack = new ExecCommandCallBack(this);
if (this.element.dataset.rteUnitTesting === 'true') {
this.userAgentData = new CustomUserAgentData(Browser.userAgent, true);
}
else {
this.userAgentData = new CustomUserAgentData(Browser.userAgent, false);
}
this.notify(events.initialEnd, {});
if (this.enableXhtml) {
this.value = getStructuredHtml(cleanHTMLString(this.value, this.element), this.enterKey, this.enableHtmlEncode);
this.setProperties({ value: this.getXhtml() });
}
if (this.toolbarSettings.enable && (this.toolbarSettings.type === 'Expand' || this.toolbarSettings.type === 'MultiRow' || this.toolbarSettings.type === 'Scrollable') && !isNOU(this.getToolbar()) &&
(this.toolbarSettings.items.indexOf('Undo') > -1 && this.toolbarSettings.items.indexOf('Redo') > -1)) {
this.disableToolbarItem(['Undo', 'Redo']);
}
if (this.value !== null) {
this.valueContainer.defaultValue = this.value;
}
// eslint-disable-next-line
(this.enabled && !this.readonly) ? this.eventInitializer() : this.unWireEvents();
this.notify(events.bindCssClass, { cssClass: this.getCssClass() });
this.addAudioVideoWrapper();
this.notify(events.tableclass, {});
this.autoResize();
this.renderComplete();
};
/**
* addAudioVideoWrapper method
*
* @returns {void}
* @hidden
*/
RichTextEditor.prototype.addAudioVideoWrapper = function () {
var _this = this;
var insertElem;
var audioElm = this.element.querySelectorAll('audio');
for (var i = 0; i < audioElm.length; i++) {
if (!audioElm[i].classList.contains('e-rte-audio')) {
audioElm[i].classList.add('e-rte-audio');
audioElm[i].classList.add(classes.CLS_AUDIOINLINE);
}
// eslint-disable-next-line max-len
if (!audioElm[i].parentElement.classList.contains(classes.CLS_CLICKELEM) && !audioElm[i].parentElement.classList.contains(classes.CLS_AUDIOWRAP)) {
var audioWrapElem = this.createElement('span', { className: classes.CLS_AUDIOWRAP });
var csstext = 'width:300px; margin:0 auto;';
updateCSSText(audioWrapElem, csstext);
audioWrapElem.contentEditable = 'false';
var audioInnerWrapElem = this.createElement('span', { className: classes.CLS_CLICKELEM });
audioWrapElem.appendChild(audioInnerWrapElem);
audioElm[i].parentNode.insertBefore(audioWrapElem, audioElm[i].nextSibling);
audioInnerWrapElem.appendChild(audioElm[i]);
if (audioWrapElem.nextElementSibling === null) {
insertElem = this.createElement('br');
audioWrapElem.parentNode.insertBefore(insertElem, audioWrapElem.nextSibling);
}
}
}
var videoElm = this.element.querySelectorAll('video');
for (var i = 0; i < videoElm.length; i++) {
if (!videoElm[i].classList.contains('e-rte-video')) {
videoElm[i].classList.add('e-rte-video');
videoElm[i].classList.add(classes.CLS_VIDEOINLINE);
}
// eslint-disable-next-line max-len
if (!videoElm[i].parentElement.classList.contains(classes.CLS_CLICKELEM) && !videoElm[i].parentElement.classList.contains(classes.CLS_VIDEOWRAP)) {
var videoWrapElem = this.createElement('span', { className: classes.CLS_VIDEOWRAP });
videoWrapElem.contentEditable = 'false';
videoElm[i].parentNode.insertBefore(videoWrapElem, videoElm[i].nextSibling);
videoWrapElem.appendChild(videoElm[i]);
if (videoWrapElem.nextElementSibling === null) {
insertElem = this.createElement('br');
videoWrapElem.parentNode.insertBefore(insertElem, videoWrapElem.nextSibling);
}
}
if (Browser.userAgent.indexOf('Firefox') !== -1) {
// eslint-disable-next-line
videoElm[i].addEventListener('play', function (args) {
_this.notify(events.mouseDown, { args: args });
_this.notify('editAreaClick', { args: args });
});
// eslint-disable-next-line
videoElm[i].addEventListener('pause', function (args) {
_this.notify(events.mouseDown, { args: args });
_this.notify('editAreaClick', { args: args });
});
}
}
};
/**
* For internal use only - Initialize the event handler
*
* @returns {void}
* @private
* @hidden
*/
RichTextEditor.prototype.eventInitializer = function () {
this.wireEvents();
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
RichTextEditor.prototype.cleanList = function (e) {
var range = this.getRange();
var currentStartContainer = range.startContainer;
var currentEndContainer = range.endContainer;
var currentStartOffset = range.startOffset;
var isSameContainer = currentStartContainer === currentEndContainer ? true : false;
// eslint-disable-next-line
var currentEndOffset = currentEndContainer.textContent.length;
var endNode = range.endContainer.nodeName === '#text' ? range.endContainer.parentElement :
range.endContainer;
var closestLI = closest(endNode, 'LI');
var isDetached = false;
var currentRangeEndOffset = range.endOffset;
if (currentEndContainer.nodeType === Node.TEXT_NODE) {
if (currentEndContainer.textContent.charAt(currentRangeEndOffset - 1) === '\uFEFF') {
currentRangeEndOffset--;
}
}
if (!isNOU(closestLI) && endNode.textContent.trim().length === currentRangeEndOffset &&
!range.collapsed && isNOU(endNode.nextElementSibling) && !endNode.classList.contains(classes.CLS_IMG_INNER)) {
for (var i = 0; i < closestLI.childNodes.length; i++) {
if (closestLI.childNodes[i].nodeName === '#text' && closestLI.childNodes[i].textContent.trim().length === 0) {
detach(closestLI.childNodes[i]);
isDetached = true;
i--;
}
}
var currentLastElem = closestLI;
while (currentLastElem.lastChild !== null && currentLastElem.nodeName !== '#text') {
currentLastElem = currentLastElem.lastChild;
}
if (isDetached) {
var currentLast = currentLastElem.nodeName === 'BR' && !isNOU(currentLastElem.previousSibling) ?
currentLastElem.previousSibling : currentLastElem;
this.formatter.editorManager.nodeSelection.setSelectionText(this.contentModule.getDocument(), isSameContainer ? currentLast : currentStartContainer, currentLast, currentStartOffset, (currentLast.nodeName === 'BR' ? 0 : currentLast.textContent.length));
}
}
};
/**
* For internal use only - keydown the event handler;
*
* @param {KeyboardEvent} e - specifies the event.
* @returns {void}
* @private
* @hidden
*/
RichTextEditor.prototype.keyDown = function (e) {
this.isSelectionStartInRTE = true;
var isMacDev = this.userAgentData.getPlatform() === 'macOS';
if (((e.ctrlKey || (e.metaKey && isMacDev)) && e.shiftKey && e.keyCode === 86) ||
(e.metaKey && isMacDev && e.altKey && e.shiftKey && e.keyCode === 86)) {
this.isPlainPaste = true;
}
if (this.inputElement.classList.contains('e-mention')) {
var mentionPopup = this.element.ownerDocument.getElementById(this.inputElement.id + '_popup');
var slashMenuPopup = this.element.ownerDocument.getElementById(this.inputElement.id + '_slash_menu_popup');
var mentionKeys = mentionRestrictKeys;
var isMentionKeys = mentionKeys.indexOf(e.key) !== -1;
var isMentionPopupOpen = mentionPopup && mentionPopup.classList.contains('e-popup-open');
var isSlashMenuPopupOpen = slashMenuPopup && slashMenuPopup.classList.contains('e-popup-open');
if (isMentionKeys && (isMentionPopupOpen || isSlashMenuPopupOpen)) {
return;
}
}
if (this.editorMode === 'HTML' && !isNOU(this.codeBlockModule)) {
var rangeForCodeBlock = this.getRange();
if (this.formatter.editorManager.codeBlockObj.isActionDisallowedInCodeBlock(e, rangeForCodeBlock)) {
e.preventDefault();
return;
}
}
if (this.enableTabKey) {
if (this.quickToolbarModule && !e.altKey && e.key !== 'F10' && e.action !== 'toolbar-focus') {
this.quickToolbarModule.hideQuickToolbars();
}
var isImageResize = this.imageModule && this.imageModule.imgResizeDiv ? true : false;
var isVideoResize = this.videoModule && this.videoModule.vidResizeDiv ? true : false;
if (isImageResize) {
this.imageModule.cancelResizeAction();
}
if (isVideoResize) {
this.videoModule.cancelResizeAction();
}
}
var isCodeBlockEnter = false;
if (!isNOU(this.codeBlockModule)) {
var range = this.getRange();
isCodeBlockEnter = this.formatter.editorManager.codeBlockObj.isCodeBlockEnterAction(range, e);
}
this.notify(events.keyDown, { member: 'keydown', args: e });
this.restrict(e);
if (this.editorMode === 'HTML') {
this.cleanList(e);
}
if (this.editorMode === 'HTML' && ((e.which === 8 && e.code === 'Backspace') || (e.which === 46 && e.code === 'Delete'))) {
var range = this.getRange();
var startNode = range.startContainer.nodeName === '#text' ? range.startContainer.parentElement :
range.startContainer;
if (closest(startNode, 'pre') &&
(e.which === 8 && range.startContainer.textContent.charCodeAt(range.startOffset - 1) === 8203) ||
(e.which === 46 && range.startContainer.textContent.charCodeAt(range.startOffset) === 8203)) {
var regEx = new RegExp('\u200B', 'g');
var pointer = e.which === 8 ? range.startOffset - 1 : range.startOffset;
range.startContainer.textContent = range.startContainer.textContent.replace(regEx, '');
this.formatter.editorManager.nodeSelection.setCursorPoint(this.contentModule.getDocument(), range.startContainer, pointer);
}
else if ((e.code === 'Backspace' && e.which === 8) &&
range.startContainer.textContent.charCodeAt(0) === 8203 && range.collapsed) {
var parentEle = range.startContainer.parentElement;
var index = void 0;
var i = void 0;
for (i = 0; i < parentEle.childNodes.length; i++) {
if (parentEle.childNodes[i] === range.startContainer) {
index = i;
}
}
var bool = true;
var removeNodeArray = [];
for (i = index; i >= 0; i--) {
// eslint-disable-next-line max-len
if (parentEle.childNodes[i].nodeType === 3 && parentEle.childNodes[i].textContent.charCodeAt(0) === 8203 && bool) {
removeNodeArray.push(i);
}
else {
bool = false;
}
}
if (removeNodeArray.length > 0) {
for (i = removeNodeArray.length - 1; i > 0; i--) {
parentEle.childNodes[removeNodeArray[i]].textContent = '';
}
}
this.formatter.editorManager.nodeSelection.setCursorPoint(this.contentModule.getDocument(), range.startContainer, range.startOffset);
}
}
var notFormatPainterCopy = isNOU(e.action) ? true : (e.action !== 'format-copy' ? true : false);
if (this.formatter.getUndoRedoStack().length === 0 && notFormatPainterCopy &&
!(e.altKey || (e.shiftKey && e.which === 16) || (e.altKey && e.shiftKey && e.which === 67))) {
this.formatter.saveData();
}
var preventingMention = false;
var allowInsideCodeBlock = true;
if (this.editorMode === 'HTML') {
var range = this.getRange();
preventingMention = !isNOU(range.startContainer) && range.startContainer === range.endContainer && range.endContainer.childNodes.length > 1 && !isNOU(range.startContainer.childNodes[range.startOffset - 1]) && range.startContainer.childNodes[range.startOffset - 1].nodeName === '#text' && !isNOU(range.startContainer.childNodes[range.startOffset - 1].previousSibling) && range.startContainer.childNodes[range.startOffset - 1].textContent.charCodeAt(0) === 32 && range.startContainer.childNodes[range.startOffset - 1].previousSibling.nodeName !== '#text' && range.startContainer.childNodes[range.startOffset - 1].previousSibling.classList.contains('e-mention-chip');
if (!isNOU(this.codeBlockModule)) {
var startInCodeBlock = this.formatter.editorManager.codeBlockObj.isValidCodeBlockStructure(range.startContainer);
var endInCodeBlock = this.formatter.editorManager.codeBlockObj.isValidCodeBlockStructure(range.endContainer);
var codeBlockElement = !isNOU(startInCodeBlock) || !isNOU(endInCodeBlock);
if (codeBlockElement) {
var currentAction = e.action;
var allowActions = ['undo', 'redo', 'indents', 'outdents', 'ordered-list', 'unordered-list'];
allowInsideCodeBlock = allowActions.indexOf(currentAction) !== -1;
}
}
}
var keyboardEventAction = ['insert-link', 'format-copy', 'format-paste', 'insert-image', 'insert-table', 'insert-audio', 'insert-video'];
if (keyboardEventAction.indexOf(e.action) === -1 &&
(!e.target || !(e.target.classList.contains('e-mention') && !isNOU(document.querySelector('#' + e.target.id + '_popup.e-popup-open')) && e.code === 'Tab')) &&
(e.action && e.action !== 'paste' && e.action !== 'space'
|| e.which === 9 || (e.code === 'Backspace' && e.which === 8)) && !preventingMention) {
var FormatPainterEscapeAction = false;
if (!isNOU(this.formatPainterModule)) {
FormatPainterEscapeAction = this.formatPainterModule.previousAction === 'escape';
}
var isUndoRedoAction = e.action === 'undo' || e.action === 'redo';
if ((!FormatPainterEscapeAction || isUndoRedoAction) && allowInsideCodeBlock && !isCodeBlockEnter) {
if (this.editorMode === 'HTML' && (e.action === 'increase-fontsize' || e.action === 'decrease-fontsize')) {
this.notify(events.onHandleFontsizeChange, { member: 'onHandleFontsizeChange', args: e });
}
else {
this.formatter.process(this, null, e);
}
}
switch (e.action) {
case 'toolbar-focus':
if (this.toolbarSettings.enable && this.getToolbarElement()) {
if (this.userAgentData.isSafari() && e.type === 'keydown' && this.formatter.editorManager.nodeSelection &&
this.formatter.editorManager.nodeSelection.get(this.contentModule.getDocument()).rangeCount > 0 &&
this.inputElement.contains(this.getRange().startContainer)) {
this.notify(events.selectionSave, {});
}
var toolbarFocusType = 'toolbar';
var firstActiveItem = this.getToolbarElement().querySelector('.e-toolbar-item:not(.e-overlay)[title]');
var quickToolbarElem = this.getRenderedQuickToolbarElem();
if (quickToolbarElem) {
firstActiveItem = quickToolbarElem.querySelector('.e-toolbar-item:not(.e-overlay)[title]');
toolbarFocusType = 'quickToolbar';
}
if (firstActiveItem) {
var firstChild = firstActiveItem.firstElementChild;
firstChild.removeAttribute('tabindex');
firstChild.focus();
if (this.userAgentData.isSafari() && (toolbarFocusType === 'toolbar' || toolbarFocusType === 'quickToolbar')) {
this.inputElement.ownerDocument.getSelection().removeAllRanges();
}
}
}
break;
case 'escape':
this.contentModule.getEditPanel().focus();
break;
}
}
this.notify(events.afterKeyDown, { member: 'afterKeyDown', args: e });
this.autoResize();
if (!isNOU(this.placeholder)) {
this.setPlaceHolder();
}
if (this.editorMode === 'HTML' && !isNOU(e) && !isNOU(e.code) && (e.code === 'Backspace' || e.code === 'Delete')) {
if (this.isEntireRTEContentSelected()) {
this.isCopyAll = true;
}
}
// Cmd + Backspace triggers only the keydown event; the keyup event is not triggered.
if (e.metaKey && e.key === 'Backspace' && this.autoSaveOnIdle) {
this.keyUp(e);
}
if (this.editorMode === 'HTML') {
var selection = this.contentModule.getDocument().getSelection();
var range = selection && selection.getRangeAt(0);
this.previousRange = range && range.cloneRange();
}
};
// Clear selection timeout for keyup event triggering
RichTextEditor.prototype.clearSelectionTimeout = function () {
if (this.selectionTimeout) {
clearTimeout(this.selectionTimeout);
this.selectionTimeout = null;
}
};
// Triggers the selectionChanged event
RichTextEditor.prototype.triggerSelectionChanged = function () {
var selection = this.contentModule.getDocument().getSelection();
var currentRange = selection && selection.rangeCount > 0 && selection.getRangeAt(0);
if (!this.isSelectionCollapsed()) {
var isSamerange = this.previousRange &&
(this.previousRange.startContainer === currentRange.startContainer
&& this.previousRange.endContainer === currentRange.endContainer
&& this.previousRange.startOffset === currentRange.startOffset
&& this.previousRange.endOffset === currentRange.endOffset);
if (!isSamerange) {
var selectionArgs = {
selectedContent: this.getSelectedHtml(),
selection: selection,
editorMode: this.editorMode
};
this.trigger(events.selectionChanged, selectionArgs);
this.previousRange = currentRange.cloneRange();
}
}
};
RichTextEditor.prototype.keyUp = function (e) {
var _this = this;
if (this.inputElement.classList.contains('e-mention')) {
var mentionPopup = this.element.ownerDocument.getElementById(this.inputElement.id + '_popup');
var slashMenuPopup = this.element.ownerDocument.getElementById(this.inputElement.id + '_slash_menu_popup');
var isMentionPopupOpen = mentionPopup && mentionPopup.classList.contains('e-popup-open');
var isSlashMenuPopupOpen = slashMenuPopup && slashMenuPopup.classList.contains('e-popup-open');
if ((isMentionPopupOpen || isSlashMenuPopupOpen)) {
return;
}
}
if (this.editorMode === 'HTML') {
var range = this.getRange();
if (!isNOU(e) && !isNOU(e.code) && (e.code === 'Backspace' || e.code === 'Delete' || e.code === 'KeyX')) {
// To prevent the reformatting the content removed browser behavior.
var currentRange = this.getRange();
var selection = this.iframeSettings.enable ? this.contentModule.getPanel().ownerDocument.getSelection() :
this.contentModule.getDocument().getSelection();
if (this.isCopyAll) {
var brElement = this.createElement('br');
var newElement = this.enterKey === 'BR' ? brElement : this.createElement(this.enterKey).appendChild(brElement).parentElement;
this.inputElement.innerHTML = '';
this.inputElement.append