: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
.on('error', function() {
confObj = editor.confObj,
spnr = jQuery('<div class="elfinder-edit-spinner elfinder-edit-photopea"></div>')
.html('<span class="elfinder-spinner-text">' + fm.i18n('nowLoading') + '</span><span class="elfinder-spinner"></span>')
saveMimes = fm.arrayFlip(confObj.info.canMakeEmpty),
getType = function(mime) {
var ext = getExtention(mime, fm),
if (!confObj.mimesFlip[extmime]) {
} else if (ext === 'jpeg') {
if (!ext || !saveMimes[extmime]) {
ifm.closest('.ui-dialog').trigger('changeType', {
if (!confObj.mimesFlip) {
confObj.mimesFlip = fm.arrayFlip(confObj.mimes, true);
confObj.liveMsg = function(ifm, spnr, file) {
var wnd = ifm.get(0).contentWindow,
dfdIni = jQuery.Deferred().done(function() {
wnd.postMessage(data, orig);
return fm.getContents(file.hash, 'arraybuffer').done(function(d) {
this.receive = function(e) {
var ev = e.originalEvent,
if (ev.origin === orig && ev.source === wnd) {
if (ev.data === 'done') {
} else if (phase === 1) {
ifm.trigger('contentsloaded');
if (dfdGet && dfdGet.state() === 'pending') {
dfdGet.reject('errDataEmpty');
} else if (ev.data === 'Save') {
if (dfdGet && dfdGet.state() === 'pending') {
if (typeof ev.data === 'object') {
dfdGet.resolve('data:' + mime + ';base64,' + fm.arrayBufferToBase64(ev.data));
dfdGet.reject('errDataEmpty');
this.getContent = function() {
dfdGet && dfdGet.state() === 'pending' && dfdGet.reject();
dfdGet = jQuery.Deferred();
dfdGet.resolve('data:' + mime + ';base64,' + fm.arrayBufferToBase64(data));
if (q = ifm.data('quality')) {
wnd.postMessage('app.activeDocument.saveToOE("' + type + '")', orig);
ifm.parent().css('padding', 0);
type = getType(file.mime);
liveMsg = editor.liveMsg = new confObj.liveMsg(ifm, spnr, file);
jQuery(window).on('message.' + fm.namespace, liveMsg.receive);
liveMsg.load().done(function() {
lang: fm.lang.replace(/_/g, '-'),
customIO: {"save": "app.echoToOE(\"Save\");"}
ifm.attr('src', orig + '/#' + encodeURI(d));
if (file.mime === 'image/jpeg' || file.mime === 'image/webp') {
ifm.data('quality', fm.storage('jpgQuality') || fm.option('jpgQuality'));
quty = jQuery('<input type="number" class="ui-corner-all elfinder-resize-quality elfinder-tabstop"/>')
.attr('title', '1 - 100')
.on('change', function() {
.val(ifm.data('quality'));
jQuery('<div class="ui-dialog-buttonset elfinder-edit-extras elfinder-edit-extras-quality"></div>')
jQuery('<span>').html(fm.i18n('quality') + ' : '), quty, jQuery('<span></span>')
.prependTo(ifm.parent().next());
var dfd = jQuery.Deferred(),
$base.on('contentsloaded', function() {
dfd.resolve(self.liveMsg);
getContent : function() {
return this.editor.liveMsg? this.editor.liveMsg.getContent() : void(0);
save : function(base, liveMsg) {
var $base = jQuery(base),
quality = $base.data('quality'),
hash = $base.data('hash'),
if (typeof quality !== 'undefined') {
this.fm.storage('jpgQuality', quality);
file = this.fm.file(hash);
$base.data('mime', file.mime);
$base.removeData('mime');
close : function(base, liveMsg) {
jQuery(base).attr('src', '');
liveMsg && jQuery(window).off('message.' + this.fm.namespace, liveMsg.receive);
// Pixo is cross-platform image editor
iconImg : 'img/editor-icons.png 0 -208',
link: 'https://pixoeditor.com/privacy-policy/'
mimes : ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/x-ms-bmp'],
html : '<div class="elfinder-edit-imageeditor"><img/></div>',
// called on initialization of elFinder cmd edit (this: this editor's config object)
setup : function(opts, fm) {
if (fm.UA.ltIE8 || !opts.extraOptions || !opts.extraOptions.pixo || !opts.extraOptions.pixo.apikey) {
this.editorOpts = opts.extraOptions.pixo;
// Initialization of editing node (this: this editors HTML node)
init : function(id, file, content, fm) {
initImgTag.call(this, id, file, content, fm);
// Get data uri scheme (this: this editors HTML node)
getContent : function() {
return jQuery(this).children('img:first').attr('src');
// Launch Pixo editor when dialog open
node = $base.children('img:first'),
dialog = $base.closest('.ui-dialog'),
dfrd = jQuery.Deferred(),
container = jQuery('#elfinder-pixo-container'),
init = function(onload) {
container = jQuery('<div id="elfinder-pixo-container" class="ui-front"></div>').css({
height: jQuery(window).height(),
}).hide().appendTo(elfNode.hasClass('elfinder-fullscreen')? elfNode : 'body');
// bind switch fullscreen event
elfNode.on('resize.'+fm.namespace, function(e, data) {
data && data.fullscreen && container.appendTo(data.fullscreen === 'on'? elfNode : 'body');
fm.bind('destroy', function() {
editor && editor.cancelEditing();
container.appendTo(container.parent());
node.on('click', launch);
parent: container.get(0),
// Check current file.hash, all callbacks are called on multiple instances
var mime = arg.toBlob().type,
ext = getExtention(mime, fm),
node.one('load error', function() {
node.data('loading') && node.data('loading')(true);
.attr('crossorigin', 'anonymous')
if (node.data('ext') !== ext) {
changeImageType(url, self.file.mime).done(function(res, cv) {
base._canvas = canvas = cv;
dialog.trigger('changeType', {
dialog.removeClass(fm.res('class', 'preventback'));
fm.toggleMaximize(container, false);
}, self.confObj.editorOpts);
// trigger event 'editEditorPrepare'
self.trigger('Prepare', {
editor = new Pixo.Bridge(opts);
$base.on('saveAsFail', launch);
dialog.addClass(fm.res('class', 'preventback'));
fm.toggleMaximize(container, true);
container.show().data('curhash', self.file.hash);
editor.edit(node.get(0));
node.data('loading')(true);
qBase, quty, qutyTm, canvas, editor;
if (self.file.mime === 'image/jpeg') {
quty = jQuery('<input type="number" class="ui-corner-all elfinder-resize-quality elfinder-tabstop"/>')
.attr('title', '1 - 100')
.on('change', function() {
qutyTm && cancelAnimationFrame(qutyTm);
qutyTm = requestAnimationFrame(function() {
canvas.toBlob(function(blob) {
blob && quty.next('span').text(' (' + fm.formatSize(blob.size) + ')');
}, 'image/jpeg', Math.max(Math.min(q, 100), 1) / 100);
.val(fm.storage('jpgQuality') || fm.option('jpgQuality'));
qBase = jQuery('<div class="ui-dialog-buttonset elfinder-edit-extras elfinder-edit-extras-quality"></div>')
jQuery('<span>').html(fm.i18n('quality') + ' : '), quty, jQuery('<span></span>')
.prependTo($base.parent().next());
$base.data('quty', quty);
if (typeof Pixo === 'undefined') {
fm.loadScript(['https://pixoeditor.com:8443/editor/scripts/bridge.m.js'], function() {
// Convert content url to data uri scheme to save content
node = $base.children('img:first'),
if ($base.data('quty')) {
q = $base.data('quty').val();
q && this.fm.storage('jpgQuality', q);
node.attr('src', base._canvas.toDataURL(self.file.mime, q? Math.max(Math.min(q, 100), 1) / 100 : void(0)));
} else if (node.attr('src').substr(0, 5) !== 'data:') {
node.attr('src', imgBase64(node, this.file.mime));
close : function(base, editor) {
editor && editor.destroy();
// called on initialization of elFinder cmd edit (this: this editor's config object)
setup : function(opts, fm) {
if (fm.UA.ltIE8 || !fm.options.cdns.ace) {
// `mimes` is not set for support everything kind of text file
iconImg : 'img/editor-icons.png 0 -96'
load : function(textarea) {
dfrd = jQuery.Deferred(),
cdn = fm.options.cdns.ace,
var editor, editorBase, mode,
dialog = taBase.parent(),
id = textarea.id + '_ace',
ext = self.file.name.replace(/^.+\.([^.]+)|(.+)$/, '$1$2').toLowerCase(),
'application/x-php' : 'php',
'application/xhtml+xml' : 'html',
'text/javascript' : 'javascript',
'application/javascript' : 'javascript',
'text/x-c++src' : 'c_cpp',
'text/x-c++hdr' : 'c_cpp',
'text/x-shellscript' : 'sh',
'application/x-csh' : 'sh',
'text/x-python' : 'python',
'text/x-java-source' : 'java',
'application/x-perl' : 'perl',
'application/docbook+xml' : 'xml',
'application/xml' : 'xml'
taBase.height(taBase.height());
ace.config.set('basePath', cdn);
// Base node of Ace editor
editorBase = jQuery('<div id="'+id+'" style="width:100%; height:100%;"></div>').text(ta.val()).insertBefore(ta.hide());
editor.$blockScrolling = Infinity;
theme: 'ace/theme/monokai',
ace.config.loadModule('ace/ext/modelist', function() {
mode = ace.require('ace/ext/modelist').getModeForPath('/' + self.file.name).name;
if (mimeMode[self.file.mime]) {
mode = mimeMode[self.file.mime];
// show MIME:mode in title bar
taBase.prev().children('.elfinder-dialog-title').append(' (' + self.file.mime + ' : ' + mode.split(/[\/\\]/).pop() + ')');
if (dfrd.state() === 'resolved') {
dialog.trigger('resize');
ace.config.loadModule('ace/ext/language_tools', function() {
ace.require('ace/ext/language_tools');
enableBasicAutocompletion: true,
enableLiveAutocompletion: false
ace.config.loadModule('ace/ext/settings_menu', function() {
ace.require('ace/ext/settings_menu').init(editor);
editor.commands.addCommand({