mkfile.js000064400000003213150732265460006362 0ustar00/** * @class elFinder command "mkfile" * Create new empty file * * @author Dmitry (dio) Levashov **/ elFinder.prototype.commands.mkfile = function() { "use strict"; var self = this; this.disableOnSearch = true; this.updateOnSelect = false; this.mime = 'text/plain'; this.prefix = 'untitled file.txt'; this.variants = []; this.getTypeName = function(mime, type) { var fm = self.fm, name; if (name = fm.messages['kind' + fm.kinds[mime]]) { name = fm.i18n(['extentiontype', type.toUpperCase(), name]); } else { name = fm.i18n(['extentionfile', type.toUpperCase()]); } return name; }; this.fm.bind('open reload canMakeEmptyFile', function() { var fm = self.fm, hides = fm.getCommand('edit').getMkfileHides(); self.variants = []; if (fm.mimesCanMakeEmpty) { jQuery.each(fm.mimesCanMakeEmpty, function(mime, type) { type && !hides[mime] && fm.uploadMimeCheck(mime) && self.variants.push([mime, self.getTypeName(mime, type)]); }); } self.change(); }); this.getstate = function() { return this.fm.cwd().write ? 0 : -1; }; this.exec = function(_dum, mime) { var fm = self.fm, type, err; if (type = fm.mimesCanMakeEmpty[mime]) { if (fm.uploadMimeCheck(mime)) { this.mime = mime; this.prefix = fm.i18n(['untitled file', type]); var prefix_val = this.prefix; if(prefix_val.includes("untitled file")){ prefix_val.replace("untitled file", "NewFile"); this.prefix = prefix_val; } return jQuery.proxy(fm.res('mixin', 'make'), self)(); } err = ['errMkfile', self.getTypeName(mime, type)]; } return jQuery.Deferred().reject(err); }; }; copy.js000064400000001732150732265460006071 0ustar00/** * @class elFinder command "copy". * Put files in filemanager clipboard. * * @type elFinder.command * @author Dmitry (dio) Levashov */ elFinder.prototype.commands.copy = function() { "use strict"; this.shortcuts = [{ pattern : 'ctrl+c ctrl+insert' }]; this.getstate = function(select) { var sel = this.files(select), cnt = sel.length, filter = function(files) { var fres = true; return jQuery.grep(files, function(f) { fres = fres && f.read ? true : false; return fres; }); }; return cnt && filter(sel).length == cnt ? 0 : -1; }; this.exec = function(hashes) { var fm = this.fm, dfrd = jQuery.Deferred() .fail(function(error) { fm.error(error); }); jQuery.each(this.files(hashes), function(i, file) { if (! file.read) { return !dfrd.reject(['errCopy', file.name, 'errPerm']); } }); return dfrd.state() == 'rejected' ? dfrd : dfrd.resolve(fm.clipboard(this.hashes(hashes))); }; }; empty.js000064400000006503150732265460006256 0ustar00/** * @class elFinder command "empty". * Empty the folder * * @type elFinder.command * @author Naoki Sawada */ elFinder.prototype.commands.empty = function() { "use strict"; var self, fm, selFiles = function(select) { var sel = self.files(select); if (!sel.length) { sel = [ fm.cwd() ]; } return sel; }; this.linkedCmds = ['rm']; this.init = function() { // lazy assign to make possible to become superclass self = this; fm = this.fm; }; this.getstate = function(select) { var sel = selFiles(select), cnt, filter = function(files) { var fres = true; return jQuery.grep(files, function(f) { fres = fres && f.read && f.write && f.mime === 'directory' ? true : false; return fres; }); }; cnt = sel.length; return filter(sel).length == cnt ? 0 : -1; }; this.exec = function(hashes) { var dirs = selFiles(hashes), cnt = dirs.length, dfrd = jQuery.Deferred() .done(function() { var data = {changed: {}}; fm.toast({msg: fm.i18n(['"'+success.join('", ')+'"', 'complete', fm.i18n('cmdempty')])}); jQuery.each(dirs, function(i, dir) { data.changed[dir.hash] = dir; }); fm.change(data); }) .always(function() { var cwd = fm.cwd().hash; fm.trigger('selectfiles', {files: jQuery.map(dirs, function(d) { return cwd === d.phash? d.hash : null; })}); }), success = [], done = function(res) { if (typeof res === 'number') { success.push(dirs[res].name); delete dirs[res].dirs; } else { res && fm.error(res); } (--cnt < 1) && dfrd[success.length? 'resolve' : 'reject'](); }; jQuery.each(dirs, function(i, dir) { var tm; if (!(dir.write && dir.mime === 'directory')) { done(['errEmpty', dir.name, 'errPerm']); return null; } if (!fm.isCommandEnabled('rm', dir.hash)) { done(['errCmdNoSupport', '"rm"']); return null; } tm = setTimeout(function() { fm.notify({type : 'search', cnt : 1, hideCnt : cnt > 1? false : true}); }, fm.notifyDelay); fm.request({ data : {cmd : 'open', target : dir.hash}, preventDefault : true, asNotOpen : true }).done(function(data) { var targets = []; tm && clearTimeout(tm); if (fm.ui.notify.children('.elfinder-notify-search').length) { fm.notify({type : 'search', cnt : -1, hideCnt : cnt > 1? false : true}); } if (data && data.files && data.files.length) { if (data.files.length > fm.maxTargets) { done(['errEmpty', dir.name, 'errMaxTargets', fm.maxTargets]); } else { fm.updateCache(data); jQuery.each(data.files, function(i, f) { if (!f.write || f.locked) { done(['errEmpty', dir.name, 'errRm', f.name, 'errPerm']); targets = []; return false; } targets.push(f.hash); }); if (targets.length) { fm.exec('rm', targets, { _userAction : true, addTexts : [ fm.i18n('folderToEmpty', dir.name) ] }) .fail(function(error) { fm.trigger('unselectfiles', {files: fm.selected()}); done(fm.parseError(error) || ''); }) .done(function() { done(i); }); } } } else { fm.toast({ mode: 'warning', msg: fm.i18n('filderIsEmpty', dir.name)}); done(''); } }).fail(function(error) { done(fm.parseError(error) || ''); }); }); return dfrd; }; }; restore.js000064400000016711150732265460006605 0ustar00/** * @class elFinder command "restore" * Restore items from the trash * * @author Naoki Sawada **/ (elFinder.prototype.commands.restore = function() { "use strict"; var self = this, fm = this.fm, fakeCnt = 0, getFilesRecursively = function(files) { var dfd = jQuery.Deferred(), dirs = [], results = [], reqs = [], phashes = [], getFile; dfd._xhrReject = function() { jQuery.each(reqs, function() { this && this.reject && this.reject(); }); getFile && getFile._xhrReject(); }; jQuery.each(files, function(i, f) { f.mime === 'directory'? dirs.push(f) : results.push(f); }); if (dirs.length) { jQuery.each(dirs, function(i, d) { reqs.push(fm.request({ data : {cmd : 'open', target : d.hash}, preventDefault : true, asNotOpen : true })); phashes[i] = d.hash; }); jQuery.when.apply($, reqs).fail(function() { dfd.reject(); }).done(function() { var items = []; jQuery.each(arguments, function(i, r) { var files; if (r.files) { if (r.files.length) { items = items.concat(r.files); } else { items.push({ hash: 'fakefile_' + (fakeCnt++), phash: phashes[i], mime: 'fakefile', name: 'fakefile', ts: 0 }); } } }); fm.cache(items); getFile = getFilesRecursively(items).done(function(res) { results = results.concat(res); dfd.resolve(results); }); }); } else { dfd.resolve(results); } return dfd; }, restore = function(dfrd, files, targets, ops) { var rHashes = {}, others = [], found = false, dirs = [], opts = ops || {}, id = +new Date(), tm, getFile; fm.lockfiles({files : targets}); dirs = jQuery.map(files, function(f) { return f.mime === 'directory'? f.hash : null; }); dfrd.done(function() { dirs && fm.exec('rm', dirs, {forceRm : true, quiet : true}); }).always(function() { fm.unlockfiles({files : targets}); }); tm = setTimeout(function() { fm.notify({type : 'search', id : id, cnt : 1, hideCnt : true, cancel : function() { getFile && getFile._xhrReject(); dfrd.reject(); }}); }, fm.notifyDelay); fakeCnt = 0; getFile = getFilesRecursively(files).always(function() { tm && clearTimeout(tm); fm.notify({type : 'search', id: id, cnt : -1, hideCnt : true}); }).fail(function() { dfrd.reject('errRestore', 'errFileNotFound'); }).done(function(res) { var errFolderNotfound = ['errRestore', 'errFolderNotFound'], dirTop = ''; if (res.length) { jQuery.each(res, function(i, f) { var phash = f.phash, pfile, srcRoot, tPath; while(phash) { if (srcRoot = fm.trashes[phash]) { if (! rHashes[srcRoot]) { if (found) { // Keep items of other trash others.push(f.hash); return null; // continue jQuery.each } rHashes[srcRoot] = {}; found = true; } tPath = fm.path(f.hash).substr(fm.path(phash).length).replace(/\\/g, '/'); tPath = tPath.replace(/\/[^\/]+?$/, ''); if (tPath === '') { tPath = '/'; } if (!rHashes[srcRoot][tPath]) { rHashes[srcRoot][tPath] = []; } if (f.mime === 'fakefile') { fm.updateCache({removed:[f.hash]}); } else { rHashes[srcRoot][tPath].push(f.hash); } if (!dirTop || dirTop.length > tPath.length) { dirTop = tPath; } break; } // Go up one level for next check pfile = fm.file(phash); if (!pfile) { phash = false; // Detection method for search results jQuery.each(fm.trashes, function(ph) { var file = fm.file(ph), filePath = fm.path(ph); if ((!file.volumeid || f.hash.indexOf(file.volumeid) === 0) && fm.path(f.hash).indexOf(filePath) === 0) { phash = ph; return false; } }); } else { phash = pfile.phash; } } }); if (found) { jQuery.each(rHashes, function(src, dsts) { var dirs = Object.keys(dsts), cnt = dirs.length; fm.request({ data : {cmd : 'mkdir', target : src, dirs : dirs}, notify : {type : 'chkdir', cnt : cnt}, preventFail : true }).fail(function(error) { dfrd.reject(error); fm.unlockfiles({files : targets}); }).done(function(data) { var cmdPaste, hashes; if (hashes = data.hashes) { cmdPaste = fm.getCommand('paste'); if (cmdPaste) { // wait until file cache made fm.one('mkdirdone', function() { var hasErr = false; jQuery.each(dsts, function(dir, files) { if (hashes[dir]) { if (files.length) { if (fm.file(hashes[dir])) { fm.clipboard(files, true); fm.exec('paste', [ hashes[dir] ], {_cmd : 'restore', noToast : (opts.noToast || dir !== dirTop)}) .done(function(data) { if (data && (data.error || data.warning)) { hasErr = true; } }) .fail(function() { hasErr = true; }) .always(function() { if (--cnt < 1) { dfrd[hasErr? 'reject' : 'resolve'](); if (others.length) { // Restore items of other trash fm.exec('restore', others); } } }); } else { dfrd.reject(errFolderNotfound); } } else { if (--cnt < 1) { dfrd.resolve(); if (others.length) { // Restore items of other trash fm.exec('restore', others); } } } } }); }); } else { dfrd.reject(['errRestore', 'errCmdNoSupport', '(paste)']); } } else { dfrd.reject(errFolderNotfound); } }); }); } else { dfrd.reject(errFolderNotfound); } } else { dfrd.reject('errFileNotFound'); dirs && fm.exec('rm', dirs, {forceRm : true, quiet : true}); } }); }; // for to be able to overwrite this.restore = restore; this.linkedCmds = ['copy', 'paste', 'mkdir', 'rm']; this.updateOnSelect = false; this.init = function() { // re-assign for extended command self = this; fm = this.fm; }; this.getstate = function(sel, e) { sel = sel || fm.selected(); return sel.length && jQuery.grep(sel, function(h) {var f = fm.file(h); return f && ! f.locked && ! fm.isRoot(f)? true : false; }).length == sel.length ? 0 : -1; }; this.exec = function(hashes, opts) { var dfrd = jQuery.Deferred() .fail(function(error) { error && fm.error(error); }), files = self.files(hashes); if (! files.length) { return dfrd.reject(); } jQuery.each(files, function(i, file) { if (fm.isRoot(file)) { return !dfrd.reject(['errRestore', file.name]); } if (file.locked) { return !dfrd.reject(['errLocked', file.name]); } }); if (dfrd.state() === 'pending') { this.restore(dfrd, files, hashes, opts); } return dfrd; }; }).prototype = { forceLoad : true }; // this is required command rm.js000064400000034652150732265460005544 0ustar00/** * @class elFinder command "rm" * Delete files * * @author Dmitry (dio) Levashov * @author Naoki Sawada **/ elFinder.prototype.commands.rm = function() { "use strict"; var self = this, fm = this.fm, tpl = '
{title}
{desc}
', confirm = function(dfrd, targets, files, tHash, addTexts) { var cnt = targets.length, cwd = fm.cwd().hash, descs = [], spinner = fm.i18n('calc') + '', dialog, text, tmb, size, f, fname; if (cnt > 1) { size = 0; jQuery.each(files, function(h, f) { if (f.size && f.size != 'unknown' && f.mime !== 'directory') { var s = parseInt(f.size); if (s >= 0 && size >= 0) { size += s; } } else { size = 'unknown'; return false; } }); getSize = (size === 'unknown'); descs.push(fm.i18n('size')+': '+(getSize? spinner : fm.formatSize(size))); text = [jQuery(tpl.replace('{class}', 'elfinder-cwd-icon-group').replace('{title}', '' + fm.i18n('items')+ ': ' + cnt + '').replace('{desc}', descs.join('
')))]; } else { f = files[0]; tmb = fm.tmb(f); getSize = (f.mime === 'directory'); descs.push(fm.i18n('size')+': '+(getSize? spinner : fm.formatSize(f.size))); descs.push(fm.i18n('modify')+': '+fm.formatDate(f)); fname = fm.escape(f.i18 || f.name).replace(/([_.])/g, '​$1'); text = [jQuery(tpl.replace('{class}', fm.mime2class(f.mime)).replace('{title}', '' + fname + '').replace('{desc}', descs.join('
')))]; } if (addTexts) { text = text.concat(addTexts); } text.push(tHash? 'confirmTrash' : 'confirmRm'); dialog = fm.confirm({ title : self.title, text : text, accept : { label : 'btnRm', callback : function() { if (tHash) { self.toTrash(dfrd, targets, tHash); } else { remove(dfrd, targets); } } }, cancel : { label : 'btnCancel', callback : function() { fm.unlockfiles({files : targets}); if (targets.length === 1 && fm.file(targets[0]).phash !== cwd) { fm.select({selected : targets}); } else { fm.selectfiles({files : targets}); } dfrd.reject(); } } }); // load thumbnail if (tmb) { jQuery('') .on('load', function() { dialog.find('.elfinder-cwd-icon').addClass(tmb.className).css('background-image', "url('"+tmb.url+"')"); }) .attr('src', tmb.url); } if (getSize) { getSize = fm.getSize(jQuery.map(files, function(f) { return f.mime === 'directory'? f.hash : null; })).done(function(data) { dialog.find('span.elfinder-spinner').parent().html(fm.i18n('size')+': '+data.formated); }).fail(function() { dialog.find('span.elfinder-spinner').parent().html(fm.i18n('size')+': '+fm.i18n('unknown')); }).always(function() { getSize = false; }); } }, toTrash = function(dfrd, targets, tHash) { var dsts = {}, itemCnt = targets.length, maxCnt = self.options.toTrashMaxItems, checkDirs = [], reqDfd = jQuery.Deferred(), req, dirs, cnt; if (itemCnt > maxCnt) { self.confirm(dfrd, targets, self.files(targets), null, [fm.i18n('tooManyToTrash')]); return; } // Directory preparation preparation and directory enumeration jQuery.each(targets, function(i, h) { var file = fm.file(h), path = fm.path(h).replace(/\\/g, '/'), m = path.match(/^[^\/]+?(\/(?:[^\/]+?\/)*)[^\/]+?$/); if (file) { if (m) { m[1] = m[1].replace(/(^\/.*?)\/?$/, '$1'); if (! dsts[m[1]]) { dsts[m[1]] = []; } dsts[m[1]].push(h); } if (file.mime === 'directory') { checkDirs.push(h); } } }); // Check directory information if (checkDirs.length) { req = fm.request({ data : {cmd : 'size', targets : checkDirs}, notify : {type: 'readdir', cnt: 1, hideCnt: true}, preventDefault : true }).done(function(data) { var cnt = 0; data.fileCnt && (cnt += parseInt(data.fileCnt)); data.dirCnt && (cnt += parseInt(data.dirCnt)); reqDfd[cnt > maxCnt ? 'reject' : 'resolve'](); }).fail(function() { reqDfd.reject(); }); setTimeout(function() { var xhr = (req && req.xhr)? req.xhr : null; if (xhr && xhr.state() == 'pending') { req.syncOnFail(false); req.reject(); reqDfd.reject(); } }, self.options.infoCheckWait * 1000); } else { reqDfd.resolve(); } // Directory creation and paste command execution reqDfd.done(function() { dirs = Object.keys(dsts); cnt = dirs.length; if (cnt) { fm.request({ data : {cmd : 'mkdir', target : tHash, dirs : dirs}, notify : {type : 'chkdir', cnt : cnt}, preventFail : true }) .fail(function(error) { dfrd.reject(error); fm.unlockfiles({files : targets}); }) .done(function(data) { var margeRes = function(data, phash, reqData) { var undo, prevUndo, redo, prevRedo; jQuery.each(data, function(k, v) { if (Array.isArray(v)) { if (res[k]) { res[k] = res[k].concat(v); } else { res[k] = v; } } }); if (data.sync) { res.sync = 1; } if (data.added && data.added.length) { undo = function() { var targets = [], dirs = jQuery.map(data.added, function(f) { return f.mime === 'directory'? f.hash : null; }); jQuery.each(data.added, function(i, f) { if (jQuery.inArray(f.phash, dirs) === -1) { targets.push(f.hash); } }); return fm.exec('restore', targets, {noToast: true}); }; redo = function() { return fm.request({ data : reqData, notify : {type : 'redo', cnt : targets.length} }); }; if (res.undo) { prevUndo = res.undo; res.undo = function() { undo(); prevUndo(); }; } else { res.undo = undo; } if (res.redo) { prevRedo = res.redo; res.redo = function() { redo(); prevRedo(); }; } else { res.redo = redo; } } }, err = ['errTrash'], res = {}, hasNtf = function() { return fm.ui.notify.children('.elfinder-notify-trash').length; }, hashes, tm, prg, prgSt; if (hashes = data.hashes) { prg = 1 / cnt * 100; prgSt = cnt === 1? 100 : 5; tm = setTimeout(function() { fm.notify({type : 'trash', cnt : 1, hideCnt : true, progress : prgSt}); }, fm.notifyDelay); jQuery.each(dsts, function(dir, files) { var phash = fm.file(files[0]).phash, reqData; if (hashes[dir]) { reqData = {cmd : 'paste', dst : hashes[dir], targets : files, cut : 1}; fm.request({ data : reqData, preventDefault : true }) .fail(function(error) { if (error) { err = err.concat(error); } }) .done(function(data) { data = fm.normalize(data); fm.updateCache(data); margeRes(data, phash, reqData); if (data.warning) { err = err.concat(data.warning); delete data.warning; } // fire some event to update cache/ui data.removed && data.removed.length && fm.remove(data); data.added && data.added.length && fm.add(data); data.changed && data.changed.length && fm.change(data); // fire event with command name fm.trigger('paste', data); // fire event with command name + 'done' fm.trigger('pastedone'); // force update content data.sync && fm.sync(); }) .always(function() { var hashes = [], addTexts, end = 2; if (hasNtf()) { fm.notify({type : 'trash', cnt : 0, hideCnt : true, progress : prg}); } else { prgSt+= prg; } if (--cnt < 1) { tm && clearTimeout(tm); hasNtf() && fm.notify({type : 'trash', cnt : -1}); fm.unlockfiles({files : targets}); if (Object.keys(res).length) { if (err.length > 1) { if (res.removed || res.removed.length) { hashes = jQuery.grep(targets, function(h) { return jQuery.inArray(h, res.removed) === -1? true : false; }); } if (hashes.length) { if (err.length > end) { end = (fm.messages[err[end-1]] || '').indexOf('$') === -1? end : end + 1; } dfrd.reject(); fm.exec('rm', hashes, { addTexts: err.slice(0, end), forceRm: true }); } else { fm.error(err); } } res._noSound = true; if (res.undo && res.redo) { res.undo = { cmd : 'trash', callback : res.undo, }; res.redo = { cmd : 'trash', callback : res.redo }; } dfrd.resolve(res); } else { dfrd.reject(err); } } }); } }); } else { dfrd.reject('errFolderNotFound'); fm.unlockfiles({files : targets}); } }); } else { dfrd.reject(['error', 'The folder hierarchy to be deleting can not be determined.']); fm.unlockfiles({files : targets}); } }).fail(function() { self.confirm(dfrd, targets, self.files(targets), null, [fm.i18n('tooManyToTrash')]); }); }, remove = function(dfrd, targets, quiet) { var notify = quiet? {} : {type : 'rm', cnt : targets.length}; fm.request({ data : {cmd : 'rm', targets : targets}, notify : notify, preventFail : true }) .fail(function(error) { dfrd.reject(error); }) .done(function(data) { if (data.error || data.warning) { data.sync = true; } dfrd.resolve(data); }) .always(function() { fm.unlockfiles({files : targets}); }); }, getTHash = function(targets) { var thash = null, root1st; if (targets && targets.length) { if (targets.length > 1 && fm.searchStatus.state === 2) { root1st = fm.file(fm.root(targets[0])).volumeid; if (!jQuery.grep(targets, function(h) { return h.indexOf(root1st) !== 0? true : false ; }).length) { thash = fm.option('trashHash', targets[0]); } } else { thash = fm.option('trashHash', targets[0]); } } return thash; }, getSize = false; // for to be able to overwrite this.confirm = confirm; this.toTrash = toTrash; this.remove = remove; this.syncTitleOnChange = true; this.updateOnSelect = false; this.shortcuts = [{ pattern : 'delete ctrl+backspace shift+delete' }]; this.value = 'rm'; this.init = function() { var update = function(origin) { var targets; delete self.extra; self.title = fm.i18n('cmd' + self.value); self.className = self.value; self.button && self.button.children('span.elfinder-button-icon')[self.value === 'trash'? 'addClass' : 'removeClass']('elfinder-button-icon-trash'); if (origin && origin !== 'cwd' && (self.state > -1 || origin === 'navbar')) { if (self.value === 'trash') { self.extra = { icon: 'rm', node: jQuery('') .attr({title: fm.i18n('cmdrm')}) .on('ready', function(e, data) { targets = data.targets; }) .on('click touchstart', function(e){ if (e.type === 'touchstart' && e.originalEvent.touches.length > 1) { return; } e.stopPropagation(); e.preventDefault(); fm.getUI().trigger('click'); // to close the context menu immediately fm.exec('rm', targets, {_userAction: true, forceRm : true}); }) }; } } }; // re-assign for extended command self = this; fm = this.fm; // bind function of change self.change(function() { update(); }); fm.bind('contextmenucreate', function(e) { update(e.data.type); }); }; this.getstate = function(select) { var sel = this.hashes(select), filter = function(files) { var fres = true; return jQuery.grep(files, function(h) { var f; fres = fres && (f = fm.file(h)) && ! f.locked && ! fm.isRoot(f)? true : false; return fres; }); }; return sel.length && filter(sel).length == sel.length ? 0 : -1; }; this.exec = function(hashes, cOpts) { var opts = cOpts || {}, dfrd = jQuery.Deferred() .always(function() { if (getSize && getSize.state && getSize.state() === 'pending') { getSize.reject(); } }) .fail(function(error) { error && fm.error(error); }).done(function(data) { !opts.quiet && !data._noSound && data.removed && data.removed.length && fm.trigger('playsound', {soundFile : 'rm.wav'}); }), files = self.files(hashes), cnt = files.length, tHash = null, addTexts = opts.addTexts? opts.addTexts : null, forceRm = opts.forceRm, quiet = opts.quiet, targets; if (! cnt) { return dfrd.reject(); } jQuery.each(files, function(i, file) { if (fm.isRoot(file)) { return !dfrd.reject(['errRm', file.name, 'errPerm']); } if (file.locked) { return !dfrd.reject(['errLocked', file.name]); } }); if (dfrd.state() === 'pending') { targets = self.hashes(hashes); cnt = files.length; if (forceRm || (self.event && self.event.originalEvent && self.event.originalEvent.shiftKey)) { tHash = ''; self.title = fm.i18n('cmdrm'); } if (tHash === null) { tHash = getTHash(targets); } fm.lockfiles({files : targets}); if (tHash && self.options.quickTrash) { self.toTrash(dfrd, targets, tHash); } else { if (quiet) { remove(dfrd, targets, quiet); } else { self.confirm(dfrd, targets, files, tHash, addTexts); } } } return dfrd; }; fm.bind('select contextmenucreate closecontextmenu', function(e) { var targets = (e.data? (e.data.selected || e.data.targets) : null) || fm.selected(); if (targets && targets.length) { self.update(void(0), (targets? getTHash(targets) : fm.option('trashHash'))? 'trash' : 'rm'); } }); }; edit.js000064400000104756150732265460006056 0ustar00/** * @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(''), hval; if (heads) { jQuery.each(heads, function(i, head) { hval = fm.escape(head.value); sel.append(''); }); } jQuery.each(self.options.encodings, function(i, v) { sel.append(''); }); 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('') .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('').hide(), setSelW = function(init) { init && wfake.appendTo(selEncoding.parent()); wfake.empty().append(jQuery('').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('
').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('
'), 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('').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 : ('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.1030) { 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('') .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 || []); }; }; preference.js000064400000052570150732265460007243 0ustar00/** * @class elFinder command "preference" * "Preference" dialog * * @author Naoki Sawada **/ elFinder.prototype.commands.preference = function() { var self = this, fm = this.fm, r = 'replace', tab = '
  • {title}
  • ', base = jQuery('
    '), ul = jQuery('