: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* @class elFinder command "edit".
* Edit text file in dialog window
* @author Dmitry (dio) Levashov, dio@std42.ru
elFinder.prototype.commands.edit = function() {
clsEditing = fm.res('class', 'editing'),
return str.replace(/\s+$/, '');
getEncSelect = function(heads) {
var sel = jQuery('<select class="ui-corner-all"></select>'),
jQuery.each(heads, function(i, head) {
hval = fm.escape(head.value);
sel.append('<option value="'+hval+'">'+(head.caption? fm.escape(head.caption) : hval)+'</option>');
jQuery.each(self.options.encodings, function(i, v) {
sel.append('<option value="'+v+'">'+v+'</option>');
getDlgWidth = function() {
var win = fm.options.dialogContained? fm.getUI() : jQuery(window),
if (typeof self.options.dialogWidth === 'string' && (m = self.options.dialogWidth.match(/(\d+)%/))) {
width = parseInt(win.width() * (m[1] / 100));
width = parseInt(self.options.dialogWidth || 650);
return Math.min(width, win.width());
getDlgHeight = function() {
if (!self.options.dialogHeight) {
var win = fm.options.dialogContained? fm.getUI() : jQuery(window),
if (typeof self.options.dialogHeight === 'string' && (m = self.options.dialogHeight.match(/(\d+)%/))) {
height = parseInt(win.height() * (m[1] / 100));
height = parseInt(self.options.dialogHeight || win.height());
return Math.min(height, win.height());
* Return files acceptable to edit
* @param Array files hashes
filter = function(files) {
ext = files[0].name.replace(/^.*(\.[^.]+)$/, '$1');
return jQuery.grep(files, function(file) {
if (skip || file.mime === 'directory') {
&& (allowAll || fm.mimeIsText(file.mime) || jQuery.inArray(file.mime, cnt === 1? mimesSingle : mimes) !== -1)
&& (!self.onlyMimes.length || jQuery.inArray(file.mime, self.onlyMimes) !== -1)
&& (cnt === 1 || (file.mime === mime && file.name.substr(ext.length * -1) === ext))
&& (fm.uploadMimeCheck(file.mime, file.phash)? true : false)
&& Object.keys(editors).length;
fileSync = function(hash) {
if (data && data.files && data.files.length) {
if (old.ts != f.ts || old.size != f.size) {
changed = { changed: [ f ] };
* Open dialog with textarea to edit file
* @param String id dialog id
* @param Object file file object
* @param String content file content
* @return jQuery.Deferred
dialog = function(id, file, content, encoding, editor, toasts) {
var dfrd = jQuery.Deferred(),
msg: fm.i18n('nowLoading')
makeToasts = function() {
if (toasts && Array.isArray(toasts)) {
jQuery.each(toasts, function() {
this.msg && fm.toast(this);
var encord = selEncoding? selEncoding.val():void(0),
saveDfd = jQuery.Deferred().fail(function(err) {
dialogNode.show().find('button.elfinder-btncnt-0,button.elfinder-btncnt-1').hide();
return saveDfd.resolve();
ta.editor.save(ta[0], ta.editor.instance);
conf = ta.editor.confObj;
if (conf.info && (conf.info.schemeContent || conf.info.arrayBufferContent)) {
tm = setTimeout(function() {
fm.notify({ type : 'chkcontent', cnt: -1 });
dfrd.notifyWith(ta, [encord, ta.data('hash'), old, saveDfd]);
dfrd.notifyWith(ta, [encord, ta.data('hash'), old, saveDfd]);
if (!loaded()) { return; }
save().fail(function(err) {
ta.elfinderdialog('close');
if (!loaded()) { return; }
if (!loaded()) { return; }
dialogs.addClass(clsEditing).fadeIn(function() {
self.mime = saveAsFile.mime || file.mime;
self.prefix = (saveAsFile.name || file.name).replace(/ \d+(\.[^.]+)?$/, '$1');
self.requestCmd = 'mkfile';
self.data = {target : phash};
jQuery.proxy(fm.res('mixin', 'make'), self)()
if (data.added && data.added.length) {
oldHash = ta.data('hash');
ta.data('hash', data.added[0].hash);
fm.exec('rm', [data.added[0].hash], { forceRm: true, quiet: true });
ta.data('hash', oldHash);
dialogNode.find('button.elfinder-btncnt-2').hide();
.progress(function(err) {
if (err && err === 'errUploadMime') {
ta.trigger('saveAsFail');
fm.trigger('unselectfiles', { files: [ file.hash ] });
dialogs = fm.getUI().children('.' + self.dialogClass + ':visible');
if (dialogNode.is(':hidden')) {
dialogs = dialogs.add(dialogNode);
dialogs.removeClass(clsEditing).fadeOut();
if (fm.searchStatus.state < 2 && phash !== fm.cwd().hash) {
reqOpen = fm.exec('open', [phash], {thash: phash});
} else if (!fm.file(phash)) {
reqInfo = fm.request({cmd: 'info', targets: [phash]});
jQuery.when([reqOpen, reqInfo]).done(function() {
fm.one('infodone', function() {
fm.file(phash)? make() : fail('errFolderNotFound');
reqOpen? fm.one('cwdrender', make) : make();
var dfd = jQuery.Deferred(),
return dfd.resolve(false);
ta.editor && ta.editor.save(ta[0], ta.editor.instance);
if (res && res.promise) {
tm = setTimeout(function() {
fm.notify({ type : 'chkcontent', cnt: -1 });
dfd.resolve(err || (old === undefined? false : true));
dfd.resolve(old !== res);
title : fm.escape(file.name),
openMaximized : editorMaximized() || (editor && editor.info && editor.info.openMaximized),
propagationEvents : ['mousemove', 'mouseup', 'click'],
if (ta.editor && dialogNode.closest('.ui-dialog').is(':hidden')) {
conf = ta.editor.confObj;
if (conf.info && conf.info.syncInterval) {
ta.editor.close(ta[0], ta.editor.instance);
conf = ta.editor.confObj;
if (conf.info && conf.info.syncInterval) {
ta.elfinderdialog('destroy');
onlySaveAs = (typeof saveAsFile.name !== 'undefined'),
requestAnimationFrame(saveAs);
changed().done(function(change) {
var msgs = ['confirmNotSave'];
if (typeof change === 'string') {
buttons : onlySaveAs? null : [{
requestAnimationFrame(saveAs);
var loadRes, conf, interval;
ta.initEditArea.call(ta, id, file, content, fm);
loadRes = ta.editor.load(ta[0]) || null;
if (loadRes && loadRes.done) {
loadRes.always(function() {
}).done(function(instance) {
ta.editor.instance = instance;
ta.editor.focus(ta[0], ta.editor.instance);
requestAnimationFrame(function() {
dialogNode.trigger('resize');
}).fail(function(error) {
error && fm.error(error);
ta.elfinderdialog('destroy');
if (loadRes && (typeof loadRes === 'string' || Array.isArray(loadRes))) {
ta.elfinderdialog('destroy');
ta.editor.instance = loadRes;
ta.editor.focus(ta[0], ta.editor.instance);
requestAnimationFrame(function() {
dialogNode.trigger('resize');
conf = ta.editor.confObj;
if (conf.info && conf.info.syncInterval) {
if (interval = parseInt(conf.info.syncInterval)) {
resize : function(e, data) {
ta.editor && ta.editor.resize(ta[0], ta.editor.instance, e, data || {});
getContent = function() {
var res = ta.getContent.call(ta, ta[0]);
if (res === undefined || res === false || res === null) {
res = jQuery.Deferred().reject();
if (res && res.promise) {
autoSync = function(interval) {
if (dialogNode.is(':visible')) {
stateChange = function() {
changed().done(function(change) {
selEncoding.attr('title', fm.i18n('saveAsEncoding')).addClass('elfinder-edit-changed');
selEncoding.attr('title', fm.i18n('openAsEncoding')).removeClass('elfinder-edit-changed');
ta, old, dialogNode, selEncoding, extEditor, maxW, syncInterval;
ta = jQuery(editor.html);
init : editor.init || null,
getContent : editor.getContent || null,
beforeclose : typeof editor.beforeclose == 'function' ? editor.beforeclose : void 0,
close : typeof editor.close == 'function' ? editor.close : function() {},
focus : typeof editor.focus == 'function' ? editor.focus : function() {},
resize : typeof editor.resize == 'function' ? editor.resize : function() {},
trigger : function(evName, data) {
fm.trigger('editEditor' + evName, Object.assign({}, editor.info || {}, data));