@syncfusion/ej2-richtexteditor
Version:
Essential JS 2 RichTextEditor component
439 lines (438 loc) • 18.8 kB
JavaScript
import { addClass, detach, isNullOrUndefined as isNOU } from '@syncfusion/ej2-base';
import { Popup } from '@syncfusion/ej2-popups';
import { Uploader } from '@syncfusion/ej2-inputs';
import * as classes from '../base/classes';
import * as events from '../base/constant';
import { ImageInputSource, MediaInputSource } from '../../common/enum';
import { CLS_IMG_FOCUS, CLS_AUD_FOCUS, CLS_VID_FOCUS } from '../../common/constant';
var PopupUploader = /** @class */ (function () {
function PopupUploader(parent) {
this.isDestroyed = false;
this.parent = parent;
this.rteID = parent.element.id;
}
/**
* Creates and renders a popup for media upload
*
* @param {MediaType} type - Type of popup (Image, Video, Audio)
* @param {HTMLElement} element - Element to append popup
* @returns {Popup} - Returns the created popup
* @hidden
*/
PopupUploader.prototype.renderPopup = function (type, element) {
var _this = this;
var popupElement = this.parent.createElement('div');
this.parent.rootContainer.appendChild(popupElement);
var uploadEle = this.parent.createElement('input', {
id: this.rteID + '_' + type.toLowerCase() + '_upload',
attrs: { type: 'File', name: 'UploadFiles' }
});
// Create popup based on type
this.popupObj = new Popup(popupElement, {
relateTo: element,
viewPortElement: this.parent.inputElement,
zIndex: 10001,
content: uploadEle,
enableRtl: this.parent.enableRtl,
height: '85px',
width: '300px',
actionOnScroll: 'none',
close: function () {
_this.parent.isBlur = false;
if (_this.popupObj) {
_this.popupObj.destroy();
detach(_this.popupObj.element);
_this.popupObj = null;
}
if (!_this.parent.inlineMode.enable && _this.parent.toolbarModule && _this.parent.toolbarModule.baseToolbar) {
_this.parent.toolbarModule.baseToolbar.toolbarObj.disable(false);
}
}
});
this.popupObj.element.style.display = 'none';
addClass([this.popupObj.element], classes.CLS_POPUP_OPEN);
addClass([this.popupObj.element], classes.CLS_RTE_UPLOAD_POPUP);
// Add type-specific class
switch (type) {
case 'Images':
this.popupObj.element.classList.add(classes.CLS_RTE_IMAGE_UPLOAD_POPUP);
break;
case 'Videos':
this.popupObj.element.classList.add(classes.CLS_RTE_VIDEO_UPLOAD_POPUP);
break;
case 'Audios':
this.popupObj.element.classList.add(classes.CLS_RTE_AUDIO_UPLOAD_POPUP);
break;
}
if (!isNOU(this.parent.cssClass)) {
addClass([this.popupObj.element], this.parent.cssClass.replace(/\s+/g, ' ').trim().split(' '));
}
return this.popupObj;
};
/**
* Creates and initializes an uploader for the specified media type
*
* @param {MediaType} type - Type of media (Image, Video, Audio)
* @param {DragEvent} dragEvent - Drag event data
* @param {HTMLElement} [mediaElement] - Optional media element for upload
* @param {HTMLElement} target - Target element to append uploader
* @returns {Uploader} - Returns the created uploader
* @hidden
*/
PopupUploader.prototype.createUploader = function (type, dragEvent, mediaElement, target) {
var _this = this;
var isUploading = false;
var allowedExtensions = '';
var saveUrl;
var removeUrl;
var maxFileSize;
// Get settings based on type
switch (type) {
case 'Images':
allowedExtensions = this.parent.insertImageSettings.allowedTypes.toString();
saveUrl = this.parent.insertImageSettings.saveUrl;
removeUrl = this.parent.insertImageSettings.removeUrl;
maxFileSize = this.parent.insertImageSettings.maxFileSize;
break;
case 'Videos':
allowedExtensions = this.parent.insertVideoSettings.allowedTypes.toString();
saveUrl = this.parent.insertVideoSettings.saveUrl;
removeUrl = this.parent.insertVideoSettings.removeUrl;
maxFileSize = this.parent.insertVideoSettings.maxFileSize;
break;
case 'Audios':
allowedExtensions = this.parent.insertAudioSettings.allowedTypes.toString();
saveUrl = this.parent.insertAudioSettings.saveUrl;
removeUrl = this.parent.insertAudioSettings.removeUrl;
maxFileSize = this.parent.insertAudioSettings.maxFileSize;
break;
}
// Create uploader with standard configuration
this.uploadObj = new Uploader({
asyncSettings: {
saveUrl: saveUrl,
removeUrl: removeUrl
},
cssClass: classes.CLS_RTE_DIALOG_UPLOAD + this.parent.getCssClass(true),
dropArea: this.parent.element,
allowedExtensions: allowedExtensions,
maxFileSize: maxFileSize,
multiple: false,
enableRtl: this.parent.enableRtl,
removing: function () {
_this.parent.inputElement.contentEditable = 'true';
isUploading = false;
if (mediaElement) {
detach(mediaElement);
}
if (_this.popupObj) {
_this.popupObj.close();
}
},
canceling: function () {
_this.parent.inputElement.contentEditable = 'true';
isUploading = false;
if (mediaElement) {
detach(mediaElement);
}
if (_this.popupObj) {
_this.popupObj.close();
}
// Handle all media type quickToolbars
if (_this.parent.quickToolbarModule) {
if (type === 'Images' && _this.parent.quickToolbarModule.imageQTBar) {
_this.parent.quickToolbarModule.imageQTBar.hidePopup();
}
else if (type === 'Videos' && _this.parent.quickToolbarModule.videoQTBar) {
_this.parent.quickToolbarModule.videoQTBar.hidePopup();
}
else if (type === 'Audios' && _this.parent.quickToolbarModule.audioQTBar) {
_this.parent.quickToolbarModule.audioQTBar.hidePopup();
}
}
_this.uploadCancelTime = setTimeout(function () {
if (_this.uploadObj && !_this.uploadObj.isDestroyed) {
_this.uploadObj.destroy();
}
}, 900);
},
beforeUpload: function (args) {
var eventName = type === 'Images' ? events.beforeImageUpload : events.beforeFileUpload;
_this.parent.trigger(eventName, args);
if (!_this.parent.inlineMode.enable && _this.parent.toolbarModule && _this.parent.toolbarModule.baseToolbar) {
_this.parent.toolbarModule.baseToolbar.toolbarObj.disable(true);
}
},
uploading: function (args) {
if (!_this.parent.isServerRendered) {
isUploading = true;
var eventName = type === 'Images' ? events.imageUploading : events.fileUploading;
_this.parent.trigger(eventName, args, function (uploadingArgs) {
if (uploadingArgs.cancel) {
if (mediaElement && !isNOU(mediaElement)) {
detach(mediaElement);
}
if (_this.popupObj && _this.popupObj.element && !isNOU(_this.popupObj.element)) {
detach(_this.popupObj.element);
}
}
else {
_this.parent.inputElement.contentEditable = 'false';
}
});
}
},
selected: function (args) {
if (isUploading) {
args.cancel = true;
}
},
failure: function (args) {
isUploading = false;
_this.parent.inputElement.contentEditable = 'true';
var popupArgs = {
args: dragEvent,
type: type,
isNotify: undefined,
elements: mediaElement
};
_this.uploadFailureTime = setTimeout(function () {
_this.uploadFailure(mediaElement, popupArgs, args);
}, 900);
},
success: function (args) {
if (args.operation === 'cancel') {
return;
}
isUploading = false;
_this.parent.inputElement.contentEditable = 'true';
var popupArgs = {
args: dragEvent,
type: type,
isNotify: undefined,
elements: mediaElement
};
var imageArgs;
var mediaArgs;
if (type === 'Images') {
imageArgs = {
e: args.e,
file: args.file,
statusText: args.statusText,
operation: args.operation,
response: args.response,
element: mediaElement,
detectImageSource: ImageInputSource.Dropped
};
}
else {
mediaArgs = {
e: args.e,
file: args.file,
statusText: args.statusText,
operation: args.operation,
response: args.response,
element: mediaElement,
detectMediaSource: MediaInputSource.Dropped
};
}
_this.uploadSuccessTime = setTimeout(function () {
// Cast args based on the type of media
if (type === 'Images') {
_this.uploadSuccess(mediaElement, dragEvent, popupArgs, imageArgs);
}
else if (type === 'Videos' || type === 'Audios') {
_this.uploadSuccess(mediaElement, dragEvent, popupArgs, mediaArgs);
}
}, 900);
}
});
this.uploadObj.appendTo(target);
return this.uploadObj;
};
/**
* Called when drop upload fails
*
* @param {HTMLElement} mediaEle - The media element
* @param {IShowPopupArgs} args - Popup arguments
* @param {FailureEventArgs} e - Failure event arguments
* @returns {void}
* @hidden
*/
PopupUploader.prototype.uploadFailure = function (mediaEle, args, e) {
if (mediaEle) {
detach(mediaEle);
}
if (this.popupObj) {
this.popupObj.close();
}
// Trigger appropriate event based on type
var eventName = args.type === 'Images' ? events.imageUploadFailed : events.fileUploadFailed;
this.parent.trigger(eventName, e);
if (this.uploadObj && !this.uploadObj.isDestroyed) {
this.uploadObj.destroy();
}
};
/**
* Called when upload is successful
*
* @param {HTMLElement} mediaElement - The media element
* @param {DragEvent} dragEvent - The drag event
* @param {IShowPopupArgs} args - Popup arguments
* @param {ImageSuccessEventArgs | MediaSuccessEventArgs} e - Success event arguments
* @returns {void}
* @hidden
*/
PopupUploader.prototype.uploadSuccess = function (mediaElement, dragEvent, args, e) {
var _this = this;
if (e.operation === 'cancel') {
return;
}
mediaElement.style.opacity = '1';
// Add appropriate class based on media type
switch (args.type) {
case 'Images':
mediaElement.classList.add(CLS_IMG_FOCUS);
break;
case 'Videos':
case 'Audios': {
var focusClass = args.type === 'Videos' ? CLS_VID_FOCUS : CLS_AUD_FOCUS;
mediaElement.classList.add(focusClass);
break;
}
}
// Trigger appropriate event based on type
var eventName = args.type === 'Images' ? events.imageUploadSuccess : events.fileUploadSuccess;
this.parent.trigger(eventName, e, function (responseData) {
if (mediaElement && responseData.file) {
var fileName = responseData.file.name;
switch (args.type) {
case 'Images':
if (!isNOU(_this.parent.insertImageSettings.path)) {
var url = _this.parent.insertImageSettings.path + fileName;
mediaElement.src = url;
mediaElement.setAttribute('alt', fileName);
}
break;
case 'Videos':
if (!isNOU(_this.parent.insertVideoSettings.path)) {
var url = _this.parent.insertVideoSettings.path + fileName;
// Find source element and update its src attribute
var sourceElement = mediaElement.querySelector('source');
if (sourceElement) {
sourceElement.setAttribute('src', url);
// Update MIME type
var fileExtension = fileName.split('.').pop().toLowerCase();
sourceElement.setAttribute('type', 'video/' + fileExtension);
// Reset opacity
mediaElement.style.opacity = '1';
}
}
break;
case 'Audios':
if (!isNOU(_this.parent.insertAudioSettings.path)) {
var url = _this.parent.insertAudioSettings.path + fileName;
// Find source element and update its src attribute
var sourceElement = mediaElement.querySelector('source');
if (sourceElement) {
sourceElement.setAttribute('src', url);
// Update MIME type
var fileExtension = fileName.split('.').pop().toLowerCase();
sourceElement.setAttribute('type', 'audio/' + fileExtension);
// Reset opacity and reload video
mediaElement.style.opacity = '1';
mediaElement.load();
}
}
break;
}
}
});
if (this.popupObj) {
this.popupObj.close();
}
if (this.uploadObj && !this.uploadObj.isDestroyed) {
this.uploadObj.destroy();
}
// Show appropriate quick toolbar and handle element based on type
if (args.type === 'Images') {
this.parent.notify(events.insertCompleted, args);
if (this.parent.insertImageSettings.resize) {
this.parent.notify(events.resizeStart, {
event: dragEvent,
element: mediaElement
});
}
}
else if (args.type === 'Videos') {
this.parent.notify(events.insertCompleted, args);
setTimeout(function () {
_this.parent.notify(events.resizeStart, {
event: dragEvent,
element: mediaElement
});
}, 100);
}
else if (args.type === 'Audios') {
this.parent.notify(events.insertCompleted, args);
}
};
/**
* Refreshes popup position relative to element
*
* @param {HTMLElement} targetElement - Element to position popup relative to
* @returns {void}
* @hidden
*/
PopupUploader.prototype.refreshPopup = function (targetElement) {
var targetPosition = this.parent.iframeSettings.enable ?
this.parent.element.offsetTop + targetElement.offsetTop : targetElement.offsetTop;
var rtePosition = this.parent.element.offsetTop + this.parent.element.offsetHeight;
if (targetPosition > rtePosition) {
this.popupObj.offsetY = this.parent.iframeSettings.enable ? -30 : -65;
this.popupObj.element.style.display = 'block';
}
else {
if (this.popupObj) {
this.popupObj.refreshPosition(targetElement);
this.popupObj.element.style.display = 'block';
}
}
};
/**
* Destroys popup and uploader
*
* @returns {void}
* @hidden
*/
PopupUploader.prototype.destroy = function () {
if (this.isDestroyed) {
return;
}
if (!isNOU(this.uploadCancelTime)) {
clearTimeout(this.uploadCancelTime);
this.uploadCancelTime = null;
}
if (!isNOU(this.uploadFailureTime)) {
clearTimeout(this.uploadFailureTime);
this.uploadFailureTime = null;
}
if (!isNOU(this.uploadSuccessTime)) {
clearTimeout(this.uploadSuccessTime);
this.uploadSuccessTime = null;
}
if (this.popupObj && !this.popupObj.isDestroyed) {
this.popupObj.destroy();
detach(this.popupObj.element);
this.popupObj = null;
}
if (this.uploadObj && !this.uploadObj.isDestroyed) {
this.uploadObj.destroy();
detach(this.uploadObj.element);
this.uploadObj = null;
}
this.isDestroyed = true;
};
return PopupUploader;
}());
export { PopupUploader };