: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if (opts.extraOptions.managerUrl) {
confObj.managerUrl = opts.extraOptions.managerUrl;
fm.bind('destroy', function() {
// Prepare on before show dialog
prepare : function(base, dialogOpts, file) {
jQuery(base).height(base.editor.fm.getUI().height() - 100);
init : function(id, file, data, fm) {
var m = data.match(/^([\s\S]*<body[^>]*>)([\s\S]+)(<\/body>[\s\S]*)$/i),
'box-sizing': 'border-box'
this._setupSelEncoding(data);
load : function(editnode) {
dfrd = jQuery.Deferred(),
mode = self.confObj.ckeditor5Mode || 'decoupled-document',
var l = fm.lang.toLowerCase().replace('_', '-');
if (l.substr(0, 2) === 'zh' && l !== 'zh-cn') {
init = function(cEditor) {
var base = jQuery(editnode).parent(),
base.height(fm.getUI().height() - 100);
// CKEditor5 configure options
toolbar: ["heading", "|", "fontSize", "fontFamily", "|", "bold", "italic", "underline", "strikethrough", "highlight", "|", "alignment", "|", "numberedList", "bulletedList", "blockQuote", "indent", "outdent", "|", "ckfinder", "link", "imageUpload", "insertTable", "mediaEmbed", "|", "undo", "redo"],
}, self.confObj.ckeOpts);
// trigger event 'editEditorPrepare'
self.trigger('Prepare', {
var ckf = editor.commands.get('ckfinder'),
fileRepo = editor.plugins.get('FileRepository'),
prevVars = {}, isImage, insertImages;
if (editor.ui.view.toolbar && (mode === 'classic' || mode === 'decoupled-document')) {
jQuery(editnode).closest('.elfinder-dialog').children('.ui-widget-header').append(jQuery(editor.ui.view.toolbar.element).css({marginRight:'-1em',marginLeft:'-1em'}));
if (mode === 'classic') {
jQuery(editnode).closest('.elfinder-edit-editor').css('overflow', 'auto');
// Set up this elFinder instead of CKFinder
return f && f.mime.match(/^image\//i);
insertImages = function(urls) {
var imgCmd = editor.commands.get('imageUpload');
var ntf = editor.plugins.get('Notification'),
ntf.showWarning(i18('Could not insert image at the current position.'), {
title: i18('Inserting image failed'),
editor.execute('imageInsert', { source: urls });
// Take over ckfinder execute()
ckf.execute = function() {
var dlg = base.closest('.elfinder-dialog'),
gf = fm.getCommand('getfile'),
dlg.off('resize close', rever);
gf.callback = prevVars.callback;
gf.options.folders = prevVars.folders;
gf.options.multiple = prevVars.multi;
fm.commandMap.open = prevVars.open;
dlg.trigger('togleminimize').one('resize close', rever);
prevVars.callback = gf.callback;
prevVars.folders = gf.options.folders;
prevVars.multi = gf.options.multiple;
prevVars.open = fm.commandMap.open;
gf.callback = function(files) {
if (files.length === 1 && files[0].mime === 'directory') {
fm.one('open', function() {
fm.commandMap.open = 'getfile';
}).getCommand('open').exec(files[0].hash);
fm.getUI('cwd').trigger('unselectall');
jQuery.each(files, function(i, f) {
imgs.push(fm.convAbsUrl(f.url));
editor.execute('link', fm.convAbsUrl(f.url));
dlg.trigger('togleminimize');
gf.options.folders = true;
gf.options.multiple = true;
fm.commandMap.open = 'getfile';
msg: fm.i18n('dblclickToSelect')
fileRepo.createUploadAdapter = function(loader) {
return new uploder(loader);
editor.setData(jQuery(editnode).data('data').body);
// move .ck-body to elFinder node for fullscreen mode
fm.getUI().append(jQuery('body > div.ck-body'));
jQuery('div.ck-balloon-panel').css({
'z-index': fm.getMaximizeCss().zIndex + 1
defaultConfig: cEditor.defaultConfig,
plugins: cEditor.builtinPlugins.map(function(p) { return p.pluginName; }),
toolbars: Array.from(editor.ui.componentFactory.names())
['catch'](function(error) { // ['cache'] instead .cache for fix error on ie8
uploder = function(loader) {
var upload = function(file, resolve, reject) {
fm.exec('upload', {files: [file]}, void(0), fm.cwd().hash)
if (data.added && data.added.length) {
fm.url(data.added[0].hash, { async: true }).done(function(url) {
'default': fm.convAbsUrl(url)
reject('errFileNotFound');
reject(fm.i18n(data.error? data.error : 'errUpload'));
var error = fm.parseError(err);
reject(fm.i18n(error? (error === 'userabort'? 'errAbort' : error) : 'errUploadNoFiles'));
.progress(function(data) {
loader.uploadTotal = data.total;
loader.uploaded = data.progress;
this.upload = function() {
return new Promise(function(resolve, reject) {
if (loader.file instanceof Promise || (loader.file && typeof loader.file.then === 'function')) {
loader.file.then(function(file) {
upload(file, resolve, reject);
upload(loader.file, resolve, reject);
this.abort = function() {
fm.getUI().trigger('uploadabort');
if (!self.confObj.editor) {
loader = jQuery.Deferred();
fm.options.cdns.ckeditor5 + '/' + mode + '/ckeditor.js'
editor = window.BalloonEditor || window.InlineEditor || window.ClassicEditor || window.DecoupledEditor;
fm.options.cdns.ckeditor5 + '/' + mode + '/translations/' + lang + '.js'
loader.done(function(editor) {
self.confObj.editor = editor;
init(self.confObj.editor);
getContent : function() {
var data = jQuery(this).data('data');
return data.header + data.body + data.footer;
close : function(editnode, instance) {
instance && instance.destroy();
save : function(editnode, instance) {
var elm = jQuery(editnode),
data.body = instance.getData();
focus : function(editnode, instance) {
jQuery(editnode).trigger('focus');
iconImg : 'img/editor-icons.png 0 -64'
exts : ['htm', 'html', 'xhtml'],
setup : function(opts, fm) {
if (!fm.options.cdns.tinymce) {
confObj.uploadOpts = Object.assign({}, opts.extraOptions.uploadOpts || {});
confObj.mceOpts = Object.assign({}, opts.extraOptions.tinymce || {});
load : function(textarea) {
dfrd = jQuery.Deferred(),
var base = jQuery(textarea).show().parent(),
dlg = base.closest('.elfinder-dialog'),
delta = base.outerHeight(true) - h,
// hide MCE dialog and modal block
hideMceDlg = function() {
if (tinymce.activeEditor.windowManager.windows) {
mceW = tinymce.activeEditor.windowManager.windows[0];
mceDlg = jQuery(mceW? mceW.getEl() : void(0)).hide();
mceCv = jQuery('#mce-modal-block').hide();
mceDlg = jQuery('.tox-dialog-wrap').hide();
// Show MCE dialog and modal block
showMceDlg = function() {
tVer = tinymce.majorVersion,
textarea._setHeight = function(height) {
var base = jQuery(this).parent(),
h = height || base.innerHeight(),
base.find('.mce-container-body:first').children('.mce-top-part,.mce-statusbar').each(function() {
ctrH += jQuery(this).outerHeight(true);
areaH = h - ctrH - delta;
base.find('.mce-edit-area iframe:first').height(areaH);
// TinyMCE configure options
selector: '#' + textarea.id,
plugins: 'print preview fullpage searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists wordcount imagetools textpattern help',
toolbar: 'formatselect | bold italic strikethrough forecolor backcolor | link image media | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat',
init_instance_callback : function(editor) {
dlg.one('beforedommove.'+fm.namespace, function() {
tinymce.execCommand('mceRemoveEditor', false, textarea.id);
}).one('dommove.'+fm.namespace, function() {
self.load(textarea).done(function(editor) {
// return editor instance
file_picker_callback : function (callback, value, meta) {
var gf = fm.getCommand('getfile'),
gf.callback = prevVars.callback;
gf.options.folders = prevVars.folders;
gf.options.multiple = prevVars.multi;
fm.commandMap.open = prevVars.open;
dlg.off('resize close', revar);
prevVars.callback = gf.callback;
prevVars.folders = gf.options.folders;
prevVars.multi = gf.options.multiple;
prevVars.open = fm.commandMap.open;
gf.callback = function(file) {
if (file.mime === 'directory') {
fm.one('open', function() {
fm.commandMap.open = 'getfile';
}).getCommand('open').exec(file.hash);
url = fm.convAbsUrl(file.url);
info = file.name + ' (' + fm.formatSize(file.size) + ')';
// Provide file and text for the link dialog
if (meta.filetype == 'file') {
callback(url, {text: info, title: info});
// Provide image and alt text for the image dialog
if (meta.filetype == 'image') {
callback(url, {alt: info});
// Provide alternative source and posted for the media dialog
if (meta.filetype == 'media') {
dlg.trigger('togleminimize');
gf.options.folders = true;
gf.options.multiple = false;
fm.commandMap.open = 'getfile';
dlg.trigger('togleminimize').one('resize close', revar);
msg: fm.i18n('dblclickToSelect')
images_upload_handler : function (blobInfo, success, failure) {
var file = blobInfo.blob(),
var dlg = e.data.dialog || {};
if (dlg.hasClass('elfinder-dialog-error') || dlg.hasClass('elfinder-confirm-upload')) {
dlg.trigger('togleminimize').one('resize close', revert);
fm.unbind('dialogopened', err);
dlg.off('resize close', revert);
// file blob of client side file object
fm.bind('dialogopened', err).exec('upload', Object.assign({
clipdata: clipdata // to get unique name on connector
}, self.confObj.uploadOpts), void(0), fm.cwd().hash).done(function(data) {
if (data.added && data.added.length) {
fm.url(data.added[0].hash, { async: true }).done(function(url) {
success(fm.convAbsUrl(url));
failure(fm.i18n('errFileNotFound'));
failure(fm.i18n(data.error? data.error : 'errUpload'));
var error = fm.parseError(err);
if (error === 'errUnknownCmd') {
} else if (error === 'userabort') {
failure(fm.i18n(error? error : 'errUploadNoFiles'));
// TinyMCE 5 supports "height: 100%"
// trigger event 'editEditorPrepare'
self.trigger('Prepare', {
tinymce.init(Object.assign(opts, self.confObj.mceOpts));
if (!self.confObj.loader) {
self.confObj.loader = jQuery.Deferred();
self.fm.loadScript([fm.options.cdns.tinymce + (fm.options.cdns.tinymce.match(/\.js/)? '' : '/tinymce.min.js')], function() {
self.confObj.loader.resolve();
self.confObj.loader.done(init);
close : function(textarea, instance) {
instance && tinymce.execCommand('mceRemoveEditor', false, textarea.id);