File: /home/deshuvsd/www/wp-content/plugins/wp-file-manager-1/lib/js/commands/edit.js
/**
* @class elFinder command "edit".
* Edit text file in dialog window
*
* @author Dmitry (dio) Levashov, dio@std42.ru
**/
elFinder.prototype.commands.edit = function () {
"use strict";
var self = this,
fm = this.fm,
clsEditing = fm.res("class", "editing"),
mimesSingle = [],
mimes = [],
allowAll = false,
rtrim = function (str) {
return str.replace(/\s+$/, "");
},
getEncSelect = function (heads) {
var sel = jQuery('<select class="ui-corner-all"></select>'),
hval;
if (heads) {
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>");
});
return sel;
},
getDlgWidth = function () {
var win = fm.options.dialogContained ? fm.getUI() : jQuery(window),
m,
width;
if (
typeof self.options.dialogWidth === "string" &&
(m = self.options.dialogWidth.match(/(\d+)%/))
) {
width = parseInt(win.width() * (m[1] / 100));
} else {
width = parseInt(self.options.dialogWidth || 650);
}
return Math.min(width, win.width());
},
getDlgHeight = function () {
if (!self.options.dialogHeight) {
return void 0;
}
var win = fm.options.dialogContained ? fm.getUI() : jQuery(window),
m,
height;
if (
typeof self.options.dialogHeight === "string" &&
(m = self.options.dialogHeight.match(/(\d+)%/))
) {
height = parseInt(win.height() * (m[1] / 100));
} else {
height = parseInt(self.options.dialogHeight || win.height());
}
return Math.min(height, win.height());
},
/**
* Return files acceptable to edit
*
* @param Array files hashes
* @return Array
**/
filter = function (files) {
var cnt = files.length,
mime,
ext,
skip;
if (cnt > 1) {
mime = files[0].mime;
ext = files[0].name.replace(/^.*(\.[^.]+)$/, "$1");
}
return jQuery.grep(files, function (file) {
var res;
if (skip || file.mime === "directory") {
return false;
}
res =
file.read &&
(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) &&
setEditors(file, cnt) &&
Object.keys(editors).length;
if (!res) {
skip = true;
}
return res;
});
},
fileSync = function (hash) {
var old = fm.file(hash),
f;
fm.request({
cmd: "info",
targets: [hash],
preventDefault: true,
}).done(function (data) {
var changed;
if (data && data.files && data.files.length) {
f = data.files[0];
if (old.ts != f.ts || old.size != f.size) {
changed = { changed: [f] };
fm.updateCache(changed);
fm.change(changed);
}
}
});
},
/**
* 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(),
_loaded = false,
loaded = function () {
if (!_loaded) {
fm.toast({
mode: "warning",
msg: fm.i18n("nowLoading"),
});
return false;
}
return true;
},
makeToasts = function () {
// make toast message
if (toasts && Array.isArray(toasts)) {
jQuery.each(toasts, function () {
this.msg && fm.toast(this);
});
}
},
save = function () {
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();
}),
conf,
res,
tm;
if (!loaded()) {
return saveDfd.resolve();
}
if (ta.editor) {
ta.editor.save(ta[0], ta.editor.instance);
conf = ta.editor.confObj;
if (
conf.info &&
(conf.info.schemeContent || conf.info.arrayBufferContent)
) {
encord = "scheme";
}
}
res = getContent();
setOld(res);
if (res.promise) {
tm = setTimeout(function () {
fm.notify({
type: "chkcontent",
cnt: 1,
hideCnt: true,
cancel: function () {
res.reject();
},
});
}, 100);
res
.always(function () {
tm && clearTimeout(tm);
fm.notify({ type: "chkcontent", cnt: -1 });
})
.done(function (data) {
dfrd.notifyWith(ta, [encord, ta.data("hash"), old, saveDfd]);
})
.fail(function (err) {
saveDfd.reject(err);
});
} else {
dfrd.notifyWith(ta, [encord, ta.data("hash"), old, saveDfd]);
}
return saveDfd;
},
saveon = function () {
if (!loaded()) {
return;
}
save().fail(function (err) {
err && fm.error(err);
});
},
cancel = function () {
ta.elfinderdialog("close");
},
savecl = function () {
if (!loaded()) {
return;
}
dialogNode.hide();
save()
.done(function () {
_loaded = false;
dialogNode.show();
cancel();
})
.fail(function (err) {
dialogNode.show();
err && fm.error(err);
});
},
saveAs = function () {
if (!loaded()) {
return;
}
var prevOld = old,
phash = file.phash,
fail = function (err) {
dialogs.addClass(clsEditing).fadeIn(function () {
err && fm.error(err);
});
old = prevOld;
fm.disable();
},
make = function () {
self.mime = saveAsFile.mime || file.mime;
self.prefix = (saveAsFile.name || file.name).replace(
/ \d+(\.[^.]+)?$/,
"$1"
);
self.requestCmd = "mkfile";
self.nextAction = {};
self.data = { target: phash };
jQuery.proxy(fm.res("mixin", "make"), self)()
.done(function (data) {
var oldHash;
if (data.added && data.added.length) {
oldHash = ta.data("hash");
ta.data("hash", data.added[0].hash);
save()
.done(function () {
_loaded = false;
dialogNode.show();
cancel();
dialogs.fadeIn();
})
.fail(function () {
fm.exec("rm", [data.added[0].hash], {
forceRm: true,
quiet: true,
});
ta.data("hash", oldHash);
dialogNode.find("button.elfinder-btncnt-2").hide();
fail();
});
} else {
fail();
}
})
.progress(function (err) {
if (err && err === "errUploadMime") {
ta.trigger("saveAsFail");
}
})
.fail(fail)
.always(function () {
delete self.mime;
delete self.prefix;
delete self.nextAction;
delete self.data;
});
fm.trigger("unselectfiles", { files: [file.hash] });
},
reqOpen = null,
reqInfo = null,
dialogs = fm.getUI().children("." + self.dialogClass + ":visible");
if (dialogNode.is(":hidden")) {
dialogs = dialogs.add(dialogNode);
}
dialogs.removeClass(clsEditing).fadeOut();
fm.enable();
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 () {
if (reqInfo) {
fm.one("infodone", function () {
fm.file(phash) ? make() : fail("errFolderNotFound");
});
} else {
reqOpen ? fm.one("cwdrender", make) : make();
}
})
.fail(fail);
},
changed = function () {
var dfd = jQuery.Deferred(),
res,
tm;
if (!_loaded) {
return dfd.resolve(false);
}
ta.editor && ta.editor.save(ta[0], ta.editor.instance);
res = getContent();
if (res && res.promise) {
tm = setTimeout(function () {
fm.notify({
type: "chkcontent",
cnt: 1,
hideCnt: true,
cancel: function () {
res.reject();
},
});
}, 100);
res
.always(function () {
tm && clearTimeout(tm);
fm.notify({ type: "chkcontent", cnt: -1 });
})
.done(function (d) {
dfd.resolve(old !== d);
})
.fail(function (err) {
dfd.resolve(err || (old === undefined ? false : true));
});
} else {
dfd.resolve(old !== res);
}
return dfd;
},
opts = {
title: fm.escape(file.name),
width: getDlgWidth(),
height: getDlgHeight(),
buttons: {},
cssClass: clsEditing,
maxWidth: "window",
maxHeight: "window",
allowMinimize: true,
allowMaximize: true,
openMaximized:
editorMaximized() ||
(editor && editor.info && editor.info.openMaximized),
btnHoverFocus: false,
closeOnEscape: false,
propagationEvents: ["mousemove", "mouseup", "click"],
minimize: function () {
var conf;
if (ta.editor && dialogNode.closest(".ui-dialog").is(":hidden")) {
conf = ta.editor.confObj;
if (conf.info && conf.info.syncInterval) {
fileSync(file.hash);
}
}
},
close: function () {
var close = function () {
var conf;
dfrd.resolve();
if (ta.editor) {
ta.editor.close(ta[0], ta.editor.instance);
conf = ta.editor.confObj;
if (conf.info && conf.info.syncInterval) {
fileSync(file.hash);
}
}
ta.elfinderdialog("destroy");
},
onlySaveAs = typeof saveAsFile.name !== "undefined",
accept = onlySaveAs
? {
label: "btnSaveAs",
callback: function () {
requestAnimationFrame(saveAs);
},
}
: {
label: "btnSaveClose",
callback: function () {
save().done(function () {
close();
});
},
};
changed().done(function (change) {
var msgs = ["confirmNotSave"];
if (change) {
if (typeof change === "string") {
msgs.unshift(change);
}
fm.confirm({
title: self.title,
text: msgs,
accept: accept,
cancel: {
label: "btnClose",
callback: close,
},
buttons: onlySaveAs
? null
: [
{
label: "btnSaveAs",
callback: function () {
requestAnimationFrame(saveAs);
},
},
],
});
} else {
close();
}
});
},
open: function () {
var loadRes, conf, interval;
ta.initEditArea.call(ta, id, file, content, fm);
if (ta.editor) {
loadRes = ta.editor.load(ta[0]) || null;
if (loadRes && loadRes.done) {
loadRes
.always(function () {
_loaded = true;
})
.done(function (instance) {
ta.editor.instance = instance;
ta.editor.focus(ta[0], ta.editor.instance);
setOld(getContent());
requestAnimationFrame(function () {
dialogNode.trigger("resize");
});
})
.fail(function (error) {
error && fm.error(error);
ta.elfinderdialog("destroy");
return;
})
.always(makeToasts);
} else {
_loaded = true;
if (
loadRes &&
(typeof loadRes === "string" || Array.isArray(loadRes))
) {
fm.error(loadRes);
ta.elfinderdialog("destroy");
return;
}
ta.editor.instance = loadRes;
ta.editor.focus(ta[0], ta.editor.instance);
setOld(getContent());
requestAnimationFrame(function () {
dialogNode.trigger("resize");
});
makeToasts();
}
conf = ta.editor.confObj;
if (conf.info && conf.info.syncInterval) {
if ((interval = parseInt(conf.info.syncInterval))) {
setTimeout(function () {
autoSync(interval);
}, interval);
}
}
} else {
_loaded = true;
setOld(getContent());
}
},
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();
}
return res;
},
setOld = function (res) {
if (res && res.promise) {
res.done(function (d) {
old = d;
});
} else {
old = res;
}
},
autoSync = function (interval) {
if (dialogNode.is(":visible")) {
fileSync(file.hash);
setTimeout(function () {
autoSync(interval);
}, interval);
}
},
stateChange = function () {
if (selEncoding) {
changed().done(function (change) {
if (change) {
selEncoding
.attr("title", fm.i18n("saveAsEncoding"))
.addClass("elfinder-edit-changed");
} else {
selEncoding
.attr("title", fm.i18n("openAsEncoding"))
.removeClass("elfinder-edit-changed");
}
});
}
},
saveAsFile = {},
ta,
old,
dialogNode,
selEncoding,
extEditor,
maxW,
syncInterval;
if (editor) {
if (editor.html) {
ta = jQuery(editor.html);
}
extEditor = {
init: editor.init || null,
load: editor.load,
getContent: editor.getContent || null,
save: editor.save,
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 () {},
instance: null,
doSave: saveon,
doCancel: cancel,
doClose: savecl,
file: file,
fm: fm,
confObj: editor,
trigger: function (evName, data) {
fm.trigger(
"editEditor" + evName,
Object.assign({}, editor.info || {}, data)
);
},
};
}
if (!ta) {
if (!fm.mimeIsText(file.mime)) {
return dfrd.reject("errEditorNotFound");
}
(function () {
ta = jQuery(
'<textarea class="elfinder-file-edit" rows="20" id="' +
id +
'-ta"></textarea>'
).on("input propertychange", stateChange);
if (!editor || !editor.info || editor.info.useTextAreaEvent) {
ta.on("keydown", function (e) {
var code = e.keyCode,
value,
start;
e.stopPropagation();
if (code == jQuery.ui.keyCode.TAB) {
e.preventDefault();
// insert tab on tab press
if (this.setSelectionRange) {
value = this.value;
start = this.selectionStart;
this.value =
value.substr(0, start) +
"\t" +
value.substr(this.selectionEnd);
start += 1;
this.setSelectionRange(start, start);
}
}
if (e.ctrlKey || e.metaKey) {
// close on ctrl+w/q
if (code == "Q".charCodeAt(0) || code == "W".charCodeAt(0)) {
e.preventDefault();
cancel();
}
if (code == "S".charCodeAt(0)) {
e.preventDefault();
saveon();
}
}
}).on("mouseenter", function () {
this.focus();
});
}
ta.initEditArea = function (id, file, content) {
// ta.hide() for performance tune. Need ta.show() in `load()` if use textarea node.
ta.hide().val(content);
this._setupSelEncoding(content);
};
})();
}
// extended function to setup selector of encoding for text editor
ta._setupSelEncoding = function (content) {
var heads =
encoding && encoding !== "unknown" ? [{ value: encoding }] : [],
wfake = jQuery("<select></select>").hide(),
setSelW = function (init) {
init && wfake.appendTo(selEncoding.parent());
wfake
.empty()
.append(jQuery("<option></option>").text(selEncoding.val()));
selEncoding.width(wfake.width());
};
if (content === "" || !encoding || encoding !== "UTF-8") {
heads.push({ value: "UTF-8" });
}
selEncoding = getEncSelect(heads)
.on("touchstart", function (e) {
// for touch punch event handler
e.stopPropagation();
})
.on("change", function () {
// reload to change encoding if not edited
changed().done(function (change) {
if (!change && getContent() !== "") {
cancel();
edit(file, selEncoding.val(), editor).fail(function (err) {
err && fm.error(err);
});
}
});
setSelW();
})
.on("mouseover", stateChange);
ta.parent()
.next()
.prepend(
jQuery(
'<div class="ui-dialog-buttonset elfinder-edit-extras"></div>'
).append(selEncoding)
);
setSelW(true);
};
ta.data("hash", file.hash);
if (extEditor) {
ta.editor = extEditor;
if (typeof extEditor.beforeclose === "function") {
opts.beforeclose = function () {
return extEditor.beforeclose(ta[0], extEditor.instance);
};
}
if (typeof extEditor.init === "function") {
ta.initEditArea = extEditor.init;
}
if (typeof extEditor.getContent === "function") {
ta.getContent = extEditor.getContent;
}
}
if (!ta.initEditArea) {
ta.initEditArea = function () {};
}
if (!ta.getContent) {
ta.getContent = function () {
return rtrim(ta.val());
};
}
if (!editor || !editor.info || !editor.info.preventGet) {
opts.buttons[fm.i18n("btnSave")] = saveon;
opts.buttons[fm.i18n("btnSaveClose")] = savecl;
opts.buttons[fm.i18n("btnSaveAs")] = saveAs;
opts.buttons[fm.i18n("btnCancel")] = cancel;
}
if (editor && typeof editor.prepare === "function") {
editor.prepare(ta, opts, file);
}
dialogNode = self
.fmDialog(ta, opts)
.attr("id", id)
.on("keydown keyup keypress", function (e) {
e.stopPropagation();
})
.css({ overflow: "hidden", minHeight: "7em" })
.addClass("elfinder-edit-editor")
.closest(".ui-dialog")
.on("changeType", function (e, data) {
if (data.extention && data.mime) {
var ext = data.extention,
mime = data.mime,
btnSet = jQuery(this)
.children(".ui-dialog-buttonpane")
.children(".ui-dialog-buttonset");
btnSet.children(".elfinder-btncnt-0,.elfinder-btncnt-1").hide();
saveAsFile.name =
fm.splitFileExtention(file.name)[0] + "." + data.extention;
saveAsFile.mime = data.mime;
if (!data.keepEditor) {
btnSet.children(".elfinder-btncnt-2").trigger("click");
}
}
});
// care to viewport scale change with mobile devices
maxW = (fm.options.dialogContained ? fm.getUI() : jQuery(window)).width();
dialogNode.width() > maxW && dialogNode.width(maxW);
return dfrd.promise();
},
/**
* Get file content and
* open dialog with textarea to edit file content
*
* @param String file hash
* @return jQuery.Deferred
**/
edit = function (file, convert, editor) {
var hash = file.hash,
opts = fm.options,
dfrd = jQuery.Deferred(),
id = "edit-" + fm.namespace + "-" + file.hash,
d = fm.getUI().find("#" + id),
conv = !convert ? 0 : convert,
noContent = false,
req,
error,
res;
if (d.length) {
d.elfinderdialog("toTop");
return dfrd.resolve();
}
if (
!file.read ||
(!file.write && (!editor.info || !editor.info.converter))
) {
error = ["errOpen", file.name, "errPerm"];
return dfrd.reject(error);
}
if (editor && editor.info) {
if (typeof editor.info.edit === "function") {
res = editor.info.edit.call(fm, file, editor);
if (res.promise) {
res
.done(function () {
dfrd.resolve();
})
.fail(function (error) {
dfrd.reject(error);
});
} else {
res ? dfrd.resolve() : dfrd.reject();
}
return dfrd;
}
noContent = editor.info.preventGet || editor.info.noContent;
if (editor.info.urlAsContent || noContent) {
req = jQuery.Deferred();
if (editor.info.urlAsContent) {
fm.url(hash, { async: true, onetime: true, temporary: true }).done(
function (url) {
req.resolve({ content: url });
}
);
} else {
req.resolve({});
}
} else {
if (conv) {
file.encoding = conv;
fm.cache(file, "change");
}
req = fm.request({
data: { cmd: "get", target: hash, conv: conv, _t: file.ts },
options: { type: "get", cache: true },
notify: { type: "file", cnt: 1 },
preventDefault: true,
});
}
req
.done(function (data) {
var selEncoding, reg, m, res;
if (data.doconv) {
fm.confirm({
title: self.title,
text:
data.doconv === "unknown"
? "confirmNonUTF8"
: "confirmConvUTF8",
accept: {
label: "btnConv",
callback: function () {
dfrd = edit(file, selEncoding.val(), editor);
},
},
cancel: {
label: "btnCancel",
callback: function () {
dfrd.reject();
},
},
optionsCallback: function (options) {
options.create = function () {
var base = jQuery(
'<div class="elfinder-dialog-confirm-encoding"></div>'
),
head = { value: data.doconv },
detected;
if (data.doconv === "unknown") {
head.caption = "-";
}
selEncoding = getEncSelect([head]);
jQuery(this)
.next()
.find(".ui-dialog-buttonset")
.prepend(
base.append(
jQuery(
"<label>" + fm.i18n("encoding") + " </label>"
).append(selEncoding)
)
);
};
},
});
} else {
if (!noContent && fm.mimeIsText(file.mime)) {
reg = new RegExp(
"^(data:" +
file.mime.replace(/([.+])/g, "\\$1") +
";base64,)",
"i"
);
if (!editor.info.dataScheme) {
if (window.atob && (m = data.content.match(reg))) {
data.content = atob(data.content.substr(m[1].length));
}
} else {
if (window.btoa && !data.content.match(reg)) {
data.content =
"data:" + file.mime + ";base64," + btoa(data.content);
}
}
}
dialog(id, file, data.content, data.encoding, editor, data.toasts)
.done(function (data) {
dfrd.resolve(data);
})
.progress(function (encoding, newHash, data, saveDfd) {
var ta = this;
if (newHash) {
hash = newHash;
}
fm.request({
options: { type: "post" },
data: {
cmd: "put",
target: hash,
encoding: encoding || data.encoding,
content: data,
},
notify: { type: "save", cnt: 1 },
syncOnFail: true,
preventFail: true,
navigate: {
target: "changed",
toast: {
inbuffer: {
msg: fm.i18n(["complete", fm.i18n("btnSave")]),
},
},
},
})
.fail(function (error) {
dfrd.reject(error);
saveDfd.reject();
})
.done(function (data) {
requestAnimationFrame(function () {
ta.trigger("focus");
ta.editor && ta.editor.focus(ta[0], ta.editor.instance);
});
saveDfd.resolve();
});
})
.fail(function (error) {
dfrd.reject(error);
});
}
})
.fail(function (error) {
var err = fm.parseError(error);
err = Array.isArray(err) ? err[0] : err;
if (file.encoding) {
file.encoding = "";
fm.cache(file, "change");
}
err !== "errConvUTF8" && fm.sync();
dfrd.reject(error);
});
}
return dfrd.promise();
},
/**
* Current editors of selected files
*
* @type Object
*/
editors = {},
/**
* Fallback editor (Simple text editor)
*
* @type Object
*/
fallbackEditor = {
// Simple Text (basic textarea editor)
info: {
id: "textarea",
name: "TextArea",
useTextAreaEvent: true,
},
load: function (textarea) {
// trigger event 'editEditorPrepare'
this.trigger("Prepare", {
node: textarea,
editorObj: void 0,
instance: void 0,
opts: {},
});
textarea.setSelectionRange && textarea.setSelectionRange(0, 0);
jQuery(textarea).trigger("focus").show();
},
save: function () {},
},
/**
* Set current editors
*
* @param Object file object
* @param Number cnt count of selected items
* @return Void
*/
setEditors = function (file, cnt) {
var mimeMatch = function (fileMime, editorMimes) {
if (!editorMimes) {
return fm.mimeIsText(fileMime);
} else {
if (
editorMimes[0] === "*" ||
jQuery.inArray(fileMime, editorMimes) !== -1
) {
return true;
}
var i, l;
l = editorMimes.length;
for (i = 0; i < l; i++) {
if (fileMime.indexOf(editorMimes[i]) === 0) {
return true;
}
}
return false;
}
},
extMatch = function (fileName, editorExts) {
if (!editorExts || !editorExts.length) {
return true;
}
var ext = fileName
.replace(/^.+\.([^.]+)|(.+)$/, "$1$2")
.toLowerCase(),
i,
l;
l = editorExts.length;
for (i = 0; i < l; i++) {
if (ext === editorExts[i].toLowerCase()) {
return true;
}
}
return false;
},
optEditors = self.options.editors || [],
cwdWrite = fm.cwd().write;
stored = fm.storage("storedEditors") || {};
editors = {};
if (!optEditors.length) {
optEditors = [fallbackEditor];
}
jQuery.each(optEditors, function (i, editor) {
var name;
if (
(cnt === 1 || !editor.info.single) &&
(!editor.info || !editor.info.converter ? file.write : cwdWrite) &&
(file.size > 0 ||
(!editor.info.converter &&
editor.info.canMakeEmpty !== false &&
fm.mimesCanMakeEmpty[file.mime])) &&
(!editor.info.maxSize || file.size <= editor.info.maxSize) &&
mimeMatch(file.mime, editor.mimes || null) &&
extMatch(file.name, editor.exts || null) &&
typeof editor.load == "function" &&
typeof editor.save == "function"
) {
name = editor.info.name ? editor.info.name : "Code Editor";
(editor.id = editor.info.id ? editor.info.id : "editor" + i),
(editor.name = name);
editor.i18n = fm.i18n(name);
editors[editor.id] = editor;
}
});
return Object.keys(editors).length ? true : false;
},
store = function (mime, editor) {
if (mime && editor) {
if (!jQuery.isPlainObject(stored)) {
stored = {};
}
stored[mime] = editor.id;
fm.storage("storedEditors", stored);
fm.trigger("selectfiles", { files: fm.selected() });
}
},
useStoredEditor = function () {
var d = fm.storage("useStoredEditor");
return d ? d > 0 : self.options.useStoredEditor;
},
editorMaximized = function () {
var d = fm.storage("editorMaximized");
return d ? d > 0 : self.options.editorMaximized;
},
getSubMenuRaw = function (files, callback) {
var subMenuRaw = [];
jQuery.each(editors, function (id, ed) {
subMenuRaw.push({
label: fm.escape(ed.i18n),
icon: ed.info && ed.info.icon ? ed.info.icon : "edit",
options: {
iconImg:
ed.info && ed.info.iconImg
? fm.baseUrl + ed.info.iconImg
: void 0,
},
callback: function () {
store(files[0].mime, ed);
callback && callback.call(ed);
},
});
});
return subMenuRaw;
},
getStoreId = function (name) {
// for compatibility to previous version
return name.toLowerCase().replace(/ +/g, "");
},
getStoredEditor = function (mime) {
var name = stored[mime];
return name && Object.keys(editors).length
? editors[getStoreId(name)]
: void 0;
},
infoRequest = function () {},
stored;
// make public method
this.getEncSelect = getEncSelect;
this.shortcuts = [
{
pattern: "ctrl+e",
},
];
this.init = function () {
var self = this,
fm = this.fm,
opts = this.options,
cmdChecks = [],
ccData,
dfd;
this.onlyMimes = this.options.mimes || [];
fm.one("open", function () {
// editors setup
if (opts.editors && Array.isArray(opts.editors)) {
fm.trigger("canMakeEmptyFile", {
mimes: Object.keys(fm.storage("mkfileTextMimes") || {}).concat(
opts.makeTextMimes || ["text/plain"]
),
});
jQuery.each(opts.editors, function (i, editor) {
if (editor.info && editor.info.cmdCheck) {
cmdChecks.push(editor.info.cmdCheck);
}
});
if (cmdChecks.length) {
if (fm.api >= 2.103) {
dfd = fm
.request({
data: {
cmd: "editor",
name: cmdChecks,
method: "enabled",
},
preventDefault: true,
})
.done(function (d) {
ccData = d;
})
.fail(function () {
ccData = {};
});
} else {
ccData = {};
dfd = jQuery.Deferred().resolve();
}
} else {
dfd = jQuery.Deferred().resolve();
}
dfd.always(function () {
if (ccData) {
opts.editors = jQuery.grep(opts.editors, function (e) {
if (e.info && e.info.cmdCheck) {
return ccData[e.info.cmdCheck] ? true : false;
} else {
return true;
}
});
}
jQuery.each(opts.editors, function (i, editor) {
if (editor.setup && typeof editor.setup === "function") {
editor.setup.call(editor, opts, fm);
}
if (!editor.disabled) {
if (editor.mimes && Array.isArray(editor.mimes)) {
mimesSingle = mimesSingle.concat(editor.mimes);
if (!editor.info || !editor.info.single) {
mimes = mimes.concat(editor.mimes);
}
}
if (!allowAll && editor.mimes && editor.mimes[0] === "*") {
allowAll = true;
}
if (!editor.info) {
editor.info = {};
}
if (editor.info.integrate) {
fm.trigger(
"helpIntegration",
Object.assign({ cmd: "edit" }, editor.info.integrate)
);
}
if (editor.info.canMakeEmpty) {
fm.trigger("canMakeEmptyFile", {
mimes: Array.isArray(editor.info.canMakeEmpty)
? editor.info.canMakeEmpty
: editor.mimes,
});
}
}
});
mimesSingle = (jQuery.uniqueSort || jQuery.unique)(mimesSingle);
mimes = (jQuery.uniqueSort || jQuery.unique)(mimes);
opts.editors = jQuery.grep(opts.editors, function (e) {
return e.disabled ? false : true;
});
});
}
})
.bind("select", function () {
editors = null;
})
.bind("contextmenucreate", function (e) {
var file,
editor,
single = function (editor) {
var title = self.title;
fm.one("contextmenucreatedone", function () {
self.title = title;
});
self.title = fm.escape(editor.i18n);
if (editor.info && editor.info.iconImg) {
self.contextmenuOpts = {
iconImg: fm.baseUrl + editor.info.iconImg,
};
}
delete self.variants;
};
self.contextmenuOpts = void 0;
if (e.data.type === "files" && self.enabled()) {
file = fm.file(e.data.targets[0]);
if (setEditors(file, e.data.targets.length)) {
if (Object.keys(editors).length > 1) {
if (
!useStoredEditor() ||
!(editor = getStoredEditor(file.mime))
) {
delete self.extra;
self.variants = [];
jQuery.each(editors, function (id, editor) {
self.variants.push([
{ editor: editor },
editor.i18n,
editor.info && editor.info.iconImg
? fm.baseUrl + editor.info.iconImg
: "edit",
]);
});
} else {
single(editor);
self.extra = {
icon: "menu",
node: jQuery("<span></span>")
.attr({ title: fm.i18n("select") })
.on("click touchstart", function (e) {
if (
e.type === "touchstart" &&
e.originalEvent.touches.length > 1
) {
return;
}
var node = jQuery(this);
e.stopPropagation();
e.preventDefault();
fm.trigger("contextmenu", {
raw: getSubMenuRaw(fm.selectedFiles(), function () {
var hashes = fm.selected();
fm.exec("edit", hashes, { editor: this });
fm.trigger("selectfiles", { files: hashes });
}),
x: node.offset().left,
y: node.offset().top,
});
}),
};
}
} else {
single(editors[Object.keys(editors)[0]]);
delete self.extra;
}
}
}
})
.bind("canMakeEmptyFile", function (e) {
if (e.data && e.data.resetTexts) {
var defs = fm.arrayFlip(self.options.makeTextMimes || ["text/plain"]),
hides = self.getMkfileHides();
jQuery.each(fm.storage("mkfileTextMimes") || {}, function (mime, type) {
if (!defs[mime]) {
delete fm.mimesCanMakeEmpty[mime];
delete hides[mime];
}
});
fm.storage("mkfileTextMimes", null);
if (Object.keys(hides).length) {
fm.storage("mkfileHides", hides);
} else {
fm.storage("mkfileHides", null);
}
}
});
};
this.getstate = function (select) {
var sel = this.files(select),
cnt = sel.length;
return cnt && filter(sel).length == cnt ? 0 : -1;
};
this.exec = function (select, opts) {
var fm = this.fm,
files = filter(this.files(select)),
hashes = jQuery.map(files, function (f) {
return f.hash;
}),
list = [],
editor = opts && opts.editor ? opts.editor : null,
node = jQuery(
opts && opts._currentNode
? opts._currentNode
: fm.cwdHash2Elm(hashes[0])
),
getEditor = function () {
var dfd = jQuery.Deferred(),
storedId;
if (!editor && Object.keys(editors).length > 1) {
if (useStoredEditor() && (editor = getStoredEditor(files[0].mime))) {
return dfd.resolve(editor);
}
fm.trigger("contextmenu", {
raw: getSubMenuRaw(files, function () {
dfd.resolve(this);
}),
x: node.offset().left,
y: node.offset().top + 22,
opened: function () {
fm.one("closecontextmenu", function () {
requestAnimationFrame(function () {
if (dfd.state() === "pending") {
dfd.reject();
}
});
});
},
});
fm.trigger("selectfiles", { files: hashes });
return dfd;
} else {
Object.keys(editors).length > 1 &&
editor &&
store(files[0].mime, editor);
return dfd.resolve(
editor
? editor
: Object.keys(editors).length
? editors[Object.keys(editors)[0]]
: null
);
}
},
dfrd = jQuery.Deferred(),
file;
if (editors === null) {
setEditors(files[0], hashes.length);
}
if (!node.length) {
node = fm.getUI("cwd");
}
getEditor()
.done(function (editor) {
while ((file = files.shift())) {
list.push(
edit(file, file.encoding || void 0, editor).fail(function (error) {
error && fm.error(error);
})
);
}
if (list.length) {
jQuery.when
.apply(null, list)
.done(function () {
dfrd.resolve();
})
.fail(function () {
dfrd.reject();
});
} else {
dfrd.reject();
}
})
.fail(function () {
dfrd.reject();
});
return dfrd;
};
this.getMkfileHides = function () {
return (
fm.storage("mkfileHides") ||
fm.arrayFlip(self.options.mkfileHideMimes || [])
);
};
};