@syncfusion/ej2-richtexteditor
Version:
Essential JS 2 RichTextEditor component
1,074 lines • 65.6 kB
JavaScript
import * as events from '../base/constant';
import { Popup } from '@syncfusion/ej2-popups';
import { RadioButton } from '@syncfusion/ej2-buttons';
import { isNullOrUndefined as isNOU, isNullOrUndefined, detach, extend, addClass, removeClass, getComponent, createElement } from '@syncfusion/ej2-base';
import { getUniqueID, Browser, closest } from '@syncfusion/ej2-base';
import { CLS_RTE_PASTE_KEEP_FORMAT, CLS_RTE_PASTE_REMOVE_FORMAT, CLS_RTE_PASTE_PLAIN_FORMAT } from '../base/classes';
import { CLS_RTE_PASTE_OK, CLS_RTE_PASTE_CANCEL, CLS_RTE_DIALOG_MIN_HEIGHT } from '../base/classes';
import { NodeSelection } from '../../selection/selection';
import * as EVENTS from './../../common/constant';
import { RenderType } from '../base/enum';
import { ImageInputSource } from '../../common/enum';
import { Uploader } from '@syncfusion/ej2-inputs';
import * as classes from '../base/classes';
import { sanitizeHelper } from '../base/util';
import { cleanHTMLString, getStructuredHtml, scrollToCursor, isBlockNode } from '../../common/util';
import { PasteCleanupAction } from '../../editor-manager/plugin/paste-clean-up-action';
import { PASTE_SOURCE } from './../../editor-manager/base';
/**
* PasteCleanup module called when pasting content in RichTextEditor
*/
var PasteCleanup = /** @class */ (function () {
function PasteCleanup(parent, serviceLocator) {
this.isNotFromHtml = false;
this.containsHtml = false;
this.cropImageData = [];
this.plainTextContent = '';
this.pendingPasteQueue = [];
this.validFiles = [];
this.parent = parent;
this.locator = serviceLocator;
this.renderFactory = this.locator.getService('rendererFactory');
this.i10n = serviceLocator.getService('rteLocale');
this.dialogRenderObj = serviceLocator.getService('dialogRenderObject');
this.addEventListener();
this.isDestroyed = false;
}
PasteCleanup.prototype.addEventListener = function () {
this.nodeSelectionObj = new NodeSelection(this.parent.inputElement);
if (this.parent.isDestroyed) {
return;
}
this.parent.on(events.pasteClean, this.pasteClean, this);
this.parent.on(events.bindOnEnd, this.bindOnEnd, this);
this.parent.on(events.bindCssClass, this.setCssClass, this);
this.parent.on(events.destroy, this.destroy, this);
this.parent.on(events.docClick, this.docClick, this);
this.parent.on(events.updateProperty, this.updatePasteCleanupProperty, this);
};
PasteCleanup.prototype.destroy = function () {
if (this.isDestroyed) {
return;
}
if (this.fireFoxUploadTime) {
clearTimeout(this.fireFoxUploadTime);
this.fireFoxUploadTime = null;
}
if (this.refreshPopupTime) {
clearTimeout(this.refreshPopupTime);
this.refreshPopupTime = null;
}
if (this.failureTime) {
clearTimeout(this.failureTime);
this.failureTime = null;
}
this.removeEventListener();
var mediaPopups = this.parent.element.querySelectorAll('.e-rte-upload-popup');
for (var i = 0; i < mediaPopups.length; i++) {
var uploader = this.getUploaderInstance(mediaPopups[i]);
if (uploader && !uploader.isDestroyed) {
uploader.destroy();
}
var popup = getComponent(mediaPopups[i], 'popup');
if (popup && !popup.isDestroyed) {
popup.destroy();
}
}
if (this.keepRadioButton && !this.keepRadioButton.isDestroyed) {
this.keepRadioButton.destroy();
this.keepRadioButton = null;
}
if (this.cleanRadioButton && !this.cleanRadioButton.isDestroyed) {
this.cleanRadioButton.destroy();
this.cleanRadioButton = null;
}
if (this.plainTextRadioButton && !this.plainTextRadioButton.isDestroyed) {
this.plainTextRadioButton.destroy();
this.plainTextRadioButton = null;
}
this.isDestroyed = true;
this.plainTextContent = '';
this.pendingPasteQueue = [];
this.validFiles = [];
};
PasteCleanup.prototype.removeEventListener = function () {
this.parent.off(events.pasteClean, this.pasteClean);
this.parent.off(events.bindCssClass, this.setCssClass);
this.parent.off(events.destroy, this.destroy);
this.parent.off(events.docClick, this.docClick);
this.parent.off(events.bindOnEnd, this.bindOnEnd);
this.parent.off(events.updateProperty, this.updatePasteCleanupProperty);
};
/*
* Initializes the PasteCleanupAction object in the editor manager after editor initialization is complete.
* This method binds the paste cleanup module to the editor's formatter for handling paste cleanup related operations.
*/
PasteCleanup.prototype.bindOnEnd = function () {
if (this.parent.editorMode === 'HTML' && this.parent.formatter && this.parent.formatter.editorManager
&& this.parent.contentModule) {
var pasteModel = this.getPasteCleanupModel();
this.parent.formatter.editorManager.pasteObj = this.pasteObj =
new PasteCleanupAction(this.parent.formatter.editorManager, pasteModel);
}
};
/* Creates and returns a paste cleanup model with editor configuration and callback methods */
PasteCleanup.prototype.getPasteCleanupModel = function () {
var _this = this;
// Create TableCommand with table model containing required methods
var pasteModel = {
rteElement: this.parent.element,
enterKey: this.parent.enterKey,
rootContainer: this.parent.rootContainer,
enableXhtml: this.parent.enableXhtml,
iframeSettings: this.parent.iframeSettings,
pasteCleanupSettings: this.parent.pasteCleanupSettings,
insertImageSettings: this.parent.insertImageSettings,
// Retrieves the maximum allowed width for an image within the editor.
getInsertImgMaxWidth: function () {
return _this.parent.getInsertImgMaxWidth();
},
// Method for retrieving the document object of the content module
getDocument: function () {
if (!_this.contentModule) {
return _this.parent.contentModule.getDocument();
}
return _this.contentModule.getDocument();
},
// Method for retrieving the editable element object of the content module
getEditPanel: function () {
if (!_this.contentModule) {
return _this.parent.contentModule.getEditPanel();
}
return _this.contentModule.getEditPanel();
},
updateValue: function () {
_this.parent.updateValue();
},
imageUpload: function () {
_this.imgUploading(_this.parent.inputElement);
},
mediaUpload: function () {
_this.mediaUploading(_this.parent.inputElement);
},
getCropImageData: function () {
return _this.getCropImageData();
}
};
return pasteModel;
};
/* Updates the paste cleanup object with the latest editor configuration settings */
PasteCleanup.prototype.updatePasteCleanupProperty = function () {
var pasteModel = this.getPasteCleanupModel();
if (!isNullOrUndefined(this.pasteObj)) {
this.pasteObj.updatePasteCleanupModel(pasteModel);
}
};
/**
* Handles the paste cleanup operation when content is pasted into the editor
*
* @param {NotifyArgs} e - The notification arguments containing event data
* @returns {void}
*/
PasteCleanup.prototype.pasteClean = function (e) {
var args = {
requestType: 'Paste',
editorMode: this.parent.editorMode,
event: e
};
var value = null;
var imageproperties;
var allowedTypes = this.parent.insertImageSettings.allowedTypes;
// Extract clipboard data if available
if (e.args && !isNOU(e.args.clipboardData)) {
value = e.args.clipboardData.getData('text/html');
// Store plain text content for later use
if (e.args.clipboardData.getData('text/plain')) {
this.plainTextContent = e.args.clipboardData.getData('text/plain');
}
}
// Process only if we have args, value, and in HTML mode
if (e.args && value !== null && this.parent.editorMode === 'HTML') {
var shouldContinue = this.processHtmlPaste(e, value, args, allowedTypes, imageproperties);
if (!shouldContinue) {
return; // Stop processing if indicated
}
}
};
/* Processes HTML content from paste operation */
PasteCleanup.prototype.processHtmlPaste = function (e, value, args, allowedTypes, imageproperties) {
var processedValue = value;
var shouldContinue = true;
var files = e.args.clipboardData.files;
var elm = createElement('p');
elm.innerHTML = value;
var source = this.findSource(elm);
// Handle empty HTML content (plain text or image)
if (source === 'html' && !isNOU(files) && files.length > 0) {
var result = this.handleFileDataPaste(e, value, args, allowedTypes, imageproperties);
processedValue = result.value;
shouldContinue = result.shouldContinue;
if (!shouldContinue) {
return false; // Stop processing
}
}
else if (value.length > 0) { // Handle non-empty HTML content
processedValue = this.handleHtmlValuePaste(e, value, args);
}
else if (value.length === 0) { // handle for the plain text case
var result = this.handlePlainTextPaste(e, value, args);
processedValue = result.value;
shouldContinue = result.shouldContinue;
if (!shouldContinue) {
return false;
}
}
processedValue = this.handleGoogleDocs(processedValue);
// Remove base tags from content
if (processedValue !== null && processedValue !== '') {
processedValue = processedValue.replace(/<base[^>]*>/g, '');
}
this.prepareAndInsertContent(e, processedValue, args);
return true;
};
// when google docs has b tags wrapped in default need to remove it
PasteCleanup.prototype.handleGoogleDocs = function (processedValue) {
// check if the content is pasted from google docs
if (processedValue && processedValue.indexOf('id="docs-internal-guid') >= 0) {
// remove the docs-internal-guid id attribute entirely
processedValue = processedValue.replace(/\s*id="docs-internal-guid[^"]*"/gi, '');
// check inside the b tags and do manipulation
processedValue = processedValue.replace(/<b\b([^>]*)>([\s\S]*?)<\/b>/gi, function (match, attrs, inner) {
// Look inside the inner HTML for a span with font-weight:700
var hasBoldSpan = /<span[^>]*style=["'][^"']*font-weight\s*:\s*700[^"']*["'][^>]*>/i.test(inner);
// Look inside the inner HTML for a span with font-style:style
var hasItalicSpan = /<span[^>]*style=["'][^"']*font-style\s*:\s*italic[^"']*["'][^>]*>/i.test(inner);
if (hasBoldSpan && hasItalicSpan) {
// Wrap with both <b> and <em>
return "<b><em>" + inner + "</em></b>";
}
if (hasBoldSpan && !hasItalicSpan) {
// keep <b> if the nested span is bold but not italic
return "<b>" + inner + "</b>";
}
if (hasItalicSpan) {
// convert to <em> if the nested span is italic
return "<em>" + inner + "</em>";
}
// otherwise unwrap <b>
return inner;
});
}
return processedValue;
};
PasteCleanup.prototype.findSource = function (element) {
var metaNodes = element.querySelectorAll('meta');
for (var i = 0; i < metaNodes.length; i++) {
var metaNode = metaNodes[i];
var content = metaNode.getAttribute('content');
var name_1 = metaNode.getAttribute('name');
if (name_1 && name_1.toLowerCase().indexOf('generator') >= 0 && content && content.toLowerCase().indexOf('microsoft') >= 0) {
for (var j = 0; j < PASTE_SOURCE.length; j++) {
if (content.toLowerCase().indexOf(PASTE_SOURCE[j]) >= 0) {
return PASTE_SOURCE[j];
}
}
}
}
// Fallback: Check for Excel-specific patterns in HTML structure
if (this.isExcelContent(element) && (this.parent.userAgentData.getBrowser() === 'Safari')) {
return 'excel';
}
return 'html';
};
/* Detects Excel content by checking for Excel-specific HTML patterns */
PasteCleanup.prototype.isExcelContent = function (element) {
// Check for Excel-specific table attributes and styles
var tables = element.querySelectorAll('table');
if (tables.length > 0) {
var table = tables[0];
// Check for Excel-specific style patterns
var style = (table.getAttribute('style') || '').toLowerCase();
if (style.indexOf('border-collapse') >= 0 || style.indexOf('mso-') >= 0) {
return true;
}
}
return false;
};
/* Handles plain text paste with event notification and callback */
PasteCleanup.prototype.handlePlainTextPaste = function (e, value, args) {
var processedValue = value || e.args.clipboardData.getData('text/plain');
var htmlRegex = new RegExp(/<\/[a-z][\s\S]*>/i);
// Trigger beforePasteCleanup event
this.parent.trigger(events.beforePasteCleanup, { value: processedValue }, function (updatedArgs) { processedValue = updatedArgs.value; });
// Escape HTML characters
processedValue = processedValue.replace(/</g, '<');
processedValue = processedValue.replace(/>/g, '>');
// Mark as plain text content
this.plainTextContent = processedValue;
// Notify paste event with callback for custom handling
this.parent.notify(events.paste, {
file: null,
args: e.args,
text: processedValue,
callBack: function (b) {
if (typeof (b) === 'string') {
processedValue = b;
}
}
});
// Format plain text with line breaks
if (!htmlRegex.test(processedValue)) {
var divElement = this.parent.createElement('div');
divElement.innerHTML = this.pasteObj.splitBreakLine(processedValue);
processedValue = divElement.innerHTML;
}
return { value: processedValue, shouldContinue: true };
};
/* Handles case when HTML value is empty but may contain plain text or images */
PasteCleanup.prototype.handleFileDataPaste = function (e, value, args, allowedTypes, imageproperties) {
var htmlRegex = new RegExp(/<\/[a-z][\s\S]*>/i);
var processedValue = e.args.clipboardData.getData('text/plain');
this.parent.trigger(events.beforePasteCleanup, { value: processedValue }, function (updatedArgs) { processedValue = updatedArgs.value; });
this.isNotFromHtml = processedValue !== '' ? true : false;
processedValue = processedValue.replace(/</g, '<');
processedValue = processedValue.replace(/>/g, '>');
this.containsHtml = htmlRegex.test(processedValue);
this.plainTextContent = processedValue;
// Collect clipboard files
var clipboardData = e.args.clipboardData;
var clipboardFiles = clipboardData && clipboardData.files && clipboardData.files.length ?
Array.from(clipboardData.files) : [];
var validImages = [];
var validVideos = [];
var validAudios = [];
var audioAllowedTypes = this.parent.insertAudioSettings && this.parent.insertAudioSettings.allowedTypes ?
this.parent.insertAudioSettings.allowedTypes : [];
var videoAllowedTypes = this.parent.insertVideoSettings && this.parent.insertVideoSettings.allowedTypes ?
this.parent.insertVideoSettings.allowedTypes : [];
for (var i = 0; i < clipboardFiles.length; i++) {
var file = clipboardFiles[i];
if (!file) {
continue;
}
var mime = (file.type || '').toLowerCase();
// Image handling: validate against image allowed types
if (mime.indexOf('image/') === 0) {
var imgType = mime.split('/')[1] ? '.' + mime.split('/')[1] : '';
if (this.isInvalidImageType(imgType, allowedTypes)) {
continue;
}
validImages.push(file);
continue;
}
// Video handling: validate against video allowed types
if (mime.indexOf('video/') === 0) {
var isValidVideo = false;
for (var j = 0; j < videoAllowedTypes.length; j++) {
if (mime.endsWith(videoAllowedTypes[j].replace('.', ''))) {
isValidVideo = true;
break;
}
}
if (!isValidVideo) {
continue;
}
validVideos.push(file);
continue;
}
// Audio handling: validate against audio allowed types
if (mime.indexOf('audio/') === 0) {
var isValidAudio = false;
for (var j = 0; j < audioAllowedTypes.length; j++) {
if (mime.endsWith(audioAllowedTypes[j].replace('.', ''))) {
isValidAudio = true;
break;
}
}
if (!isValidAudio) {
continue;
}
validAudios.push(file);
}
}
this.validFiles = validImages;
// Process video files
if (validVideos.length > 0) {
var videoResult = this.processPasteWithMedia('video', validVideos, e, value);
if (!videoResult.shouldContinue) {
return videoResult;
}
}
// Process audio files
if (validAudios.length > 0) {
var audioResult = this.processPasteWithMedia('audio', validAudios, e, value);
if (!audioResult.shouldContinue) {
return audioResult;
}
}
return this.processPasteWithMedia('image', validImages, e, processedValue, args, imageproperties, htmlRegex);
};
// Unified handler for pasting image, audio, or video files.
PasteCleanup.prototype.processPasteWithMedia = function (mediaType, file, e, value, args, imageproperties, htmlRegex) {
var _this = this;
// Media-specific configuration
var mediaConfig = {
image: { event: events.paste, command: 'Images', subCommand: 'Image' },
audio: { event: events.audioPaste, command: 'Audios', subCommand: 'Audio' },
video: { event: events.videoPaste, command: 'Videos', subCommand: 'Video' }
};
var config = mediaConfig[mediaType];
// For audio/video: ensure there are files and track them as valid files
if (mediaType !== 'image') {
var files = file;
if (files.length === 0) {
return { value: value, shouldContinue: true };
}
this.validFiles = files;
}
var processedValue = value;
var mediaproperties = imageproperties;
// Choose the correct formatter callback based on media type
var formatterCallback = mediaType === 'image' ?
this.imageFormatting.bind(this, args) :
this.mediaFormatting.bind(this, e.args);
// Notify the appropriate paste event to let the respective module insert markup
this.parent.notify(config.event, {
file: file,
args: e.args,
text: processedValue,
isWordPaste: mediaType !== 'image' ? false : undefined,
callBack: function (b) {
mediaproperties = b;
if (typeof (mediaproperties) === 'object') {
_this.parent.formatter.editorManager.execCommand(config.command, config.subCommand, e.args, formatterCallback, 'pasteCleanup', mediaproperties, 'pasteCleanupModule');
}
else {
processedValue = mediaproperties;
}
}
});
// Image flow: continue processing, format plain text with line breaks if not HTML
if (mediaType === 'image') {
if (htmlRegex && !htmlRegex.test(processedValue)) {
var divElement = this.parent.createElement('div');
divElement.innerHTML = this.pasteObj.splitBreakLine(processedValue);
processedValue = divElement.innerHTML;
}
return { value: processedValue, shouldContinue: true };
}
// Audio/Video flow: stop further processing
return { value: '', shouldContinue: false };
};
/* Processes and uploads audios from pasted content */
/* Processes and uploads audios from pasted content with base64 sources */
PasteCleanup.prototype.processMediassWithSaveUrl = function (allMediaElm) {
var base64Src = [];
var mediaName = [];
var uploadMedia = [];
// Collect base64 audios
for (var i = 0; i < allMediaElm.length; i++) {
var audioSrc = allMediaElm[i].querySelector('source').src;
if (!isNOU(audioSrc) && audioSrc.split(',')[0].indexOf('base64') >= 0) {
base64Src.push(audioSrc);
if (allMediaElm[i].classList.contains('pasteContent_Audio')) {
mediaName.push(getUniqueID('rte_audio'));
}
if (allMediaElm[i].classList.contains('pasteContent_Video')) {
mediaName.push(getUniqueID('rte_video'));
}
uploadMedia.push(allMediaElm[i]);
}
}
// Convert base64 to files and upload
var fileList = [];
for (var i = 0; i < base64Src.length; i++) {
fileList.push(this.pasteObj.base64ToFile(base64Src[i], mediaName[i]));
}
// Upload each file with opacity effect
for (var i = 0; i < fileList.length; i++) {
var audioSrc = allMediaElm[i].querySelector('source');
this.uploadMethod(fileList[i], audioSrc);
}
};
PasteCleanup.prototype.mediaFormatting = function (pasteArgs, audioElement) {
var mediaELm = audioElement.elements[0];
var mediaValueValue;
if (mediaELm.tagName === 'AUDIO') {
var audioWrapper = createElement('span', { className: classes.CLS_AUDIOWRAP, attrs: { contentEditable: 'false' } });
var audElement = createElement('span', { className: classes.CLS_CLICKELEM });
audioWrapper.appendChild(audElement);
audElement.appendChild(mediaELm);
if (!isNOU(mediaELm.querySelector('source'))) {
audioWrapper.classList.add('pasteContent_Audio');
}
mediaValueValue = audioWrapper.outerHTML;
}
if (mediaELm.tagName === 'VIDEO') {
var videoWrapper = createElement('span', { className: classes.CLS_VIDEOWRAP, attrs: { contentEditable: 'false' } });
var vidElement = createElement('span', { className: classes.CLS_CLICKELEM });
videoWrapper.appendChild(vidElement);
vidElement.appendChild(mediaELm);
if (!isNOU(mediaELm.querySelector('source'))) {
videoWrapper.classList.add('pasteContent_Video');
}
mediaValueValue = videoWrapper.outerHTML;
}
this.contentModule = this.renderFactory.getRenderer(RenderType.Content);
var currentDocument = this.contentModule.getDocument();
var range = this.nodeSelectionObj.getRange(currentDocument);
this.saveSelection = this.nodeSelectionObj.save(range, currentDocument);
var settings = this.parent.pasteCleanupSettings;
// Queue audio similar to image flow so batch insertion and imgUploading() detection works
this.pendingPasteQueue.push(mediaValueValue);
var isAudioQueueCompleted = (this.validFiles.length === 0) || (this.pendingPasteQueue.length === this.validFiles.length);
if (!isAudioQueueCompleted) {
return;
}
var combinedHtml = this.pendingPasteQueue.join('');
if (settings.prompt) {
this.pasteDialog(combinedHtml, pasteArgs);
return;
}
else if (settings.plainText) {
this.plainFormatting(combinedHtml, pasteArgs);
this.pendingPasteQueue = [];
}
else if (settings.keepFormat) {
this.formatting(combinedHtml, false, pasteArgs);
this.pendingPasteQueue = [];
}
else {
this.formatting(combinedHtml, true, pasteArgs);
this.pendingPasteQueue = [];
}
};
/* Checks if image type is not in allowed types */
PasteCleanup.prototype.isInvalidImageType = function (imgType, allowedTypes) {
return allowedTypes.every(function (type) { return type.toLowerCase() !== imgType; });
};
/* Handles non-empty HTML content */
PasteCleanup.prototype.handleHtmlValuePaste = function (e, value, args) {
var _this = this;
var processedValue = value;
this.parent.trigger(events.beforePasteCleanup, { value: processedValue }, function (updatedArgs) { processedValue = updatedArgs.value; });
this.parent.formatter.editorManager.observer.notify(EVENTS.MS_WORD_CLEANUP, {
args: e.args,
text: processedValue,
allowedStylePropertiesArray: this.parent.pasteCleanupSettings.allowedStyleProps,
callBack: function (a, cropImageData, pasteTableSource) {
args.pasteTableSource = pasteTableSource;
processedValue = a.trim();
_this.cropImageData = cropImageData;
}
});
return processedValue;
};
/* Prepares and inserts content into the editor */
PasteCleanup.prototype.prepareAndInsertContent = function (e, value, args) {
this.contentModule = this.renderFactory.getRenderer(RenderType.Content);
var currentDocument = this.contentModule.getDocument();
var range = this.nodeSelectionObj.getRange(currentDocument);
this.saveSelection = this.nodeSelectionObj.save(range, currentDocument);
// Process content through temp div
var tempDivElem = this.parent.createElement('div');
tempDivElem.innerHTML = value;
// Handle unsupported images
this.processUnsupportedImages(tempDivElem);
var processedValue = tempDivElem.innerHTML;
// Check if content is not empty
var isValueNotEmpty = tempDivElem.textContent !== '' ||
!isNOU(tempDivElem.querySelector('img')) ||
!isNOU(tempDivElem.querySelector('table'));
// Clean up resize elements
var finalValue = processedValue;
this.parent.notify(events.cleanupResizeElements, {
value: processedValue,
callBack: function (currentValue) {
finalValue = currentValue;
}
});
// Removes the \n from the value
finalValue = cleanHTMLString(finalValue, this.parent.element);
finalValue = getStructuredHtml(finalValue, this.parent.enterKey, this.parent.enableHtmlEncode, true);
finalValue = this.handleBlockEleInsideInlineEle(finalValue);
// Handle paste based on settings
this.handlePasteBasedOnSettings(e, finalValue, args, isValueNotEmpty);
};
/* When copying and pasting content which has block element inside inline elements */
PasteCleanup.prototype.handleBlockEleInsideInlineEle = function (innerValue) {
// Create a safe wrapper element for HTML manipulation
var tempDiv = document.createElement('div');
tempDiv.innerHTML = innerValue;
var nodes = Array.from(tempDiv.childNodes);
var isBlockInsideInlineEle = false;
for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) {
var child = nodes_1[_i];
if (child.nodeType === Node.ELEMENT_NODE && !isBlockNode(child)) {
var childElement = Array.from(child.childNodes);
for (var _a = 0, childElement_1 = childElement; _a < childElement_1.length; _a++) {
var childrens = childElement_1[_a];
if (isBlockNode(childrens)) {
isBlockInsideInlineEle = true;
}
else {
isBlockInsideInlineEle = false;
}
}
}
}
if (isBlockInsideInlineEle) {
for (var _b = 0, nodes_2 = nodes; _b < nodes_2.length; _b++) {
var child = nodes_2[_b];
if (child.nodeType === Node.ELEMENT_NODE) {
var childElement = child;
while (childElement.firstChild) {
childElement.parentNode.insertBefore(childElement.firstChild, childElement);
}
childElement.remove();
return tempDiv.innerHTML;
}
}
}
return tempDiv.innerHTML;
};
/* Processes unsupported images in pasted content */
PasteCleanup.prototype.processUnsupportedImages = function (tempDivElem) {
var unsupportedImg = tempDivElem.querySelectorAll('.e-rte-image-unsupported');
for (var index = 0; index < unsupportedImg.length; index++) {
unsupportedImg[index].setAttribute('alt', this.i10n.getConstant('unsupportedImage'));
unsupportedImg[index].classList.remove('e-rte-image-unsupported');
}
};
/* Handles paste based on editor settings */
PasteCleanup.prototype.handlePasteBasedOnSettings = function (e, value, args, isValueNotEmpty) {
if (this.parent.pasteCleanupSettings.prompt && !e.isPlainPaste) {
if (isValueNotEmpty) {
e.args.preventDefault();
this.pasteDialog(value, args);
}
}
else if (this.parent.pasteCleanupSettings.plainText) {
e.args.preventDefault();
this.plainFormatting(value, args);
}
else if (this.parent.pasteCleanupSettings.keepFormat || e.isPlainPaste) {
e.args.preventDefault();
this.formatting(value, false, args);
}
else {
e.args.preventDefault();
this.formatting(value, true, args);
}
};
/* Processes and uploads images from pasted content */
PasteCleanup.prototype.imgUploading = function (elm) {
var allImgElm = elm.querySelectorAll('.pasteContent_Img');
// Handle image upload if save URL is configured and images exist
if (this.parent.insertImageSettings && this.parent.insertImageSettings.saveUrl && allImgElm.length > 0) {
this.processImagesWithSaveUrl(allImgElm);
}
else if (this.parent.insertImageSettings && this.parent.insertImageSettings.saveFormat === 'Blob') {
// Convert to blob format if specified
this.pasteObj.getBlob(allImgElm);
}
// Clean up temporary CSS classes from images and audios
this.cleanupMediaClasses(elm, allImgElm);
};
/* Processes and uploads audio and video from pasted content */
PasteCleanup.prototype.mediaUploading = function (elm) {
var allAudioElm = elm.querySelectorAll('.pasteContent_Audio');
var allVideoElm = elm.querySelectorAll('.pasteContent_Video');
// Handle audio upload if save URL is configured and audios exist
if (this.parent.insertAudioSettings && this.parent.insertAudioSettings.saveUrl && allAudioElm.length > 0) {
this.processMediassWithSaveUrl(allAudioElm);
}
else if (this.parent.insertAudioSettings && this.parent.insertAudioSettings.saveFormat === 'Blob') {
// Convert to blob format if specified
this.pasteObj.getBlob(allAudioElm);
}
// Handle audio upload if save URL is configured and audios exist
if (this.parent.insertVideoSettings && this.parent.insertVideoSettings.saveUrl && allVideoElm.length > 0) {
this.processMediassWithSaveUrl(allVideoElm);
}
else if (this.parent.insertVideoSettings && this.parent.insertVideoSettings.saveFormat === 'Blob') {
// Convert to blob format if specified
this.pasteObj.getBlob(allVideoElm);
}
// Clean up temporary CSS classes from videos and audios
this.cleanupMediaClasses(elm, allAudioElm);
this.cleanupMediaClasses(elm, allVideoElm);
};
/* Processes images when save URL is configured */
PasteCleanup.prototype.processImagesWithSaveUrl = function (allImgElm) {
var base64Src = [];
var imgName = [];
var uploadImg = [];
// Collect base64 images
for (var i = 0; i < allImgElm.length; i++) {
var imgSrc = allImgElm[i].getAttribute('src');
if (!isNOU(imgSrc) && imgSrc.split(',')[0].indexOf('base64') >= 0) {
base64Src.push(imgSrc);
imgName.push(getUniqueID('rte_image'));
uploadImg.push(allImgElm[i]);
}
}
// Convert base64 to files
var fileList = [];
for (var i = 0; i < base64Src.length; i++) {
fileList.push(this.pasteObj.base64ToFile(base64Src[i], imgName[i]));
}
// Upload each file
for (var i = 0; i < fileList.length; i++) {
this.uploadMethod(fileList[i], uploadImg[i]);
}
// Convert to blob if needed
if (isNOU(this.parent.insertImageSettings.path) &&
this.parent.insertImageSettings.saveFormat === 'Blob') {
this.pasteObj.getBlob(allImgElm);
}
};
/* Removes temporary CSS classes from processed images */
PasteCleanup.prototype.cleanupMediaClasses = function (elm, allImgElm) {
var allImgElmId = elm.querySelectorAll('.pasteContent_Img');
var allAudioElmId = elm.querySelectorAll('.pasteContent_Audio');
var allVideoElmId = elm.querySelectorAll('.pasteContent_Video');
for (var i = 0; i < allImgElmId.length; i++) {
allImgElmId[i].classList.remove('pasteContent_Img');
// Remove class attribute if empty
if (allImgElmId[i].getAttribute('class').trim() === '') {
allImgElm[i].removeAttribute('class');
}
}
for (var i = 0; i < allAudioElmId.length; i++) {
allAudioElmId[i].classList.remove('pasteContent_Audio');
if (allAudioElmId[i].getAttribute('class').trim() === '') {
allAudioElmId[i].removeAttribute('class');
}
}
for (var i = 0; i < allVideoElmId.length; i++) {
allVideoElmId[i].classList.remove('pasteContent_Video');
if (allVideoElmId[i].getAttribute('class').trim() === '') {
allVideoElmId[i].removeAttribute('class');
}
}
};
/* Enables or disables the toolbar based on state */
PasteCleanup.prototype.toolbarEnableDisable = function (state) {
if (!this.parent.inlineMode.enable && this.parent.toolbarModule && this.parent.toolbarModule.baseToolbar) {
if (state) {
// To disable toolbar items
this.parent.toolbarModule.baseToolbar.toolbarObj.disable(state);
}
else {
var mediaPopups = this.parent.element.querySelectorAll('.e-rte-upload-popup');
if (mediaPopups.length === 0) {
//To enable Toolbar items
this.parent.toolbarModule.baseToolbar.toolbarObj.disable(state);
}
}
}
};
/* Handles the upload process for an image file */
PasteCleanup.prototype.uploadMethod = function (file, mediaElem) {
this.pasteObj.setImageOpacity(mediaElem);
var popupObj;
if (mediaElem.tagName === 'SOURCE') {
popupObj = this.createPopupObject(mediaElem.parentElement, file);
}
else {
popupObj = this.createPopupObject(mediaElem, file);
}
this.createUploader(mediaElem, popupObj, file);
this.hideFileSelectWrapper(popupObj);
};
/* Creates and configures the popup object */
PasteCleanup.prototype.createPopupObject = function (imgElem, file) {
var popupEle = this.pasteObj.createPopupElement();
popupEle.setAttribute('id', getUniqueID(this.parent.getID() + '_upload_popup'));
var boundObj = { popupRoot: popupEle, self: this };
var contentEle = this.parent.createElement('input', {
id: getUniqueID(this.parent.getID() + '_upload'), attrs: { type: 'File', name: 'UploadFiles' }
});
var popup = new Popup(popupEle, {
relateTo: imgElem,
height: '85px',
width: '300px',
content: contentEle,
viewPortElement: this.parent.inputElement,
enableRtl: this.parent.enableRtl,
zIndex: 10001,
close: this.onPopupClose.bind(boundObj)
});
this.configurePopupStyles(popup);
this.schedulePopupRefresh(imgElem, file, popup);
return popup;
};
/* Handle uploader popup close behavior */
PasteCleanup.prototype.onPopupClose = function () {
var currentPopupElem = this.popupRoot;
var currentPasteCleanupObj = this.self;
if (!isNOU(currentPopupElem) && !isNOU(currentPasteCleanupObj)) {
var popupObj = getComponent(currentPopupElem, 'popup');
currentPasteCleanupObj.parent.isBlur = false;
if (isNOU(popupObj)) {
return;
}
var uploaderObj = currentPasteCleanupObj.getUploaderInstance(currentPopupElem);
if (isNOU(uploaderObj)) {
return;
}
uploaderObj.destroy();
popupObj.destroy();
detach(currentPopupElem);
}
};
/* To get the uploader object from popup element */
PasteCleanup.prototype.getUploaderInstance = function (element) {
var currentUploader = element.querySelector('.e-uploader');
return getComponent(currentUploader, 'uploader');
};
/* Configures popup styles and CSS classes */
PasteCleanup.prototype.configurePopupStyles = function (popup) {
if (isNOU(popup) || isNOU(popup.element)) {
return;
}
popup.element.style.display = 'none';
addClass([popup.element], [classes.CLS_POPUP_OPEN, classes.CLS_RTE_UPLOAD_POPUP]);
if (!isNOU(this.parent.cssClass)) {
addClass([popup.element], this.parent.cssClass.replace(/\s+/g, ' ').trim().split(' '));
}
};
/* Schedules popup refresh based on file size */
PasteCleanup.prototype.schedulePopupRefresh = function (imgElem, file, popupObj) {
var _this = this;
var timeOut = file.size > 1000000 ? 300 : 100;
this.refreshPopupTime = setTimeout(function () {
_this.refreshPopup(imgElem, popupObj);
}, timeOut);
};
/* Creates and configures the uploader component */
PasteCleanup.prototype.createUploader = function (imgElem, popup, file) {
var _this = this;
var uploadObj = new Uploader({
asyncSettings: {
saveUrl: this.parent.insertImageSettings.saveUrl,
removeUrl: this.parent.insertImageSettings.removeUrl
},
cssClass: classes.CLS_RTE_DIALOG_UPLOAD,
allowedExtensions: this.parent.insertImageSettings.allowedTypes.toString(),
success: function (e) {
_this.popupClose(popup, imgElem, e);
},
uploading: function (e) { return _this.handleUploading(e, imgElem, popup); },
beforeUpload: function (args) { return _this.handleBeforeUpload(args); },
failure: function (e) { return _this.handleFailure(e, imgElem, popup); },
canceling: function () { return _this.handleCanceling(imgElem, popup); },
selected: function (e) { e.cancel = true; },
removing: function () { return _this.handleRemoving(imgElem, popup); }
});
uploadObj.appendTo(popup.element.childNodes[0]);
this.initializeUpload(file, uploadObj);
return uploadObj;
};
/* Handles the uploading event */
PasteCleanup.prototype.handleUploading = function (e, imgElem, popupObj) {
if (!this.parent.isServerRendered) {
this.parent.trigger(events.imageUploading, e, function (imageUploadingArgs) {
if (imageUploadingArgs.cancel) {
if (!isNullOrUndefined(imgElem)) {
detach(imgElem);
}
if (!isNullOrUndefined(popupObj.element)) {
detach(popupObj.element);
}
}
});
}
};
/* Handles the beforeUpload event */
PasteCleanup.prototype.handleBeforeUpload = function (args) {
this.parent.trigger(events.beforeImageUpload, args);
this.toolbarEnableDisable(true);
};
/* Handles upload failure */
PasteCleanup.prototype.handleFailure = function (e, imgElem, popupObj) {
var _this = this;
this.failureTime = setTimeout(function () {
_this.uploadFailure(imgElem, popupObj, e);
}, 900);
};
/* Handles upload cancellation */
PasteCleanup.prototype.handleCanceling = function (imgElem, popupObj) {
if (imgElem.nextSibling && imgElem.nextSibling.textContent === ' ') {
detach(imgElem.nextSibling);
}
detach(imgElem);
popupObj.close();
};
/* Handles file removal */
PasteCleanup.prototype.handleRemoving = function (imgElem, popupObj) {
if (imgElem.nextSibling && imgElem.nextSibling.textContent === ' ') {
detach(imgElem.nextSibling);
}
detach(imgElem);
popupObj.close();
};
/* Initializes the upload process */
PasteCleanup.prototype.initializeUpload = function (file, uploadObj) {
var fileInfo = [{
name: file.name,
rawFile: file,
size: file.size,
type: file.type,
status: 'Ready to Upload',
validationMessages: { minSize: '', maxSize: '' },
statusCode: '1'
}];
uploadObj.createFileList(fileInfo);
uploadObj.upload(fileInfo);
};
/* Hides the file select wrapper */
PasteCleanup.prototype.hideFileSelectWrapper = function (popupObj) {
if (isNOU(popupObj) || isNOU(popupObj.element)) {
return;
}
var fileSelectWrap = popupObj.element.getElementsByClassName('e-file-select-wrap')[0];
if (fileSelectWrap) {
fileSelectWrap.style.display = 'none';
}
};
/* Handles image upload failure */
PasteCleanup.prototype.uploadFailure = function (imgElem, popupObj, e) {
if ((this.parent && this.parent.isDestroyed) || isNOU(popupObj)) {
return;
}
detach(imgElem);
popupObj.close();
this.parent.trigger(events.imageUploadFailed, e);
};
/* Handles popup close after successful upload */
PasteCleanup.prototype.popupClose = function (popupObj, imgElem, e) {
this.prepareEventArgs(e, imgElem);
this.handleUploadStatus(e, imgElem);
this.scheduleCleanup(popupObj, imgElem);
};
/* Prepares event arguments for upload events */
PasteCleanup.prototype.prepareEventArgs = function (e, imgElem) {
e.element = imgElem;
e.detectImageSource = ImageInputSource.Pasted;
};
/* Handles different upload status codes */
PasteCleanup.prototype.handleUploadStatus = function (e, imgElem) {
var element = e.file;
if (isNOU(element)) {
return;
}
if (element.statusCode === '2') {
this.handleSuccessfulUpload(e, imgElem);
}
else if (element.statusCode === '5') {
this.handleImageRemoval(e);
}
};
/* Handles successful image upload */
PasteCleanup.prototype.handleSuccessfulUpload = function (e, imgElem) {
var _this = this;
this.parent.trigger(events.imageUploadSuccess, e, function (e) {
if (!isNullOrUndefined(_this.parent.insertImageSettings.path)) {
var url = _this.parent.insertImageSettings.path + e.file.name;
_this.updateImageSource(imgElem, url, e.file.name);
}
});
};
/* Updates image source after successful upload */
PasteCleanup.prototype.updateImageSource = function (imgElem, url, altText) {
// Handle detached images with ID
if (!this.parent.inputElement.contains(imgElem) && imgElem.id) {
var imgHtmlElems = this.parent.inputElement.querySelectorAll('#' + imgElem.id);
this.updateDetachedImages(imgHtmlElems, url, altText);
}
else {
imgElem.src = url;
imgElem.setAttribute('alt', altText);
}
};
/* Updates detached images by ID */
PasteCleanup.prototype.updateDetachedImages = function (imgHtmlElems, url, altText) {
for (var i = 0; i < imgHtmlElems.length; i++) {
var imgHtmlElem = imgHtmlElems[i];
if (imgHtmlElem && imgHtmlElem.style && imgHtmlElem.style.opacity === '0.5') {
imgHtmlElem.src = url;
imgHtmlElem.setAttribute('alt', altText);
}
}
};
/* Handles image removal */
PasteCleanup.prototype.handleImageRemoval = function (e) {
this.parent.trigger(events.imageRemoving, e, function (e) {
if (!isNullOrUndefined(e.element.src)) {
e.element.src = '';
}
});
};
/* Schedules cleanup after upload completion */
PasteCleanup.prototype.scheduleCleanup = function (popupObj, imgElem) {
popupObj.close();
this.resetImageOpacity(imgElem);
this.toolbarEnableDisable(false);
};
/* Resets image opacity after upload */
PasteCleanup.prototype.resetImageOpacity = function (imgElem) {
if (!this.parent.inputElement.contains(imgElem) && (imgElem.id || imgElem.alt)) {
this.resetDetachedImageOpacity(imgElem);
}
else {
imgElem.style.opacity = '1';
}
};
/* Resets opacity for detached images */
PasteCleanup.prototype.resetDetachedImageOpacity = function (imgElem) {
var selector = imgElem.id ?
"#" + imgElem.id :
"[alt=\"" + imgElem.alt + "\"]";
if (selector) {
var imgHtmlElems = this.parent.inputElement.querySelectorAll(selector);
for (var i = 0; i < imgHtmlElems.length; i++) {
var imgHtmlElem = imgHtmlElems[i];
if (imgHtmlElem && imgHtmlElem.style && imgHtmlElem.style.opacity === '0.5') {
imgHtmlElem.style.opacity = '1';
}
}
}
};
/* Refreshes popup position relative to image */
PasteCleanup.prototype.refreshPopup = function (imageElement, popupObj) {
var imgPosition = this.calculateImagePosition(imageElement);
var rtePosition = this.parent.element.offsetTop + this.parent.element.offsetHeight;
if (imgPosition > rtePosition) {
this.positionPopupAtTop(popupObj);
}
else {
this.positionPopupAtImage(popupObj, imageElement);
}
};
/* Calculates image position considering iframe */
PasteCleanup.prototype.calculateImagePosition = function (imageElement) {
return this.parent.iframeSettings.enable ?
this.parent.element.offsetTop + imageElement.offsetTop :
imageElement.offsetTop;
};
/* Positions popup at the top of editor */
PasteCleanup.prototype.positionPopupAtTop = function (popupObj) {
popupObj.offsetY = this.parent.iframeSettings.enable ? -30 : -65;
popupObj.element.style.display = 'block';
};
/* Positions popup relative to image */
PasteCleanup.prototype.positionPopupAtImage = function (popupObj, imageElement) {
if (popupObj) {
popupObj.refreshPosition(imageElement);
popupObj.element.style.display = 'block';
}
};
/* Method for image formatting when pasting */
PasteCleanup.prototype.imageFormatting = function (pasteArgs, imgElement) {
var imgElem