initial
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* @class elFinder command "archive"
|
||||
* Archive selected files
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
elFinder.prototype.commands.archive = function() {
|
||||
"use strict";
|
||||
var self = this,
|
||||
fm = self.fm,
|
||||
mimes = [],
|
||||
dfrd;
|
||||
|
||||
this.variants = [];
|
||||
|
||||
this.disableOnSearch = false;
|
||||
|
||||
this.nextAction = {};
|
||||
|
||||
/**
|
||||
* Update mimes on open/reload
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
fm.bind('open reload', function() {
|
||||
self.variants = [];
|
||||
$.each((mimes = fm.option('archivers')['create'] || []), function(i, mime) {
|
||||
self.variants.push([mime, fm.mime2kind(mime)]);
|
||||
});
|
||||
self.change();
|
||||
});
|
||||
|
||||
this.getstate = function(select) {
|
||||
var sel = this.files(select),
|
||||
cnt = sel.length,
|
||||
chk = (cnt && ! fm.isRoot(sel[0]) && (fm.file(sel[0].phash) || {}).write),
|
||||
filter = function(files) {
|
||||
var fres = true;
|
||||
return $.grep(files, function(f) {
|
||||
fres = fres && f.read && f.hash.indexOf(cwdId) === 0 ? true : false;
|
||||
return fres;
|
||||
});
|
||||
},
|
||||
cwdId;
|
||||
|
||||
if (chk && fm.searchStatus.state > 1) {
|
||||
if (chk = (cnt === filter(sel).length)) {
|
||||
cwdId = fm.cwd().volumeid;
|
||||
}
|
||||
}
|
||||
|
||||
return chk && !this._disabled && mimes.length && (cnt || (dfrd && dfrd.state() == 'pending')) ? 0 : -1;
|
||||
};
|
||||
|
||||
this.exec = function(hashes, type) {
|
||||
var files = this.files(hashes),
|
||||
cnt = files.length,
|
||||
mime = type || mimes[0],
|
||||
cwd = fm.file(files[0].phash) || null,
|
||||
error = ['errArchive', 'errPerm', 'errCreatingTempDir', 'errFtpDownloadFile', 'errFtpUploadFile', 'errFtpMkdir', 'errArchiveExec', 'errExtractExec', 'errRm'],
|
||||
i, open;
|
||||
|
||||
dfrd = $.Deferred().fail(function(error) {
|
||||
error && fm.error(error);
|
||||
});
|
||||
|
||||
if (! (cnt && mimes.length && $.inArray(mime, mimes) !== -1)) {
|
||||
return dfrd.reject();
|
||||
}
|
||||
|
||||
if (!cwd.write) {
|
||||
return dfrd.reject(error);
|
||||
}
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
if (!files[i].read) {
|
||||
return dfrd.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
self.mime = mime;
|
||||
self.prefix = ((cnt > 1)? 'Archive' : files[0].name) + (fm.option('archivers')['createext']? '.' + fm.option('archivers')['createext'][mime] : '');
|
||||
self.data = {targets : self.hashes(hashes), type : mime};
|
||||
|
||||
if (fm.cwd().hash !== cwd.hash) {
|
||||
open = fm.exec('open', cwd.hash).done(function() {
|
||||
fm.one('cwdrender', function() {
|
||||
fm.selectfiles({files : hashes});
|
||||
dfrd = $.proxy(fm.res('mixin', 'make'), self)();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
fm.selectfiles({files : hashes});
|
||||
dfrd = $.proxy(fm.res('mixin', 'make'), self)();
|
||||
}
|
||||
|
||||
return dfrd;
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @class elFinder command "back"
|
||||
* Open last visited folder
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
(elFinder.prototype.commands.back = function() {
|
||||
"use strict";
|
||||
this.alwaysEnabled = true;
|
||||
this.updateOnSelect = false;
|
||||
this.shortcuts = [{
|
||||
pattern : 'ctrl+left backspace'
|
||||
}];
|
||||
|
||||
this.getstate = function() {
|
||||
return this.fm.history.canBack() ? 0 : -1;
|
||||
};
|
||||
|
||||
this.exec = function() {
|
||||
return this.fm.history.back();
|
||||
};
|
||||
|
||||
}).prototype = { forceLoad : true }; // this is required command
|
||||
@@ -0,0 +1,323 @@
|
||||
/**
|
||||
* @class elFinder command "chmod".
|
||||
* Chmod files.
|
||||
*
|
||||
* @type elFinder.command
|
||||
* @author Naoki Sawada
|
||||
*/
|
||||
elFinder.prototype.commands.chmod = function() {
|
||||
"use strict";
|
||||
this.updateOnSelect = false;
|
||||
var fm = this.fm,
|
||||
level = {
|
||||
0 : 'owner',
|
||||
1 : 'group',
|
||||
2 : 'other'
|
||||
},
|
||||
msg = {
|
||||
read : fm.i18n('read'),
|
||||
write : fm.i18n('write'),
|
||||
execute : fm.i18n('execute'),
|
||||
perm : fm.i18n('perm'),
|
||||
kind : fm.i18n('kind'),
|
||||
files : fm.i18n('files')
|
||||
},
|
||||
isPerm = function(perm){
|
||||
return (!isNaN(parseInt(perm, 8)) && parseInt(perm, 8) <= 511) || perm.match(/^([r-][w-][x-]){3}$/i);
|
||||
};
|
||||
|
||||
this.tpl = {
|
||||
main : '<div class="ui-helper-clearfix elfinder-info-title"><span class="elfinder-cwd-icon {class} ui-corner-all"></span>{title}</div>'
|
||||
+'{dataTable}',
|
||||
itemTitle : '<strong>{name}</strong><span id="elfinder-info-kind">{kind}</span>',
|
||||
groupTitle : '<strong>{items}: {num}</strong>',
|
||||
dataTable : '<table id="{id}-table-perm"><tr><td>{0}</td><td>{1}</td><td>{2}</td></tr></table>'
|
||||
+'<div class="">'+msg.perm+': <input class="elfinder-tabstop elfinder-focus" id="{id}-perm" type="text" size="4" maxlength="3" value="{value}"></div>',
|
||||
fieldset : '<fieldset id="{id}-fieldset-{level}"><legend>{f_title}{name}</legend>'
|
||||
+'<input type="checkbox" value="4" class="elfinder-tabstop" id="{id}-read-{level}-perm"{checked-r}> <label for="{id}-read-{level}-perm">'+msg.read+'</label><br>'
|
||||
+'<input type="checkbox" value="6" class="elfinder-tabstop" id="{id}-write-{level}-perm"{checked-w}> <label for="{id}-write-{level}-perm">'+msg.write+'</label><br>'
|
||||
+'<input type="checkbox" value="5" class="elfinder-tabstop" id="{id}-execute-{level}-perm"{checked-x}> <label for="{id}-execute-{level}-perm">'+msg.execute+'</label><br>'
|
||||
};
|
||||
|
||||
this.shortcuts = [{
|
||||
//pattern : 'ctrl+p'
|
||||
}];
|
||||
|
||||
this.getstate = function(sel) {
|
||||
var fm = this.fm;
|
||||
sel = sel || fm.selected();
|
||||
if (sel.length == 0) {
|
||||
sel = [ fm.cwd().hash ];
|
||||
}
|
||||
return this.checkstate(this.files(sel)) ? 0 : -1;
|
||||
};
|
||||
|
||||
this.checkstate = function(sel) {
|
||||
var cnt = sel.length,
|
||||
filter = function(files) {
|
||||
var fres = true;
|
||||
return $.grep(sel, function(f) {
|
||||
fres = fres && f.isowner && f.perm && isPerm(f.perm) && (cnt == 1 || f.mime != 'directory') ? true : false;
|
||||
return fres;
|
||||
});
|
||||
};
|
||||
return (cnt && cnt === filter(sel).length)? true : false;
|
||||
};
|
||||
|
||||
this.exec = function(select) {
|
||||
var hashes = this.hashes(select),
|
||||
files = this.files(hashes);
|
||||
if (! files.length) {
|
||||
hashes = [ this.fm.cwd().hash ];
|
||||
files = this.files(hashes);
|
||||
}
|
||||
var fm = this.fm,
|
||||
dfrd = $.Deferred().always(function() {
|
||||
fm.enable();
|
||||
}),
|
||||
tpl = this.tpl,
|
||||
cnt = files.length,
|
||||
file = files[0],
|
||||
id = fm.namespace + '-perm-' + file.hash,
|
||||
view = tpl.main,
|
||||
checked = ' checked="checked"',
|
||||
buttons = function() {
|
||||
var buttons = {};
|
||||
buttons[fm.i18n('btnApply')] = save;
|
||||
buttons[fm.i18n('btnCancel')] = function() { dialog.elfinderdialog('close'); };
|
||||
return buttons;
|
||||
},
|
||||
save = function() {
|
||||
var perm = $.trim($('#'+id+'-perm').val()),
|
||||
reqData;
|
||||
|
||||
if (!isPerm(perm)) return false;
|
||||
|
||||
dialog.elfinderdialog('close');
|
||||
|
||||
reqData = {
|
||||
cmd : 'chmod',
|
||||
targets : hashes,
|
||||
mode : perm
|
||||
};
|
||||
fm.request({
|
||||
data : reqData,
|
||||
notify : {type : 'chmod', cnt : cnt}
|
||||
})
|
||||
.fail(function(error) {
|
||||
dfrd.reject(error);
|
||||
})
|
||||
.done(function(data) {
|
||||
if (data.changed && data.changed.length) {
|
||||
data.undo = {
|
||||
cmd : 'chmod',
|
||||
callback : function() {
|
||||
var reqs = [];
|
||||
$.each(prevVals, function(perm, hashes) {
|
||||
reqs.push(fm.request({
|
||||
data : {cmd : 'chmod', targets : hashes, mode : perm},
|
||||
notify : {type : 'undo', cnt : hashes.length}
|
||||
}));
|
||||
});
|
||||
return $.when.apply(null, reqs);
|
||||
}
|
||||
};
|
||||
data.redo = {
|
||||
cmd : 'chmod',
|
||||
callback : function() {
|
||||
return fm.request({
|
||||
data : reqData,
|
||||
notify : {type : 'redo', cnt : hashes.length}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
dfrd.resolve(data);
|
||||
});
|
||||
},
|
||||
setperm = function() {
|
||||
var perm = '';
|
||||
var _perm;
|
||||
for (var i = 0; i < 3; i++){
|
||||
_perm = 0;
|
||||
if ($("#"+id+"-read-"+level[i]+'-perm').is(':checked')) {
|
||||
_perm = (_perm | 4);
|
||||
}
|
||||
if ($("#"+id+"-write-"+level[i]+'-perm').is(':checked')) {
|
||||
_perm = (_perm | 2);
|
||||
}
|
||||
if ($("#"+id+"-execute-"+level[i]+'-perm').is(':checked')) {
|
||||
_perm = (_perm | 1);
|
||||
}
|
||||
perm += _perm.toString(8);
|
||||
}
|
||||
$('#'+id+'-perm').val(perm);
|
||||
},
|
||||
setcheck = function(perm) {
|
||||
var _perm;
|
||||
for (var i = 0; i < 3; i++){
|
||||
_perm = parseInt(perm.slice(i, i+1), 8);
|
||||
$("#"+id+"-read-"+level[i]+'-perm').prop("checked", false);
|
||||
$("#"+id+"-write-"+level[i]+'-perm').prop("checked", false);
|
||||
$("#"+id+"-execute-"+level[i]+'-perm').prop("checked", false);
|
||||
if ((_perm & 4) == 4) {
|
||||
$("#"+id+"-read-"+level[i]+'-perm').prop("checked", true);
|
||||
}
|
||||
if ((_perm & 2) == 2) {
|
||||
$("#"+id+"-write-"+level[i]+'-perm').prop("checked", true);
|
||||
}
|
||||
if ((_perm & 1) == 1) {
|
||||
$("#"+id+"-execute-"+level[i]+'-perm').prop("checked", true);
|
||||
}
|
||||
}
|
||||
setperm();
|
||||
},
|
||||
makeperm = function(files) {
|
||||
var perm = '777', ret = '', chk, _chk, _perm;
|
||||
var len = files.length;
|
||||
for (var i2 = 0; i2 < len; i2++) {
|
||||
chk = getPerm(files[i2].perm);
|
||||
if (! prevVals[chk]) {
|
||||
prevVals[chk] = [];
|
||||
}
|
||||
prevVals[chk].push(files[i2].hash);
|
||||
ret = '';
|
||||
for (var i = 0; i < 3; i++){
|
||||
_chk = parseInt(chk.slice(i, i+1), 8);
|
||||
_perm = parseInt(perm.slice(i, i+1), 8);
|
||||
if ((_chk & 4) != 4 && (_perm & 4) == 4) {
|
||||
_perm -= 4;
|
||||
}
|
||||
if ((_chk & 2) != 2 && (_perm & 2) == 2) {
|
||||
_perm -= 2;
|
||||
}
|
||||
if ((_chk & 1) != 1 && (_perm & 1) == 1) {
|
||||
_perm -= 1;
|
||||
}
|
||||
ret += _perm.toString(8);
|
||||
}
|
||||
perm = ret;
|
||||
}
|
||||
return perm;
|
||||
},
|
||||
makeName = function(name) {
|
||||
return name? ':'+name : '';
|
||||
},
|
||||
makeDataTable = function(perm, f) {
|
||||
var _perm, fieldset;
|
||||
var value = '';
|
||||
var dataTable = tpl.dataTable;
|
||||
for (var i = 0; i < 3; i++){
|
||||
_perm = parseInt(perm.slice(i, i+1), 8);
|
||||
value += _perm.toString(8);
|
||||
fieldset = tpl.fieldset.replace('{f_title}', fm.i18n(level[i])).replace('{name}', makeName(f[level[i]])).replace(/\{level\}/g, level[i]);
|
||||
dataTable = dataTable.replace('{'+i+'}', fieldset)
|
||||
.replace('{checked-r}', ((_perm & 4) == 4)? checked : '')
|
||||
.replace('{checked-w}', ((_perm & 2) == 2)? checked : '')
|
||||
.replace('{checked-x}', ((_perm & 1) == 1)? checked : '');
|
||||
}
|
||||
dataTable = dataTable.replace('{value}', value).replace('{valueCaption}', msg['perm']);
|
||||
return dataTable;
|
||||
},
|
||||
getPerm = function(perm){
|
||||
if (isNaN(parseInt(perm, 8))) {
|
||||
var mode_array = perm.split('');
|
||||
var a = [];
|
||||
|
||||
for (var i = 0, l = mode_array.length; i < l; i++) {
|
||||
if (i === 0 || i === 3 || i === 6) {
|
||||
if (mode_array[i].match(/[r]/i)) {
|
||||
a.push(1);
|
||||
} else if (mode_array[i].match(/[-]/)) {
|
||||
a.push(0);
|
||||
}
|
||||
} else if ( i === 1 || i === 4 || i === 7) {
|
||||
if (mode_array[i].match(/[w]/i)) {
|
||||
a.push(1);
|
||||
} else if (mode_array[i].match(/[-]/)) {
|
||||
a.push(0);
|
||||
}
|
||||
} else {
|
||||
if (mode_array[i].match(/[x]/i)) {
|
||||
a.push(1);
|
||||
} else if (mode_array[i].match(/[-]/)) {
|
||||
a.push(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a.splice(3, 0, ",");
|
||||
a.splice(7, 0, ",");
|
||||
|
||||
var b = a.join("");
|
||||
var b_array = b.split(",");
|
||||
var c = [];
|
||||
|
||||
for (var j = 0, m = b_array.length; j < m; j++) {
|
||||
var p = parseInt(b_array[j], 2).toString(8);
|
||||
c.push(p);
|
||||
}
|
||||
|
||||
perm = c.join('');
|
||||
} else {
|
||||
perm = parseInt(perm, 8).toString(8);
|
||||
}
|
||||
return perm;
|
||||
},
|
||||
opts = {
|
||||
title : this.title,
|
||||
width : 'auto',
|
||||
buttons : buttons(),
|
||||
close : function() { $(this).elfinderdialog('destroy'); }
|
||||
},
|
||||
dialog = fm.getUI().find('#'+id),
|
||||
prevVals = {},
|
||||
tmb = '', title, dataTable;
|
||||
|
||||
if (dialog.length) {
|
||||
dialog.elfinderdialog('toTop');
|
||||
return $.Deferred().resolve();
|
||||
}
|
||||
|
||||
view = view.replace('{class}', cnt > 1 ? 'elfinder-cwd-icon-group' : fm.mime2class(file.mime));
|
||||
if (cnt > 1) {
|
||||
title = tpl.groupTitle.replace('{items}', fm.i18n('items')).replace('{num}', cnt);
|
||||
} else {
|
||||
title = tpl.itemTitle.replace('{name}', file.name).replace('{kind}', fm.mime2kind(file));
|
||||
tmb = fm.tmb(file);
|
||||
}
|
||||
|
||||
dataTable = makeDataTable(makeperm(files), files.length == 1? files[0] : {});
|
||||
|
||||
view = view.replace('{title}', title).replace('{dataTable}', dataTable).replace(/{id}/g, id);
|
||||
|
||||
dialog = this.fmDialog(view, opts);
|
||||
dialog.attr('id', id);
|
||||
|
||||
// load thumbnail
|
||||
if (tmb) {
|
||||
$('<img/>')
|
||||
.on('load', function() { dialog.find('.elfinder-cwd-icon').addClass(tmb.className).css('background-image', "url('"+tmb.url+"')"); })
|
||||
.attr('src', tmb.url);
|
||||
}
|
||||
|
||||
$('#' + id + '-table-perm :checkbox').on('click', function(){setperm('perm');});
|
||||
$('#' + id + '-perm').on('keydown', function(e) {
|
||||
var c = e.keyCode;
|
||||
if (c == $.ui.keyCode.ENTER) {
|
||||
e.stopPropagation();
|
||||
save();
|
||||
return;
|
||||
}
|
||||
}).on('focus', function(e){
|
||||
$(this).trigger('select');
|
||||
}).on('keyup', function(e) {
|
||||
if ($(this).val().length == 3) {
|
||||
$(this).trigger('select');
|
||||
setcheck($(this).val());
|
||||
}
|
||||
});
|
||||
|
||||
return dfrd;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @class elFinder command "colwidth"
|
||||
* CWD list table columns width to auto
|
||||
*
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
elFinder.prototype.commands.colwidth = function() {
|
||||
"use strict";
|
||||
this.alwaysEnabled = true;
|
||||
this.updateOnSelect = false;
|
||||
|
||||
this.getstate = function() {
|
||||
return this.fm.getUI('cwd').find('table').css('table-layout') === 'fixed' ? 0 : -1;
|
||||
};
|
||||
|
||||
this.exec = function() {
|
||||
this.fm.getUI('cwd').trigger('colwidth');
|
||||
return $.Deferred().resolve();
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @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 $.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 = $.Deferred()
|
||||
.fail(function(error) {
|
||||
fm.error(error);
|
||||
});
|
||||
|
||||
$.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)));
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @class elFinder command "copy".
|
||||
* Put files in filemanager clipboard.
|
||||
*
|
||||
* @type elFinder.command
|
||||
* @author Dmitry (dio) Levashov
|
||||
*/
|
||||
elFinder.prototype.commands.cut = function() {
|
||||
"use strict";
|
||||
var fm = this.fm;
|
||||
|
||||
this.shortcuts = [{
|
||||
pattern : 'ctrl+x shift+insert'
|
||||
}];
|
||||
|
||||
this.getstate = function(select) {
|
||||
var sel = this.files(select),
|
||||
cnt = sel.length,
|
||||
filter = function(files) {
|
||||
var fres = true;
|
||||
return $.grep(files, function(f) {
|
||||
fres = fres && f.read && ! f.locked && ! fm.isRoot(f) ? true : false;
|
||||
return fres;
|
||||
});
|
||||
};
|
||||
|
||||
return cnt && filter(sel).length == cnt ? 0 : -1;
|
||||
};
|
||||
|
||||
this.exec = function(hashes) {
|
||||
var dfrd = $.Deferred()
|
||||
.fail(function(error) {
|
||||
fm.error(error);
|
||||
});
|
||||
|
||||
$.each(this.files(hashes), function(i, file) {
|
||||
if (!(file.read && ! file.locked && ! fm.isRoot(file)) ) {
|
||||
return !dfrd.reject(['errCopy', file.name, 'errPerm']);
|
||||
}
|
||||
if (file.locked) {
|
||||
return !dfrd.reject(['errLocked', file.name]);
|
||||
}
|
||||
});
|
||||
|
||||
return dfrd.state() == 'rejected' ? dfrd : dfrd.resolve(fm.clipboard(this.hashes(hashes), true));
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,466 @@
|
||||
/**
|
||||
* @class elFinder command "download".
|
||||
* Download selected files.
|
||||
* Only for new api
|
||||
*
|
||||
* @author Dmitry (dio) Levashov, dio@std42.ru
|
||||
**/
|
||||
elFinder.prototype.commands.zipdl = function() {};
|
||||
elFinder.prototype.commands.download = function() {
|
||||
"use strict";
|
||||
var self = this,
|
||||
fm = this.fm,
|
||||
czipdl = null,
|
||||
zipOn = false,
|
||||
mixed = false,
|
||||
dlntf = false,
|
||||
cpath = window.location.pathname || '/',
|
||||
filter = function(hashes, inExec) {
|
||||
var volumeid, mixedCmd;
|
||||
|
||||
if (czipdl !== null) {
|
||||
if (fm.searchStatus.state > 1) {
|
||||
mixed = fm.searchStatus.mixed;
|
||||
} else if (fm.leafRoots[fm.cwd().hash]) {
|
||||
volumeid = fm.cwd().volumeid;
|
||||
$.each(hashes, function(i, h) {
|
||||
if (h.indexOf(volumeid) !== 0) {
|
||||
mixed = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
zipOn = (fm.isCommandEnabled('zipdl', hashes[0]));
|
||||
}
|
||||
|
||||
if (mixed) {
|
||||
mixedCmd = czipdl? 'zipdl' : 'download';
|
||||
hashes = $.grep(hashes, function(h) {
|
||||
var f = fm.file(h),
|
||||
res = (! f || (! czipdl && f.mime === 'directory') || ! fm.isCommandEnabled(mixedCmd, h))? false : true;
|
||||
if (f && inExec && ! res) {
|
||||
fm.cwdHash2Elm(f.hash).trigger('unselect');
|
||||
}
|
||||
return res;
|
||||
});
|
||||
if (! hashes.length) {
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
if (!fm.isCommandEnabled('download', hashes[0])) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
return $.grep(self.files(hashes), function(f) {
|
||||
var res = (! f.read || (! zipOn && f.mime == 'directory')) ? false : true;
|
||||
if (inExec && ! res) {
|
||||
fm.cwdHash2Elm(f.hash).trigger('unselect');
|
||||
}
|
||||
return res;
|
||||
});
|
||||
};
|
||||
|
||||
this.linkedCmds = ['zipdl'];
|
||||
|
||||
this.shortcuts = [{
|
||||
pattern : 'shift+enter'
|
||||
}];
|
||||
|
||||
this.getstate = function(select) {
|
||||
var sel = this.hashes(select),
|
||||
cnt = sel.length,
|
||||
maxReq = this.options.maxRequests || 10,
|
||||
mixed = false,
|
||||
croot = '';
|
||||
|
||||
if (cnt < 1) {
|
||||
return -1;
|
||||
}
|
||||
cnt = filter(sel).length;
|
||||
|
||||
return (cnt && (zipOn || (cnt <= maxReq && ((!fm.UA.IE && !fm.UA.Mobile) || cnt == 1))) ? 0 : -1);
|
||||
};
|
||||
|
||||
fm.bind('contextmenu', function(e){
|
||||
var fm = self.fm,
|
||||
helper = null,
|
||||
targets, file, link,
|
||||
getExtra = function(file) {
|
||||
var link = file.url || fm.url(file.hash);
|
||||
return {
|
||||
icon: 'link',
|
||||
node: $('<a></a>')
|
||||
.attr({href: link, target: '_blank', title: fm.i18n('link')})
|
||||
.text(file.name)
|
||||
.on('mousedown click touchstart touchmove touchend contextmenu', function(e){
|
||||
e.stopPropagation();
|
||||
})
|
||||
.on('dragstart', function(e) {
|
||||
var dt = e.dataTransfer || e.originalEvent.dataTransfer || null;
|
||||
helper = null;
|
||||
if (dt) {
|
||||
var icon = function(f) {
|
||||
var mime = f.mime, i, tmb = fm.tmb(f);
|
||||
i = '<div class="elfinder-cwd-icon '+fm.mime2class(mime)+' ui-corner-all"></div>';
|
||||
if (tmb) {
|
||||
i = $(i).addClass(tmb.className).css('background-image', "url('"+tmb.url+"')").get(0).outerHTML;
|
||||
}
|
||||
return i;
|
||||
};
|
||||
dt.effectAllowed = 'copyLink';
|
||||
if (dt.setDragImage) {
|
||||
helper = $('<div class="elfinder-drag-helper html5-native">').append(icon(file)).appendTo($(document.body));
|
||||
dt.setDragImage(helper.get(0), 50, 47);
|
||||
}
|
||||
if (!fm.UA.IE) {
|
||||
dt.setData('elfinderfrom', window.location.href + file.phash);
|
||||
dt.setData('elfinderfrom:' + dt.getData('elfinderfrom'), '');
|
||||
}
|
||||
}
|
||||
})
|
||||
.on('dragend', function(e) {
|
||||
helper && helper.remove();
|
||||
})
|
||||
};
|
||||
};
|
||||
self.extra = null;
|
||||
if (e.data) {
|
||||
targets = e.data.targets || [];
|
||||
if (targets.length === 1 && (file = fm.file(targets[0])) && file.mime !== 'directory') {
|
||||
if (file.url != '1') {
|
||||
self.extra = getExtra(file);
|
||||
} else {
|
||||
// Get URL ondemand
|
||||
var node;
|
||||
self.extra = {
|
||||
icon: 'link',
|
||||
node: $('<a></a>')
|
||||
.attr({href: '#', title: fm.i18n('getLink'), draggable: 'false'})
|
||||
.text(file.name)
|
||||
.on('click touchstart', function(e){
|
||||
if (e.type === 'touchstart' && e.originalEvent.touches.length > 1) {
|
||||
return;
|
||||
}
|
||||
var parent = node.parent();
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
parent.removeClass('ui-state-disabled').addClass('elfinder-button-icon-spinner');
|
||||
fm.request({
|
||||
data : {cmd : 'url', target : file.hash},
|
||||
preventDefault : true
|
||||
})
|
||||
.always(function(data) {
|
||||
parent.removeClass('elfinder-button-icon-spinner');
|
||||
if (data.url) {
|
||||
var rfile = fm.file(file.hash);
|
||||
rfile.url = data.url;
|
||||
node.replaceWith(getExtra(file).node);
|
||||
} else {
|
||||
parent.addClass('ui-state-disabled');
|
||||
}
|
||||
});
|
||||
|
||||
})
|
||||
};
|
||||
node = self.extra.node;
|
||||
node.ready(function(){
|
||||
requestAnimationFrame(function(){
|
||||
node.parent().addClass('ui-state-disabled').css('pointer-events', 'auto');
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}).one('open', function() {
|
||||
if (fm.api >= 2.1012) {
|
||||
czipdl = fm.getCommand('zipdl');
|
||||
}
|
||||
dlntf = fm.cookieEnabled && fm.api > 2.1038 && !fm.isCORS;
|
||||
});
|
||||
|
||||
this.exec = function(select) {
|
||||
var hashes = this.hashes(select),
|
||||
fm = this.fm,
|
||||
base = fm.options.url,
|
||||
files = filter(hashes, true),
|
||||
dfrd = $.Deferred(),
|
||||
iframes = '',
|
||||
cdata = '',
|
||||
targets = {},
|
||||
i, url,
|
||||
linkdl = false,
|
||||
getTask = function(hashes) {
|
||||
return function() {
|
||||
var dfd = $.Deferred(),
|
||||
root = fm.file(fm.root(hashes[0])),
|
||||
single = (hashes.length === 1),
|
||||
volName = root? (root.i18 || root.name) : null,
|
||||
dir, dlName, phash;
|
||||
if (single) {
|
||||
if (dir = fm.file(hashes[0])) {
|
||||
dlName = (dir.i18 || dir.name);
|
||||
}
|
||||
} else {
|
||||
$.each(hashes, function() {
|
||||
var d = fm.file(this);
|
||||
if (d && (!phash || phash === d.phash)) {
|
||||
phash = d.phash;
|
||||
} else {
|
||||
phash = null;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (phash && (dir = fm.file(phash))) {
|
||||
dlName = (dir.i18 || dir.name) + '-' + hashes.length;
|
||||
}
|
||||
}
|
||||
if (dlName) {
|
||||
volName = dlName;
|
||||
}
|
||||
volName && (volName = ' (' + volName + ')');
|
||||
fm.request({
|
||||
data : {cmd : 'zipdl', targets : hashes},
|
||||
notify : {type : 'zipdl', cnt : 1, hideCnt : true, msg : fm.i18n('ntfzipdl') + volName},
|
||||
cancel : true,
|
||||
eachCancel : true,
|
||||
preventDefault : true
|
||||
}).done(function(e) {
|
||||
var zipdl, dialog, btn = {}, dllink, form, iframe, m,
|
||||
uniq = 'dlw' + (+new Date()),
|
||||
zipdlFn = function(url) {
|
||||
dllink = $('<a></a>')
|
||||
.attr('href', url)
|
||||
.attr('download', fm.escape(dlName))
|
||||
.on('click', function() {
|
||||
dfd.resolve();
|
||||
dialog && dialog.elfinderdialog('destroy');
|
||||
});
|
||||
if (linkdl) {
|
||||
dllink.attr('target', '_blank')
|
||||
.append('<span class="elfinder-button-icon elfinder-button-icon-download"></span>'+fm.escape(dlName));
|
||||
btn[fm.i18n('btnCancel')] = function() {
|
||||
dialog.elfinderdialog('destroy');
|
||||
};
|
||||
dialog = self.fmDialog(dllink, {
|
||||
title: fm.i18n('link'),
|
||||
buttons: btn,
|
||||
width: '200px',
|
||||
destroyOnClose: true,
|
||||
close: function() {
|
||||
(dfd.state() !== 'resolved') && dfd.resolve();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
click(dllink.hide().appendTo('body').get(0));
|
||||
dllink.remove();
|
||||
}
|
||||
};
|
||||
if (e.error) {
|
||||
fm.error(e.error);
|
||||
dfd.resolve();
|
||||
} else if (e.zipdl) {
|
||||
zipdl = e.zipdl;
|
||||
if (dlName) {
|
||||
m = fm.splitFileExtention(zipdl.name || '');
|
||||
dlName += m[1]? ('.' + m[1]) : '.zip';
|
||||
} else {
|
||||
dlName = zipdl.name;
|
||||
}
|
||||
if (html5dl || linkdl) {
|
||||
url = fm.options.url + (fm.options.url.indexOf('?') === -1 ? '?' : '&')
|
||||
+ 'cmd=zipdl&download=1';
|
||||
$.each([hashes[0], zipdl.file, dlName, zipdl.mime], function(key, val) {
|
||||
url += '&targets%5B%5D='+encodeURIComponent(val);
|
||||
});
|
||||
$.each(fm.customData, function(key, val) {
|
||||
url += '&'+encodeURIComponent(key)+'='+encodeURIComponent(val);
|
||||
});
|
||||
url += '&'+encodeURIComponent(dlName);
|
||||
if (fm.hasParrotHeaders()) {
|
||||
fm.getBinaryByUrl({url: url}, function(blob) {
|
||||
if (blob instanceof Blob) {
|
||||
url = (window.URL || window.webkitURL).createObjectURL(blob);
|
||||
zipdlFn(url);
|
||||
} else {
|
||||
fm.error(['errUploadTransfer', fm.i18n('kindZIP')]);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
zipdlFn(url);
|
||||
}
|
||||
} else {
|
||||
form = $('<form action="'+fm.options.url+'" method="post" target="'+uniq+'" style="display:none"></form>')
|
||||
.append('<input type="hidden" name="cmd" value="zipdl"/>')
|
||||
.append('<input type="hidden" name="download" value="1"/>');
|
||||
$.each([hashes[0], zipdl.file, dlName, zipdl.mime], function(key, val) {
|
||||
form.append('<input type="hidden" name="targets[]" value="'+fm.escape(val)+'"/>');
|
||||
});
|
||||
$.each(fm.customData, function(key, val) {
|
||||
form.append('<input type="hidden" name="'+key+'" value="'+fm.escape(val)+'"/>');
|
||||
});
|
||||
form.attr('target', uniq).appendTo('body');
|
||||
iframe = $('<iframe style="display:none" name="'+uniq+'">')
|
||||
.appendTo('body')
|
||||
.ready(function() {
|
||||
form.submit().remove();
|
||||
dfd.resolve();
|
||||
setTimeout(function() {
|
||||
iframe.remove();
|
||||
}, 20000); // give 20 sec file to be saved
|
||||
});
|
||||
}
|
||||
}
|
||||
}).fail(function(error) {
|
||||
error && fm.error(error);
|
||||
dfd.resolve();
|
||||
});
|
||||
return dfd.promise();
|
||||
};
|
||||
},
|
||||
// use MouseEvent to click element for Safari etc
|
||||
click = function(a) {
|
||||
var clickEv;
|
||||
if (typeof MouseEvent === 'function') {
|
||||
clickEv = new MouseEvent('click');
|
||||
} else {
|
||||
clickEv = document.createEvent('MouseEvents');
|
||||
clickEv.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||
}
|
||||
fm.pauseUnloadCheck(true);
|
||||
a.dispatchEvent(clickEv);
|
||||
},
|
||||
checkCookie = function(id) {
|
||||
var name = 'elfdl' + id,
|
||||
parts;
|
||||
parts = document.cookie.split(name + "=");
|
||||
if (parts.length === 2) {
|
||||
ntftm && clearTimeout(ntftm);
|
||||
document.cookie = name + '=; path=' + cpath + '; max-age=0';
|
||||
closeNotify();
|
||||
} else {
|
||||
setTimeout(function() { checkCookie(id); }, 200);
|
||||
}
|
||||
},
|
||||
closeNotify = function() {
|
||||
if (fm.ui.notify.children('.elfinder-notify-download').length) {
|
||||
fm.notify({
|
||||
type : 'download',
|
||||
cnt : -1
|
||||
});
|
||||
}
|
||||
},
|
||||
reqids = [],
|
||||
link, html5dl, fileCnt, clickEv, cid, ntftm, reqid, getUrlDfrd, urls;
|
||||
|
||||
if (!files.length) {
|
||||
return dfrd.reject();
|
||||
}
|
||||
|
||||
fileCnt = $.grep(files, function(f) { return f.mime === 'directory'? false : true; }).length;
|
||||
link = $('<a>').hide().appendTo('body');
|
||||
html5dl = (typeof link.get(0).download === 'string');
|
||||
|
||||
if (zipOn && (fileCnt !== files.length || fileCnt >= (this.options.minFilesZipdl || 1))) {
|
||||
link.remove();
|
||||
linkdl = (!html5dl && fm.UA.Mobile);
|
||||
if (mixed) {
|
||||
targets = {};
|
||||
$.each(files, function(i, f) {
|
||||
var p = f.hash.split('_', 2);
|
||||
if (! targets[p[0]]) {
|
||||
targets[p[0]] = [ f.hash ];
|
||||
} else {
|
||||
targets[p[0]].push(f.hash);
|
||||
}
|
||||
});
|
||||
if (!linkdl && fm.UA.Mobile && Object.keys(targets).length > 1) {
|
||||
linkdl = true;
|
||||
}
|
||||
} else {
|
||||
targets = [ $.map(files, function(f) { return f.hash; }) ];
|
||||
}
|
||||
dfrd = fm.sequence($.map(targets, function(t) { return getTask(t); })).always(
|
||||
function() {
|
||||
fm.trigger('download', {files : files});
|
||||
}
|
||||
);
|
||||
return dfrd;
|
||||
} else {
|
||||
reqids = [];
|
||||
getUrlDfrd = $.Deferred().done(function(urls) {
|
||||
for (i = 0; i < urls.length; i++) {
|
||||
url = urls[i];
|
||||
if (dlntf && url.substr(0, fm.options.url.length) === fm.options.url) {
|
||||
reqid = fm.getRequestId();
|
||||
reqids.push(reqid);
|
||||
url += '&cpath=' + cpath + '&reqid=' + reqid;
|
||||
ntftm = setTimeout(function() {
|
||||
fm.notify({
|
||||
type : 'download',
|
||||
cnt : 1,
|
||||
cancel : (fm.UA.IE || fm.UA.Edge)? void(0) : function() {
|
||||
if (reqids.length) {
|
||||
$.each(reqids, function() {
|
||||
fm.request({
|
||||
data: {
|
||||
cmd: 'abort',
|
||||
id: this
|
||||
},
|
||||
preventDefault: true
|
||||
});
|
||||
});
|
||||
}
|
||||
reqids = [];
|
||||
}
|
||||
});
|
||||
}, fm.notifyDelay);
|
||||
checkCookie(reqid);
|
||||
}
|
||||
if (html5dl) {
|
||||
click(link.attr('href', url)
|
||||
.attr('download', fm.escape(files[i].name))
|
||||
.get(0)
|
||||
);
|
||||
} else {
|
||||
if (fm.UA.Mobile) {
|
||||
setTimeout(function(){
|
||||
if (! window.open(url)) {
|
||||
fm.error('errPopup');
|
||||
ntftm && cleaerTimeout(ntftm);
|
||||
closeNotify();
|
||||
}
|
||||
}, 100);
|
||||
} else {
|
||||
iframes += '<iframe class="downloader" id="downloader-' + files[i].hash+'" style="display:none" src="'+url+'"></iframe>';
|
||||
}
|
||||
}
|
||||
}
|
||||
link.remove();
|
||||
$(iframes)
|
||||
.appendTo('body')
|
||||
.ready(function() {
|
||||
setTimeout(function() {
|
||||
$(iframes).each(function() {
|
||||
$('#' + $(this).attr('id')).remove();
|
||||
});
|
||||
}, 20000 + (10000 * i)); // give 20 sec + 10 sec for each file to be saved
|
||||
});
|
||||
fm.trigger('download', {files : files});
|
||||
dfrd.resolve();
|
||||
});
|
||||
fileCnt = files.length;
|
||||
urls = [];
|
||||
for (i = 0; i < files.length; i++) {
|
||||
fm.openUrl(files[i].hash, true, function(v) {
|
||||
v && urls.push(v);
|
||||
if (--fileCnt < 1) {
|
||||
getUrlDfrd.resolve(urls);
|
||||
}
|
||||
});
|
||||
}
|
||||
return dfrd;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* @class elFinder command "duplicate"
|
||||
* Create file/folder copy with suffix "copy Number"
|
||||
*
|
||||
* @type elFinder.command
|
||||
* @author Dmitry (dio) Levashov
|
||||
*/
|
||||
elFinder.prototype.commands.duplicate = function() {
|
||||
"use strict";
|
||||
var fm = this.fm;
|
||||
|
||||
this.getstate = function(select) {
|
||||
var sel = this.files(select),
|
||||
cnt = sel.length,
|
||||
filter = function(files) {
|
||||
var fres = true;
|
||||
return $.grep(files, function(f) {
|
||||
fres = fres && f.read && f.phash === fm.cwd().hash && ! fm.isRoot(f)? true : false;
|
||||
return fres;
|
||||
});
|
||||
};
|
||||
|
||||
return cnt && fm.cwd().write && filter(sel).length == cnt ? 0 : -1;
|
||||
};
|
||||
|
||||
this.exec = function(hashes) {
|
||||
var fm = this.fm,
|
||||
files = this.files(hashes),
|
||||
cnt = files.length,
|
||||
dfrd = $.Deferred()
|
||||
.fail(function(error) {
|
||||
error && fm.error(error);
|
||||
}),
|
||||
args = [];
|
||||
|
||||
if (! cnt) {
|
||||
return dfrd.reject();
|
||||
}
|
||||
|
||||
$.each(files, function(i, file) {
|
||||
if (!file.read || !fm.file(file.phash).write) {
|
||||
return !dfrd.reject(['errCopy', file.name, 'errPerm']);
|
||||
}
|
||||
});
|
||||
|
||||
if (dfrd.state() == 'rejected') {
|
||||
return dfrd;
|
||||
}
|
||||
|
||||
return fm.request({
|
||||
data : {cmd : 'duplicate', targets : this.hashes(hashes)},
|
||||
notify : {type : 'copy', cnt : cnt},
|
||||
navigate : {
|
||||
toast : {
|
||||
inbuffer : {msg: fm.i18n(['complete', fm.i18n('cmdduplicate')])}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* @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 $.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 = $.Deferred()
|
||||
.done(function() {
|
||||
var data = {changed: {}};
|
||||
fm.toast({msg: fm.i18n(['"'+success.join('", ')+'"', 'complete', fm.i18n('cmdempty')])});
|
||||
$.each(dirs, function(i, dir) {
|
||||
data.changed[dir.hash] = dir;
|
||||
});
|
||||
fm.change(data);
|
||||
})
|
||||
.always(function() {
|
||||
var cwd = fm.cwd().hash;
|
||||
fm.trigger('selectfiles', {files: $.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']();
|
||||
};
|
||||
|
||||
$.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);
|
||||
$.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;
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,225 @@
|
||||
/**
|
||||
* @class elFinder command "extract"
|
||||
* Extract files from archive
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
elFinder.prototype.commands.extract = function() {
|
||||
"use strict";
|
||||
var self = this,
|
||||
fm = self.fm,
|
||||
mimes = [],
|
||||
filter = function(files) {
|
||||
var fres = true;
|
||||
return $.grep(files, function(file) {
|
||||
fres = fres && file.read && $.inArray(file.mime, mimes) !== -1 ? true : false;
|
||||
return fres;
|
||||
});
|
||||
};
|
||||
|
||||
this.variants = [];
|
||||
this.disableOnSearch = true;
|
||||
|
||||
// Update mimes list on open/reload
|
||||
fm.bind('open reload', function() {
|
||||
mimes = fm.option('archivers')['extract'] || [];
|
||||
if (fm.api > 2) {
|
||||
self.variants = [[{makedir: true}, fm.i18n('cmdmkdir')], [{}, fm.i18n('btnCwd')]];
|
||||
} else {
|
||||
self.variants = [[{}, fm.i18n('btnCwd')]];
|
||||
}
|
||||
self.change();
|
||||
});
|
||||
|
||||
this.getstate = function(select) {
|
||||
var sel = this.files(select),
|
||||
cnt = sel.length,
|
||||
cwdHash, cwdChk;
|
||||
if (!cnt || filter(sel).length != cnt) {
|
||||
return -1;
|
||||
} else if (fm.searchStatus.state > 0) {
|
||||
cwdHash = this.fm.cwd().hash;
|
||||
$.each(sel, function(i, file) {
|
||||
cwdChk = (file.phash === cwdHash);
|
||||
return cwdChk;
|
||||
});
|
||||
return cwdChk? 0 : -1;
|
||||
} else {
|
||||
return this.fm.cwd().write? 0 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
this.exec = function(hashes, opts) {
|
||||
var files = this.files(hashes),
|
||||
dfrd = $.Deferred(),
|
||||
cnt = files.length,
|
||||
makedir = opts && opts.makedir ? 1 : 0,
|
||||
i, error,
|
||||
decision,
|
||||
|
||||
overwriteAll = false,
|
||||
omitAll = false,
|
||||
mkdirAll = 0,
|
||||
siblings = fm.files(files[0].phash),
|
||||
|
||||
names = [],
|
||||
map = {};
|
||||
|
||||
$.each(siblings, function(id, file) {
|
||||
map[file.name] = file;
|
||||
names.push(file.name);
|
||||
});
|
||||
|
||||
var decide = function(decision) {
|
||||
switch (decision) {
|
||||
case 'overwrite_all' :
|
||||
overwriteAll = true;
|
||||
break;
|
||||
case 'omit_all':
|
||||
omitAll = true;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
var unpack = function(file) {
|
||||
if (!(file.read && fm.file(file.phash).write)) {
|
||||
error = ['errExtract', file.name, 'errPerm'];
|
||||
fm.error(error);
|
||||
dfrd.reject(error);
|
||||
} else if ($.inArray(file.mime, mimes) === -1) {
|
||||
error = ['errExtract', file.name, 'errNoArchive'];
|
||||
fm.error(error);
|
||||
dfrd.reject(error);
|
||||
} else {
|
||||
fm.request({
|
||||
data:{cmd:'extract', target:file.hash, makedir:makedir},
|
||||
notify:{type:'extract', cnt:1},
|
||||
syncOnFail:true,
|
||||
navigate:{
|
||||
toast : makedir? {
|
||||
incwd : {msg: fm.i18n(['complete', fm.i18n('cmdextract')]), action: {cmd: 'open', msg: 'cmdopen'}},
|
||||
inbuffer : {msg: fm.i18n(['complete', fm.i18n('cmdextract')]), action: {cmd: 'open', msg: 'cmdopen'}}
|
||||
} : {
|
||||
inbuffer : {msg: fm.i18n(['complete', fm.i18n('cmdextract')])}
|
||||
}
|
||||
}
|
||||
})
|
||||
.fail(function (error) {
|
||||
if (dfrd.state() != 'rejected') {
|
||||
dfrd.reject(error);
|
||||
}
|
||||
})
|
||||
.done(function () {
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var confirm = function(files, index) {
|
||||
var file = files[index],
|
||||
name = fm.splitFileExtention(file.name)[0],
|
||||
existed = ($.inArray(name, names) >= 0),
|
||||
next = function(){
|
||||
if((index+1) < cnt) {
|
||||
confirm(files, index+1);
|
||||
} else {
|
||||
dfrd.resolve();
|
||||
}
|
||||
};
|
||||
if (!makedir && existed && map[name].mime != 'directory') {
|
||||
fm.confirm(
|
||||
{
|
||||
title : fm.i18n('ntfextract'),
|
||||
text : ['errExists', name, 'confirmRepl'],
|
||||
accept:{
|
||||
label : 'btnYes',
|
||||
callback:function (all) {
|
||||
decision = all ? 'overwrite_all' : 'overwrite';
|
||||
decide(decision);
|
||||
if(!overwriteAll && !omitAll) {
|
||||
if('overwrite' == decision) {
|
||||
unpack(file);
|
||||
}
|
||||
if((index+1) < cnt) {
|
||||
confirm(files, index+1);
|
||||
} else {
|
||||
dfrd.resolve();
|
||||
}
|
||||
} else if(overwriteAll) {
|
||||
for (i = index; i < cnt; i++) {
|
||||
unpack(files[i]);
|
||||
}
|
||||
dfrd.resolve();
|
||||
}
|
||||
}
|
||||
},
|
||||
reject : {
|
||||
label : 'btnNo',
|
||||
callback:function (all) {
|
||||
decision = all ? 'omit_all' : 'omit';
|
||||
decide(decision);
|
||||
if(!overwriteAll && !omitAll && (index+1) < cnt) {
|
||||
confirm(files, index+1);
|
||||
} else if (omitAll) {
|
||||
dfrd.resolve();
|
||||
}
|
||||
}
|
||||
},
|
||||
cancel : {
|
||||
label : 'btnCancel',
|
||||
callback:function () {
|
||||
dfrd.resolve();
|
||||
}
|
||||
},
|
||||
all : ((index+1) < cnt)
|
||||
}
|
||||
);
|
||||
} else if (!makedir) {
|
||||
if (mkdirAll == 0) {
|
||||
fm.confirm({
|
||||
title : fm.i18n('cmdextract'),
|
||||
text : [fm.i18n('cmdextract')+' "'+file.name+'"', 'confirmRepl'],
|
||||
accept:{
|
||||
label : 'btnYes',
|
||||
callback:function (all) {
|
||||
all && (mkdirAll = 1);
|
||||
unpack(file);
|
||||
next();
|
||||
}
|
||||
},
|
||||
reject : {
|
||||
label : 'btnNo',
|
||||
callback:function (all) {
|
||||
all && (mkdirAll = -1);
|
||||
next();
|
||||
}
|
||||
},
|
||||
cancel : {
|
||||
label : 'btnCancel',
|
||||
callback:function () {
|
||||
dfrd.resolve();
|
||||
}
|
||||
},
|
||||
all : ((index+1) < cnt)
|
||||
});
|
||||
} else {
|
||||
(mkdirAll > 0) && unpack(file);
|
||||
next();
|
||||
}
|
||||
} else {
|
||||
unpack(file);
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
||||
if (!(this.enabled() && cnt && mimes.length)) {
|
||||
return dfrd.reject();
|
||||
}
|
||||
|
||||
if(cnt > 0) {
|
||||
confirm(files, 0);
|
||||
}
|
||||
|
||||
return dfrd;
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @class elFinder command "forward"
|
||||
* Open next visited folder
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
(elFinder.prototype.commands.forward = function() {
|
||||
"use strict";
|
||||
this.alwaysEnabled = true;
|
||||
this.updateOnSelect = true;
|
||||
this.shortcuts = [{
|
||||
pattern : 'ctrl+right'
|
||||
}];
|
||||
|
||||
this.getstate = function() {
|
||||
return this.fm.history.canForward() ? 0 : -1;
|
||||
};
|
||||
|
||||
this.exec = function() {
|
||||
return this.fm.history.forward();
|
||||
};
|
||||
|
||||
}).prototype = { forceLoad : true }; // this is required command
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @class elFinder command "fullscreen"
|
||||
* elFinder node to full scrren mode
|
||||
*
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
|
||||
elFinder.prototype.commands.fullscreen = function() {
|
||||
"use strict";
|
||||
var self = this,
|
||||
fm = this.fm,
|
||||
update = function(e, data) {
|
||||
var full;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (data && data.fullscreen) {
|
||||
full = (data.fullscreen === 'on');
|
||||
self.update(void(0), full);
|
||||
self.title = fm.i18n(full ? 'reinstate' : 'cmdfullscreen');
|
||||
}
|
||||
};
|
||||
|
||||
this.alwaysEnabled = true;
|
||||
this.updateOnSelect = false;
|
||||
this.syncTitleOnChange = true;
|
||||
this.value = false;
|
||||
|
||||
this.options = {
|
||||
ui : 'fullscreenbutton'
|
||||
};
|
||||
|
||||
this.getstate = function() {
|
||||
return 0;
|
||||
};
|
||||
|
||||
this.exec = function() {
|
||||
var node = fm.getUI().get(0),
|
||||
full = (node === fm.toggleFullscreen(node));
|
||||
self.title = fm.i18n(full ? 'reinstate' : 'cmdfullscreen');
|
||||
self.update(void(0), full);
|
||||
return $.Deferred().resolve();
|
||||
};
|
||||
|
||||
fm.bind('init', function() {
|
||||
fm.getUI().off('resize.' + fm.namespace, update).on('resize.' + fm.namespace, update);
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* @class elFinder command "getfile".
|
||||
* Return selected files info into outer callback.
|
||||
* For use elFinder with wysiwyg editors etc.
|
||||
*
|
||||
* @author Dmitry (dio) Levashov, dio@std42.ru
|
||||
**/
|
||||
(elFinder.prototype.commands.getfile = function() {
|
||||
"use strict";
|
||||
var self = this,
|
||||
fm = this.fm,
|
||||
filter = function(files) {
|
||||
var o = self.options,
|
||||
fres = true;
|
||||
|
||||
files = $.grep(files, function(file) {
|
||||
fres = fres && (file.mime != 'directory' || o.folders) && file.read ? true : false;
|
||||
return fres;
|
||||
});
|
||||
|
||||
return o.multiple || files.length == 1 ? files : [];
|
||||
};
|
||||
|
||||
this.alwaysEnabled = true;
|
||||
this.callback = fm.options.getFileCallback;
|
||||
this._disabled = typeof(this.callback) == 'function';
|
||||
|
||||
this.getstate = function(select) {
|
||||
var sel = this.files(select),
|
||||
cnt = sel.length;
|
||||
|
||||
return this.callback && cnt && filter(sel).length == cnt ? 0 : -1;
|
||||
};
|
||||
|
||||
this.exec = function(hashes) {
|
||||
var fm = this.fm,
|
||||
opts = this.options,
|
||||
files = this.files(hashes),
|
||||
cnt = files.length,
|
||||
url = fm.option('url'),
|
||||
tmb = fm.option('tmbUrl'),
|
||||
dfrd = $.Deferred()
|
||||
.done(function(data) {
|
||||
var res,
|
||||
done = function() {
|
||||
if (opts.oncomplete == 'close') {
|
||||
fm.hide();
|
||||
} else if (opts.oncomplete == 'destroy') {
|
||||
fm.destroy();
|
||||
}
|
||||
},
|
||||
fail = function(error) {
|
||||
if (opts.onerror == 'close') {
|
||||
fm.hide();
|
||||
} else if (opts.onerror == 'destroy') {
|
||||
fm.destroy();
|
||||
} else {
|
||||
error && fm.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
fm.trigger('getfile', {files : data});
|
||||
|
||||
try {
|
||||
res = self.callback(data, fm);
|
||||
} catch(e) {
|
||||
fail(['Error in `getFileCallback`.', e.message]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof res === 'object' && typeof res.done === 'function') {
|
||||
res.done(done).fail(fail);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
}),
|
||||
result = function(file) {
|
||||
return opts.onlyURL
|
||||
? opts.multiple ? $.map(files, function(f) { return f.url; }) : files[0].url
|
||||
: opts.multiple ? files : files[0];
|
||||
},
|
||||
req = [],
|
||||
i, file, dim;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
file = files[i];
|
||||
if (file.mime == 'directory' && !opts.folders) {
|
||||
return dfrd.reject();
|
||||
}
|
||||
file.baseUrl = url;
|
||||
if (file.url == '1') {
|
||||
req.push(fm.request({
|
||||
data : {cmd : 'url', target : file.hash},
|
||||
notify : {type : 'url', cnt : 1, hideCnt : true},
|
||||
preventDefault : true
|
||||
})
|
||||
.done(function(data) {
|
||||
if (data.url) {
|
||||
var rfile = fm.file(this.hash);
|
||||
rfile.url = this.url = data.url;
|
||||
}
|
||||
}.bind(file)));
|
||||
} else {
|
||||
file.url = fm.url(file.hash);
|
||||
}
|
||||
if (! opts.onlyURL) {
|
||||
if (opts.getPath) {
|
||||
file.path = fm.path(file.hash);
|
||||
if (file.path === '' && file.phash) {
|
||||
// get parents
|
||||
(function() {
|
||||
var dfd = $.Deferred();
|
||||
req.push(dfd);
|
||||
fm.path(file.hash, false, {})
|
||||
.done(function(path) {
|
||||
file.path = path;
|
||||
})
|
||||
.fail(function() {
|
||||
file.path = '';
|
||||
})
|
||||
.always(function() {
|
||||
dfd.resolve();
|
||||
});
|
||||
})();
|
||||
}
|
||||
}
|
||||
if (file.tmb && file.tmb != 1) {
|
||||
file.tmb = tmb + file.tmb;
|
||||
}
|
||||
if (!file.width && !file.height) {
|
||||
if (file.dim) {
|
||||
dim = file.dim.split('x');
|
||||
file.width = dim[0];
|
||||
file.height = dim[1];
|
||||
} else if (opts.getImgSize && file.mime.indexOf('image') !== -1) {
|
||||
req.push(fm.request({
|
||||
data : {cmd : 'dim', target : file.hash},
|
||||
notify : {type : 'dim', cnt : 1, hideCnt : true},
|
||||
preventDefault : true
|
||||
})
|
||||
.done(function(data) {
|
||||
if (data.dim) {
|
||||
var dim = data.dim.split('x');
|
||||
var rfile = fm.file(this.hash);
|
||||
rfile.width = this.width = dim[0];
|
||||
rfile.height = this.height = dim[1];
|
||||
}
|
||||
}.bind(file)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (req.length) {
|
||||
$.when.apply(null, req).always(function() {
|
||||
dfrd.resolve(result(files));
|
||||
});
|
||||
return dfrd;
|
||||
}
|
||||
|
||||
return dfrd.resolve(result(files));
|
||||
};
|
||||
|
||||
}).prototype = { forceLoad : true }; // this is required command
|
||||
@@ -0,0 +1,414 @@
|
||||
/**
|
||||
* @class elFinder command "help"
|
||||
* "About" dialog
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
(elFinder.prototype.commands.help = function() {
|
||||
"use strict";
|
||||
var fm = this.fm,
|
||||
self = this,
|
||||
linktpl = '<div class="elfinder-help-link"> <a href="{url}">{link}</a></div>',
|
||||
linktpltgt = '<div class="elfinder-help-link"> <a href="{url}" target="_blank">{link}</a></div>',
|
||||
atpl = '<div class="elfinder-help-team"><div>{author}</div>{work}</div>',
|
||||
url = /\{url\}/,
|
||||
link = /\{link\}/,
|
||||
author = /\{author\}/,
|
||||
work = /\{work\}/,
|
||||
r = 'replace',
|
||||
prim = 'ui-priority-primary',
|
||||
sec = 'ui-priority-secondary',
|
||||
lic = 'elfinder-help-license',
|
||||
tab = '<li class="' + fm.res('class', 'tabstab') + ' elfinder-help-tab-{id}"><a href="#'+fm.namespace+'-help-{id}" class="ui-tabs-anchor">{title}</a></li>',
|
||||
html = ['<div class="ui-tabs ui-widget ui-widget-content ui-corner-all elfinder-help">',
|
||||
'<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-top">'],
|
||||
stpl = '<div class="elfinder-help-shortcut"><div class="elfinder-help-shortcut-pattern">{pattern}</div> {descrip}</div>',
|
||||
sep = '<div class="elfinder-help-separator"></div>',
|
||||
selfUrl = $('base').length? fm.escape(document.location.href.replace(/#.*$/, '')) : '',
|
||||
clTabActive = fm.res('class', 'tabsactive'),
|
||||
|
||||
getTheme = function() {
|
||||
var src;
|
||||
if (fm.theme && fm.theme.author) {
|
||||
src = atpl[r]('elfinder-help-team', 'elfinder-help-team elfinder-help-term-theme')[r](author, fm.i18n(fm.theme.author) + (fm.theme.email? ' <'+fm.theme.email+'>' : ''))[r](work, fm.i18n('theme') + ' ('+fm.i18n(fm.theme.name)+')');
|
||||
} else {
|
||||
src = '<div class="elfinder-help-team elfinder-help-term-theme" style="display:none"></div>';
|
||||
}
|
||||
return src;
|
||||
},
|
||||
|
||||
about = function() {
|
||||
html.push('<div id="'+fm.namespace+'-help-about" class="ui-tabs-panel ui-widget-content ui-corner-bottom"><div class="elfinder-help-logo"></div>');
|
||||
html.push('<h3>elFinder</h3>');
|
||||
html.push('<div class="'+prim+'">'+fm.i18n('webfm')+'</div>');
|
||||
html.push('<div class="'+sec+'">'+fm.i18n('ver')+': '+fm.version+'</div>');
|
||||
html.push('<div class="'+sec+'">'+fm.i18n('protocolver')+': <span class="apiver"></span></div>');
|
||||
html.push('<div class="'+sec+'">jQuery/jQuery UI: '+$().jquery+'/'+$.ui.version+'</div>');
|
||||
|
||||
html.push(sep);
|
||||
|
||||
html.push(linktpltgt[r](url, 'https://studio-42.github.io/elFinder/')[r](link, fm.i18n('homepage')));
|
||||
html.push(linktpltgt[r](url, 'https://github.com/Studio-42/elFinder/wiki')[r](link, fm.i18n('docs')));
|
||||
html.push(linktpltgt[r](url, 'https://github.com/Studio-42/elFinder')[r](link, fm.i18n('github')));
|
||||
//html.push(linktpltgt[r](url, 'http://twitter.com/elrte_elfinder')[r](link, fm.i18n('twitter')));
|
||||
|
||||
html.push(sep);
|
||||
|
||||
html.push('<div class="'+prim+'">'+fm.i18n('team')+'</div>');
|
||||
|
||||
html.push(atpl[r](author, 'Dmitry "dio" Levashov <dio@std42.ru>')[r](work, fm.i18n('chiefdev')));
|
||||
html.push(atpl[r](author, 'Naoki Sawada (nao-pon)<hypweb+elfinder@gmail.com>')[r](work, fm.i18n('developer')));
|
||||
html.push(atpl[r](author, 'Troex Nevelin <troex@fury.scancode.ru>')[r](work, fm.i18n('maintainer')));
|
||||
html.push(atpl[r](author, 'Alexey Sukhotin <strogg@yandex.ru>')[r](work, fm.i18n('contributor')));
|
||||
|
||||
if (fm.i18[fm.lang].translator) {
|
||||
$.each(fm.i18[fm.lang].translator.split(', '), function() {
|
||||
html.push(atpl[r](author, $.trim(this))[r](work, fm.i18n('translator')+' ('+fm.i18[fm.lang].language+')'));
|
||||
});
|
||||
}
|
||||
|
||||
html.push(getTheme());
|
||||
|
||||
html.push(sep);
|
||||
html.push('<div class="'+lic+'">'+fm.i18n('icons')+': Pixelmixer, <a href="http://p.yusukekamiyamane.com" target="_blank">Fugue</a>, <a href="https://icons8.com" target="_blank">Icons8</a></div>');
|
||||
|
||||
html.push(sep);
|
||||
html.push('<div class="'+lic+'">Licence: 3-clauses BSD Licence</div>');
|
||||
html.push('<div class="'+lic+'">Copyright © 2009-2022, Studio 42 / nao-pon</div>');
|
||||
html.push('<div class="'+lic+'">„ …'+fm.i18n('dontforget')+' ”</div>');
|
||||
html.push('</div>');
|
||||
},
|
||||
shortcuts = function() {
|
||||
var sh = fm.shortcuts();
|
||||
// shortcuts tab
|
||||
html.push('<div id="'+fm.namespace+'-help-shortcuts" class="ui-tabs-panel ui-widget-content ui-corner-bottom">');
|
||||
|
||||
if (sh.length) {
|
||||
html.push('<div class="ui-widget-content elfinder-help-shortcuts">');
|
||||
$.each(sh, function(i, s) {
|
||||
html.push(stpl.replace(/\{pattern\}/, s[0]).replace(/\{descrip\}/, s[1]));
|
||||
});
|
||||
|
||||
html.push('</div>');
|
||||
} else {
|
||||
html.push('<div class="elfinder-help-disabled">'+fm.i18n('shortcutsof')+'</div>');
|
||||
}
|
||||
|
||||
|
||||
html.push('</div>');
|
||||
|
||||
},
|
||||
help = function() {
|
||||
// help tab
|
||||
html.push('<div id="'+fm.namespace+'-help-help" class="ui-tabs-panel ui-widget-content ui-corner-bottom">');
|
||||
html.push('<a href="https://github.com/Studio-42/elFinder/wiki" target="_blank" class="elfinder-dont-panic"><span>DON\'T PANIC</span></a>');
|
||||
html.push('</div>');
|
||||
// end help
|
||||
},
|
||||
useInteg = false,
|
||||
integrations = function() {
|
||||
useInteg = true;
|
||||
html.push('<div id="'+fm.namespace+'-help-integrations" class="ui-tabs-panel ui-widget-content ui-corner-bottom"></div>');
|
||||
},
|
||||
useDebug = false,
|
||||
debug = function() {
|
||||
useDebug = true;
|
||||
// debug tab
|
||||
html.push('<div id="'+fm.namespace+'-help-debug" class="ui-tabs-panel ui-widget-content ui-corner-bottom">');
|
||||
html.push('<div class="ui-widget-content elfinder-help-debug"><ul></ul></div>');
|
||||
html.push('</div>');
|
||||
// end debug
|
||||
},
|
||||
debugRender = function() {
|
||||
var render = function(elm, obj) {
|
||||
$.each(obj, function(k, v) {
|
||||
elm.append($('<dt></dt>').text(k));
|
||||
if (typeof v === 'undefined') {
|
||||
elm.append($('<dd></dd>').append($('<span></span>').text('undfined')));
|
||||
} else if (typeof v === 'object' && !v) {
|
||||
elm.append($('<dd></dd>').append($('<span></span>').text('null')));
|
||||
} else if (typeof v === 'object' && ($.isPlainObject(v) || v.length)) {
|
||||
elm.append( $('<dd></dd>').append(render($('<dl></dl>'), v)));
|
||||
} else {
|
||||
elm.append($('<dd></dd>').append($('<span></span>').text((v && typeof v === 'object')? '[]' : (v? v : '""'))));
|
||||
}
|
||||
});
|
||||
return elm;
|
||||
},
|
||||
cnt = debugUL.children('li').length,
|
||||
targetL, target, tabId,
|
||||
info, lastUL, lastDIV;
|
||||
|
||||
if (self.debug.options || self.debug.debug) {
|
||||
if (cnt >= 5) {
|
||||
lastUL = debugUL.children('li:last');
|
||||
lastDIV = debugDIV.children('div:last');
|
||||
if (lastDIV.is(':hidden')) {
|
||||
lastUL.remove();
|
||||
lastDIV.remove();
|
||||
} else {
|
||||
lastUL.prev().remove();
|
||||
lastDIV.prev().remove();
|
||||
}
|
||||
}
|
||||
|
||||
tabId = fm.namespace + '-help-debug-' + (+new Date());
|
||||
targetL = $('<li></li>').html('<a href="'+selfUrl+'#'+tabId+'">'+self.debug.debug.cmd+'</a>').prependTo(debugUL);
|
||||
target = $('<div id="'+tabId+'"></div>').data('debug', self.debug);
|
||||
|
||||
targetL.on('click.debugrender', function() {
|
||||
var debug = target.data('debug');
|
||||
target.removeData('debug');
|
||||
if (debug) {
|
||||
target.hide();
|
||||
if (debug.debug) {
|
||||
info = $('<fieldset>').append($('<legend></legend>').text('debug'), render($('<dl></dl>'), debug.debug));
|
||||
target.append(info);
|
||||
}
|
||||
if (debug.options) {
|
||||
info = $('<fieldset>').append($('<legend></legend>').text('options'), render($('<dl></dl>'), debug.options));
|
||||
target.append(info);
|
||||
}
|
||||
target.show();
|
||||
}
|
||||
targetL.off('click.debugrender');
|
||||
});
|
||||
|
||||
debugUL.after(target);
|
||||
|
||||
opened && debugDIV.tabs('refresh');
|
||||
}
|
||||
},
|
||||
content = '',
|
||||
opened, tabInteg, integDIV, tabDebug, debugDIV, debugUL;
|
||||
|
||||
this.alwaysEnabled = true;
|
||||
this.updateOnSelect = false;
|
||||
this.state = -1;
|
||||
|
||||
this.shortcuts = [{
|
||||
pattern : 'f1',
|
||||
description : this.title
|
||||
}];
|
||||
|
||||
fm.bind('load', function() {
|
||||
var parts = self.options.view || ['about', 'shortcuts', 'help', 'integrations', 'debug'],
|
||||
i, helpSource, tabBase, tabNav, tabs, delta;
|
||||
|
||||
// remove 'preference' tab, it moved to command 'preference'
|
||||
if ((i = $.inArray('preference', parts)) !== -1) {
|
||||
parts.splice(i, 1);
|
||||
}
|
||||
|
||||
// debug tab require jQueryUI Tabs Widget
|
||||
if (! $.fn.tabs) {
|
||||
if ((i = $.inArray(parts, 'debug')) !== -1) {
|
||||
parts.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
$.each(parts, function(i, title) {
|
||||
html.push(tab[r](/\{id\}/g, title)[r](/\{title\}/, fm.i18n(title)));
|
||||
});
|
||||
|
||||
html.push('</ul>');
|
||||
|
||||
$.inArray('about', parts) !== -1 && about();
|
||||
$.inArray('shortcuts', parts) !== -1 && shortcuts();
|
||||
if ($.inArray('help', parts) !== -1) {
|
||||
helpSource = fm.i18nBaseUrl + 'help/%s.html.js';
|
||||
help();
|
||||
}
|
||||
$.inArray('integrations', parts) !== -1 && integrations();
|
||||
$.inArray('debug', parts) !== -1 && debug();
|
||||
|
||||
html.push('</div>');
|
||||
content = $(html.join(''));
|
||||
|
||||
content.find('.ui-tabs-nav li')
|
||||
.on('mouseenter mouseleave', function(e) {
|
||||
$(this).toggleClass('ui-state-hover', e.type === 'mouseenter');
|
||||
})
|
||||
.on('focus blur', 'a', function(e) {
|
||||
$(e.delegateTarget).toggleClass('ui-state-focus', e.type === 'focusin');
|
||||
})
|
||||
.children()
|
||||
.on('click', function(e) {
|
||||
var link = $(this);
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
link.parent().addClass(clTabActive).siblings().removeClass(clTabActive);
|
||||
content.children('.ui-tabs-panel').hide().filter(link.attr('href')).show();
|
||||
})
|
||||
.filter(':first').trigger('click');
|
||||
|
||||
if (useInteg) {
|
||||
tabInteg = content.find('.elfinder-help-tab-integrations').hide();
|
||||
integDIV = content.find('#'+fm.namespace+'-help-integrations').hide().append($('<div class="elfinder-help-integrations-desc"></div>').html(fm.i18n('integrationWith')));
|
||||
fm.bind('helpIntegration', function(e) {
|
||||
var ul = integDIV.children('ul:first'),
|
||||
data, elm, cmdUL, cmdCls;
|
||||
if (e.data) {
|
||||
if ($.isPlainObject(e.data)) {
|
||||
data = Object.assign({
|
||||
link: '',
|
||||
title: '',
|
||||
banner: ''
|
||||
}, e.data);
|
||||
if (data.title || data.link) {
|
||||
if (!data.title) {
|
||||
data.title = data.link;
|
||||
}
|
||||
if (data.link) {
|
||||
elm = $('<a></a>').attr('href', data.link).attr('target', '_blank').text(data.title);
|
||||
} else {
|
||||
elm = $('<span></span>').text(data.title);
|
||||
}
|
||||
if (data.banner) {
|
||||
elm = $('<span></span>').append($('<img/>').attr(data.banner), elm);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
elm = $(e.data);
|
||||
elm.filter('a').each(function() {
|
||||
var tgt = $(this);
|
||||
if (!tgt.attr('target')) {
|
||||
tgt.attr('target', '_blank');;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (elm) {
|
||||
tabInteg.show();
|
||||
if (!ul.length) {
|
||||
ul = $('<ul class="elfinder-help-integrations"></ul>').appendTo(integDIV);
|
||||
}
|
||||
if (data && data.cmd) {
|
||||
cmdCls = 'elfinder-help-integration-' + data.cmd;
|
||||
cmdUL = ul.find('ul.' + cmdCls);
|
||||
if (!cmdUL.length) {
|
||||
cmdUL = $('<ul class="'+cmdCls+'"></ul>');
|
||||
ul.append($('<li></li>').append($('<span></span>').html(fm.i18n('cmd'+data.cmd))).append(cmdUL));
|
||||
}
|
||||
elm = cmdUL.append($('<li></li>').append(elm));
|
||||
} else {
|
||||
ul.append($('<li></li>').append(elm));
|
||||
}
|
||||
}
|
||||
}
|
||||
}).bind('themechange', function() {
|
||||
content.find('div.elfinder-help-term-theme').replaceWith(getTheme());
|
||||
});
|
||||
}
|
||||
|
||||
// debug
|
||||
if (useDebug) {
|
||||
tabDebug = content.find('.elfinder-help-tab-debug').hide();
|
||||
debugDIV = content.find('#'+fm.namespace+'-help-debug').children('div:first');
|
||||
debugUL = debugDIV.children('ul:first').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
self.debug = {};
|
||||
|
||||
fm.bind('backenddebug', function(e) {
|
||||
// CAUTION: DO NOT TOUCH `e.data`
|
||||
if (useDebug && e.data && e.data.debug) {
|
||||
self.debug = { options : e.data.options, debug : Object.assign({ cmd : fm.currentReqCmd }, e.data.debug) };
|
||||
if (self.dialog) {
|
||||
debugRender();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
content.find('#'+fm.namespace+'-help-about').find('.apiver').text(fm.api);
|
||||
self.dialog = self.fmDialog(content, {
|
||||
title : self.title,
|
||||
width : 530,
|
||||
maxWidth: 'window',
|
||||
maxHeight: 'window',
|
||||
autoOpen : false,
|
||||
destroyOnClose : false,
|
||||
close : function() {
|
||||
if (useDebug) {
|
||||
tabDebug.hide();
|
||||
debugDIV.tabs('destroy');
|
||||
}
|
||||
opened = false;
|
||||
}
|
||||
})
|
||||
.on('click', function(e) {
|
||||
e.stopPropagation();
|
||||
})
|
||||
.css({
|
||||
overflow: 'hidden'
|
||||
});
|
||||
|
||||
tabBase = self.dialog.children('.ui-tabs');
|
||||
tabNav = tabBase.children('.ui-tabs-nav:first');
|
||||
tabs = tabBase.children('.ui-tabs-panel');
|
||||
delta = self.dialog.outerHeight(true) - self.dialog.height();
|
||||
self.dialog.closest('.ui-dialog').on('resize', function() {
|
||||
tabs.height(self.dialog.height() - delta - tabNav.outerHeight(true) - 20);
|
||||
});
|
||||
|
||||
if (helpSource) {
|
||||
self.dialog.one('initContents', function() {
|
||||
$.ajax({
|
||||
url: self.options.helpSource? self.options.helpSource : helpSource.replace('%s', fm.lang),
|
||||
dataType: 'html'
|
||||
}).done(function(source) {
|
||||
$('#'+fm.namespace+'-help-help').html(source);
|
||||
}).fail(function() {
|
||||
$.ajax({
|
||||
url: helpSource.replace('%s', 'en'),
|
||||
dataType: 'html'
|
||||
}).done(function(source) {
|
||||
$('#'+fm.namespace+'-help-help').html(source);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
self.state = 0;
|
||||
|
||||
fm.trigger('helpBuilded', self.dialog);
|
||||
}).one('open', function() {
|
||||
var debug = false;
|
||||
fm.one('backenddebug', function() {
|
||||
debug =true;
|
||||
}).one('opendone', function() {
|
||||
requestAnimationFrame(function() {
|
||||
if (! debug && useDebug) {
|
||||
useDebug = false;
|
||||
tabDebug.hide();
|
||||
debugDIV.hide();
|
||||
debugUL.hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
this.getstate = function() {
|
||||
return 0;
|
||||
};
|
||||
|
||||
this.exec = function(sel, opts) {
|
||||
var tab = opts? opts.tab : void(0),
|
||||
debugShow = function() {
|
||||
if (useDebug) {
|
||||
debugDIV.tabs();
|
||||
debugUL.find('a:first').trigger('click');
|
||||
tabDebug.show();
|
||||
opened = true;
|
||||
}
|
||||
};
|
||||
debugShow();
|
||||
this.dialog.trigger('initContents').elfinderdialog('open').find((tab? '.elfinder-help-tab-'+tab : '.ui-tabs-nav li') + ' a:first').trigger('click');
|
||||
return $.Deferred().resolve();
|
||||
};
|
||||
|
||||
}).prototype = { forceLoad : true }; // this is required command
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @class elFinder command "hidden"
|
||||
* Always hidden command for uiCmdMap
|
||||
*
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
elFinder.prototype.commands.hidden = function() {
|
||||
"use strict";
|
||||
this.hidden = true;
|
||||
this.updateOnSelect = false;
|
||||
this.getstate = function() {
|
||||
return -1;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* @class elFinder command "hide".
|
||||
* folders/files to hide as personal setting.
|
||||
*
|
||||
* @type elFinder.command
|
||||
* @author Naoki Sawada
|
||||
*/
|
||||
elFinder.prototype.commands.hide = function() {
|
||||
"use strict";
|
||||
|
||||
var self = this,
|
||||
nameCache = {},
|
||||
hideData, hideCnt, cMenuType, sOrigin;
|
||||
|
||||
this.syncTitleOnChange = true;
|
||||
|
||||
this.shortcuts = [{
|
||||
pattern : 'ctrl+shift+dot',
|
||||
description : this.fm.i18n('toggleHidden')
|
||||
}];
|
||||
|
||||
this.init = function() {
|
||||
var fm = this.fm;
|
||||
|
||||
hideData = fm.storage('hide') || {items: {}};
|
||||
hideCnt = Object.keys(hideData.items).length;
|
||||
|
||||
this.title = fm.i18n(hideData.show? 'hideHidden' : 'showHidden');
|
||||
self.update(void(0), self.title);
|
||||
};
|
||||
|
||||
this.fm.bind('select contextmenucreate closecontextmenu', function(e, fm) {
|
||||
var sel = (e.data? (e.data.selected || e.data.targets) : null) || fm.selected();
|
||||
if (e.type === 'select' && e.data) {
|
||||
sOrigin = e.data.origin;
|
||||
} else if (e.type === 'contextmenucreate') {
|
||||
cMenuType = e.data.type;
|
||||
}
|
||||
if (!sel.length || (((e.type !== 'contextmenucreate' && sOrigin !== 'navbar') || cMenuType === 'cwd') && sel[0] === fm.cwd().hash)) {
|
||||
self.title = fm.i18n(hideData.show? 'hideHidden' : 'showHidden');
|
||||
} else {
|
||||
self.title = fm.i18n('cmdhide');
|
||||
}
|
||||
if (e.type !== 'closecontextmenu') {
|
||||
self.update(cMenuType === 'cwd'? (hideCnt? 0 : -1) : void(0), self.title);
|
||||
} else {
|
||||
cMenuType = '';
|
||||
requestAnimationFrame(function() {
|
||||
self.update(void(0), self.title);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.getstate = function(sel) {
|
||||
return (this.fm.cookieEnabled && cMenuType !== 'cwd' && (sel || this.fm.selected()).length) || hideCnt? 0 : -1;
|
||||
};
|
||||
|
||||
this.exec = function(hashes, opts) {
|
||||
var fm = this.fm,
|
||||
dfrd = $.Deferred()
|
||||
.done(function() {
|
||||
fm.trigger('hide', {items: items, opts: opts});
|
||||
})
|
||||
.fail(function(error) {
|
||||
fm.error(error);
|
||||
}),
|
||||
o = opts || {},
|
||||
items = o.targets? o.targets : (hashes || fm.selected()),
|
||||
added = [],
|
||||
removed = [],
|
||||
notifyto, files, res;
|
||||
|
||||
hideData = fm.storage('hide') || {};
|
||||
if (!$.isPlainObject(hideData)) {
|
||||
hideData = {};
|
||||
}
|
||||
if (!$.isPlainObject(hideData.items)) {
|
||||
hideData.items = {};
|
||||
}
|
||||
if (opts._currentType === 'shortcut' || !items.length || (opts._currentType !== 'navbar' && sOrigin !=='navbar' && items[0] === fm.cwd().hash)) {
|
||||
if (hideData.show) {
|
||||
o.hide = true;
|
||||
} else if (Object.keys(hideData.items).length) {
|
||||
o.show = true;
|
||||
}
|
||||
}
|
||||
if (o.reset) {
|
||||
o.show = true;
|
||||
hideCnt = 0;
|
||||
}
|
||||
if (o.show || o.hide) {
|
||||
if (o.show) {
|
||||
hideData.show = true;
|
||||
} else {
|
||||
delete hideData.show;
|
||||
}
|
||||
if (o.show) {
|
||||
fm.storage('hide', o.reset? null : hideData);
|
||||
self.title = fm.i18n('hideHidden');
|
||||
self.update(o.reset? -1 : void(0), self.title);
|
||||
$.each(hideData.items, function(h) {
|
||||
var f = fm.file(h, true);
|
||||
if (f && (fm.searchStatus.state || !f.phash || fm.file(f.phash))) {
|
||||
added.push(f);
|
||||
}
|
||||
});
|
||||
if (added.length) {
|
||||
fm.updateCache({added: added});
|
||||
fm.add({added: added});
|
||||
}
|
||||
if (o.reset) {
|
||||
hideData = {items: {}};
|
||||
}
|
||||
return dfrd.resolve();
|
||||
}
|
||||
items = Object.keys(hideData.items);
|
||||
}
|
||||
|
||||
if (items.length) {
|
||||
$.each(items, function(i, h) {
|
||||
var f;
|
||||
if (!hideData.items[h]) {
|
||||
f = fm.file(h);
|
||||
if (f) {
|
||||
nameCache[h] = f.i18 || f.name;
|
||||
}
|
||||
hideData.items[h] = nameCache[h]? nameCache[h] : h;
|
||||
}
|
||||
});
|
||||
hideCnt = Object.keys(hideData.items).length;
|
||||
files = this.files(items);
|
||||
fm.storage('hide', hideData);
|
||||
fm.remove({removed: items});
|
||||
if (hideData.show) {
|
||||
this.exec(void(0), {hide: true});
|
||||
}
|
||||
if (!o.hide) {
|
||||
res = {};
|
||||
res.undo = {
|
||||
cmd : 'hide',
|
||||
callback : function() {
|
||||
var nData = fm.storage('hide');
|
||||
if (nData) {
|
||||
$.each(items, function(i, h) {
|
||||
delete nData.items[h];
|
||||
});
|
||||
hideCnt = Object.keys(nData.items).length;
|
||||
fm.storage('hide', nData);
|
||||
fm.trigger('hide', {items: items, opts: {}});
|
||||
self.update(hideCnt? 0 : -1);
|
||||
}
|
||||
fm.updateCache({added: files});
|
||||
fm.add({added: files});
|
||||
}
|
||||
};
|
||||
res.redo = {
|
||||
cmd : 'hide',
|
||||
callback : function() {
|
||||
return fm.exec('hide', void(0), {targets: items});
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return dfrd.state() == 'rejected' ? dfrd : dfrd.resolve(res);
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
(elFinder.prototype.commands.home = function() {
|
||||
"use strict";
|
||||
this.title = 'Home';
|
||||
this.alwaysEnabled = true;
|
||||
this.updateOnSelect = false;
|
||||
this.shortcuts = [{
|
||||
pattern : 'ctrl+home ctrl+shift+up',
|
||||
description : 'Home'
|
||||
}];
|
||||
|
||||
this.getstate = function() {
|
||||
var root = this.fm.root(),
|
||||
cwd = this.fm.cwd().hash;
|
||||
|
||||
return root && cwd && root != cwd ? 0: -1;
|
||||
};
|
||||
|
||||
this.exec = function() {
|
||||
return this.fm.exec('open', this.fm.root());
|
||||
};
|
||||
|
||||
|
||||
}).prototype = { forceLoad : true }; // this is required command
|
||||
@@ -0,0 +1,345 @@
|
||||
/**
|
||||
* @class elFinder command "info".
|
||||
* Display dialog with file properties.
|
||||
*
|
||||
* @author Dmitry (dio) Levashov, dio@std42.ru
|
||||
**/
|
||||
(elFinder.prototype.commands.info = function() {
|
||||
"use strict";
|
||||
var m = 'msg',
|
||||
fm = this.fm,
|
||||
spclass = 'elfinder-spinner',
|
||||
btnclass = 'elfinder-info-button',
|
||||
msg = {
|
||||
calc : fm.i18n('calc'),
|
||||
size : fm.i18n('size'),
|
||||
unknown : fm.i18n('unknown'),
|
||||
path : fm.i18n('path'),
|
||||
aliasfor : fm.i18n('aliasfor'),
|
||||
modify : fm.i18n('modify'),
|
||||
perms : fm.i18n('perms'),
|
||||
locked : fm.i18n('locked'),
|
||||
dim : fm.i18n('dim'),
|
||||
kind : fm.i18n('kind'),
|
||||
files : fm.i18n('files'),
|
||||
folders : fm.i18n('folders'),
|
||||
roots : fm.i18n('volumeRoots'),
|
||||
items : fm.i18n('items'),
|
||||
yes : fm.i18n('yes'),
|
||||
no : fm.i18n('no'),
|
||||
link : fm.i18n('link'),
|
||||
owner : fm.i18n('owner'),
|
||||
group : fm.i18n('group'),
|
||||
perm : fm.i18n('perm'),
|
||||
getlink : fm.i18n('getLink')
|
||||
},
|
||||
applyZWSP = function(str, remove) {
|
||||
if (remove) {
|
||||
return str.replace(/\u200B/g, '');
|
||||
} else {
|
||||
return str.replace(/(\/|\\)/g, "$1\u200B");
|
||||
}
|
||||
};
|
||||
|
||||
this.items = ['size', 'aliasfor', 'path', 'link', 'dim', 'modify', 'perms', 'locked', 'owner', 'group', 'perm'];
|
||||
if (this.options.custom && Object.keys(this.options.custom).length) {
|
||||
$.each(this.options.custom, function(name, details) {
|
||||
details.label && this.items.push(details.label);
|
||||
});
|
||||
}
|
||||
|
||||
this.tpl = {
|
||||
main : '<div class="ui-helper-clearfix elfinder-info-title {dirclass}"><span class="elfinder-cwd-icon {class} ui-corner-all"{style}></span>{title}</div><table class="elfinder-info-tb">{content}</table>',
|
||||
itemTitle : '<strong>{name}</strong><span class="elfinder-info-kind">{kind}</span>',
|
||||
groupTitle : '<strong>{items}: {num}</strong>',
|
||||
row : '<tr><td class="elfinder-info-label">{label} : </td><td class="{class}">{value}</td></tr>',
|
||||
spinner : '<span>{text}</span> <span class="'+spclass+' '+spclass+'-{name}"></span>'
|
||||
};
|
||||
|
||||
this.alwaysEnabled = true;
|
||||
this.updateOnSelect = false;
|
||||
this.shortcuts = [{
|
||||
pattern : 'ctrl+i'
|
||||
}];
|
||||
|
||||
this.init = function() {
|
||||
$.each(msg, function(k, v) {
|
||||
msg[k] = fm.i18n(v);
|
||||
});
|
||||
};
|
||||
|
||||
this.getstate = function() {
|
||||
return 0;
|
||||
};
|
||||
|
||||
this.exec = function(hashes) {
|
||||
var files = this.files(hashes);
|
||||
if (! files.length) {
|
||||
files = this.files([ this.fm.cwd().hash ]);
|
||||
}
|
||||
var self = this,
|
||||
fm = this.fm,
|
||||
o = this.options,
|
||||
tpl = this.tpl,
|
||||
row = tpl.row,
|
||||
cnt = files.length,
|
||||
content = [],
|
||||
view = tpl.main,
|
||||
l = '{label}',
|
||||
v = '{value}',
|
||||
reqs = [],
|
||||
reqDfrd = null,
|
||||
opts = {
|
||||
title : fm.i18n('selectionInfo'),
|
||||
width : 'auto',
|
||||
close : function() {
|
||||
$(this).elfinderdialog('destroy');
|
||||
if (reqDfrd && reqDfrd.state() === 'pending') {
|
||||
reqDfrd.reject();
|
||||
}
|
||||
$.grep(reqs, function(r) {
|
||||
r && r.state() === 'pending' && r.reject();
|
||||
});
|
||||
}
|
||||
},
|
||||
count = [],
|
||||
replSpinner = function(msg, name, className) {
|
||||
dialog.find('.'+spclass+'-'+name).parent().html(msg).addClass(className || '');
|
||||
},
|
||||
id = fm.namespace+'-info-'+$.map(files, function(f) { return f.hash; }).join('-'),
|
||||
dialog = fm.getUI().find('#'+id),
|
||||
customActions = [],
|
||||
style = '',
|
||||
hashClass = 'elfinder-font-mono elfinder-info-hash',
|
||||
getHashAlgorisms = [],
|
||||
ndialog = fm.ui.notify,
|
||||
size, tmb, file, title, dcnt, rdcnt, path, hideItems, hashProg;
|
||||
|
||||
if (ndialog.is(':hidden') && ndialog.children('.elfinder-notify').length) {
|
||||
ndialog.elfinderdialog('open').height('auto');
|
||||
}
|
||||
|
||||
if (!cnt) {
|
||||
return $.Deferred().reject();
|
||||
}
|
||||
|
||||
if (dialog.length) {
|
||||
dialog.elfinderdialog('toTop');
|
||||
return $.Deferred().resolve();
|
||||
}
|
||||
|
||||
hideItems = fm.storage('infohides') || fm.arrayFlip(o.hideItems, true);
|
||||
|
||||
if (cnt === 1) {
|
||||
file = files[0];
|
||||
|
||||
if (file.icon) {
|
||||
style = ' '+fm.getIconStyle(file);
|
||||
}
|
||||
|
||||
view = view.replace('{dirclass}', file.csscls? fm.escape(file.csscls) : '').replace('{class}', fm.mime2class(file.mime)).replace('{style}', style);
|
||||
title = tpl.itemTitle.replace('{name}', fm.escape(file.i18 || file.name)).replace('{kind}', '<span title="'+fm.escape(file.mime)+'">'+fm.mime2kind(file)+'</span>');
|
||||
|
||||
tmb = fm.tmb(file);
|
||||
|
||||
if (!file.read) {
|
||||
size = msg.unknown;
|
||||
} else if (file.mime != 'directory' || file.alias) {
|
||||
size = fm.formatSize(file.size);
|
||||
} else {
|
||||
size = tpl.spinner.replace('{text}', msg.calc).replace('{name}', 'size');
|
||||
count.push(file.hash);
|
||||
}
|
||||
|
||||
!hideItems.size && content.push(row.replace(l, msg.size).replace(v, size));
|
||||
!hideItems.aleasfor && file.alias && content.push(row.replace(l, msg.aliasfor).replace(v, file.alias));
|
||||
if (!hideItems.path) {
|
||||
if (path = fm.path(file.hash, true)) {
|
||||
content.push(row.replace(l, msg.path).replace(v, applyZWSP(fm.escape(path))).replace('{class}', 'elfinder-info-path'));
|
||||
} else {
|
||||
content.push(row.replace(l, msg.path).replace(v, tpl.spinner.replace('{text}', msg.calc).replace('{name}', 'path')).replace('{class}', 'elfinder-info-path'));
|
||||
reqs.push(fm.path(file.hash, true, {notify: null})
|
||||
.fail(function() {
|
||||
replSpinner(msg.unknown, 'path');
|
||||
})
|
||||
.done(function(path) {
|
||||
replSpinner(applyZWSP(path), 'path');
|
||||
}));
|
||||
}
|
||||
}
|
||||
if (!hideItems.link && file.read) {
|
||||
var href,
|
||||
name_esc = fm.escape(file.name);
|
||||
if (file.url == '1') {
|
||||
content.push(row.replace(l, msg.link).replace(v, '<button class="'+btnclass+' '+spclass+'-url">'+msg.getlink+'</button>'));
|
||||
} else {
|
||||
if (file.url) {
|
||||
href = file.url;
|
||||
} else if (file.mime === 'directory') {
|
||||
if (o.nullUrlDirLinkSelf && file.url === null) {
|
||||
var loc = window.location;
|
||||
href = loc.pathname + loc.search + '#elf_' + file.hash;
|
||||
} else if (file.url !== '' && fm.option('url', (!fm.isRoot(file) && file.phash) || file.hash)) {
|
||||
href = fm.url(file.hash);
|
||||
}
|
||||
} else {
|
||||
href = fm.url(file.hash);
|
||||
}
|
||||
href && content.push(row.replace(l, msg.link).replace(v, '<a href="'+href+'" target="_blank">'+name_esc+'</a>'));
|
||||
}
|
||||
}
|
||||
|
||||
if (!hideItems.dim) {
|
||||
if (file.dim) { // old api
|
||||
content.push(row.replace(l, msg.dim).replace(v, file.dim));
|
||||
} else if (file.mime.indexOf('image') !== -1) {
|
||||
if (file.width && file.height) {
|
||||
content.push(row.replace(l, msg.dim).replace(v, file.width+'x'+file.height));
|
||||
} else if (file.size && file.size !== '0') {
|
||||
content.push(row.replace(l, msg.dim).replace(v, tpl.spinner.replace('{text}', msg.calc).replace('{name}', 'dim')));
|
||||
reqs.push(fm.request({
|
||||
data : {cmd : 'dim', target : file.hash},
|
||||
preventDefault : true
|
||||
})
|
||||
.fail(function() {
|
||||
replSpinner(msg.unknown, 'dim');
|
||||
})
|
||||
.done(function(data) {
|
||||
replSpinner(data.dim || msg.unknown, 'dim');
|
||||
if (data.dim) {
|
||||
var dim = data.dim.split('x');
|
||||
var rfile = fm.file(file.hash);
|
||||
rfile.width = dim[0];
|
||||
rfile.height = dim[1];
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
!hideItems.modify && content.push(row.replace(l, msg.modify).replace(v, fm.formatDate(file)));
|
||||
!hideItems.perms && content.push(row.replace(l, msg.perms).replace(v, fm.formatPermissions(file)));
|
||||
!hideItems.locked && content.push(row.replace(l, msg.locked).replace(v, file.locked ? msg.yes : msg.no));
|
||||
!hideItems.owner && file.owner && content.push(row.replace(l, msg.owner).replace(v, file.owner));
|
||||
!hideItems.group && file.group && content.push(row.replace(l, msg.group).replace(v, file.group));
|
||||
!hideItems.perm && file.perm && content.push(row.replace(l, msg.perm).replace(v, fm.formatFileMode(file.perm)));
|
||||
// Add custom info fields
|
||||
if (o.custom) {
|
||||
$.each(o.custom, function(name, details) {
|
||||
if (
|
||||
!hideItems[details.label]
|
||||
&&
|
||||
(!details.mimes || $.grep(details.mimes, function(m){return (file.mime === m || file.mime.indexOf(m+'/') === 0)? true : false;}).length)
|
||||
&&
|
||||
(!details.hashRegex || file.hash.match(details.hashRegex))
|
||||
) {
|
||||
// Add to the content
|
||||
content.push(row.replace(l, fm.i18n(details.label)).replace(v , details.tpl.replace('{id}', id)));
|
||||
// Register the action
|
||||
if (details.action && (typeof details.action == 'function')) {
|
||||
customActions.push(details.action);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
view = view.replace('{class}', 'elfinder-cwd-icon-group');
|
||||
title = tpl.groupTitle.replace('{items}', msg.items).replace('{num}', cnt);
|
||||
dcnt = $.grep(files, function(f) { return f.mime == 'directory' ? true : false ; }).length;
|
||||
if (!dcnt) {
|
||||
size = 0;
|
||||
$.each(files, function(h, f) {
|
||||
var s = parseInt(f.size);
|
||||
|
||||
if (s >= 0 && size >= 0) {
|
||||
size += s;
|
||||
} else {
|
||||
size = 'unknown';
|
||||
}
|
||||
});
|
||||
content.push(row.replace(l, msg.kind).replace(v, msg.files));
|
||||
!hideItems.size && content.push(row.replace(l, msg.size).replace(v, fm.formatSize(size)));
|
||||
} else {
|
||||
rdcnt = $.grep(files, function(f) { return f.mime === 'directory' && (! f.phash || f.isroot)? true : false ; }).length;
|
||||
dcnt -= rdcnt;
|
||||
content.push(row.replace(l, msg.kind).replace(v, (rdcnt === cnt || dcnt === cnt)? msg[rdcnt? 'roots' : 'folders'] : $.map({roots: rdcnt, folders: dcnt, files: cnt - rdcnt - dcnt}, function(c, t) { return c? msg[t]+' '+c : null; }).join(', ')));
|
||||
!hideItems.size && content.push(row.replace(l, msg.size).replace(v, tpl.spinner.replace('{text}', msg.calc).replace('{name}', 'size')));
|
||||
count = $.map(files, function(f) { return f.hash; });
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
view = view.replace('{title}', title).replace('{content}', content.join('').replace(/{class}/g, ''));
|
||||
|
||||
dialog = self.fmDialog(view, opts);
|
||||
dialog.attr('id', id).one('mousedown', '.elfinder-info-path', function() {
|
||||
$(this).html(applyZWSP($(this).html(), true));
|
||||
});
|
||||
|
||||
if (getHashAlgorisms.length) {
|
||||
hashProg.appendTo(dialog.find('.'+spclass+'-'+getHashAlgorisms[0]).parent());
|
||||
}
|
||||
|
||||
if (fm.UA.Mobile && $.fn.tooltip) {
|
||||
dialog.children('.ui-dialog-content .elfinder-info-title').tooltip({
|
||||
classes: {
|
||||
'ui-tooltip': 'elfinder-ui-tooltip ui-widget-shadow'
|
||||
},
|
||||
tooltipClass: 'elfinder-ui-tooltip ui-widget-shadow',
|
||||
track: true
|
||||
});
|
||||
}
|
||||
|
||||
if (file && file.url == '1') {
|
||||
dialog.on('click', '.'+spclass+'-url', function(){
|
||||
$(this).parent().html(tpl.spinner.replace('{text}', fm.i18n('ntfurl')).replace('{name}', 'url'));
|
||||
fm.request({
|
||||
data : {cmd : 'url', target : file.hash},
|
||||
preventDefault : true
|
||||
})
|
||||
.fail(function() {
|
||||
replSpinner(name_esc, 'url');
|
||||
})
|
||||
.done(function(data) {
|
||||
if (data.url) {
|
||||
replSpinner('<a href="'+data.url+'" target="_blank">'+name_esc+'</a>' || name_esc, 'url');
|
||||
var rfile = fm.file(file.hash);
|
||||
rfile.url = data.url;
|
||||
} else {
|
||||
replSpinner(name_esc, 'url');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// load thumbnail
|
||||
if (tmb) {
|
||||
$('<img/>')
|
||||
.on('load', function() { dialog.find('.elfinder-cwd-icon').addClass(tmb.className).css('background-image', "url('"+tmb.url+"')"); })
|
||||
.attr('src', tmb.url);
|
||||
}
|
||||
|
||||
// send request to count total size
|
||||
if (count.length) {
|
||||
reqDfrd = fm.getSize(count).done(function(data) {
|
||||
replSpinner(data.formated, 'size');
|
||||
}).fail(function() {
|
||||
replSpinner(msg.unknown, 'size');
|
||||
});
|
||||
}
|
||||
|
||||
// call custom actions
|
||||
if (customActions.length) {
|
||||
$.each(customActions, function(i, action) {
|
||||
try {
|
||||
action(file, fm, dialog);
|
||||
} catch(e) {
|
||||
fm.debug('error', e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return $.Deferred().resolve();
|
||||
};
|
||||
|
||||
}).prototype = { forceLoad : true }; // this is required command
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* @class elFinder command "mkdir"
|
||||
* Create new folder
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
elFinder.prototype.commands.mkdir = function() {
|
||||
"use strict";
|
||||
var fm = this.fm,
|
||||
self = this,
|
||||
curOrg;
|
||||
|
||||
this.value = '';
|
||||
this.disableOnSearch = true;
|
||||
this.updateOnSelect = false;
|
||||
this.syncTitleOnChange = true;
|
||||
this.mime = 'directory';
|
||||
this.prefix = 'untitled folder';
|
||||
this.exec = function(select, cOpts) {
|
||||
var onCwd;
|
||||
|
||||
if (select && select.length && cOpts && cOpts._currentType && cOpts._currentType === 'navbar') {
|
||||
this.origin = cOpts._currentType;
|
||||
this.data = {
|
||||
target: select[0]
|
||||
};
|
||||
} else {
|
||||
onCwd = fm.cwd().hash === select[0];
|
||||
this.origin = curOrg && !onCwd? curOrg : 'cwd';
|
||||
delete this.data;
|
||||
}
|
||||
if (! select && ! this.options.intoNewFolderToolbtn) {
|
||||
fm.getUI('cwd').trigger('unselectall');
|
||||
}
|
||||
//this.move = (!onCwd && curOrg !== 'navbar' && fm.selected().length)? true : false;
|
||||
this.move = this.value === fm.i18n('cmdmkdirin');
|
||||
return $.proxy(fm.res('mixin', 'make'), self)();
|
||||
};
|
||||
|
||||
this.shortcuts = [{
|
||||
pattern : 'ctrl+shift+n'
|
||||
}];
|
||||
|
||||
this.init = function() {
|
||||
if (this.options.intoNewFolderToolbtn) {
|
||||
this.syncTitleOnChange = true;
|
||||
}
|
||||
};
|
||||
|
||||
fm.bind('select contextmenucreate closecontextmenu', function(e) {
|
||||
var sel = (e.data? (e.data.selected || e.data.targets) : null) || fm.selected();
|
||||
|
||||
self.className = 'mkdir';
|
||||
curOrg = e.data && sel.length? (e.data.origin || e.data.type || '') : '';
|
||||
if (!self.options.intoNewFolderToolbtn && curOrg === '') {
|
||||
curOrg = 'cwd';
|
||||
}
|
||||
if (sel.length && curOrg !== 'navbar' && curOrg !== 'cwd' && fm.cwd().hash !== sel[0]) {
|
||||
self.title = fm.i18n('cmdmkdirin');
|
||||
self.className += ' elfinder-button-icon-mkdirin';
|
||||
} else {
|
||||
self.title = fm.i18n('cmdmkdir');
|
||||
}
|
||||
if (e.type !== 'closecontextmenu') {
|
||||
self.update(void(0), self.title);
|
||||
} else {
|
||||
requestAnimationFrame(function() {
|
||||
self.update(void(0), self.title);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.getstate = function(select) {
|
||||
var cwd = fm.cwd(),
|
||||
sel = (curOrg === 'navbar' || (select && select[0] !== cwd.hash))? this.files(select || fm.selected()) : [],
|
||||
cnt = sel.length,
|
||||
filter = function(files) {
|
||||
var fres = true;
|
||||
return $.grep(files, function(f) {
|
||||
fres = fres && f.read && ! f.locked? true : false;
|
||||
return fres;
|
||||
});
|
||||
};
|
||||
|
||||
if (curOrg === 'navbar') {
|
||||
return cnt && sel[0].write && sel[0].read? 0 : -1;
|
||||
} else {
|
||||
return cwd.write && (!cnt || filter(sel).length == cnt)? 0 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @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) {
|
||||
$.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]);
|
||||
return $.proxy(fm.res('mixin', 'make'), self)();
|
||||
}
|
||||
err = ['errMkfile', self.getTypeName(mime, type)];
|
||||
}
|
||||
return $.Deferred().reject(err);
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,381 @@
|
||||
/**
|
||||
* @class elFinder command "netmount"
|
||||
* Mount network volume with user credentials.
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
elFinder.prototype.commands.netmount = function() {
|
||||
"use strict";
|
||||
var self = this,
|
||||
hasMenus = false,
|
||||
content;
|
||||
|
||||
this.alwaysEnabled = true;
|
||||
this.updateOnSelect = false;
|
||||
|
||||
this.drivers = [];
|
||||
|
||||
this.handlers = {
|
||||
load : function() {
|
||||
var fm = self.fm;
|
||||
if (fm.cookieEnabled) {
|
||||
fm.one('open', function() {
|
||||
self.drivers = fm.netDrivers;
|
||||
if (self.drivers.length) {
|
||||
$.each(self.drivers, function() {
|
||||
var d = self.options[this];
|
||||
if (d) {
|
||||
hasMenus = true;
|
||||
if (d.integrateInfo) {
|
||||
fm.trigger('helpIntegration', Object.assign({cmd: 'netmount'}, d.integrateInfo));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.getstate = function() {
|
||||
return hasMenus ? 0 : -1;
|
||||
};
|
||||
|
||||
this.exec = function() {
|
||||
var fm = self.fm,
|
||||
dfrd = $.Deferred(),
|
||||
o = self.options,
|
||||
create = function() {
|
||||
var winFocus = function() {
|
||||
inputs.protocol.trigger('change', 'winfocus');
|
||||
},
|
||||
inputs = {
|
||||
protocol : $('<select></select>')
|
||||
.on('change', function(e, data){
|
||||
var protocol = this.value;
|
||||
content.find('.elfinder-netmount-tr').hide();
|
||||
content.find('.elfinder-netmount-tr-'+protocol).show();
|
||||
dialogNode && dialogNode.children('.ui-dialog-buttonpane:first').find('button').show();
|
||||
if (typeof o[protocol].select == 'function') {
|
||||
o[protocol].select(fm, e, data);
|
||||
}
|
||||
})
|
||||
.addClass('ui-corner-all')
|
||||
},
|
||||
opts = {
|
||||
title : fm.i18n('netMountDialogTitle'),
|
||||
resizable : true,
|
||||
modal : true,
|
||||
destroyOnClose : false,
|
||||
open : function() {
|
||||
$(window).on('focus.'+fm.namespace, winFocus);
|
||||
inputs.protocol.trigger('change');
|
||||
},
|
||||
close : function() {
|
||||
dfrd.state() == 'pending' && dfrd.reject();
|
||||
$(window).off('focus.'+fm.namespace, winFocus);
|
||||
},
|
||||
buttons : {}
|
||||
},
|
||||
doMount = function() {
|
||||
var protocol = inputs.protocol.val(),
|
||||
data = {cmd : 'netmount', protocol: protocol},
|
||||
cur = o[protocol],
|
||||
mnt2res;
|
||||
$.each(content.find('input.elfinder-netmount-inputs-'+protocol), function(name, input) {
|
||||
var val, elm;
|
||||
elm = $(input);
|
||||
if (elm.is(':radio,:checkbox')) {
|
||||
if (elm.is(':checked')) {
|
||||
val = $.trim(elm.val());
|
||||
}
|
||||
} else {
|
||||
val = $.trim(elm.val());
|
||||
}
|
||||
if (val) {
|
||||
data[input.name] = val;
|
||||
}
|
||||
});
|
||||
|
||||
if (!data.host) {
|
||||
return fm.trigger('error', {error : 'errNetMountHostReq', opts : {modal: true}});
|
||||
}
|
||||
|
||||
if (data.mnt2res) {
|
||||
mnt2res = true;
|
||||
}
|
||||
|
||||
fm.request({data : data, notify : {type : 'netmount', cnt : 1, hideCnt : true}})
|
||||
.done(function(data) {
|
||||
var pdir;
|
||||
if (data.added && data.added.length) {
|
||||
mnt2res && inputs.protocol.trigger('change', 'reset');
|
||||
if (data.added[0].phash) {
|
||||
if (pdir = fm.file(data.added[0].phash)) {
|
||||
if (! pdir.dirs) {
|
||||
pdir.dirs = 1;
|
||||
fm.change({ changed: [ pdir ] });
|
||||
}
|
||||
}
|
||||
}
|
||||
fm.one('netmountdone', function() {
|
||||
fm.exec('open', data.added[0].hash);
|
||||
});
|
||||
}
|
||||
dfrd.resolve();
|
||||
})
|
||||
.fail(function(error) {
|
||||
if (cur.fail && typeof cur.fail == 'function') {
|
||||
cur.fail(fm, fm.parseError(error));
|
||||
}
|
||||
dfrd.reject(error);
|
||||
});
|
||||
|
||||
self.dialog.elfinderdialog('close');
|
||||
},
|
||||
form = $('<form autocomplete="off"></form>').on('keydown', 'input', function(e) {
|
||||
var comp = true,
|
||||
next;
|
||||
if (e.keyCode === $.ui.keyCode.ENTER) {
|
||||
$.each(form.find('input:visible:not(.elfinder-input-optional)'), function() {
|
||||
if ($(this).val() === '') {
|
||||
comp = false;
|
||||
next = $(this);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (comp) {
|
||||
doMount();
|
||||
} else {
|
||||
next.trigger('focus');
|
||||
}
|
||||
}
|
||||
}),
|
||||
hidden = $('<div></div>'),
|
||||
dialog;
|
||||
|
||||
content = $('<table class="elfinder-info-tb elfinder-netmount-tb"></table>')
|
||||
.append($('<tr></tr>').append($('<td>'+fm.i18n('protocol')+'</td>')).append($('<td></td>').append(inputs.protocol)));
|
||||
|
||||
$.each(self.drivers, function(i, protocol) {
|
||||
if (o[protocol]) {
|
||||
inputs.protocol.append('<option value="'+protocol+'">'+fm.i18n(o[protocol].name || protocol)+'</option>');
|
||||
$.each(o[protocol].inputs, function(name, input) {
|
||||
input.attr('name', name);
|
||||
if (input.attr('type') != 'hidden') {
|
||||
input.addClass('ui-corner-all elfinder-netmount-inputs-'+protocol);
|
||||
content.append($('<tr></tr>').addClass('elfinder-netmount-tr elfinder-netmount-tr-'+protocol).append($('<td>'+fm.i18n(name)+'</td>')).append($('<td></td>').append(input)));
|
||||
} else {
|
||||
input.addClass('elfinder-netmount-inputs-'+protocol);
|
||||
hidden.append(input);
|
||||
}
|
||||
});
|
||||
o[protocol].protocol = inputs.protocol;
|
||||
}
|
||||
});
|
||||
|
||||
content.append(hidden);
|
||||
|
||||
content.find('.elfinder-netmount-tr').hide();
|
||||
content.find('.elfinder-netmount-tr-' + self.drivers[0]).show();
|
||||
|
||||
opts.buttons[fm.i18n('btnMount')] = doMount;
|
||||
|
||||
opts.buttons[fm.i18n('btnCancel')] = function() {
|
||||
self.dialog.elfinderdialog('close');
|
||||
};
|
||||
|
||||
content.find('select,input').addClass('elfinder-tabstop');
|
||||
|
||||
dialog = self.fmDialog(form.append(content), opts).ready(function() {
|
||||
inputs.protocol.trigger('change');
|
||||
dialog.elfinderdialog('posInit');
|
||||
});
|
||||
dialogNode = dialog.closest('.ui-dialog');
|
||||
return dialog;
|
||||
},
|
||||
dialogNode;
|
||||
|
||||
if (!self.dialog) {
|
||||
self.dialog = create();
|
||||
} else {
|
||||
self.dialog.elfinderdialog('open');
|
||||
}
|
||||
|
||||
return dfrd.promise();
|
||||
};
|
||||
|
||||
self.fm.bind('netmount', function(e) {
|
||||
var d = e.data || null,
|
||||
o = self.options,
|
||||
done = function() {
|
||||
if (o[d.protocol] && typeof o[d.protocol].done == 'function') {
|
||||
o[d.protocol].done(self.fm, d);
|
||||
content.find('select,input').addClass('elfinder-tabstop');
|
||||
self.dialog.elfinderdialog('tabstopsInit');
|
||||
}
|
||||
};
|
||||
if (d && d.protocol) {
|
||||
if (d.mode && d.mode === 'redirect') {
|
||||
// To support of third-party cookie blocking (ITP) on CORS
|
||||
// On iOS and iPadOS 13.4 and Safari 13.1 on macOS, the session cannot be continued when redirecting OAuth in CORS mode
|
||||
self.fm.request({
|
||||
data : {cmd : 'netmount', protocol : d.protocol, host: d.host, user : 'init', pass : 'return', options: d.options},
|
||||
preventDefault : true
|
||||
}).done(function(data) {
|
||||
d = JSON.parse(data.body);
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
elFinder.prototype.commands.netunmount = function() {
|
||||
var self = this;
|
||||
|
||||
this.alwaysEnabled = true;
|
||||
this.updateOnSelect = false;
|
||||
|
||||
this.drivers = [];
|
||||
|
||||
this.handlers = {
|
||||
load : function() {
|
||||
this.drivers = this.fm.netDrivers;
|
||||
}
|
||||
};
|
||||
|
||||
this.getstate = function(sel) {
|
||||
var fm = this.fm,
|
||||
file;
|
||||
return !!sel && this.drivers.length && !this._disabled && (file = fm.file(sel[0])) && file.netkey ? 0 : -1;
|
||||
};
|
||||
|
||||
this.exec = function(hashes) {
|
||||
var self = this,
|
||||
fm = this.fm,
|
||||
dfrd = $.Deferred()
|
||||
.fail(function(error) {
|
||||
error && fm.error(error);
|
||||
}),
|
||||
drive = fm.file(hashes[0]),
|
||||
childrenRoots = function(hash) {
|
||||
var roots = [],
|
||||
work;
|
||||
if (fm.leafRoots) {
|
||||
work = [];
|
||||
$.each(fm.leafRoots, function(phash, hashes) {
|
||||
var parents = fm.parents(phash),
|
||||
idx, deep;
|
||||
if ((idx = $.inArray(hash, parents)) !== -1) {
|
||||
idx = parents.length - idx;
|
||||
$.each(hashes, function(i, h) {
|
||||
work.push({i: idx, hash: h});
|
||||
});
|
||||
}
|
||||
});
|
||||
if (work.length) {
|
||||
work.sort(function(a, b) { return a.i < b.i; });
|
||||
$.each(work, function(i, o) {
|
||||
roots.push(o.hash);
|
||||
});
|
||||
}
|
||||
}
|
||||
return roots;
|
||||
};
|
||||
|
||||
if (this._disabled) {
|
||||
return dfrd.reject();
|
||||
}
|
||||
|
||||
if (dfrd.state() == 'pending') {
|
||||
fm.confirm({
|
||||
title : self.title,
|
||||
text : fm.i18n('confirmUnmount', drive.name),
|
||||
accept : {
|
||||
label : 'btnUnmount',
|
||||
callback : function() {
|
||||
var target = drive.hash,
|
||||
roots = childrenRoots(target),
|
||||
requests = [],
|
||||
removed = [],
|
||||
doUmount = function() {
|
||||
$.when(requests).done(function() {
|
||||
fm.request({
|
||||
data : {cmd : 'netmount', protocol : 'netunmount', host: drive.netkey, user : target, pass : 'dum'},
|
||||
notify : {type : 'netunmount', cnt : 1, hideCnt : true},
|
||||
preventFail : true
|
||||
})
|
||||
.fail(function(error) {
|
||||
dfrd.reject(error);
|
||||
})
|
||||
.done(function(data) {
|
||||
drive.volumeid && delete fm.volumeExpires[drive.volumeid];
|
||||
dfrd.resolve();
|
||||
});
|
||||
}).fail(function(error) {
|
||||
if (removed.length) {
|
||||
fm.remove({ removed: removed });
|
||||
}
|
||||
dfrd.reject(error);
|
||||
});
|
||||
};
|
||||
|
||||
if (roots.length) {
|
||||
fm.confirm({
|
||||
title : self.title,
|
||||
text : (function() {
|
||||
var msgs = ['unmountChildren'];
|
||||
$.each(roots, function(i, hash) {
|
||||
msgs.push([fm.file(hash).name]);
|
||||
});
|
||||
return msgs;
|
||||
})(),
|
||||
accept : {
|
||||
label : 'btnUnmount',
|
||||
callback : function() {
|
||||
$.each(roots, function(i, hash) {
|
||||
var d = fm.file(hash);
|
||||
if (d.netkey) {
|
||||
requests.push(fm.request({
|
||||
data : {cmd : 'netmount', protocol : 'netunmount', host: d.netkey, user : d.hash, pass : 'dum'},
|
||||
notify : {type : 'netunmount', cnt : 1, hideCnt : true},
|
||||
preventDefault : true
|
||||
}).done(function(data) {
|
||||
if (data.removed) {
|
||||
d.volumeid && delete fm.volumeExpires[d.volumeid];
|
||||
removed = removed.concat(data.removed);
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
doUmount();
|
||||
}
|
||||
},
|
||||
cancel : {
|
||||
label : 'btnCancel',
|
||||
callback : function() {
|
||||
dfrd.reject();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
requests = null;
|
||||
doUmount();
|
||||
}
|
||||
}
|
||||
},
|
||||
cancel : {
|
||||
label : 'btnCancel',
|
||||
callback : function() { dfrd.reject(); }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return dfrd;
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* @class elFinder command "open"
|
||||
* Enter folder or open files in new windows
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
(elFinder.prototype.commands.open = function() {
|
||||
"use strict";
|
||||
var fm = this.fm,
|
||||
self = this;
|
||||
this.alwaysEnabled = true;
|
||||
this.noChangeDirOnRemovedCwd = true;
|
||||
|
||||
this._handlers = {
|
||||
dblclick : function(e) {
|
||||
var arg = e.data && e.data.file? [ e.data.file ]: void(0);
|
||||
if (self.getstate(arg) === 0) {
|
||||
e.preventDefault();
|
||||
fm.exec('open', arg);
|
||||
}
|
||||
},
|
||||
'select enable disable reload' : function(e) { this.update(e.type == 'disable' ? -1 : void(0)); }
|
||||
};
|
||||
|
||||
this.shortcuts = [{
|
||||
pattern : 'ctrl+down numpad_enter'+(fm.OS != 'mac' && ' enter')
|
||||
}];
|
||||
|
||||
this.getstate = function(select) {
|
||||
var sel = this.files(select),
|
||||
cnt = sel.length,
|
||||
filter = function(files) {
|
||||
var fres = true;
|
||||
return $.grep(files, function(file) {
|
||||
fres = fres && file.mime == 'directory' || ! file.read ? false : true;
|
||||
return fres;
|
||||
});
|
||||
};
|
||||
|
||||
return cnt == 1
|
||||
? (sel[0].read ? 0 : -1)
|
||||
: (cnt && !fm.UA.Mobile) ? ($.grep(sel, function(file) { return file.mime == 'directory' || ! file.read ? false : true;}).length == cnt ? 0 : -1) : -1;
|
||||
};
|
||||
|
||||
this.exec = function(hashes, cOpts) {
|
||||
var dfrd = $.Deferred().fail(function(error) { error && fm.error(error); }),
|
||||
files = this.files(hashes),
|
||||
cnt = files.length,
|
||||
thash = (typeof cOpts == 'object')? cOpts.thash : false,
|
||||
opts = this.options,
|
||||
into = opts.into || 'window',
|
||||
file, url, s, w, imgW, imgH, winW, winH, reg, link, html5dl, inline,
|
||||
selAct, cmd;
|
||||
|
||||
if (!cnt && !thash) {
|
||||
{
|
||||
return dfrd.reject();
|
||||
}
|
||||
}
|
||||
|
||||
// open folder
|
||||
if (thash || (cnt == 1 && (file = files[0]) && file.mime == 'directory')) {
|
||||
if (!thash && file && !file.read) {
|
||||
return dfrd.reject(['errOpen', file.name, 'errPerm']);
|
||||
} else {
|
||||
if (fm.keyState.ctrlKey && (fm.keyState.shiftKey || typeof fm.options.getFileCallback !== 'function')) {
|
||||
if (fm.getCommand('opennew')) {
|
||||
return fm.exec('opennew', [thash? thash : file.hash]);
|
||||
}
|
||||
}
|
||||
|
||||
return fm.request({
|
||||
data : {cmd : 'open', target : thash || file.hash},
|
||||
notify : {type : 'open', cnt : 1, hideCnt : true},
|
||||
syncOnFail : true,
|
||||
lazy : false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
files = $.grep(files, function(file) { return file.mime != 'directory' ? true : false; });
|
||||
|
||||
// nothing to open or files and folders selected - do nothing
|
||||
if (cnt != files.length) {
|
||||
return dfrd.reject();
|
||||
}
|
||||
|
||||
var doOpen = function() {
|
||||
var openCB = function(url) {
|
||||
var link = $('<a rel="noopener">').hide().appendTo($('body'));
|
||||
if (fm.UA.Mobile || !inline) {
|
||||
if (html5dl) {
|
||||
if (!inline) {
|
||||
link.attr('download', file.name);
|
||||
} else {
|
||||
link.attr('target', '_blank');
|
||||
}
|
||||
link.attr('href', url).get(0).click();
|
||||
} else {
|
||||
wnd = window.open(url);
|
||||
if (!wnd) {
|
||||
return dfrd.reject('errPopup');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getOnly = (typeof opts.method === 'string' && opts.method.toLowerCase() === 'get');
|
||||
if (!getOnly
|
||||
&& url.indexOf(fm.options.url) === 0
|
||||
&& fm.customData
|
||||
&& Object.keys(fm.customData).length
|
||||
// Since playback by POST request can not be done in Chrome, media allows GET request
|
||||
&& !file.mime.match(/^(?:video|audio)/)
|
||||
) {
|
||||
// Send request as 'POST' method to hide custom data at location bar
|
||||
url = '';
|
||||
}
|
||||
if (into === 'window') {
|
||||
// set window size for image if set
|
||||
imgW = winW = Math.round(2 * screen.availWidth / 3);
|
||||
imgH = winH = Math.round(2 * screen.availHeight / 3);
|
||||
if (parseInt(file.width) && parseInt(file.height)) {
|
||||
imgW = parseInt(file.width);
|
||||
imgH = parseInt(file.height);
|
||||
} else if (file.dim) {
|
||||
s = file.dim.split('x');
|
||||
imgW = parseInt(s[0]);
|
||||
imgH = parseInt(s[1]);
|
||||
}
|
||||
if (winW >= imgW && winH >= imgH) {
|
||||
winW = imgW;
|
||||
winH = imgH;
|
||||
} else {
|
||||
if ((imgW - winW) > (imgH - winH)) {
|
||||
winH = Math.round(imgH * (winW / imgW));
|
||||
} else {
|
||||
winW = Math.round(imgW * (winH / imgH));
|
||||
}
|
||||
}
|
||||
w = 'width='+winW+',height='+winH;
|
||||
wnd = window.open(url, target, w + ',top=50,left=50,scrollbars=yes,resizable=yes,titlebar=no');
|
||||
} else {
|
||||
if (into === 'tabs') {
|
||||
target = file.hash;
|
||||
}
|
||||
wnd = window.open('about:blank', target);
|
||||
}
|
||||
|
||||
if (!wnd) {
|
||||
return dfrd.reject('errPopup');
|
||||
}
|
||||
|
||||
if (url === '') {
|
||||
var form = document.createElement("form");
|
||||
form.action = fm.options.url;
|
||||
form.method = 'POST';
|
||||
form.target = target;
|
||||
form.style.display = 'none';
|
||||
var params = Object.assign({}, fm.customData, {
|
||||
cmd: 'file',
|
||||
target: file.hash,
|
||||
_t: file.ts || parseInt(+new Date()/1000)
|
||||
});
|
||||
$.each(params, function(key, val)
|
||||
{
|
||||
var input = document.createElement("input");
|
||||
input.name = key;
|
||||
input.value = val;
|
||||
form.appendChild(input);
|
||||
});
|
||||
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
} else if (into !== 'window') {
|
||||
wnd.location = url;
|
||||
}
|
||||
$(wnd).trigger('focus');
|
||||
}
|
||||
link.remove();
|
||||
},
|
||||
wnd, target, getOnly;
|
||||
|
||||
try {
|
||||
reg = new RegExp(fm.option('dispInlineRegex'), 'i');
|
||||
} catch(e) {
|
||||
reg = false;
|
||||
}
|
||||
|
||||
// open files
|
||||
html5dl = (typeof $('<a>').get(0).download === 'string');
|
||||
cnt = files.length;
|
||||
while (cnt--) {
|
||||
target = 'elf_open_window';
|
||||
file = files[cnt];
|
||||
|
||||
if (!file.read) {
|
||||
return dfrd.reject(['errOpen', file.name, 'errPerm']);
|
||||
}
|
||||
|
||||
inline = (reg && file.mime.match(reg));
|
||||
fm.openUrl(file.hash, !inline, openCB);
|
||||
}
|
||||
return dfrd.resolve(hashes);
|
||||
};
|
||||
|
||||
if (cnt > 1) {
|
||||
fm.confirm({
|
||||
title: 'openMulti',
|
||||
text : ['openMultiConfirm', cnt + ''],
|
||||
accept : {
|
||||
label : 'cmdopen',
|
||||
callback : function() { doOpen(); }
|
||||
},
|
||||
cancel : {
|
||||
label : 'btnCancel',
|
||||
callback : function() {
|
||||
dfrd.reject();
|
||||
}
|
||||
},
|
||||
buttons : (fm.getCommand('zipdl') && fm.isCommandEnabled('zipdl', fm.cwd().hash))? [
|
||||
{
|
||||
label : 'cmddownload',
|
||||
callback : function() {
|
||||
fm.exec('download', hashes);
|
||||
dfrd.reject();
|
||||
}
|
||||
}
|
||||
] : []
|
||||
});
|
||||
} else {
|
||||
selAct = fm.storage('selectAction') || opts.selectAction;
|
||||
if (selAct) {
|
||||
$.each(selAct.split('/'), function() {
|
||||
var cmdName = this.valueOf();
|
||||
if (cmdName !== 'open' && (cmd = fm.getCommand(cmdName)) && cmd.enabled()) {
|
||||
return false;
|
||||
}
|
||||
cmd = null;
|
||||
});
|
||||
if (cmd) {
|
||||
return fm.exec(cmd.name);
|
||||
}
|
||||
}
|
||||
doOpen();
|
||||
}
|
||||
|
||||
return dfrd;
|
||||
};
|
||||
|
||||
}).prototype = { forceLoad : true }; // this is required command
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @class elFinder command "opendir"
|
||||
* Enter parent folder
|
||||
*
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
elFinder.prototype.commands.opendir = function() {
|
||||
"use strict";
|
||||
this.alwaysEnabled = true;
|
||||
|
||||
this.getstate = function() {
|
||||
var sel = this.fm.selected(),
|
||||
cnt = sel.length,
|
||||
wz;
|
||||
if (cnt !== 1) {
|
||||
return -1;
|
||||
}
|
||||
wz = this.fm.getUI('workzone');
|
||||
return wz.hasClass('elfinder-search-result')? 0 : -1;
|
||||
};
|
||||
|
||||
this.exec = function(hashes) {
|
||||
var fm = this.fm,
|
||||
dfrd = $.Deferred(),
|
||||
files = this.files(hashes),
|
||||
cnt = files.length,
|
||||
hash, pcheck = null;
|
||||
|
||||
if (!cnt || !files[0].phash) {
|
||||
return dfrd.reject();
|
||||
}
|
||||
|
||||
hash = files[0].phash;
|
||||
fm.trigger('searchend', { noupdate: true });
|
||||
fm.request({
|
||||
data : {cmd : 'open', target : hash},
|
||||
notify : {type : 'open', cnt : 1, hideCnt : true},
|
||||
syncOnFail : false
|
||||
});
|
||||
|
||||
return dfrd;
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @class elFinder command "opennew"
|
||||
* Open folder in new window
|
||||
*
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
elFinder.prototype.commands.opennew = function() {
|
||||
"use strict";
|
||||
var fm = this.fm;
|
||||
|
||||
this.shortcuts = [{
|
||||
pattern : (typeof(fm.options.getFileCallback) === 'function'? 'shift+' : '') + 'ctrl+enter'
|
||||
}];
|
||||
|
||||
this.getstate = function(select) {
|
||||
var sel = this.files(select),
|
||||
cnt = sel.length;
|
||||
|
||||
return cnt === 1
|
||||
? (sel[0].mime === 'directory' && sel[0].read? 0 : -1)
|
||||
: -1;
|
||||
};
|
||||
|
||||
this.exec = function(hashes) {
|
||||
var dfrd = $.Deferred(),
|
||||
files = this.files(hashes),
|
||||
cnt = files.length,
|
||||
opts = this.options,
|
||||
file, loc, url, win;
|
||||
|
||||
// open folder to new tab (window)
|
||||
if (cnt === 1 && (file = files[0]) && file.mime === 'directory') {
|
||||
loc = window.location;
|
||||
if (opts.url) {
|
||||
url = opts.url;
|
||||
} else {
|
||||
url = loc.pathname;
|
||||
}
|
||||
if (opts.useOriginQuery) {
|
||||
if (!url.match(/\?/)) {
|
||||
url += loc.search;
|
||||
} else if (loc.search) {
|
||||
url += '&' + loc.search.substr(1);
|
||||
}
|
||||
}
|
||||
url += '#elf_' + file.hash;
|
||||
win = window.open(url, '_blank');
|
||||
setTimeout(function() {
|
||||
win.focus();
|
||||
}, 1000);
|
||||
return dfrd.resolve();
|
||||
} else {
|
||||
return dfrd.reject();
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,412 @@
|
||||
/**
|
||||
* @class elFinder command "paste"
|
||||
* Paste filesfrom clipboard into directory.
|
||||
* If files pasted in its parent directory - files duplicates will created
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
elFinder.prototype.commands.paste = function() {
|
||||
"use strict";
|
||||
this.updateOnSelect = false;
|
||||
|
||||
this.handlers = {
|
||||
changeclipboard : function() { this.update(); }
|
||||
};
|
||||
|
||||
this.shortcuts = [{
|
||||
pattern : 'ctrl+v shift+insert'
|
||||
}];
|
||||
|
||||
this.getstate = function(dst) {
|
||||
if (this._disabled) {
|
||||
return -1;
|
||||
}
|
||||
if (dst) {
|
||||
if (Array.isArray(dst)) {
|
||||
if (dst.length != 1) {
|
||||
return -1;
|
||||
}
|
||||
dst = this.fm.file(dst[0]);
|
||||
}
|
||||
} else {
|
||||
dst = this.fm.cwd();
|
||||
}
|
||||
|
||||
return this.fm.clipboard().length && dst.mime == 'directory' && dst.write ? 0 : -1;
|
||||
};
|
||||
|
||||
this.exec = function(select, cOpts) {
|
||||
var self = this,
|
||||
fm = self.fm,
|
||||
opts = cOpts || {},
|
||||
dst = select ? this.files(select)[0] : fm.cwd(),
|
||||
files = fm.clipboard(),
|
||||
cnt = files.length,
|
||||
cut = cnt ? files[0].cut : false,
|
||||
cmd = opts._cmd? opts._cmd : (cut? 'move' : 'copy'),
|
||||
error = 'err' + cmd.charAt(0).toUpperCase() + cmd.substr(1),
|
||||
fpaste = [],
|
||||
fcopy = [],
|
||||
dfrd = $.Deferred()
|
||||
.fail(function(error) {
|
||||
error && fm.error(error);
|
||||
})
|
||||
.always(function() {
|
||||
fm.unlockfiles({files : $.map(files, function(f) { return f.hash; })});
|
||||
}),
|
||||
copy = function(files) {
|
||||
return files.length && fm._commands.duplicate
|
||||
? fm.exec('duplicate', files)
|
||||
: $.Deferred().resolve();
|
||||
},
|
||||
paste = function(files) {
|
||||
var dfrd = $.Deferred(),
|
||||
existed = [],
|
||||
hashes = {},
|
||||
intersect = function(files, names) {
|
||||
var ret = [],
|
||||
i = files.length;
|
||||
|
||||
while (i--) {
|
||||
$.inArray(files[i].name, names) !== -1 && ret.unshift(i);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
confirm = function(ndx) {
|
||||
var i = existed[ndx],
|
||||
file = files[i],
|
||||
last = ndx == existed.length-1;
|
||||
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
|
||||
fm.confirm({
|
||||
title : fm.i18n(cmd + 'Files'),
|
||||
text : ['errExists', file.name, cmd === 'restore'? 'confirmRest' : 'confirmRepl'],
|
||||
all : !last,
|
||||
accept : {
|
||||
label : 'btnYes',
|
||||
callback : function(all) {
|
||||
!last && !all
|
||||
? confirm(++ndx)
|
||||
: paste(files);
|
||||
}
|
||||
},
|
||||
reject : {
|
||||
label : 'btnNo',
|
||||
callback : function(all) {
|
||||
var i;
|
||||
|
||||
if (all) {
|
||||
i = existed.length;
|
||||
while (ndx < i--) {
|
||||
files[existed[i]].remove = true;
|
||||
}
|
||||
} else {
|
||||
files[existed[ndx]].remove = true;
|
||||
}
|
||||
|
||||
!last && !all
|
||||
? confirm(++ndx)
|
||||
: paste(files);
|
||||
}
|
||||
},
|
||||
cancel : {
|
||||
label : 'btnCancel',
|
||||
callback : function() {
|
||||
dfrd.resolve();
|
||||
}
|
||||
},
|
||||
buttons : [
|
||||
{
|
||||
label : 'btnBackup',
|
||||
callback : function(all) {
|
||||
var i;
|
||||
if (all) {
|
||||
i = existed.length;
|
||||
while (ndx < i--) {
|
||||
files[existed[i]].rename = true;
|
||||
}
|
||||
} else {
|
||||
files[existed[ndx]].rename = true;
|
||||
}
|
||||
!last && !all
|
||||
? confirm(++ndx)
|
||||
: paste(files);
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
},
|
||||
valid = function(names) {
|
||||
var exists = {}, existedArr;
|
||||
if (names) {
|
||||
if (Array.isArray(names)) {
|
||||
if (names.length) {
|
||||
if (typeof names[0] == 'string') {
|
||||
// elFinder <= 2.1.6 command `is` results
|
||||
existed = intersect(files, names);
|
||||
} else {
|
||||
$.each(names, function(i, v) {
|
||||
exists[v.name] = v.hash;
|
||||
});
|
||||
existed = intersect(files, $.map(exists, function(h, n) { return n; }));
|
||||
$.each(files, function(i, file) {
|
||||
if (exists[file.name]) {
|
||||
hashes[exists[file.name]] = file.name;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
existedArr = [];
|
||||
existed = $.map(names, function(n) {
|
||||
if (typeof n === 'string') {
|
||||
return n;
|
||||
} else {
|
||||
// support to >=2.1.11 plugin Normalizer, Sanitizer
|
||||
existedArr = existedArr.concat(n);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (existedArr.length) {
|
||||
existed = existed.concat(existedArr);
|
||||
}
|
||||
existed = intersect(files, existed);
|
||||
hashes = names;
|
||||
}
|
||||
}
|
||||
existed.length ? confirm(0) : paste(files);
|
||||
},
|
||||
paste = function(selFiles) {
|
||||
var renames = [],
|
||||
files = $.grep(selFiles, function(file) {
|
||||
if (file.rename) {
|
||||
renames.push(file.name);
|
||||
}
|
||||
return !file.remove ? true : false;
|
||||
}),
|
||||
cnt = files.length,
|
||||
groups = {},
|
||||
args = [],
|
||||
targets, reqData;
|
||||
|
||||
if (!cnt) {
|
||||
return dfrd.resolve();
|
||||
}
|
||||
|
||||
targets = $.map(files, function(f) { return f.hash; });
|
||||
|
||||
reqData = {cmd : 'paste', dst : dst.hash, targets : targets, cut : cut ? 1 : 0, renames : renames, hashes : hashes, suffix : fm.options.backupSuffix};
|
||||
if (fm.api < 2.1) {
|
||||
reqData.src = files[0].phash;
|
||||
}
|
||||
|
||||
fm.request({
|
||||
data : reqData,
|
||||
notify : {type : cmd, cnt : cnt},
|
||||
cancel : true,
|
||||
navigate : {
|
||||
toast : opts.noToast? {} : {
|
||||
inbuffer : {msg: fm.i18n(['complete', fm.i18n('cmd' + cmd)]), action: {
|
||||
cmd: 'open',
|
||||
msg: 'cmdopendir',
|
||||
data: [dst.hash],
|
||||
done: 'select',
|
||||
cwdNot: dst.hash
|
||||
}}
|
||||
}
|
||||
}
|
||||
})
|
||||
.done(function(data) {
|
||||
var dsts = {},
|
||||
added = data.added && data.added.length? data.added : null;
|
||||
if (cut && added) {
|
||||
// undo/redo
|
||||
$.each(files, function(i, f) {
|
||||
var phash = f.phash,
|
||||
srcHash = function(name) {
|
||||
var hash;
|
||||
$.each(added, function(i, f) {
|
||||
if (f.name === name) {
|
||||
hash = f.hash;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return hash;
|
||||
},
|
||||
shash = srcHash(f.name);
|
||||
if (shash) {
|
||||
if (dsts[phash]) {
|
||||
dsts[phash].push(shash);
|
||||
} else {
|
||||
dsts[phash] = [ shash ];
|
||||
}
|
||||
}
|
||||
});
|
||||
if (Object.keys(dsts).length) {
|
||||
data.undo = {
|
||||
cmd : 'move',
|
||||
callback : function() {
|
||||
var reqs = [];
|
||||
$.each(dsts, function(dst, targets) {
|
||||
reqs.push(fm.request({
|
||||
data : {cmd : 'paste', dst : dst, targets : targets, cut : 1},
|
||||
notify : {type : 'undo', cnt : targets.length}
|
||||
}));
|
||||
});
|
||||
return $.when.apply(null, reqs);
|
||||
}
|
||||
};
|
||||
data.redo = {
|
||||
cmd : 'move',
|
||||
callback : function() {
|
||||
return fm.request({
|
||||
data : reqData,
|
||||
notify : {type : 'redo', cnt : cnt}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
dfrd.resolve(data);
|
||||
})
|
||||
.fail(function(flg) {
|
||||
dfrd.reject();
|
||||
if (flg === 0) {
|
||||
// canceling
|
||||
fm.sync();
|
||||
}
|
||||
})
|
||||
.always(function() {
|
||||
fm.unlockfiles({files : files});
|
||||
});
|
||||
},
|
||||
internames;
|
||||
|
||||
if (!fm.isCommandEnabled(self.name, dst.hash) || !files.length) {
|
||||
return dfrd.resolve();
|
||||
}
|
||||
|
||||
if (fm.oldAPI) {
|
||||
paste(files);
|
||||
} else {
|
||||
|
||||
if (!fm.option('copyOverwrite', dst.hash)) {
|
||||
paste(files);
|
||||
} else {
|
||||
internames = $.map(files, function(f) { return f.name; });
|
||||
dst.hash == fm.cwd().hash
|
||||
? valid($.map(fm.files(), function(file) { return file.phash == dst.hash ? {hash: file.hash, name: file.name} : null; }))
|
||||
: fm.request({
|
||||
data : {cmd : 'ls', target : dst.hash, intersect : internames},
|
||||
notify : {type : 'prepare', cnt : 1, hideCnt : true},
|
||||
preventFail : true
|
||||
})
|
||||
.always(function(data) {
|
||||
valid(data.list);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return dfrd;
|
||||
},
|
||||
parents, fparents, cutDfrd;
|
||||
|
||||
|
||||
if (!cnt || !dst || dst.mime != 'directory') {
|
||||
return dfrd.reject();
|
||||
}
|
||||
|
||||
if (!dst.write) {
|
||||
return dfrd.reject([error, files[0].name, 'errPerm']);
|
||||
}
|
||||
|
||||
parents = fm.parents(dst.hash);
|
||||
|
||||
$.each(files, function(i, file) {
|
||||
if (!file.read) {
|
||||
return !dfrd.reject([error, file.name, 'errPerm']);
|
||||
}
|
||||
|
||||
if (cut && file.locked) {
|
||||
return !dfrd.reject(['errLocked', file.name]);
|
||||
}
|
||||
|
||||
if ($.inArray(file.hash, parents) !== -1) {
|
||||
return !dfrd.reject(['errCopyInItself', file.name]);
|
||||
}
|
||||
|
||||
if (file.mime && file.mime !== 'directory' && ! fm.uploadMimeCheck(file.mime, dst.hash)) {
|
||||
return !dfrd.reject([error, file.name, 'errUploadMime']);
|
||||
}
|
||||
|
||||
fparents = fm.parents(file.hash);
|
||||
fparents.pop();
|
||||
if ($.inArray(dst.hash, fparents) !== -1) {
|
||||
|
||||
if ($.grep(fparents, function(h) { var d = fm.file(h); return d.phash == dst.hash && d.name == file.name ? true : false; }).length) {
|
||||
return !dfrd.reject(['errReplByChild', file.name]);
|
||||
}
|
||||
}
|
||||
|
||||
if (file.phash == dst.hash) {
|
||||
fcopy.push(file.hash);
|
||||
} else {
|
||||
fpaste.push({
|
||||
hash : file.hash,
|
||||
phash : file.phash,
|
||||
name : file.name
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (dfrd.state() === 'rejected') {
|
||||
return dfrd;
|
||||
}
|
||||
|
||||
cutDfrd = $.Deferred();
|
||||
if (cut && self.options.moveConfirm) {
|
||||
fm.confirm({
|
||||
title : 'moveFiles',
|
||||
text : fm.i18n('confirmMove', dst.i18 || dst.name),
|
||||
accept : {
|
||||
label : 'btnYes',
|
||||
callback : function() {
|
||||
cutDfrd.resolve();
|
||||
}
|
||||
},
|
||||
cancel : {
|
||||
label : 'btnCancel',
|
||||
callback : function() {
|
||||
cutDfrd.reject();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
cutDfrd.resolve();
|
||||
}
|
||||
|
||||
cutDfrd.done(function() {
|
||||
$.when(
|
||||
copy(fcopy),
|
||||
paste(fpaste)
|
||||
)
|
||||
.done(function(cr, pr) {
|
||||
dfrd.resolve(pr && pr.undo? pr : void(0));
|
||||
})
|
||||
.fail(function() {
|
||||
dfrd.reject();
|
||||
})
|
||||
.always(function() {
|
||||
cut && fm.clipboard([]);
|
||||
});
|
||||
}).fail(function() {
|
||||
dfrd.reject();
|
||||
});
|
||||
|
||||
return dfrd;
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @class elFinder command "places"
|
||||
* Regist to Places
|
||||
*
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
elFinder.prototype.commands.places = function() {
|
||||
"use strict";
|
||||
var self = this,
|
||||
fm = this.fm,
|
||||
filter = function(hashes) {
|
||||
var fres = true;
|
||||
return $.grep(self.files(hashes), function(f) {
|
||||
fres = fres && f.mime == 'directory' ? true : false;
|
||||
return fres;
|
||||
});
|
||||
},
|
||||
places = null;
|
||||
|
||||
this.getstate = function(select) {
|
||||
var sel = this.hashes(select),
|
||||
cnt = sel.length;
|
||||
|
||||
return places && cnt && cnt == filter(sel).length ? 0 : -1;
|
||||
};
|
||||
|
||||
this.exec = function(hashes) {
|
||||
var files = this.files(hashes);
|
||||
places.trigger('regist', [ files ]);
|
||||
return $.Deferred().resolve();
|
||||
};
|
||||
|
||||
fm.one('load', function(){
|
||||
places = fm.ui.places;
|
||||
});
|
||||
|
||||
};
|
||||
+605
@@ -0,0 +1,605 @@
|
||||
/**
|
||||
* @class elFinder command "preference"
|
||||
* "Preference" dialog
|
||||
*
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
elFinder.prototype.commands.preference = function() {
|
||||
var self = this,
|
||||
fm = this.fm,
|
||||
r = 'replace',
|
||||
tab = '<li class="' + fm.res('class', 'tabstab') + ' elfinder-preference-tab-{id}"><a href="#'+fm.namespace+'-preference-{id}" id="'+fm.namespace+'-preference-tab-{id}" class="ui-tabs-anchor {class}">{title}</a></li>',
|
||||
base = $('<div class="ui-tabs ui-widget ui-widget-content ui-corner-all elfinder-preference">'),
|
||||
ul = $('<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-top">'),
|
||||
tabs = $('<div class="elfinder-preference-tabs ui-tabs-panel ui-widget-content ui-corner-bottom"></div>'),
|
||||
sep = '<div class="elfinder-preference-separator"></div>',
|
||||
selfUrl = $('base').length? document.location.href.replace(/#.*$/, '') : '',
|
||||
selectTab = function(tab) {
|
||||
$('#'+fm.namespace+'-preference-tab-'+tab).trigger('mouseover').trigger('click');
|
||||
openTab = tab;
|
||||
},
|
||||
clTabActive = fm.res('class', 'tabsactive'),
|
||||
build = function() {
|
||||
var cats = self.options.categories || {
|
||||
'language' : ['language'],
|
||||
'theme' : ['theme'],
|
||||
'toolbar' : ['toolbarPref'],
|
||||
'workspace' : ['iconSize','columnPref', 'selectAction', 'makefileTypes', 'useStoredEditor', 'editorMaximized', 'useFullscreen', 'showHidden'],
|
||||
'dialog' : ['autoFocusDialog'],
|
||||
'selectionInfo' : ['infoItems', 'hashChecker'],
|
||||
'reset' : ['clearBrowserData'],
|
||||
'all' : true
|
||||
},
|
||||
forms = self.options.prefs || ['language', 'theme', 'toolbarPref', 'iconSize', 'columnPref', 'selectAction', 'makefileTypes', 'useStoredEditor', 'editorMaximized', 'useFullscreen', 'showHidden', 'infoItems', 'hashChecker', 'autoFocusDialog', 'clearBrowserData'];
|
||||
|
||||
if (!fm.cookieEnabled) {
|
||||
delete cats.language;
|
||||
}
|
||||
|
||||
forms = fm.arrayFlip(forms, true);
|
||||
|
||||
if (fm.options.getFileCallback) {
|
||||
delete forms.selectAction;
|
||||
}
|
||||
if (!fm.UA.Fullscreen) {
|
||||
delete forms.useFullscreen;
|
||||
}
|
||||
|
||||
forms.language && (forms.language = (function() {
|
||||
var langSel = $('<select></select>').on('change', function() {
|
||||
var lang = $(this).val();
|
||||
fm.storage('lang', lang);
|
||||
$('#'+fm.id).elfinder('reload');
|
||||
}),
|
||||
optTags = [],
|
||||
langs = self.options.langs || {
|
||||
ar: 'العربية',
|
||||
bg: 'Български',
|
||||
ca: 'Català',
|
||||
cs: 'Čeština',
|
||||
da: 'Dansk',
|
||||
de: 'Deutsch',
|
||||
el: 'Ελληνικά',
|
||||
en: 'English',
|
||||
es: 'Español',
|
||||
fa: 'فارسی',
|
||||
fo: 'Føroyskt',
|
||||
fr: 'Français',
|
||||
fr_CA: 'Français (Canada)',
|
||||
he: 'עברית',
|
||||
hr: 'Hrvatski',
|
||||
hu: 'Magyar',
|
||||
id: 'Bahasa Indonesia',
|
||||
it: 'Italiano',
|
||||
ja: '日本語',
|
||||
ko: '한국어',
|
||||
nl: 'Nederlands',
|
||||
no: 'Norsk',
|
||||
pl: 'Polski',
|
||||
pt_BR: 'Português',
|
||||
ro: 'Română',
|
||||
ru: 'Pусский',
|
||||
si: 'සිංහල',
|
||||
sk: 'Slovenčina',
|
||||
sl: 'Slovenščina',
|
||||
sr: 'Srpski',
|
||||
sv: 'Svenska',
|
||||
tr: 'Türkçe',
|
||||
ug_CN: 'ئۇيغۇرچە',
|
||||
uk: 'Український',
|
||||
vi: 'Tiếng Việt',
|
||||
zh_CN: '简体中文',
|
||||
zh_TW: '正體中文'
|
||||
};
|
||||
if (!fm.cookieEnabled) {
|
||||
return $();
|
||||
}
|
||||
$.each(langs, function(lang, name) {
|
||||
optTags.push('<option value="'+lang+'">'+name+'</option>');
|
||||
});
|
||||
return langSel.append(optTags.join('')).val(fm.lang);
|
||||
})());
|
||||
|
||||
forms.theme && (forms.theme = (function() {
|
||||
var cnt = fm.options.themes? Object.keys(fm.options.themes).length : 0;
|
||||
if (cnt === 0 || (cnt === 1 && fm.options.themes.default)) {
|
||||
return null;
|
||||
}
|
||||
var themeSel = $('<select></select>').on('change', function() {
|
||||
var theme = $(this).val();
|
||||
fm.changeTheme(theme).storage('theme', theme);
|
||||
}),
|
||||
optTags = [],
|
||||
tpl = {
|
||||
image: '<img class="elfinder-preference-theme elfinder-preference-theme-image" src="$2" />',
|
||||
link: '<a href="$1" target="_blank" title="$3">$2</a>',
|
||||
data: '<dt>$1</dt><dd><span class="elfinder-preference-theme elfinder-preference-theme-$0">$2</span></dd>'
|
||||
},
|
||||
items = ['image', 'description', 'author', 'email', 'license'],
|
||||
render = function(key, data) {
|
||||
},
|
||||
defBtn = $('<button class="ui-button ui-corner-all ui-widget elfinder-preference-theme-default"></button>').text(fm.i18n('default')).on('click', function(e) {
|
||||
themeSel.val('default').trigger('change');
|
||||
}),
|
||||
list = $('<div class="elfinder-reference-hide-taball"></div>').on('click', 'button', function() {
|
||||
var val = $(this).data('themeid');
|
||||
themeSel.val(val).trigger('change');
|
||||
});
|
||||
|
||||
if (!fm.options.themes.default) {
|
||||
themeSel.append('<option value="default">'+fm.i18n('default')+'</option>');
|
||||
}
|
||||
$.each(fm.options.themes, function(id, val) {
|
||||
var opt = $('<option class="elfinder-theme-option-'+id+'" value="'+id+'">'+fm.i18n(id)+'</option>'),
|
||||
dsc = $('<fieldset class="ui-widget ui-widget-content ui-corner-all elfinder-theme-list-'+id+'"><legend>'+fm.i18n(id)+'</legend><div><span class="elfinder-spinner"></span></div></fieldset>'),
|
||||
tm;
|
||||
themeSel.append(opt);
|
||||
list.append(dsc);
|
||||
tm = setTimeout(function() {
|
||||
dsc.find('span.elfinder-spinner').replaceWith(fm.i18n(['errRead', id]));
|
||||
}, 10000);
|
||||
fm.getTheme(id).always(function() {
|
||||
tm && clearTimeout(tm);
|
||||
}).done(function(data) {
|
||||
var link, val = $(), dl = $('<dl></dl>');
|
||||
link = data.link? tpl.link.replace(/\$1/g, data.link).replace(/\$3/g, fm.i18n('website')) : '$2';
|
||||
if (data.name) {
|
||||
opt.html(fm.i18n(data.name));
|
||||
}
|
||||
dsc.children('legend').html(link.replace(/\$2/g, fm.i18n(data.name) || id));
|
||||
$.each(items, function(i, key) {
|
||||
var t = tpl[key] || tpl.data,
|
||||
elm;
|
||||
if (data[key]) {
|
||||
elm = t.replace(/\$0/g, fm.escape(key)).replace(/\$1/g, fm.i18n(key)).replace(/\$2/g, fm.i18n(data[key]));
|
||||
if (key === 'image' && data.link) {
|
||||
elm = $(elm).on('click', function() {
|
||||
themeSel.val(id).trigger('change');
|
||||
}).attr('title', fm.i18n('select'));
|
||||
}
|
||||
dl.append(elm);
|
||||
}
|
||||
});
|
||||
val = val.add(dl);
|
||||
val = val.add($('<div class="elfinder-preference-theme-btn"></div>').append($('<button class="ui-button ui-corner-all ui-widget"></button>').data('themeid', id).html(fm.i18n('select'))));
|
||||
dsc.find('span.elfinder-spinner').replaceWith(val);
|
||||
}).fail(function() {
|
||||
dsc.find('span.elfinder-spinner').replaceWith(fm.i18n(['errRead', id]));
|
||||
});
|
||||
});
|
||||
return $('<div></div>').append(themeSel.val(fm.theme && fm.theme.id? fm.theme.id : 'default'), defBtn, list);
|
||||
})());
|
||||
|
||||
forms.toolbarPref && (forms.toolbarPref = (function() {
|
||||
var pnls = $.map(fm.options.uiOptions.toolbar, function(v) {
|
||||
return $.isArray(v)? v : null;
|
||||
}),
|
||||
tags = [],
|
||||
hides = fm.storage('toolbarhides') || {};
|
||||
$.each(pnls, function() {
|
||||
var cmd = this,
|
||||
name = fm.i18n('cmd'+cmd);
|
||||
if (name === 'cmd'+cmd) {
|
||||
name = fm.i18n(cmd);
|
||||
}
|
||||
tags.push('<span class="elfinder-preference-toolbar-item"><label><input type="checkbox" value="'+cmd+'" '+(hides[cmd]? '' : 'checked')+'/>'+name+'</label></span>');
|
||||
});
|
||||
return $(tags.join(' ')).on('change', 'input', function() {
|
||||
var v = $(this).val(),
|
||||
o = $(this).is(':checked');
|
||||
if (!o && !hides[v]) {
|
||||
hides[v] = true;
|
||||
} else if (o && hides[v]) {
|
||||
delete hides[v];
|
||||
}
|
||||
fm.storage('toolbarhides', hides);
|
||||
fm.trigger('toolbarpref');
|
||||
});
|
||||
})());
|
||||
|
||||
forms.iconSize && (forms.iconSize = (function() {
|
||||
var max = fm.options.uiOptions.cwd.iconsView.sizeMax || 3,
|
||||
size = fm.storage('iconsize') || fm.options.uiOptions.cwd.iconsView.size || 0,
|
||||
sld = $('<div class="touch-punch"></div>').slider({
|
||||
classes: {
|
||||
'ui-slider-handle': 'elfinder-tabstop',
|
||||
},
|
||||
value: size,
|
||||
max: max,
|
||||
slide: function(e, ui) {
|
||||
fm.getUI('cwd').trigger('iconpref', {size: ui.value});
|
||||
},
|
||||
change: function(e, ui) {
|
||||
fm.storage('iconsize', ui.value);
|
||||
}
|
||||
});
|
||||
fm.getUI('cwd').on('iconpref', function(e, data) {
|
||||
sld.slider('option', 'value', data.size);
|
||||
});
|
||||
return sld;
|
||||
})());
|
||||
|
||||
forms.columnPref && (forms.columnPref = (function() {
|
||||
var cols = fm.options.uiOptions.cwd.listView.columns,
|
||||
tags = [],
|
||||
hides = fm.storage('columnhides') || {};
|
||||
$.each(cols, function() {
|
||||
var key = this,
|
||||
name = fm.getColumnName(key);
|
||||
tags.push('<span class="elfinder-preference-column-item"><label><input type="checkbox" value="'+key+'" '+(hides[key]? '' : 'checked')+'/>'+name+'</label></span>');
|
||||
});
|
||||
return $(tags.join(' ')).on('change', 'input', function() {
|
||||
var v = $(this).val(),
|
||||
o = $(this).is(':checked');
|
||||
if (!o && !hides[v]) {
|
||||
hides[v] = true;
|
||||
} else if (o && hides[v]) {
|
||||
delete hides[v];
|
||||
}
|
||||
fm.storage('columnhides', hides);
|
||||
fm.trigger('columnpref', { repaint: true });
|
||||
});
|
||||
})());
|
||||
|
||||
forms.selectAction && (forms.selectAction = (function() {
|
||||
var actSel = $('<select></select>').on('change', function() {
|
||||
var act = $(this).val();
|
||||
fm.storage('selectAction', act === 'default'? null : act);
|
||||
}),
|
||||
optTags = [],
|
||||
acts = self.options.selectActions,
|
||||
defAct = fm.getCommand('open').options.selectAction || 'open';
|
||||
|
||||
if ($.inArray(defAct, acts) === -1) {
|
||||
acts.unshift(defAct);
|
||||
}
|
||||
$.each(acts, function(i, act) {
|
||||
var names = $.map(act.split('/'), function(cmd) {
|
||||
var name = fm.i18n('cmd'+cmd);
|
||||
if (name === 'cmd'+cmd) {
|
||||
name = fm.i18n(cmd);
|
||||
}
|
||||
return name;
|
||||
});
|
||||
optTags.push('<option value="'+act+'">'+names.join('/')+'</option>');
|
||||
});
|
||||
return actSel.append(optTags.join('')).val(fm.storage('selectAction') || defAct);
|
||||
})());
|
||||
|
||||
forms.makefileTypes && (forms.makefileTypes = (function() {
|
||||
var hides = fm.getCommand('edit').getMkfileHides(),
|
||||
getTag = function() {
|
||||
var tags = [];
|
||||
// re-assign hides
|
||||
hides = fm.getCommand('edit').getMkfileHides();
|
||||
$.each(fm.mimesCanMakeEmpty, function(mime, type) {
|
||||
var name = fm.getCommand('mkfile').getTypeName(mime, type);
|
||||
tags.push('<span class="elfinder-preference-column-item" title="'+fm.escape(name)+'"><label><input type="checkbox" value="'+mime+'" '+(hides[mime]? '' : 'checked')+'/>'+type+'</label></span>');
|
||||
});
|
||||
return tags.join(' ');
|
||||
},
|
||||
elm = $('<div></div>').on('change', 'input', function() {
|
||||
var v = $(this).val(),
|
||||
o = $(this).is(':checked');
|
||||
if (!o && !hides[v]) {
|
||||
hides[v] = true;
|
||||
} else if (o && hides[v]) {
|
||||
delete hides[v];
|
||||
}
|
||||
fm.storage('mkfileHides', hides);
|
||||
fm.trigger('canMakeEmptyFile');
|
||||
}).append(getTag()),
|
||||
add = $('<div></div>').append(
|
||||
$('<input type="text" placeholder="'+fm.i18n('typeOfTextfile')+'"/>').on('keydown', function(e) {
|
||||
(e.keyCode === $.ui.keyCode.ENTER) && $(this).next().trigger('click');
|
||||
}),
|
||||
$('<button class="ui-button"></button>').html(fm.i18n('add')).on('click', function() {
|
||||
var input = $(this).prev(),
|
||||
val = input.val(),
|
||||
uiToast = fm.getUI('toast'),
|
||||
err = function() {
|
||||
uiToast.appendTo(input.closest('.ui-dialog'));
|
||||
fm.toast({
|
||||
msg: fm.i18n('errUsupportType'),
|
||||
mode: 'warning',
|
||||
onHidden: function() {
|
||||
uiToast.children().length === 1 && uiToast.appendTo(fm.getUI());
|
||||
}
|
||||
});
|
||||
input.trigger('focus');
|
||||
return false;
|
||||
},
|
||||
tmpMimes;
|
||||
if (!val.match(/\//)) {
|
||||
val = fm.arrayFlip(fm.mimeTypes)[val];
|
||||
if (!val) {
|
||||
return err();
|
||||
}
|
||||
input.val(val);
|
||||
}
|
||||
if (!fm.mimeIsText(val) || !fm.mimeTypes[val]) {
|
||||
return err();
|
||||
}
|
||||
fm.trigger('canMakeEmptyFile', {mimes: [val], unshift: true});
|
||||
tmpMimes = {};
|
||||
tmpMimes[val] = fm.mimeTypes[val];
|
||||
fm.storage('mkfileTextMimes', Object.assign(tmpMimes, fm.storage('mkfileTextMimes') || {}));
|
||||
input.val('');
|
||||
uiToast.appendTo(input.closest('.ui-dialog'));
|
||||
fm.toast({
|
||||
msg: fm.i18n(['complete', val + ' (' + tmpMimes[val] + ')']),
|
||||
onHidden: function() {
|
||||
uiToast.children().length === 1 && uiToast.appendTo(fm.getUI());
|
||||
}
|
||||
});
|
||||
}),
|
||||
$('<button class="ui-button"></button>').html(fm.i18n('reset')).on('click', function() {
|
||||
fm.one('canMakeEmptyFile', {done: function() {
|
||||
elm.empty().append(getTag());
|
||||
}});
|
||||
fm.trigger('canMakeEmptyFile', {resetTexts: true});
|
||||
})
|
||||
),
|
||||
tm;
|
||||
fm.bind('canMakeEmptyFile', {done: function(e) {
|
||||
if (e.data && e.data.mimes && e.data.mimes.length) {
|
||||
elm.empty().append(getTag());
|
||||
}
|
||||
}});
|
||||
return $('<div></div>').append(elm, add);
|
||||
})());
|
||||
|
||||
forms.useStoredEditor && (forms.useStoredEditor = $('<input type="checkbox"/>').prop('checked', (function() {
|
||||
var s = fm.storage('useStoredEditor');
|
||||
return s? (s > 0) : fm.options.commandsOptions.edit.useStoredEditor;
|
||||
})()).on('change', function(e) {
|
||||
fm.storage('useStoredEditor', $(this).is(':checked')? 1 : -1);
|
||||
}));
|
||||
|
||||
forms.editorMaximized && (forms.editorMaximized = $('<input type="checkbox"/>').prop('checked', (function() {
|
||||
var s = fm.storage('editorMaximized');
|
||||
return s? (s > 0) : fm.options.commandsOptions.edit.editorMaximized;
|
||||
})()).on('change', function(e) {
|
||||
fm.storage('editorMaximized', $(this).is(':checked')? 1 : -1);
|
||||
}));
|
||||
|
||||
forms.useFullscreen && (forms.useFullscreen = $('<input type="checkbox"/>').prop('checked', (function() {
|
||||
var s = fm.storage('useFullscreen');
|
||||
return s? (s > 0) : fm.options.commandsOptions.fullscreen.mode === 'screen';
|
||||
})()).on('change', function(e) {
|
||||
fm.storage('useFullscreen', $(this).is(':checked')? 1 : -1);
|
||||
}));
|
||||
|
||||
if (forms.showHidden) {
|
||||
(function() {
|
||||
var setTitle = function() {
|
||||
var s = fm.storage('hide'),
|
||||
t = [],
|
||||
v;
|
||||
if (s && s.items) {
|
||||
$.each(s.items, function(h, n) {
|
||||
t.push(fm.escape(n));
|
||||
});
|
||||
}
|
||||
elms.prop('disabled', !t.length)[t.length? 'removeClass' : 'addClass']('ui-state-disabled');
|
||||
v = t.length? t.join('\n') : '';
|
||||
forms.showHidden.attr('title',v);
|
||||
useTooltip && forms.showHidden.tooltip('option', 'content', v.replace(/\n/g, '<br>')).tooltip('close');
|
||||
},
|
||||
chk = $('<input type="checkbox"/>').prop('checked', (function() {
|
||||
var s = fm.storage('hide');
|
||||
return s && s.show;
|
||||
})()).on('change', function(e) {
|
||||
var o = {};
|
||||
o[$(this).is(':checked')? 'show' : 'hide'] = true;
|
||||
fm.exec('hide', void(0), o);
|
||||
}),
|
||||
btn = $('<button class="ui-button ui-corner-all ui-widget"></button>').append(fm.i18n('reset')).on('click', function() {
|
||||
fm.exec('hide', void(0), {reset: true});
|
||||
$(this).parent().find('input:first').prop('checked', false);
|
||||
setTitle();
|
||||
}),
|
||||
elms = $().add(chk).add(btn),
|
||||
useTooltip;
|
||||
|
||||
forms.showHidden = $('<div></div>').append(chk, btn);
|
||||
fm.bind('hide', function(e) {
|
||||
var d = e.data;
|
||||
if (!d.opts || (!d.opts.show && !d.opts.hide)) {
|
||||
setTitle();
|
||||
}
|
||||
});
|
||||
if (fm.UA.Mobile && $.fn.tooltip) {
|
||||
useTooltip = true;
|
||||
forms.showHidden.tooltip({
|
||||
classes: {
|
||||
'ui-tooltip': 'elfinder-ui-tooltip ui-widget-shadow'
|
||||
},
|
||||
tooltipClass: 'elfinder-ui-tooltip ui-widget-shadow',
|
||||
track: true
|
||||
}).css('user-select', 'none');
|
||||
btn.css('user-select', 'none');
|
||||
}
|
||||
setTitle();
|
||||
})();
|
||||
}
|
||||
|
||||
forms.infoItems && (forms.infoItems = (function() {
|
||||
var items = fm.getCommand('info').items,
|
||||
tags = [],
|
||||
hides = fm.storage('infohides') || fm.arrayFlip(fm.options.commandsOptions.info.hideItems, true);
|
||||
$.each(items, function() {
|
||||
var key = this,
|
||||
name = fm.i18n(key);
|
||||
tags.push('<span class="elfinder-preference-info-item"><label><input type="checkbox" value="'+key+'" '+(hides[key]? '' : 'checked')+'/>'+name+'</label></span>');
|
||||
});
|
||||
return $(tags.join(' ')).on('change', 'input', function() {
|
||||
var v = $(this).val(),
|
||||
o = $(this).is(':checked');
|
||||
if (!o && !hides[v]) {
|
||||
hides[v] = true;
|
||||
} else if (o && hides[v]) {
|
||||
delete hides[v];
|
||||
}
|
||||
fm.storage('infohides', hides);
|
||||
fm.trigger('infopref', { repaint: true });
|
||||
});
|
||||
})());
|
||||
|
||||
forms.hashChecker && fm.hashCheckers.length && (forms.hashChecker = (function() {
|
||||
var tags = [],
|
||||
enabled = fm.arrayFlip(fm.storage('hashchekcer') || fm.options.commandsOptions.info.showHashAlgorisms, true);
|
||||
$.each(fm.hashCheckers, function() {
|
||||
var cmd = this,
|
||||
name = fm.i18n(cmd);
|
||||
tags.push('<span class="elfinder-preference-hashchecker-item"><label><input type="checkbox" value="'+cmd+'" '+(enabled[cmd]? 'checked' : '')+'/>'+name+'</label></span>');
|
||||
});
|
||||
return $(tags.join(' ')).on('change', 'input', function() {
|
||||
var v = $(this).val(),
|
||||
o = $(this).is(':checked');
|
||||
if (o) {
|
||||
enabled[v] = true;
|
||||
} else if (enabled[v]) {
|
||||
delete enabled[v];
|
||||
}
|
||||
fm.storage('hashchekcer', $.grep(fm.hashCheckers, function(v) {
|
||||
return enabled[v];
|
||||
}));
|
||||
});
|
||||
})());
|
||||
|
||||
forms.autoFocusDialog && (forms.autoFocusDialog = $('<input type="checkbox"/>').prop('checked', (function() {
|
||||
var s = fm.storage('autoFocusDialog');
|
||||
return s? (s > 0) : fm.options.uiOptions.dialog.focusOnMouseOver;
|
||||
})()).on('change', function(e) {
|
||||
fm.storage('autoFocusDialog', $(this).is(':checked')? 1 : -1);
|
||||
}));
|
||||
|
||||
forms.clearBrowserData && (forms.clearBrowserData = $('<button></button>').text(fm.i18n('reset')).button().on('click', function(e) {
|
||||
e.preventDefault();
|
||||
fm.storage();
|
||||
$('#'+fm.id).elfinder('reload');
|
||||
}));
|
||||
|
||||
$.each(cats, function(id, prefs) {
|
||||
var dls, found;
|
||||
if (prefs === true) {
|
||||
found = 1;
|
||||
} else if (prefs) {
|
||||
dls = $();
|
||||
$.each(prefs, function(i, n) {
|
||||
var f, title, chks = '', cbox;
|
||||
if (f = forms[n]) {
|
||||
found = 2;
|
||||
title = fm.i18n(n);
|
||||
cbox = $(f).filter('input[type="checkbox"]');
|
||||
if (!cbox.length) {
|
||||
cbox = $(f).find('input[type="checkbox"]');
|
||||
}
|
||||
if (cbox.length === 1) {
|
||||
if (!cbox.attr('id')) {
|
||||
cbox.attr('id', 'elfinder-preference-'+n+'-checkbox');
|
||||
}
|
||||
title = '<label for="'+cbox.attr('id')+'">'+title+'</label>';
|
||||
} else if (cbox.length > 1) {
|
||||
chks = ' elfinder-preference-checkboxes';
|
||||
}
|
||||
dls = dls.add($('<dt class="elfinder-preference-'+n+chks+'">'+title+'</dt>')).add($('<dd class="elfinder-preference-'+n+chks+'"></dd>').append(f));
|
||||
}
|
||||
});
|
||||
}
|
||||
if (found) {
|
||||
ul.append(tab[r](/\{id\}/g, id)[r](/\{title\}/, fm.i18n(id))[r](/\{class\}/, openTab === id? 'elfinder-focus' : ''));
|
||||
if (found === 2) {
|
||||
tabs.append(
|
||||
$('<div id="'+fm.namespace+'-preference-'+id+'" class="elfinder-preference-content"></div>')
|
||||
.hide()
|
||||
.append($('<dl></dl>').append(dls))
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ul.on('click', 'a', function(e) {
|
||||
var t = $(e.target),
|
||||
h = t.attr('href');
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
ul.children().removeClass(clTabActive);
|
||||
t.removeClass('ui-state-hover').parent().addClass(clTabActive);
|
||||
|
||||
if (h.match(/all$/)) {
|
||||
tabs.addClass('elfinder-preference-taball').children().show();
|
||||
} else {
|
||||
tabs.removeClass('elfinder-preference-taball').children().hide();
|
||||
$(h).show();
|
||||
}
|
||||
}).on('focus blur', 'a', function(e) {
|
||||
$(this).parent().toggleClass('ui-state-focus', e.type === 'focusin');
|
||||
}).on('mouseenter mouseleave', 'li', function(e) {
|
||||
$(this).toggleClass('ui-state-hover', e.type === 'mouseenter');
|
||||
});
|
||||
|
||||
tabs.find('a,input,select,button').addClass('elfinder-tabstop');
|
||||
base.append(ul, tabs);
|
||||
|
||||
dialog = self.fmDialog(base, {
|
||||
title : self.title,
|
||||
width : self.options.width || 600,
|
||||
height: self.options.height || 400,
|
||||
maxWidth: 'window',
|
||||
maxHeight: 'window',
|
||||
autoOpen : false,
|
||||
destroyOnClose : false,
|
||||
allowMinimize : false,
|
||||
open : function() {
|
||||
openTab && selectTab(openTab);
|
||||
openTab = null;
|
||||
},
|
||||
resize : function() {
|
||||
tabs.height(dialog.height() - ul.outerHeight(true) - (tabs.outerHeight(true) - tabs.height()) - 5);
|
||||
}
|
||||
})
|
||||
.on('click', function(e) {
|
||||
e.stopPropagation();
|
||||
})
|
||||
.css({
|
||||
overflow: 'hidden'
|
||||
});
|
||||
|
||||
dialog.closest('.ui-dialog')
|
||||
.css({
|
||||
overflow: 'hidden'
|
||||
})
|
||||
.addClass('elfinder-bg-translucent');
|
||||
|
||||
openTab = 'all';
|
||||
},
|
||||
dialog, openTab;
|
||||
|
||||
this.shortcuts = [{
|
||||
pattern : 'ctrl+comma',
|
||||
description : this.title
|
||||
}];
|
||||
|
||||
this.alwaysEnabled = true;
|
||||
|
||||
this.getstate = function() {
|
||||
return 0;
|
||||
};
|
||||
|
||||
this.exec = function(sel, cOpts) {
|
||||
!dialog && build();
|
||||
if (cOpts) {
|
||||
if (cOpts.tab) {
|
||||
selectTab(cOpts.tab);
|
||||
} else if (cOpts._currentType === 'cwd') {
|
||||
selectTab('workspace');
|
||||
}
|
||||
}
|
||||
dialog.elfinderdialog('open');
|
||||
return $.Deferred().resolve();
|
||||
};
|
||||
|
||||
};
|
||||
+885
@@ -0,0 +1,885 @@
|
||||
/**
|
||||
* @class elFinder command "quicklook"
|
||||
* Fast preview for some files types
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
(elFinder.prototype.commands.quicklook = function() {
|
||||
"use strict";
|
||||
var self = this,
|
||||
fm = self.fm,
|
||||
/**
|
||||
* window closed state
|
||||
*
|
||||
* @type Number
|
||||
**/
|
||||
closed = 0,
|
||||
/**
|
||||
* window animated state
|
||||
*
|
||||
* @type Number
|
||||
**/
|
||||
animated = 1,
|
||||
/**
|
||||
* window opened state
|
||||
*
|
||||
* @type Number
|
||||
**/
|
||||
opened = 2,
|
||||
/**
|
||||
* window docked state
|
||||
*
|
||||
* @type Number
|
||||
**/
|
||||
docked = 3,
|
||||
/**
|
||||
* window docked and hidden state
|
||||
*
|
||||
* @type Number
|
||||
**/
|
||||
dockedhidden = 4,
|
||||
/**
|
||||
* window state
|
||||
*
|
||||
* @type Number
|
||||
**/
|
||||
state = closed,
|
||||
/**
|
||||
* Event name of update
|
||||
* for fix conflicts with Prototype.JS
|
||||
*
|
||||
* `@see https://github.com/Studio-42/elFinder/pull/2346
|
||||
* @type String
|
||||
**/
|
||||
evUpdate = Element.update? 'quicklookupdate' : 'update',
|
||||
/**
|
||||
* navbar icon class
|
||||
*
|
||||
* @type String
|
||||
**/
|
||||
navicon = 'elfinder-quicklook-navbar-icon',
|
||||
/**
|
||||
* navbar "fullscreen" icon class
|
||||
*
|
||||
* @type String
|
||||
**/
|
||||
fullscreen = 'elfinder-quicklook-fullscreen',
|
||||
/**
|
||||
* info wrapper class
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
infocls = 'elfinder-quicklook-info-wrapper',
|
||||
/**
|
||||
* Triger keydown/keypress event with left/right arrow key code
|
||||
*
|
||||
* @param Number left/right arrow key code
|
||||
* @return void
|
||||
**/
|
||||
navtrigger = function(code) {
|
||||
$(document).trigger($.Event('keydown', { keyCode: code, ctrlKey : false, shiftKey : false, altKey : false, metaKey : false }));
|
||||
},
|
||||
/**
|
||||
* Return css for closed window
|
||||
*
|
||||
* @param jQuery file node in cwd
|
||||
* @return void
|
||||
**/
|
||||
closedCss = function(node) {
|
||||
var elf = fm.getUI().offset(),
|
||||
base = (function() {
|
||||
var target = node.find('.elfinder-cwd-file-wrapper');
|
||||
return target.length? target : node;
|
||||
})(),
|
||||
baseOffset = base.offset() || { top: 0, left: 0 };
|
||||
return {
|
||||
opacity : 0,
|
||||
width : base.width(),
|
||||
height : base.height() - 30,
|
||||
top : baseOffset.top - elf.top,
|
||||
left : baseOffset.left - elf.left
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Return css for opened window
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
openedCss = function() {
|
||||
var contain = self.options.contain || fm.options.dialogContained,
|
||||
win = contain? fm.getUI() : $(window),
|
||||
elf = fm.getUI().offset(),
|
||||
w = Math.min(width, win.width()-10),
|
||||
h = Math.min(height, win.height()-80);
|
||||
return {
|
||||
opacity : 1,
|
||||
width : w,
|
||||
height : h,
|
||||
top : parseInt((win.height() - h - 60) / 2 + (contain? 0 : win.scrollTop() - elf.top)),
|
||||
left : parseInt((win.width() - w) / 2 + (contain? 0 : win.scrollLeft() - elf.left))
|
||||
};
|
||||
},
|
||||
|
||||
mediaNode = {},
|
||||
support = function(codec, name) {
|
||||
var node = name || codec.substr(0, codec.indexOf('/')),
|
||||
media = mediaNode[node]? mediaNode[node] : (mediaNode[node] = document.createElement(node)),
|
||||
value = false;
|
||||
|
||||
try {
|
||||
value = media.canPlayType && media.canPlayType(codec);
|
||||
} catch(e) {}
|
||||
|
||||
return (value && value !== '' && value != 'no')? true : false;
|
||||
},
|
||||
|
||||
platformWin = (window.navigator.platform.indexOf('Win') != -1),
|
||||
|
||||
/**
|
||||
* Opened window width (from config)
|
||||
*
|
||||
* @type Number
|
||||
**/
|
||||
width,
|
||||
/**
|
||||
* Opened window height (from config)
|
||||
*
|
||||
* @type Number
|
||||
**/
|
||||
height,
|
||||
/**
|
||||
* Previous style before docked
|
||||
*
|
||||
* @type String
|
||||
**/
|
||||
prevStyle,
|
||||
/**
|
||||
* elFinder node
|
||||
*
|
||||
* @type jQuery
|
||||
**/
|
||||
parent,
|
||||
/**
|
||||
* elFinder current directory node
|
||||
*
|
||||
* @type jQuery
|
||||
**/
|
||||
cwd,
|
||||
/**
|
||||
* Current directory hash
|
||||
*
|
||||
* @type String
|
||||
**/
|
||||
cwdHash,
|
||||
dockEnabled = false,
|
||||
navdrag = false,
|
||||
navmove = false,
|
||||
navtm = null,
|
||||
leftKey = $.ui.keyCode.LEFT,
|
||||
rightKey = $.ui.keyCode.RIGHT,
|
||||
coverEv = 'mousemove touchstart ' + ('onwheel' in document? 'wheel' : 'onmousewheel' in document? 'mousewheel' : 'DOMMouseScroll'),
|
||||
title = $('<span class="elfinder-dialog-title elfinder-quicklook-title"></span>'),
|
||||
icon = $('<div></div>'),
|
||||
info = $('<div class="elfinder-quicklook-info"></div>'),//.hide(),
|
||||
cover = $('<div class="ui-front elfinder-quicklook-cover"></div>'),
|
||||
fsicon = $('<div class="'+navicon+' '+navicon+'-fullscreen"></div>')
|
||||
.on('click touchstart', function(e) {
|
||||
if (navmove) {
|
||||
return;
|
||||
}
|
||||
|
||||
var win = self.window,
|
||||
full = win.hasClass(fullscreen),
|
||||
$window = $(window),
|
||||
resize = function() { self.preview.trigger('changesize'); };
|
||||
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
if (full) {
|
||||
navStyle = '';
|
||||
navShow();
|
||||
win.toggleClass(fullscreen)
|
||||
.css(win.data('position'));
|
||||
$window.trigger(self.resize).off(self.resize, resize);
|
||||
navbar.off('mouseenter mouseleave');
|
||||
cover.off(coverEv);
|
||||
} else {
|
||||
win.toggleClass(fullscreen)
|
||||
.data('position', {
|
||||
left : win.css('left'),
|
||||
top : win.css('top'),
|
||||
width : win.width(),
|
||||
height : win.height(),
|
||||
display: 'block'
|
||||
})
|
||||
.removeAttr('style');
|
||||
|
||||
$(window).on(self.resize, resize)
|
||||
.trigger(self.resize);
|
||||
|
||||
cover.on(coverEv, function(e) {
|
||||
if (! navdrag) {
|
||||
if (e.type === 'mousemove' || e.type === 'touchstart') {
|
||||
navShow();
|
||||
navtm = setTimeout(function() {
|
||||
if (fm.UA.Mobile || navbar.parent().find('.elfinder-quicklook-navbar:hover').length < 1) {
|
||||
navbar.fadeOut('slow', function() {
|
||||
cover.show();
|
||||
});
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
if (cover.is(':visible')) {
|
||||
coverHide();
|
||||
cover.data('tm', setTimeout(function() {
|
||||
cover.show();
|
||||
}, 3000));
|
||||
}
|
||||
}
|
||||
}).show().trigger('mousemove');
|
||||
|
||||
navbar.on('mouseenter mouseleave', function(e) {
|
||||
if (! navdrag) {
|
||||
if (e.type === 'mouseenter') {
|
||||
navShow();
|
||||
} else {
|
||||
cover.trigger('mousemove');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (fm.zIndex) {
|
||||
win.css('z-index', fm.zIndex + 1);
|
||||
}
|
||||
if (fm.UA.Mobile) {
|
||||
navbar.attr('style', navStyle);
|
||||
} else {
|
||||
navbar.attr('style', navStyle).draggable(full ? 'destroy' : {
|
||||
start: function() {
|
||||
navdrag = true;
|
||||
navmove = true;
|
||||
cover.show();
|
||||
navShow();
|
||||
},
|
||||
stop: function() {
|
||||
navdrag = false;
|
||||
navStyle = self.navbar.attr('style');
|
||||
requestAnimationFrame(function() {
|
||||
navmove = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
$(this).toggleClass(navicon+'-fullscreen-off');
|
||||
var collection = win;
|
||||
if (parent.is('.ui-resizable')) {
|
||||
collection = collection.add(parent);
|
||||
}
|
||||
collection.resizable(full ? 'enable' : 'disable').removeClass('ui-state-disabled');
|
||||
|
||||
win.trigger('viewchange');
|
||||
}
|
||||
),
|
||||
|
||||
updateOnSel = function() {
|
||||
self.update(void(0), (function() {
|
||||
var fm = self.fm,
|
||||
files = fm.selectedFiles(),
|
||||
cnt = files.length,
|
||||
inDock = self.docked(),
|
||||
getInfo = function() {
|
||||
var ts = 0;
|
||||
$.each(files, function(i, f) {
|
||||
var t = parseInt(f.ts);
|
||||
if (ts >= 0) {
|
||||
if (t > ts) {
|
||||
ts = t;
|
||||
}
|
||||
} else {
|
||||
ts = 'unknown';
|
||||
}
|
||||
});
|
||||
return {
|
||||
hash : files[0].hash + '/' + (+new Date()),
|
||||
name : fm.i18n('items') + ': ' + cnt,
|
||||
mime : 'group',
|
||||
size : spinner,
|
||||
ts : ts,
|
||||
files : $.map(files, function(f) { return f.hash; }),
|
||||
getSize : true
|
||||
};
|
||||
};
|
||||
if (! cnt) {
|
||||
cnt = 1;
|
||||
files = [fm.cwd()];
|
||||
}
|
||||
return (cnt === 1)? files[0] : getInfo();
|
||||
})());
|
||||
},
|
||||
|
||||
navShow = function() {
|
||||
if (self.window.hasClass(fullscreen)) {
|
||||
navtm && clearTimeout(navtm);
|
||||
navtm = null;
|
||||
// if use `show()` it make infinite loop with old jQuery (jQuery/jQuery UI: 1.8.0/1.9.0)
|
||||
// see #1478 https://github.com/Studio-42/elFinder/issues/1478
|
||||
navbar.stop(true, true).css('display', 'block');
|
||||
coverHide();
|
||||
}
|
||||
},
|
||||
|
||||
coverHide = function() {
|
||||
cover.data('tm') && clearTimeout(cover.data('tm'));
|
||||
cover.removeData('tm');
|
||||
cover.hide();
|
||||
},
|
||||
|
||||
prev = $('<div class="'+navicon+' '+navicon+'-prev"></div>').on('click touchstart', function(e) { ! navmove && navtrigger(leftKey); return false; }),
|
||||
next = $('<div class="'+navicon+' '+navicon+'-next"></div>').on('click touchstart', function(e) { ! navmove && navtrigger(rightKey); return false; }),
|
||||
navbar = $('<div class="elfinder-quicklook-navbar"></div>')
|
||||
.append(prev)
|
||||
.append(fsicon)
|
||||
.append(next)
|
||||
.append('<div class="elfinder-quicklook-navbar-separator"></div>')
|
||||
.append($('<div class="'+navicon+' '+navicon+'-close"></div>').on('click touchstart', function(e) { ! navmove && self.window.trigger('close'); return false; }))
|
||||
,
|
||||
titleClose = $('<span class="ui-front ui-icon elfinder-icon-close ui-icon-closethick"></span>').on('mousedown', function(e) {
|
||||
e.stopPropagation();
|
||||
self.window.trigger('close');
|
||||
}),
|
||||
titleDock = $('<span class="ui-front ui-icon elfinder-icon-minimize ui-icon-minusthick"></span>').on('mousedown', function(e) {
|
||||
e.stopPropagation();
|
||||
if (! self.docked()) {
|
||||
self.window.trigger('navdockin');
|
||||
} else {
|
||||
self.window.trigger('navdockout');
|
||||
}
|
||||
}),
|
||||
spinner = '<span class="elfinder-spinner-text">' + fm.i18n('calc') + '</span>' + '<span class="elfinder-spinner"></span>',
|
||||
navStyle = '',
|
||||
init = true,
|
||||
dockHeight, getSize, tm4cwd, dockedNode, selectTm;
|
||||
|
||||
/**
|
||||
* Any flags for each plugin
|
||||
*/
|
||||
this.flags = {};
|
||||
|
||||
this.cover = cover;
|
||||
this.evUpdate = evUpdate;
|
||||
(this.navbar = navbar)._show = navShow;
|
||||
this.resize = 'resize.'+fm.namespace;
|
||||
this.info = $('<div></div>').addClass(infocls)
|
||||
.append(icon)
|
||||
.append(info);
|
||||
this.autoPlay = function() {
|
||||
if (self.opened()) {
|
||||
return !! self.options[self.docked()? 'dockAutoplay' : 'autoplay'];
|
||||
}
|
||||
return false;
|
||||
};
|
||||
this.preview = $('<div class="elfinder-quicklook-preview ui-helper-clearfix"></div>')
|
||||
// clean info/icon
|
||||
.on('change', function() {
|
||||
navShow();
|
||||
navbar.attr('style', navStyle);
|
||||
self.docked() && navbar.hide();
|
||||
self.preview.attr('style', '').removeClass('elfinder-overflow-auto');
|
||||
self.info.attr('style', '').hide();
|
||||
self.cover.removeClass('elfinder-quicklook-coverbg');
|
||||
icon.removeAttr('class').attr('style', '');
|
||||
info.html('');
|
||||
})
|
||||
// update info/icon
|
||||
.on(evUpdate, function(e) {
|
||||
var preview = self.preview,
|
||||
file = e.file,
|
||||
tpl = '<div class="elfinder-quicklook-info-data">{value}</div>',
|
||||
update = function() {
|
||||
var win = self.window.css('overflow', 'hidden');
|
||||
name = fm.escape(file.i18 || file.name);
|
||||
!file.read && e.stopImmediatePropagation();
|
||||
self.window.data('hash', file.hash);
|
||||
self.preview.off('changesize').trigger('change').children().remove();
|
||||
title.html(name);
|
||||
|
||||
prev.css('visibility', '');
|
||||
next.css('visibility', '');
|
||||
if (file.hash === fm.cwdId2Hash(cwd.find('[id]:not(.elfinder-cwd-parent):first').attr('id'))) {
|
||||
prev.css('visibility', 'hidden');
|
||||
}
|
||||
if (file.hash === fm.cwdId2Hash(cwd.find('[id]:last').attr('id'))) {
|
||||
next.css('visibility', 'hidden');
|
||||
}
|
||||
|
||||
if (file.mime === 'directory') {
|
||||
getSizeHashes = [ file.hash ];
|
||||
} else if (file.mime === 'group' && file.getSize) {
|
||||
getSizeHashes = file.files;
|
||||
}
|
||||
|
||||
info.html(
|
||||
tpl.replace(/\{value\}/, name)
|
||||
+ tpl.replace(/\{value\}/, fm.mime2kind(file))
|
||||
+ tpl.replace(/\{value\}/, getSizeHashes.length ? spinner : fm.formatSize(file.size))
|
||||
+ tpl.replace(/\{value\}/, fm.i18n('modify')+': '+ fm.formatDate(file))
|
||||
);
|
||||
|
||||
if (getSizeHashes.length) {
|
||||
getSize = fm.getSize(getSizeHashes).done(function(data) {
|
||||
info.find('span.elfinder-spinner').parent().html(data.formated);
|
||||
}).fail(function() {
|
||||
info.find('span.elfinder-spinner').parent().html(fm.i18n('unknown'));
|
||||
}).always(function() {
|
||||
getSize = null;
|
||||
});
|
||||
getSize._hash = file.hash;
|
||||
}
|
||||
|
||||
icon.addClass('elfinder-cwd-icon ui-corner-all '+fm.mime2class(file.mime));
|
||||
|
||||
if (file.icon) {
|
||||
icon.css(fm.getIconStyle(file, true));
|
||||
}
|
||||
|
||||
self.info.attr('class', infocls);
|
||||
if (file.csscls) {
|
||||
self.info.addClass(file.csscls);
|
||||
}
|
||||
|
||||
if (file.read && (tmb = fm.tmb(file))) {
|
||||
$('<img/>')
|
||||
.hide()
|
||||
.appendTo(self.preview)
|
||||
.on('load', function() {
|
||||
icon.addClass(tmb.className).css('background-image', "url('"+tmb.url+"')");
|
||||
$(this).remove();
|
||||
})
|
||||
.attr('src', tmb.url);
|
||||
}
|
||||
self.info.delay(100).fadeIn(10);
|
||||
if (self.window.hasClass(fullscreen)) {
|
||||
cover.trigger('mousemove');
|
||||
}
|
||||
win.css('overflow', '');
|
||||
},
|
||||
tmb, name, getSizeHashes = [];
|
||||
|
||||
if (file && ! Object.keys(file).length) {
|
||||
file = fm.cwd();
|
||||
}
|
||||
if (file && getSize && getSize.state() === 'pending' && getSize._hash !== file.hash) {
|
||||
getSize.reject();
|
||||
}
|
||||
if (file && (e.forceUpdate || self.window.data('hash') !== file.hash)) {
|
||||
update();
|
||||
} else {
|
||||
e.stopImmediatePropagation();
|
||||
}
|
||||
});
|
||||
|
||||
this.window = $('<div class="ui-front ui-helper-reset ui-widget elfinder-quicklook touch-punch" style="position:absolute"></div>')
|
||||
.hide()
|
||||
.addClass(fm.UA.Touch? 'elfinder-touch' : '')
|
||||
.on('click', function(e) {
|
||||
var win = this;
|
||||
e.stopPropagation();
|
||||
if (state === opened) {
|
||||
requestAnimationFrame(function() {
|
||||
state === opened && fm.toFront(win);
|
||||
});
|
||||
}
|
||||
})
|
||||
.append(
|
||||
$('<div class="ui-dialog-titlebar ui-widget-header ui-corner-top ui-helper-clearfix elfinder-quicklook-titlebar"></div>')
|
||||
.append(
|
||||
$('<span class="ui-widget-header ui-dialog-titlebar-close ui-corner-all elfinder-titlebar-button elfinder-quicklook-titlebar-icon'+(platformWin? ' elfinder-titlebar-button-right' : '')+'"></span>').append(
|
||||
titleClose, titleDock
|
||||
),
|
||||
title
|
||||
),
|
||||
this.preview,
|
||||
self.info.hide(),
|
||||
cover.hide(),
|
||||
navbar
|
||||
)
|
||||
.draggable({handle : 'div.elfinder-quicklook-titlebar'})
|
||||
.on('open', function(e, clcss) {
|
||||
var win = self.window,
|
||||
file = self.value,
|
||||
node = fm.getUI('cwd'),
|
||||
open = function(status) {
|
||||
state = status;
|
||||
self.update(1, self.value);
|
||||
self.change();
|
||||
win.trigger('resize.' + fm.namespace);
|
||||
};
|
||||
|
||||
if (!init && state === closed) {
|
||||
if (file && file.hash !== cwdHash) {
|
||||
node = fm.cwdHash2Elm(file.hash.split('/', 2)[0]);
|
||||
}
|
||||
navStyle = '';
|
||||
navbar.attr('style', '');
|
||||
state = animated;
|
||||
node.trigger('scrolltoview');
|
||||
coverHide();
|
||||
win.css(clcss || closedCss(node))
|
||||
.show()
|
||||
.animate(openedCss(), 550, function() {
|
||||
open(opened);
|
||||
navShow();
|
||||
});
|
||||
fm.toFront(win);
|
||||
} else if (state === dockedhidden) {
|
||||
fm.getUI('navdock').data('addNode')(dockedNode);
|
||||
open(docked);
|
||||
self.preview.trigger('changesize');
|
||||
fm.storage('previewDocked', '1');
|
||||
if (fm.getUI('navdock').width() === 0) {
|
||||
win.trigger('navdockout');
|
||||
}
|
||||
}
|
||||
})
|
||||
.on('close', function(e, dfd) {
|
||||
var win = self.window,
|
||||
preview = self.preview.trigger('change'),
|
||||
file = self.value,
|
||||
hash = (win.data('hash') || '').split('/', 2)[0],
|
||||
close = function(status, winhide) {
|
||||
state = status;
|
||||
winhide && fm.toHide(win);
|
||||
preview.children().remove();
|
||||
self.update(0, self.value);
|
||||
win.data('hash', '');
|
||||
dfd && dfd.resolve();
|
||||
},
|
||||
node;
|
||||
|
||||
if (self.opened()) {
|
||||
getSize && getSize.state() === 'pending' && getSize.reject();
|
||||
if (! self.docked()) {
|
||||
state = animated;
|
||||
win.hasClass(fullscreen) && fsicon.click();
|
||||
(hash && (node = cwd.find('#'+hash)).length)
|
||||
? win.animate(closedCss(node), 500, function() {
|
||||
preview.off('changesize');
|
||||
close(closed, true);
|
||||
})
|
||||
: close(closed, true);
|
||||
} else {
|
||||
dockedNode = fm.getUI('navdock').data('removeNode')(self.window.attr('id'), 'detach');
|
||||
close(dockedhidden);
|
||||
fm.storage('previewDocked', '2');
|
||||
}
|
||||
}
|
||||
})
|
||||
.on('navdockin', function(e, data) {
|
||||
var w = self.window,
|
||||
box = fm.getUI('navdock'),
|
||||
height = dockHeight || box.width(),
|
||||
opts = data || {};
|
||||
|
||||
if (init) {
|
||||
opts.init = true;
|
||||
}
|
||||
state = docked;
|
||||
prevStyle = w.attr('style');
|
||||
w.toggleClass('ui-front').removeClass('ui-widget').draggable('disable').resizable('disable').removeAttr('style').css({
|
||||
width: '100%',
|
||||
height: height,
|
||||
boxSizing: 'border-box',
|
||||
paddingBottom: 0,
|
||||
zIndex: 'unset'
|
||||
});
|
||||
navbar.hide();
|
||||
titleDock.toggleClass('ui-icon-plusthick ui-icon-minusthick elfinder-icon-full elfinder-icon-minimize');
|
||||
|
||||
fm.toHide(w, true);
|
||||
box.data('addNode')(w, opts);
|
||||
|
||||
self.preview.trigger('changesize');
|
||||
|
||||
fm.storage('previewDocked', '1');
|
||||
})
|
||||
.on('navdockout', function(e) {
|
||||
var w = self.window,
|
||||
box = fm.getUI('navdock'),
|
||||
dfd = $.Deferred(),
|
||||
clcss = closedCss(self.preview);
|
||||
|
||||
dockHeight = w.outerHeight();
|
||||
box.data('removeNode')(w.attr('id'), fm.getUI());
|
||||
w.toggleClass('ui-front').addClass('ui-widget').draggable('enable').resizable('enable').attr('style', prevStyle);
|
||||
titleDock.toggleClass('ui-icon-plusthick ui-icon-minusthick elfinder-icon-full elfinder-icon-minimize');
|
||||
|
||||
state = closed;
|
||||
w.trigger('open', clcss);
|
||||
|
||||
fm.storage('previewDocked', '0');
|
||||
})
|
||||
.on('resize.' + fm.namespace, function() {
|
||||
self.preview.trigger('changesize');
|
||||
});
|
||||
|
||||
/**
|
||||
* This command cannot be disable by backend
|
||||
*
|
||||
* @type Boolean
|
||||
**/
|
||||
this.alwaysEnabled = true;
|
||||
|
||||
/**
|
||||
* Selected file
|
||||
*
|
||||
* @type Object
|
||||
**/
|
||||
this.value = null;
|
||||
|
||||
this.handlers = {
|
||||
// save selected file
|
||||
select : function(e, d) {
|
||||
selectTm && cancelAnimationFrame(selectTm);
|
||||
if (! e.data || ! e.data.selected || ! e.data.selected.length) {
|
||||
selectTm = requestAnimationFrame(function() {
|
||||
self.opened() && updateOnSel();
|
||||
});
|
||||
} else {
|
||||
self.opened() && updateOnSel();
|
||||
}
|
||||
},
|
||||
error : function() { self.window.is(':visible') && self.window.trigger('close'); },
|
||||
'searchshow searchhide' : function() { this.opened() && this.window.trigger('close'); },
|
||||
navbarshow : function() {
|
||||
requestAnimationFrame(function() {
|
||||
self.docked() && self.preview.trigger('changesize');
|
||||
});
|
||||
},
|
||||
destroy : function() { self.window.remove(); }
|
||||
};
|
||||
|
||||
this.shortcuts = [{
|
||||
pattern : 'space'
|
||||
}];
|
||||
|
||||
this.support = {
|
||||
audio : {
|
||||
ogg : support('audio/ogg;'),
|
||||
webm: support('audio/webm;'),
|
||||
mp3 : support('audio/mpeg;'),
|
||||
wav : support('audio/wav;'),
|
||||
m4a : support('audio/mp4;') || support('audio/x-m4a;') || support('audio/aac;'),
|
||||
flac: support('audio/flac;'),
|
||||
amr : support('audio/amr;')
|
||||
},
|
||||
video : {
|
||||
ogg : support('video/ogg;'),
|
||||
webm : support('video/webm;'),
|
||||
mp4 : support('video/mp4;'),
|
||||
mkv : support('video/x-matroska;') || support('video/webm;'),
|
||||
'3gp': support('video/3gpp;') || support('video/mp4;'), // try as mp4
|
||||
m3u8 : support('application/x-mpegURL', 'video') || support('application/vnd.apple.mpegURL', 'video'),
|
||||
mpd : support('application/dash+xml', 'video')
|
||||
}
|
||||
};
|
||||
// for GC
|
||||
mediaNode = {};
|
||||
|
||||
/**
|
||||
* Return true if quickLoock window is hiddenReturn true if quickLoock window is visible and not animated
|
||||
*
|
||||
* @return Boolean
|
||||
**/
|
||||
this.closed = function() {
|
||||
return (state == closed || state == dockedhidden);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return true if quickLoock window is visible and not animated
|
||||
*
|
||||
* @return Boolean
|
||||
**/
|
||||
this.opened = function() {
|
||||
return state == opened || state == docked;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return true if quickLoock window is in NavDock
|
||||
*
|
||||
* @return Boolean
|
||||
**/
|
||||
this.docked = function() {
|
||||
return state == docked;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds an integration into help dialog.
|
||||
*
|
||||
* @param Object opts options
|
||||
*/
|
||||
this.addIntegration = function(opts) {
|
||||
requestAnimationFrame(function() {
|
||||
fm.trigger('helpIntegration', Object.assign({cmd: 'quicklook'}, opts));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Init command.
|
||||
* Add default plugins and init other plugins
|
||||
*
|
||||
* @return Object
|
||||
**/
|
||||
this.init = function() {
|
||||
var o = this.options,
|
||||
win = this.window,
|
||||
preview = this.preview,
|
||||
i, p, cwdDispInlineRegex;
|
||||
|
||||
width = o.width > 0 ? parseInt(o.width) : 450;
|
||||
height = o.height > 0 ? parseInt(o.height) : 300;
|
||||
if (o.dockHeight !== 'auto') {
|
||||
dockHeight = parseInt(o.dockHeight);
|
||||
if (! dockHeight) {
|
||||
dockHeight = void(0);
|
||||
}
|
||||
}
|
||||
|
||||
fm.one('load', function() {
|
||||
|
||||
dockEnabled = fm.getUI('navdock').data('dockEnabled');
|
||||
|
||||
! dockEnabled && titleDock.hide();
|
||||
|
||||
parent = fm.getUI();
|
||||
cwd = fm.getUI('cwd');
|
||||
|
||||
if (fm.zIndex) {
|
||||
win.css('z-index', fm.zIndex + 1);
|
||||
}
|
||||
|
||||
win.appendTo(parent);
|
||||
|
||||
// close window on escape
|
||||
$(document).on('keydown.'+fm.namespace, function(e) {
|
||||
e.keyCode == $.ui.keyCode.ESCAPE && self.opened() && ! self.docked() && win.hasClass('elfinder-frontmost') && win.trigger('close');
|
||||
});
|
||||
|
||||
win.resizable({
|
||||
handles : 'se',
|
||||
minWidth : 350,
|
||||
minHeight : 120,
|
||||
resize : function() {
|
||||
// use another event to avoid recursion in fullscreen mode
|
||||
// may be there is clever solution, but i cant find it :(
|
||||
preview.trigger('changesize');
|
||||
}
|
||||
});
|
||||
|
||||
self.change(function() {
|
||||
if (self.opened()) {
|
||||
if (self.value) {
|
||||
if (self.value.tmb && self.value.tmb == 1) {
|
||||
// try re-get file object
|
||||
self.value = Object.assign({}, fm.file(self.value.hash));
|
||||
}
|
||||
preview.trigger($.Event(evUpdate, {file : self.value}));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
preview.on(evUpdate, function(e) {
|
||||
var file, hash, serach;
|
||||
|
||||
if (file = e.file) {
|
||||
hash = file.hash;
|
||||
serach = (fm.searchStatus.mixed && fm.searchStatus.state > 1);
|
||||
|
||||
if (file.mime !== 'directory') {
|
||||
if (parseInt(file.size) || file.mime.match(o.mimeRegexNotEmptyCheck)) {
|
||||
// set current dispInlineRegex
|
||||
self.dispInlineRegex = cwdDispInlineRegex;
|
||||
if (serach || fm.optionsByHashes[hash]) {
|
||||
try {
|
||||
self.dispInlineRegex = new RegExp(fm.option('dispInlineRegex', hash), 'i');
|
||||
} catch(e) {
|
||||
try {
|
||||
self.dispInlineRegex = new RegExp(!fm.isRoot(file)? fm.option('dispInlineRegex', file.phash) : fm.options.dispInlineRegex, 'i');
|
||||
} catch(e) {
|
||||
self.dispInlineRegex = /^$/;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// do not preview of file that size = 0
|
||||
e.stopImmediatePropagation();
|
||||
}
|
||||
} else {
|
||||
self.dispInlineRegex = /^$/;
|
||||
}
|
||||
|
||||
self.info.show();
|
||||
} else {
|
||||
e.stopImmediatePropagation();
|
||||
}
|
||||
});
|
||||
|
||||
$.each(fm.commands.quicklook.plugins || [], function(i, plugin) {
|
||||
if (typeof(plugin) == 'function') {
|
||||
new plugin(self);
|
||||
}
|
||||
});
|
||||
}).one('open', function() {
|
||||
var dock = Number(fm.storage('previewDocked') || o.docked),
|
||||
win;
|
||||
if (dockEnabled && dock >= 1) {
|
||||
win = self.window;
|
||||
self.exec();
|
||||
win.trigger('navdockin', { init : true });
|
||||
if (dock === 2) {
|
||||
win.trigger('close');
|
||||
} else {
|
||||
self.update(void(0), fm.cwd());
|
||||
self.change();
|
||||
}
|
||||
}
|
||||
init = false;
|
||||
}).bind('open', function() {
|
||||
cwdHash = fm.cwd().hash;
|
||||
self.value = fm.cwd();
|
||||
// set current volume dispInlineRegex
|
||||
try {
|
||||
cwdDispInlineRegex = new RegExp(fm.option('dispInlineRegex'), 'i');
|
||||
} catch(e) {
|
||||
cwdDispInlineRegex = /^$/;
|
||||
}
|
||||
}).bind('change', function(e) {
|
||||
if (e.data && e.data.changed && self.opened()) {
|
||||
$.each(e.data.changed, function() {
|
||||
if (self.window.data('hash') === this.hash) {
|
||||
self.window.data('hash', null);
|
||||
self.preview.trigger(evUpdate);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}).bind('navdockresizestart navdockresizestop', function(e) {
|
||||
cover[e.type === 'navdockresizestart'? 'show' : 'hide']();
|
||||
});
|
||||
};
|
||||
|
||||
this.getstate = function() {
|
||||
return self.opened()? 1 : 0;
|
||||
};
|
||||
|
||||
this.exec = function() {
|
||||
self.closed() && updateOnSel();
|
||||
self.enabled() && self.window.trigger(self.opened() ? 'close' : 'open');
|
||||
return $.Deferred().resolve();
|
||||
};
|
||||
|
||||
this.hideinfo = function() {
|
||||
this.info.stop(true, true).hide();
|
||||
};
|
||||
|
||||
}).prototype = { forceLoad : true }; // this is required command
|
||||
+1950
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @class elFinder command "reload"
|
||||
* Sync files and folders
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
(elFinder.prototype.commands.reload = function() {
|
||||
"use strict";
|
||||
var self = this,
|
||||
search = false;
|
||||
|
||||
this.alwaysEnabled = true;
|
||||
this.updateOnSelect = true;
|
||||
|
||||
this.shortcuts = [{
|
||||
pattern : 'ctrl+shift+r f5'
|
||||
}];
|
||||
|
||||
this.getstate = function() {
|
||||
return 0;
|
||||
};
|
||||
|
||||
this.init = function() {
|
||||
this.fm.bind('search searchend', function() {
|
||||
search = this.type == 'search';
|
||||
});
|
||||
};
|
||||
|
||||
this.fm.bind('contextmenu', function(){
|
||||
var fm = self.fm;
|
||||
if (fm.options.sync >= 1000) {
|
||||
self.extra = {
|
||||
icon: 'accept',
|
||||
node: $('<span></span>')
|
||||
.attr({title: fm.i18n('autoSync')})
|
||||
.on('click touchstart', function(e){
|
||||
if (e.type === 'touchstart' && e.originalEvent.touches.length > 1) {
|
||||
return;
|
||||
}
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
$(this).parent()
|
||||
.toggleClass('ui-state-disabled', fm.options.syncStart)
|
||||
.parent().removeClass('ui-state-hover');
|
||||
fm.options.syncStart = !fm.options.syncStart;
|
||||
fm.autoSync(fm.options.syncStart? null : 'stop');
|
||||
}).on('ready', function(){
|
||||
$(this).parent().toggleClass('ui-state-disabled', !fm.options.syncStart).css('pointer-events', 'auto');
|
||||
})
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
this.exec = function() {
|
||||
var fm = this.fm;
|
||||
if (!search) {
|
||||
var dfrd = fm.sync(),
|
||||
timeout = setTimeout(function() {
|
||||
fm.notify({type : 'reload', cnt : 1, hideCnt : true});
|
||||
dfrd.always(function() { fm.notify({type : 'reload', cnt : -1}); });
|
||||
}, fm.notifyDelay);
|
||||
|
||||
return dfrd.always(function() {
|
||||
clearTimeout(timeout);
|
||||
fm.trigger('reload');
|
||||
});
|
||||
} else {
|
||||
$('div.elfinder-toolbar > div.'+fm.res('class', 'searchbtn') + ' > span.ui-icon-search').click();
|
||||
}
|
||||
};
|
||||
|
||||
}).prototype = { forceLoad : true }; // this is required command
|
||||
@@ -0,0 +1,583 @@
|
||||
/**
|
||||
* @class elFinder command "rename".
|
||||
* Rename selected file.
|
||||
*
|
||||
* @author Dmitry (dio) Levashov, dio@std42.ru
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
elFinder.prototype.commands.rename = function() {
|
||||
"use strict";
|
||||
|
||||
// set alwaysEnabled to allow root rename on client size
|
||||
this.alwaysEnabled = true;
|
||||
|
||||
this.syncTitleOnChange = true;
|
||||
|
||||
var self = this,
|
||||
fm = self.fm,
|
||||
request = function(dfrd, targtes, file, name) {
|
||||
var sel = targtes? [file.hash].concat(targtes) : [file.hash],
|
||||
cnt = sel.length,
|
||||
data = {}, rootNames;
|
||||
|
||||
fm.lockfiles({files : sel});
|
||||
|
||||
if (fm.isRoot(file) && !file.netkey) {
|
||||
if (!(rootNames = fm.storage('rootNames'))) {
|
||||
rootNames = {};
|
||||
}
|
||||
if (name === '') {
|
||||
if (rootNames[file.hash]) {
|
||||
file.name = file._name;
|
||||
file.i18 = file._i18;
|
||||
delete rootNames[file.hash];
|
||||
delete file._name;
|
||||
delete file._i18;
|
||||
} else {
|
||||
dfrd && dfrd.reject();
|
||||
fm.unlockfiles({files : sel}).trigger('selectfiles', {files : sel});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (typeof file._name === 'undefined') {
|
||||
file._name = file.name;
|
||||
file._i18 = file.i18;
|
||||
}
|
||||
file.name = rootNames[file.hash] = name;
|
||||
delete file.i18;
|
||||
}
|
||||
fm.storage('rootNames', rootNames);
|
||||
data = { changed: [file] };
|
||||
fm.updateCache(data);
|
||||
fm.change(data);
|
||||
dfrd && dfrd.resolve(data);
|
||||
fm.unlockfiles({files : sel}).trigger('selectfiles', {files : sel});
|
||||
return;
|
||||
}
|
||||
|
||||
data = {
|
||||
cmd : 'rename',
|
||||
name : name,
|
||||
target : file.hash
|
||||
};
|
||||
|
||||
if (cnt > 1) {
|
||||
data['targets'] = targtes;
|
||||
if (name.match(/\*/)) {
|
||||
data['q'] = name;
|
||||
}
|
||||
}
|
||||
|
||||
fm.request({
|
||||
data : data,
|
||||
notify : {type : 'rename', cnt : cnt},
|
||||
navigate : {}
|
||||
})
|
||||
.fail(function(error) {
|
||||
var err = fm.parseError(error);
|
||||
dfrd && dfrd.reject();
|
||||
if (! err || ! Array.isArray(err) || err[0] !== 'errRename') {
|
||||
fm.sync();
|
||||
}
|
||||
})
|
||||
.done(function(data) {
|
||||
var cwdHash;
|
||||
if (data.added && data.added.length && cnt === 1) {
|
||||
data.undo = {
|
||||
cmd : 'rename',
|
||||
callback : function() {
|
||||
return fm.request({
|
||||
data : {cmd : 'rename', target : data.added[0].hash, name : file.name},
|
||||
notify : {type : 'undo', cnt : 1}
|
||||
});
|
||||
}
|
||||
};
|
||||
data.redo = {
|
||||
cmd : 'rename',
|
||||
callback : function() {
|
||||
return fm.request({
|
||||
data : {cmd : 'rename', target : file.hash, name : name},
|
||||
notify : {type : 'rename', cnt : 1}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
dfrd && dfrd.resolve(data);
|
||||
if (!(cwdHash = fm.cwd().hash) || cwdHash === file.hash) {
|
||||
fm.exec('open', $.map(data.added, function(f) {
|
||||
return (f.mime === 'directory')? f.hash : null;
|
||||
})[0]);
|
||||
}
|
||||
})
|
||||
.always(function() {
|
||||
fm.unlockfiles({files : sel}).trigger('selectfiles', {files : sel});
|
||||
}
|
||||
);
|
||||
},
|
||||
getHint = function(name, target) {
|
||||
var sel = target || fm.selected(),
|
||||
splits = fm.splitFileExtention(name),
|
||||
f1 = fm.file(sel[0]),
|
||||
f2 = fm.file(sel[1]),
|
||||
ext, hint, add;
|
||||
|
||||
ext = splits[1]? ('.' + splits[1]) : '';
|
||||
if (splits[1] && splits[0] === '*') {
|
||||
// change extention
|
||||
hint = '"' + fm.splitFileExtention(f1.name)[0] + ext + '", ';
|
||||
hint += '"' + fm.splitFileExtention(f2.name)[0] + ext + '"';
|
||||
} else if (splits[0].length > 1) {
|
||||
if (splits[0].substr(-1) === '*') {
|
||||
// add prefix
|
||||
add = splits[0].substr(0, splits[0].length - 1);
|
||||
hint = '"' + add + f1.name+'", ';
|
||||
hint += '"' + add + f2.name+'"';
|
||||
} else if (splits[0].substr(0, 1) === '*') {
|
||||
// add suffix
|
||||
add = splits[0].substr(1);
|
||||
hint = '"'+fm.splitFileExtention(f1.name)[0] + add + ext + '", ';
|
||||
hint += '"'+fm.splitFileExtention(f2.name)[0] + add + ext + '"';
|
||||
}
|
||||
}
|
||||
if (!hint) {
|
||||
hint = '"'+splits[0] + '1' + ext + '", "' + splits[0] + '2' + ext + '"';
|
||||
}
|
||||
if (sel.length > 2) {
|
||||
hint += ' ...';
|
||||
}
|
||||
return hint;
|
||||
},
|
||||
batchRename = function() {
|
||||
var sel = fm.selected(),
|
||||
tplr = '<input name="type" type="radio" class="elfinder-tabstop">',
|
||||
mkChk = function(node, label) {
|
||||
return $('<label class="elfinder-rename-batch-checks">' + fm.i18n(label) + '</label>').prepend(node);
|
||||
},
|
||||
name = $('<input type="text" class="ui-corner-all elfinder-tabstop">'),
|
||||
num = $(tplr),
|
||||
prefix = $(tplr),
|
||||
suffix = $(tplr),
|
||||
extention = $(tplr),
|
||||
checks = $('<div></div>').append(
|
||||
mkChk(num, 'plusNumber'),
|
||||
mkChk(prefix, 'asPrefix'),
|
||||
mkChk(suffix, 'asSuffix'),
|
||||
mkChk(extention, 'changeExtention')
|
||||
),
|
||||
preview = $('<div class="elfinder-rename-batch-preview"></div>'),
|
||||
node = $('<div class="elfinder-rename-batch"></div>').append(
|
||||
$('<div class="elfinder-rename-batch-name"></div>').append(name),
|
||||
$('<div class="elfinder-rename-batch-type"></div>').append(checks),
|
||||
preview
|
||||
),
|
||||
opts = {
|
||||
title : fm.i18n('batchRename'),
|
||||
modal : true,
|
||||
destroyOnClose : true,
|
||||
width: Math.min(380, fm.getUI().width() - 20),
|
||||
buttons : {},
|
||||
open : function() {
|
||||
name.on('input', mkPrev).trigger('focus');
|
||||
}
|
||||
},
|
||||
getName = function() {
|
||||
var vName = name.val(),
|
||||
ext = fm.splitFileExtention(fm.file(sel[0]).name)[1];
|
||||
if (vName !== '' || num.is(':checked')) {
|
||||
if (prefix.is(':checked')) {
|
||||
vName += '*';
|
||||
} else if (suffix.is(':checked')) {
|
||||
vName = '*' + vName + '.' + ext;
|
||||
} else if (extention.is(':checked')) {
|
||||
vName = '*.' + vName;
|
||||
} else if (ext) {
|
||||
vName += '.' + ext;
|
||||
}
|
||||
}
|
||||
return vName;
|
||||
},
|
||||
mkPrev = function() {
|
||||
var vName = getName();
|
||||
if (vName !== '') {
|
||||
preview.html(fm.i18n(['renameMultiple', sel.length, getHint(vName)]));
|
||||
} else {
|
||||
preview.empty();
|
||||
}
|
||||
},
|
||||
radios = checks.find('input:radio').on('change', mkPrev),
|
||||
dialog;
|
||||
|
||||
opts.buttons[fm.i18n('btnApply')] = function() {
|
||||
var vName = getName(),
|
||||
file, targets;
|
||||
if (vName !== '') {
|
||||
dialog.elfinderdialog('close');
|
||||
targets = sel;
|
||||
file = fm.file(targets.shift());
|
||||
request(void(0), targets, file, vName);
|
||||
}
|
||||
};
|
||||
opts.buttons[fm.i18n('btnCancel')] = function() {
|
||||
dialog.elfinderdialog('close');
|
||||
};
|
||||
if ($.fn.checkboxradio) {
|
||||
radios.checkboxradio({
|
||||
create: function(e, ui) {
|
||||
if (this === num.get(0)) {
|
||||
num.prop('checked', true).change();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
checks.buttonset({
|
||||
create: function(e, ui) {
|
||||
num.prop('checked', true).change();
|
||||
}
|
||||
});
|
||||
}
|
||||
dialog = self.fmDialog(node, opts);
|
||||
};
|
||||
|
||||
this.noChangeDirOnRemovedCwd = true;
|
||||
|
||||
this.shortcuts = [{
|
||||
pattern : 'f2' + (fm.OS == 'mac' ? ' enter' : '')
|
||||
}, {
|
||||
pattern : 'shift+f2',
|
||||
description : 'batchRename',
|
||||
callback : function() {
|
||||
fm.selected().length > 1 && batchRename();
|
||||
}
|
||||
}];
|
||||
|
||||
this.getstate = function(select) {
|
||||
var sel = this.files(select),
|
||||
cnt = sel.length,
|
||||
phash, ext, mime, brk, state, isRoot;
|
||||
|
||||
if (!cnt) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cnt > 1 && sel[0].phash) {
|
||||
phash = sel[0].phash;
|
||||
ext = fm.splitFileExtention(sel[0].name)[1].toLowerCase();
|
||||
mime = sel[0].mime;
|
||||
}
|
||||
if (cnt === 1) {
|
||||
isRoot = fm.isRoot(sel[0]);
|
||||
}
|
||||
|
||||
state = (cnt === 1 && ((fm.cookieEnabled && isRoot) || !sel[0].locked) || (fm.api > 2.1030 && cnt === $.grep(sel, function(f) {
|
||||
if (!brk && !f.locked && f.phash === phash && !fm.isRoot(f) && (mime === f.mime || ext === fm.splitFileExtention(f.name)[1].toLowerCase())) {
|
||||
return true;
|
||||
} else {
|
||||
brk && (brk = true);
|
||||
return false;
|
||||
}
|
||||
}).length)) ? 0 : -1;
|
||||
|
||||
// because alwaysEnabled = true, it need check disabled on connector
|
||||
if (!isRoot && state === 0 && fm.option('disabledFlip', sel[0].hash)['rename']) {
|
||||
state = -1;
|
||||
}
|
||||
|
||||
if (state !== -1 && cnt > 1) {
|
||||
self.extra = {
|
||||
icon: 'preference',
|
||||
node: $('<span></span>')
|
||||
.attr({title: fm.i18n('batchRename')})
|
||||
.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
|
||||
batchRename();
|
||||
})
|
||||
};
|
||||
} else {
|
||||
delete self.extra;
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
this.exec = function(hashes, cOpts) {
|
||||
var cwd = fm.getUI('cwd'),
|
||||
sel = hashes || (fm.selected().length? fm.selected() : false) || [fm.cwd().hash],
|
||||
cnt = sel.length,
|
||||
file = fm.file(sel.shift()),
|
||||
filename = '.elfinder-cwd-filename',
|
||||
opts = cOpts || {},
|
||||
incwd = (fm.cwd().hash == file.hash),
|
||||
type = (opts._currentType === 'navbar' || opts._currentType === 'files')? opts._currentType : (incwd? 'navbar' : 'files'),
|
||||
navbar = (type !== 'files'),
|
||||
target = fm[navbar? 'navHash2Elm' : 'cwdHash2Elm'](file.hash),
|
||||
tarea = (!navbar && fm.storage('view') != 'list'),
|
||||
split = function(name) {
|
||||
var ext = fm.splitFileExtention(name)[1];
|
||||
return [name.substr(0, name.length - ext.length - 1), ext];
|
||||
},
|
||||
unselect = function() {
|
||||
requestAnimationFrame(function() {
|
||||
input && input.trigger('blur');
|
||||
});
|
||||
},
|
||||
rest = function(){
|
||||
if (!overlay.is(':hidden')) {
|
||||
overlay.elfinderoverlay('hide').off('click close', cancel);
|
||||
}
|
||||
pnode.removeClass('ui-front')
|
||||
.css('position', '')
|
||||
.off('unselect.'+fm.namespace, unselect);
|
||||
if (tarea) {
|
||||
node && node.css('max-height', '');
|
||||
} else if (!navbar) {
|
||||
pnode.css('width', '')
|
||||
.parent('td').css('overflow', '');
|
||||
}
|
||||
}, colwidth,
|
||||
dfrd = $.Deferred()
|
||||
.fail(function(error) {
|
||||
var parent = input.parent(),
|
||||
name = fm.escape(file.i18 || file.name);
|
||||
|
||||
input.off();
|
||||
if (tarea) {
|
||||
name = name.replace(/([_.])/g, '​$1');
|
||||
}
|
||||
requestAnimationFrame(function() {
|
||||
if (navbar) {
|
||||
input.replaceWith(name);
|
||||
} else {
|
||||
if (parent.length) {
|
||||
input.remove();
|
||||
parent.html(name);
|
||||
} else {
|
||||
target.find(filename).html(name);
|
||||
}
|
||||
}
|
||||
});
|
||||
error && fm.error(error);
|
||||
})
|
||||
.always(function() {
|
||||
rest();
|
||||
fm.unbind('resize', resize);
|
||||
fm.enable();
|
||||
}),
|
||||
blur = function(e) {
|
||||
var name = $.trim(input.val()),
|
||||
splits = fm.splitFileExtention(name),
|
||||
valid = true,
|
||||
req = function() {
|
||||
input.off();
|
||||
rest();
|
||||
if (navbar) {
|
||||
input.replaceWith(fm.escape(name));
|
||||
} else {
|
||||
node.html(fm.escape(name));
|
||||
}
|
||||
request(dfrd, sel, file, name);
|
||||
};
|
||||
|
||||
if (!overlay.is(':hidden')) {
|
||||
pnode.css('z-index', '');
|
||||
}
|
||||
if (name === '') {
|
||||
if (!fm.isRoot(file)) {
|
||||
return cancel();
|
||||
}
|
||||
if (navbar) {
|
||||
input.replaceWith(fm.escape(file.name));
|
||||
} else {
|
||||
node.html(fm.escape(file.name));
|
||||
}
|
||||
}
|
||||
if (!inError && pnode.length) {
|
||||
|
||||
input.off('blur');
|
||||
|
||||
if (cnt === 1 && name === file.name) {
|
||||
return dfrd.reject();
|
||||
}
|
||||
if (fm.options.validName && fm.options.validName.test) {
|
||||
try {
|
||||
valid = fm.options.validName.test(name);
|
||||
} catch(e) {
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
if (name === '.' || name === '..' || !valid) {
|
||||
inError = true;
|
||||
fm.error(file.mime === 'directory'? 'errInvDirname' : 'errInvName', {modal: true, close: function(){setTimeout(select, 120);}});
|
||||
return false;
|
||||
}
|
||||
if (cnt === 1 && fm.fileByName(name, file.phash)) {
|
||||
inError = true;
|
||||
fm.error(['errExists', name], {modal: true, close: function(){setTimeout(select, 120);}});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cnt === 1) {
|
||||
req();
|
||||
} else {
|
||||
fm.confirm({
|
||||
title : 'cmdrename',
|
||||
text : ['renameMultiple', cnt, getHint(name, [file.hash].concat(sel))],
|
||||
accept : {
|
||||
label : 'btnYes',
|
||||
callback : req
|
||||
},
|
||||
cancel : {
|
||||
label : 'btnCancel',
|
||||
callback : function() {
|
||||
setTimeout(function() {
|
||||
inError = true;
|
||||
select();
|
||||
}, 120);
|
||||
}
|
||||
}
|
||||
});
|
||||
setTimeout(function() {
|
||||
fm.trigger('unselectfiles', {files: fm.selected()})
|
||||
.trigger('selectfiles', {files : [file.hash].concat(sel)});
|
||||
}, 120);
|
||||
}
|
||||
}
|
||||
},
|
||||
input = $(tarea? '<textarea></textarea>' : '<input type="text"/>')
|
||||
.on('keyup text', function(){
|
||||
if (tarea) {
|
||||
this.style.height = '1px';
|
||||
this.style.height = this.scrollHeight + 'px';
|
||||
} else if (colwidth) {
|
||||
this.style.width = colwidth + 'px';
|
||||
if (this.scrollWidth > colwidth) {
|
||||
this.style.width = this.scrollWidth + 10 + 'px';
|
||||
}
|
||||
}
|
||||
})
|
||||
.on('keydown', function(e) {
|
||||
e.stopImmediatePropagation();
|
||||
if (e.keyCode == $.ui.keyCode.ESCAPE) {
|
||||
dfrd.reject();
|
||||
} else if (e.keyCode == $.ui.keyCode.ENTER) {
|
||||
e.preventDefault();
|
||||
input.trigger('blur');
|
||||
}
|
||||
})
|
||||
.on('mousedown click dblclick', function(e) {
|
||||
e.stopPropagation();
|
||||
if (e.type === 'dblclick') {
|
||||
e.preventDefault();
|
||||
}
|
||||
})
|
||||
.on('blur', blur)
|
||||
.on('dragenter dragleave dragover drop', function(e) {
|
||||
// stop bubbling to prevent upload with native drop event
|
||||
e.stopPropagation();
|
||||
}),
|
||||
select = function() {
|
||||
var name = fm.splitFileExtention(input.val())[0];
|
||||
if (!inError && fm.UA.Mobile && !fm.UA.iOS) { // since iOS has a bug? (z-index not effect) so disable it
|
||||
overlay.on('click close', cancel).elfinderoverlay('show');
|
||||
pnode.css('z-index', overlay.css('z-index') + 1);
|
||||
}
|
||||
! fm.enabled() && fm.enable();
|
||||
if (inError) {
|
||||
inError = false;
|
||||
input.on('blur', blur);
|
||||
}
|
||||
input.trigger('focus').trigger('select');
|
||||
input[0].setSelectionRange && input[0].setSelectionRange(0, name.length);
|
||||
},
|
||||
node = navbar? target.contents().filter(function(){ return this.nodeType==3 && $(this).parent().attr('id') === fm.navHash2Id(file.hash); })
|
||||
: target.find(filename),
|
||||
pnode = node.parent(),
|
||||
overlay = fm.getUI('overlay'),
|
||||
cancel = function(e) {
|
||||
if (!overlay.is(':hidden')) {
|
||||
pnode.css('z-index', '');
|
||||
}
|
||||
if (! inError) {
|
||||
dfrd.reject();
|
||||
if (e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
},
|
||||
resize = function() {
|
||||
target.trigger('scrolltoview', {blink : false});
|
||||
},
|
||||
inError = false;
|
||||
|
||||
pnode.addClass('ui-front')
|
||||
.css('position', 'relative')
|
||||
.on('unselect.'+fm.namespace, unselect);
|
||||
fm.bind('resize', resize);
|
||||
if (navbar) {
|
||||
node.replaceWith(input.val(file.name));
|
||||
} else {
|
||||
if (tarea) {
|
||||
node.css('max-height', 'none');
|
||||
} else if (!navbar) {
|
||||
colwidth = pnode.width();
|
||||
pnode.width(colwidth - 15)
|
||||
.parent('td').css('overflow', 'visible');
|
||||
}
|
||||
node.empty().append(input.val(file.name));
|
||||
}
|
||||
|
||||
if (cnt > 1 && fm.api <= 2.1030) {
|
||||
return dfrd.reject();
|
||||
}
|
||||
|
||||
if (!file || !node.length) {
|
||||
return dfrd.reject('errCmdParams', this.title);
|
||||
}
|
||||
|
||||
if (file.locked && !fm.isRoot(file)) {
|
||||
return dfrd.reject(['errLocked', file.name]);
|
||||
}
|
||||
|
||||
fm.one('select', function() {
|
||||
input.parent().length && file && $.inArray(file.hash, fm.selected()) === -1 && input.trigger('blur');
|
||||
});
|
||||
|
||||
input.trigger('keyup');
|
||||
|
||||
select();
|
||||
|
||||
return dfrd;
|
||||
};
|
||||
|
||||
fm.bind('select contextmenucreate closecontextmenu', function(e) {
|
||||
var sel = (e.data? (e.data.selected || e.data.targets) : null) || fm.selected(),
|
||||
file;
|
||||
if (sel && sel.length === 1 && (file = fm.file(sel[0])) && fm.isRoot(file)) {
|
||||
self.title = fm.i18n('kindAlias') + ' (' + fm.i18n('preference') + ')';
|
||||
} else {
|
||||
self.title = fm.i18n('cmdrename');
|
||||
}
|
||||
if (e.type !== 'closecontextmenu') {
|
||||
self.update(void(0), self.title);
|
||||
} else {
|
||||
requestAnimationFrame(function() {
|
||||
self.update(void(0), self.title);
|
||||
});
|
||||
}
|
||||
}).remove(function(e) {
|
||||
var rootNames;
|
||||
if (e.data && e.data.removed && (rootNames = fm.storage('rootNames'))) {
|
||||
$.each(e.data.removed, function(i, h) {
|
||||
if (rootNames[h]) {
|
||||
delete rootNames[h];
|
||||
}
|
||||
});
|
||||
fm.storage('rootNames', rootNames);
|
||||
}
|
||||
});
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,286 @@
|
||||
/**
|
||||
* @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 = $.Deferred(),
|
||||
dirs = [],
|
||||
results = [],
|
||||
reqs = [],
|
||||
phashes = [],
|
||||
getFile;
|
||||
|
||||
dfd._xhrReject = function() {
|
||||
$.each(reqs, function() {
|
||||
this && this.reject && this.reject();
|
||||
});
|
||||
getFile && getFile._xhrReject();
|
||||
};
|
||||
|
||||
$.each(files, function(i, f) {
|
||||
f.mime === 'directory'? dirs.push(f) : results.push(f);
|
||||
});
|
||||
|
||||
if (dirs.length) {
|
||||
$.each(dirs, function(i, d) {
|
||||
reqs.push(fm.request({
|
||||
data : {cmd : 'open', target : d.hash},
|
||||
preventDefault : true,
|
||||
asNotOpen : true
|
||||
}));
|
||||
phashes[i] = d.hash;
|
||||
});
|
||||
$.when.apply($, reqs).fail(function() {
|
||||
dfd.reject();
|
||||
}).done(function() {
|
||||
var items = [];
|
||||
$.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 = $.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) {
|
||||
$.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 $.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
|
||||
$.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) {
|
||||
$.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;
|
||||
$.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 && $.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 = $.Deferred()
|
||||
.fail(function(error) {
|
||||
error && fm.error(error);
|
||||
}),
|
||||
files = self.files(hashes);
|
||||
|
||||
if (! files.length) {
|
||||
return dfrd.reject();
|
||||
}
|
||||
|
||||
$.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
|
||||
@@ -0,0 +1,501 @@
|
||||
/**
|
||||
* @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 = '<div class="ui-helper-clearfix elfinder-rm-title"><span class="elfinder-cwd-icon {class} ui-corner-all"></span>{title}<div class="elfinder-rm-desc">{desc}</div></div>',
|
||||
confirm = function(dfrd, targets, files, tHash, addTexts) {
|
||||
var cnt = targets.length,
|
||||
cwd = fm.cwd().hash,
|
||||
descs = [],
|
||||
spinner = fm.i18n('calc') + '<span class="elfinder-spinner"></span>',
|
||||
dialog, text, tmb, size, f, fname;
|
||||
|
||||
if (cnt > 1) {
|
||||
size = 0;
|
||||
$.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 = [$(tpl.replace('{class}', 'elfinder-cwd-icon-group').replace('{title}', '<strong>' + fm.i18n('items')+ ': ' + cnt + '</strong>').replace('{desc}', descs.join('<br>')))];
|
||||
} 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 = [$(tpl.replace('{class}', fm.mime2class(f.mime)).replace('{title}', '<strong>' + fname + '</strong>').replace('{desc}', descs.join('<br>')))];
|
||||
}
|
||||
|
||||
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) {
|
||||
$('<img/>')
|
||||
.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($.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 = $.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
|
||||
$.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;
|
||||
$.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 = $.map(data.added, function(f) { return f.mime === 'directory'? f.hash : null; });
|
||||
$.each(data.added, function(i, f) {
|
||||
if ($.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);
|
||||
$.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 = $.grep(targets, function(h) {
|
||||
return $.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 (!$.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: $('<span></span>')
|
||||
.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 $.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 = $.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();
|
||||
}
|
||||
|
||||
$.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');
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* @class elFinder command "search"
|
||||
* Find files
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
elFinder.prototype.commands.search = function() {
|
||||
"use strict";
|
||||
this.title = 'Find files';
|
||||
this.options = {ui : 'searchbutton'};
|
||||
this.alwaysEnabled = true;
|
||||
this.updateOnSelect = false;
|
||||
|
||||
/**
|
||||
* Return command status.
|
||||
* Search does not support old api.
|
||||
*
|
||||
* @return Number
|
||||
**/
|
||||
this.getstate = function() {
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Send search request to backend.
|
||||
*
|
||||
* @param String search string
|
||||
* @return $.Deferred
|
||||
**/
|
||||
this.exec = function(q, target, mime, type) {
|
||||
var fm = this.fm,
|
||||
reqDef = [],
|
||||
sType = type || '',
|
||||
onlyMimes = fm.options.onlyMimes,
|
||||
phash, targetVolids = [],
|
||||
setType = function(data) {
|
||||
if (sType && sType !== 'SearchName' && sType !== 'SearchMime') {
|
||||
data.type = sType;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
rootCnt;
|
||||
|
||||
if (typeof q == 'string' && q) {
|
||||
if (typeof target == 'object') {
|
||||
mime = target.mime || '';
|
||||
target = target.target || '';
|
||||
}
|
||||
target = target? target : '';
|
||||
if (mime) {
|
||||
mime = $.trim(mime).replace(',', ' ').split(' ');
|
||||
if (onlyMimes.length) {
|
||||
mime = $.map(mime, function(m){
|
||||
m = $.trim(m);
|
||||
return m && ($.inArray(m, onlyMimes) !== -1
|
||||
|| $.grep(onlyMimes, function(om) { return m.indexOf(om) === 0? true : false; }).length
|
||||
)? m : null;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
mime = [].concat(onlyMimes);
|
||||
}
|
||||
|
||||
fm.trigger('searchstart', setType({query : q, target : target, mimes : mime}));
|
||||
|
||||
if (! onlyMimes.length || mime.length) {
|
||||
if (target === '' && fm.api >= 2.1) {
|
||||
rootCnt = Object.keys(fm.roots).length;
|
||||
$.each(fm.roots, function(id, hash) {
|
||||
reqDef.push(fm.request({
|
||||
data : setType({cmd : 'search', q : q, target : hash, mimes : mime}),
|
||||
notify : {type : 'search', cnt : 1, hideCnt : (rootCnt > 1? false : true)},
|
||||
cancel : true,
|
||||
preventDone : true
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
reqDef.push(fm.request({
|
||||
data : setType({cmd : 'search', q : q, target : target, mimes : mime}),
|
||||
notify : {type : 'search', cnt : 1, hideCnt : true},
|
||||
cancel : true,
|
||||
preventDone : true
|
||||
}));
|
||||
if (target !== '' && fm.api >= 2.1 && Object.keys(fm.leafRoots).length) {
|
||||
$.each(fm.leafRoots, function(hash, roots) {
|
||||
phash = hash;
|
||||
while(phash) {
|
||||
if (target === phash) {
|
||||
$.each(roots, function() {
|
||||
var f = fm.file(this);
|
||||
f && f.volumeid && targetVolids.push(f.volumeid);
|
||||
reqDef.push(fm.request({
|
||||
data : setType({cmd : 'search', q : q, target : this, mimes : mime}),
|
||||
notify : {type : 'search', cnt : 1, hideCnt : false},
|
||||
cancel : true,
|
||||
preventDone : true
|
||||
}));
|
||||
});
|
||||
}
|
||||
phash = (fm.file(phash) || {}).phash;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reqDef = [$.Deferred().resolve({files: []})];
|
||||
}
|
||||
|
||||
fm.searchStatus.mixed = (reqDef.length > 1)? targetVolids : false;
|
||||
|
||||
return $.when.apply($, reqDef).done(function(data) {
|
||||
var argLen = arguments.length,
|
||||
i;
|
||||
|
||||
data.warning && fm.error(data.warning);
|
||||
|
||||
if (argLen > 1) {
|
||||
data.files = (data.files || []);
|
||||
for(i = 1; i < argLen; i++) {
|
||||
arguments[i].warning && fm.error(arguments[i].warning);
|
||||
|
||||
if (arguments[i].files) {
|
||||
data.files.push.apply(data.files, arguments[i].files);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// because "preventDone : true" so update files cache
|
||||
data.files && data.files.length && fm.cache(data.files);
|
||||
|
||||
fm.lazy(function() {
|
||||
fm.trigger('search', data);
|
||||
}).then(function() {
|
||||
// fire event with command name + 'done'
|
||||
return fm.lazy(function() {
|
||||
fm.trigger('searchdone');
|
||||
});
|
||||
}).then(function() {
|
||||
// force update content
|
||||
data.sync && fm.sync();
|
||||
});
|
||||
});
|
||||
}
|
||||
fm.getUI('toolbar').find('.'+fm.res('class', 'searchbtn')+' :text').trigger('focus');
|
||||
return $.Deferred().reject();
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @class elFinder command "selectall"
|
||||
* Select ALL of cwd items
|
||||
*
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
elFinder.prototype.commands.selectall = function() {
|
||||
"use strict";
|
||||
var self = this,
|
||||
state = 0;
|
||||
|
||||
this.fm.bind('select', function(e) {
|
||||
state = (e.data && e.data.selectall)? -1 : 0;
|
||||
});
|
||||
|
||||
this.state = 0;
|
||||
this.updateOnSelect = false;
|
||||
|
||||
this.getstate = function() {
|
||||
return state;
|
||||
};
|
||||
|
||||
this.exec = function() {
|
||||
$(document).trigger($.Event('keydown', { keyCode: 65, ctrlKey : true, shiftKey : false, altKey : false, metaKey : false }));
|
||||
return $.Deferred().resolve();
|
||||
};
|
||||
};
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @class elFinder command "selectinvert"
|
||||
* Invert Selection of cwd items
|
||||
*
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
elFinder.prototype.commands.selectinvert = function() {
|
||||
"use strict";
|
||||
this.updateOnSelect = false;
|
||||
|
||||
this.getstate = function() {
|
||||
return 0;
|
||||
};
|
||||
|
||||
this.exec = function() {
|
||||
$(document).trigger($.Event('keydown', { keyCode: 73, ctrlKey : true, shiftKey : true, altKey : false, metaKey : false }));
|
||||
return $.Deferred().resolve();
|
||||
};
|
||||
|
||||
};
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* @class elFinder command "selectnone"
|
||||
* Unselect ALL of cwd items
|
||||
*
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
elFinder.prototype.commands.selectnone = function() {
|
||||
"use strict";
|
||||
var self = this,
|
||||
fm = this.fm,
|
||||
state = -1;
|
||||
|
||||
fm.bind('select', function(e) {
|
||||
state = (e.data && e.data.unselectall)? -1 : 0;
|
||||
});
|
||||
|
||||
this.state = -1;
|
||||
this.updateOnSelect = false;
|
||||
|
||||
this.getstate = function() {
|
||||
return state;
|
||||
};
|
||||
|
||||
this.exec = function() {
|
||||
fm.getUI('cwd').trigger('unselectall');
|
||||
return $.Deferred().resolve();
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* @class elFinder command "sort"
|
||||
* Change sort files rule
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
elFinder.prototype.commands.sort = function() {
|
||||
"use strict";
|
||||
var self = this,
|
||||
fm = self.fm,
|
||||
setVar = function() {
|
||||
self.variants = [];
|
||||
$.each(fm.sortRules, function(name, value) {
|
||||
if (fm.sorters[name]) {
|
||||
var arr = (name === fm.sortType)? (fm.sortOrder === 'asc'? 'n' : 's') : '';
|
||||
self.variants.push([name, (arr? '<span class="ui-icon ui-icon-arrowthick-1-'+arr+'"></span>' : '') + ' ' + fm.i18n('sort'+name)]);
|
||||
}
|
||||
});
|
||||
self.variants.push('|');
|
||||
self.variants.push([
|
||||
'stick',
|
||||
(fm.sortStickFolders? '<span class="ui-icon ui-icon-check"></span>' : '') + ' ' + fm.i18n('sortFoldersFirst')
|
||||
]);
|
||||
if (fm.ui.tree && fm.options.sortAlsoTreeview !== null) {
|
||||
self.variants.push('|');
|
||||
self.variants.push([
|
||||
'tree',
|
||||
(fm.sortAlsoTreeview? '<span class="ui-icon ui-icon-check"></span>' : '') + ' ' + fm.i18n('sortAlsoTreeview')
|
||||
]);
|
||||
}
|
||||
updateContextmenu();
|
||||
},
|
||||
updateContextmenu = function() {
|
||||
var cm = fm.getUI('contextmenu'),
|
||||
icon, sub;
|
||||
if (cm.is(':visible')) {
|
||||
icon = cm.find('span.elfinder-button-icon-sort');
|
||||
sub = icon.siblings('div.elfinder-contextmenu-sub');
|
||||
sub.find('span.ui-icon').remove();
|
||||
sub.children('div.elfinder-contextsubmenu-item').each(function() {
|
||||
var tgt = $(this).children('span'),
|
||||
name = tgt.text().trim(),
|
||||
arr;
|
||||
if (name === (i18Name.stick || (i18Name.stick = fm.i18n('sortFoldersFirst')))) {
|
||||
if (fm.sortStickFolders) {
|
||||
tgt.prepend('<span class="ui-icon ui-icon-check"></span>');
|
||||
}
|
||||
} else if (name === (i18Name.tree || (i18Name.tree = fm.i18n('sortAlsoTreeview')))) {
|
||||
if (fm.sortAlsoTreeview) {
|
||||
tgt.prepend('<span class="ui-icon ui-icon-check"></span>');
|
||||
}
|
||||
} else if (name === (i18Name[fm.sortType] || (i18Name[fm.sortType] = fm.i18n('sort' + fm.sortType)))) {
|
||||
arr = fm.sortOrder === 'asc'? 'n' : 's';
|
||||
tgt.prepend('<span class="ui-icon ui-icon-arrowthick-1-'+arr+'"></span>');
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
i18Name = {};
|
||||
|
||||
/**
|
||||
* Command options
|
||||
*
|
||||
* @type Object
|
||||
*/
|
||||
this.options = {ui : 'sortbutton'};
|
||||
|
||||
this.keepContextmenu = true;
|
||||
|
||||
fm.bind('sortchange', setVar)
|
||||
.bind('sorterupdate', function() {
|
||||
setVar();
|
||||
fm.getUI().children('.elfinder-button-sort-menu').children('.elfinder-button-menu-item').each(function() {
|
||||
var tgt = $(this),
|
||||
rel = tgt.attr('rel');
|
||||
tgt.toggle(!!(! rel || fm.sorters[rel]));
|
||||
});
|
||||
})
|
||||
.bind('cwdrender', function() {
|
||||
var cols = $(fm.cwd).find('div.elfinder-cwd-wrapper-list table');
|
||||
if (cols.length) {
|
||||
$.each(fm.sortRules, function(name, value) {
|
||||
var td = cols.find('thead tr td.elfinder-cwd-view-th-'+name);
|
||||
if (td.length) {
|
||||
var current = ( name == fm.sortType),
|
||||
sort = {
|
||||
type : name,
|
||||
order : current ? fm.sortOrder == 'asc' ? 'desc' : 'asc' : fm.sortOrder
|
||||
},arr;
|
||||
if (current) {
|
||||
td.addClass('ui-state-active');
|
||||
arr = fm.sortOrder == 'asc' ? 'n' : 's';
|
||||
$('<span class="ui-icon ui-icon-triangle-1-'+arr+'"></span>').appendTo(td);
|
||||
}
|
||||
$(td).on('click', function(e){
|
||||
if (! $(this).data('dragging')) {
|
||||
e.stopPropagation();
|
||||
if (! fm.getUI('cwd').data('longtap')) {
|
||||
fm.exec('sort', [], sort);
|
||||
}
|
||||
}
|
||||
})
|
||||
.on('mouseenter mouseleave', function(e) {
|
||||
$(this).toggleClass('ui-state-hover', e.type === 'mouseenter');
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.getstate = function() {
|
||||
return 0;
|
||||
};
|
||||
|
||||
this.exec = function(hashes, cOpt) {
|
||||
var fm = this.fm,
|
||||
sortopt = $.isPlainObject(cOpt)? cOpt : (function() {
|
||||
cOpt += '';
|
||||
var sOpts = {};
|
||||
if (cOpt === 'stick') {
|
||||
sOpts.stick = !fm.sortStickFolders;
|
||||
} else if (cOpt === 'tree') {
|
||||
sOpts.tree = !fm.sortAlsoTreeview;
|
||||
} else if (fm.sorters[cOpt]) {
|
||||
if (fm.sortType === cOpt) {
|
||||
sOpts.order = fm.sortOrder === 'asc'? 'desc' : 'asc';
|
||||
} else {
|
||||
sOpts.type = cOpt;
|
||||
}
|
||||
}
|
||||
return sOpts;
|
||||
})(),
|
||||
sort = Object.assign({
|
||||
type : fm.sortType,
|
||||
order : fm.sortOrder,
|
||||
stick : fm.sortStickFolders,
|
||||
tree : fm.sortAlsoTreeview
|
||||
}, sortopt);
|
||||
|
||||
return fm.lazy(function() {
|
||||
fm.setSort(sort.type, sort.order, sort.stick, sort.tree);
|
||||
this.resolve();
|
||||
});
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,189 @@
|
||||
/**
|
||||
* @class elFinder command "undo"
|
||||
* Undo previous commands
|
||||
*
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
elFinder.prototype.commands.undo = function() {
|
||||
"use strict";
|
||||
var self = this,
|
||||
fm = this.fm,
|
||||
setTitle = function(undo) {
|
||||
if (undo) {
|
||||
self.title = fm.i18n('cmdundo') + ' ' + fm.i18n('cmd'+undo.cmd);
|
||||
self.state = 0;
|
||||
} else {
|
||||
self.title = fm.i18n('cmdundo');
|
||||
self.state = -1;
|
||||
}
|
||||
self.change();
|
||||
},
|
||||
cmds = [];
|
||||
|
||||
this.alwaysEnabled = true;
|
||||
this.updateOnSelect = false;
|
||||
this.shortcuts = [{
|
||||
pattern : 'ctrl+z'
|
||||
}];
|
||||
this.syncTitleOnChange = true;
|
||||
|
||||
this.getstate = function() {
|
||||
return cmds.length? 0 : -1;
|
||||
};
|
||||
|
||||
this.setUndo = function(undo, redo) {
|
||||
var _undo = {};
|
||||
if (undo) {
|
||||
if ($.isPlainObject(undo) && undo.cmd && undo.callback) {
|
||||
Object.assign(_undo, undo);
|
||||
if (redo) {
|
||||
delete redo.undo;
|
||||
_undo.redo = redo;
|
||||
} else {
|
||||
fm.getCommand('redo').setRedo(null);
|
||||
}
|
||||
cmds.push(_undo);
|
||||
setTitle(_undo);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.exec = function() {
|
||||
var redo = fm.getCommand('redo'),
|
||||
dfd = $.Deferred(),
|
||||
undo, res, _redo = {};
|
||||
if (cmds.length) {
|
||||
undo = cmds.pop();
|
||||
if (undo.redo) {
|
||||
Object.assign(_redo, undo.redo);
|
||||
delete undo.redo;
|
||||
} else {
|
||||
_redo = null;
|
||||
}
|
||||
dfd.done(function() {
|
||||
if (_redo) {
|
||||
redo.setRedo(_redo, undo);
|
||||
}
|
||||
});
|
||||
|
||||
setTitle(cmds.length? cmds[cmds.length-1] : void(0));
|
||||
|
||||
res = undo.callback();
|
||||
|
||||
if (res && res.done) {
|
||||
res.done(function() {
|
||||
dfd.resolve();
|
||||
}).fail(function() {
|
||||
dfd.reject();
|
||||
});
|
||||
} else {
|
||||
dfd.resolve();
|
||||
}
|
||||
if (cmds.length) {
|
||||
this.update(0, cmds[cmds.length - 1].name);
|
||||
} else {
|
||||
this.update(-1, '');
|
||||
}
|
||||
} else {
|
||||
dfd.reject();
|
||||
}
|
||||
return dfd;
|
||||
};
|
||||
|
||||
fm.bind('exec', function(e) {
|
||||
var data = e.data || {};
|
||||
if (data.opts && data.opts._userAction) {
|
||||
if (data.dfrd && data.dfrd.done) {
|
||||
data.dfrd.done(function(res) {
|
||||
if (res && res.undo && res.redo) {
|
||||
res.undo.redo = res.redo;
|
||||
self.setUndo(res.undo);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @class elFinder command "redo"
|
||||
* Redo previous commands
|
||||
*
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
elFinder.prototype.commands.redo = function() {
|
||||
"use strict";
|
||||
var self = this,
|
||||
fm = this.fm,
|
||||
setTitle = function(redo) {
|
||||
if (redo && redo.callback) {
|
||||
self.title = fm.i18n('cmdredo') + ' ' + fm.i18n('cmd'+redo.cmd);
|
||||
self.state = 0;
|
||||
} else {
|
||||
self.title = fm.i18n('cmdredo');
|
||||
self.state = -1;
|
||||
}
|
||||
self.change();
|
||||
},
|
||||
cmds = [];
|
||||
|
||||
this.alwaysEnabled = true;
|
||||
this.updateOnSelect = false;
|
||||
this.shortcuts = [{
|
||||
pattern : 'shift+ctrl+z ctrl+y'
|
||||
}];
|
||||
this.syncTitleOnChange = true;
|
||||
|
||||
this.getstate = function() {
|
||||
return cmds.length? 0 : -1;
|
||||
};
|
||||
|
||||
this.setRedo = function(redo, undo) {
|
||||
if (redo === null) {
|
||||
cmds = [];
|
||||
setTitle();
|
||||
} else {
|
||||
if (redo && redo.cmd && redo.callback) {
|
||||
if (undo) {
|
||||
redo.undo = undo;
|
||||
}
|
||||
cmds.push(redo);
|
||||
setTitle(redo);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.exec = function() {
|
||||
var undo = fm.getCommand('undo'),
|
||||
dfd = $.Deferred(),
|
||||
redo, res, _undo = {}, _redo = {};
|
||||
if (cmds.length) {
|
||||
redo = cmds.pop();
|
||||
if (redo.undo) {
|
||||
Object.assign(_undo, redo.undo);
|
||||
Object.assign(_redo, redo);
|
||||
delete _redo.undo;
|
||||
dfd.done(function() {
|
||||
undo.setUndo(_undo, _redo);
|
||||
});
|
||||
}
|
||||
|
||||
setTitle(cmds.length? cmds[cmds.length-1] : void(0));
|
||||
|
||||
res = redo.callback();
|
||||
|
||||
if (res && res.done) {
|
||||
res.done(function() {
|
||||
dfd.resolve();
|
||||
}).fail(function() {
|
||||
dfd.reject();
|
||||
});
|
||||
} else {
|
||||
dfd.resolve();
|
||||
}
|
||||
return dfd;
|
||||
} else {
|
||||
return dfd.reject();
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @class elFinder command "up"
|
||||
* Go into parent directory
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
(elFinder.prototype.commands.up = function() {
|
||||
"use strict";
|
||||
this.alwaysEnabled = true;
|
||||
this.updateOnSelect = false;
|
||||
|
||||
this.shortcuts = [{
|
||||
pattern : 'ctrl+up'
|
||||
}];
|
||||
|
||||
this.getstate = function() {
|
||||
return this.fm.cwd().phash ? 0 : -1;
|
||||
};
|
||||
|
||||
this.exec = function() {
|
||||
var fm = this.fm,
|
||||
cwdhash = fm.cwd().hash;
|
||||
return this.fm.cwd().phash ? this.fm.exec('open', this.fm.cwd().phash).done(function() {
|
||||
fm.one('opendone', function() {
|
||||
fm.selectfiles({files : [cwdhash]});
|
||||
});
|
||||
}) : $.Deferred().reject();
|
||||
};
|
||||
|
||||
}).prototype = { forceLoad : true }; // this is required command
|
||||
@@ -0,0 +1,423 @@
|
||||
/**
|
||||
* @class elFinder command "upload"
|
||||
* Upload files using iframe or XMLHttpRequest & FormData.
|
||||
* Dialog allow to send files using drag and drop
|
||||
*
|
||||
* @type elFinder.command
|
||||
* @author Dmitry (dio) Levashov
|
||||
*/
|
||||
elFinder.prototype.commands.upload = function() {
|
||||
"use strict";
|
||||
var hover = this.fm.res('class', 'hover');
|
||||
|
||||
this.disableOnSearch = true;
|
||||
this.updateOnSelect = false;
|
||||
|
||||
// Shortcut opens dialog
|
||||
this.shortcuts = [{
|
||||
pattern : 'ctrl+u'
|
||||
}];
|
||||
|
||||
/**
|
||||
* Return command state
|
||||
*
|
||||
* @return Number
|
||||
**/
|
||||
this.getstate = function(select) {
|
||||
var fm = this.fm, f,
|
||||
sel = (select || [fm.cwd().hash]);
|
||||
if (!this._disabled && sel.length == 1) {
|
||||
f = fm.file(sel[0]);
|
||||
}
|
||||
return (f && f.mime == 'directory' && f.write)? 0 : -1;
|
||||
};
|
||||
|
||||
|
||||
this.exec = function(data) {
|
||||
var fm = this.fm,
|
||||
cwdHash = fm.cwd().hash,
|
||||
getTargets = function() {
|
||||
var tgts = data && (data instanceof Array)? data : null,
|
||||
sel;
|
||||
if (! data || data instanceof Array) {
|
||||
if (! tgts && (sel = fm.selected()).length === 1 && fm.file(sel[0]).mime === 'directory') {
|
||||
tgts = sel;
|
||||
} else if (!tgts || tgts.length !== 1 || fm.file(tgts[0]).mime !== 'directory') {
|
||||
tgts = [ cwdHash ];
|
||||
}
|
||||
}
|
||||
return tgts;
|
||||
},
|
||||
targets = getTargets(),
|
||||
check = targets? targets[0] : (data && data.target? data.target : null),
|
||||
targetDir = check? fm.file(check) : fm.cwd(),
|
||||
fmUpload = function(data) {
|
||||
fm.upload(data)
|
||||
.fail(function(error) {
|
||||
dfrd.reject(error);
|
||||
})
|
||||
.done(function(data) {
|
||||
var cwd = fm.getUI('cwd'),
|
||||
node;
|
||||
dfrd.resolve(data);
|
||||
if (data && data.added && data.added[0] && ! fm.ui.notify.children('.elfinder-notify-upload').length) {
|
||||
var newItem = fm.findCwdNodes(data.added);
|
||||
if (newItem.length) {
|
||||
newItem.trigger('scrolltoview');
|
||||
} else {
|
||||
if (targetDir.hash !== cwdHash) {
|
||||
node = $('<div></div>').append(
|
||||
$('<button type="button" class="ui-button ui-widget ui-state-default ui-corner-all elfinder-tabstop"><span class="ui-button-text">'+fm.i18n('cmdopendir')+'</span></button>')
|
||||
.on('mouseenter mouseleave', function(e) {
|
||||
$(this).toggleClass('ui-state-hover', e.type == 'mouseenter');
|
||||
}).on('click', function() {
|
||||
fm.exec('open', check).done(function() {
|
||||
fm.one('opendone', function() {
|
||||
fm.trigger('selectfiles', {files : $.map(data.added, function(f) {return f.hash;})});
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
} else {
|
||||
fm.trigger('selectfiles', {files : $.map(data.added, function(f) {return f.hash;})});
|
||||
}
|
||||
fm.toast({msg: fm.i18n(['complete', fm.i18n('cmdupload')]), extNode: node});
|
||||
}
|
||||
}
|
||||
})
|
||||
.progress(function() {
|
||||
dfrd.notifyWith(this, Array.from(arguments));
|
||||
});
|
||||
},
|
||||
upload = function(data) {
|
||||
dialog.elfinderdialog('close');
|
||||
if (targets) {
|
||||
data.target = targets[0];
|
||||
}
|
||||
fmUpload(data);
|
||||
},
|
||||
getSelector = function() {
|
||||
var hash = targetDir.hash,
|
||||
dirs = $.map(fm.files(hash), function(f) {
|
||||
return (f.mime === 'directory' && f.write)? f : null;
|
||||
});
|
||||
|
||||
if (! dirs.length) {
|
||||
return $();
|
||||
}
|
||||
|
||||
return $('<div class="elfinder-upload-dirselect elfinder-tabstop" title="' + fm.i18n('folders') + '"></div>')
|
||||
.on('click', function(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
dirs = fm.sortFiles(dirs);
|
||||
var $this = $(this),
|
||||
cwd = fm.cwd(),
|
||||
base = dialog.closest('div.ui-dialog'),
|
||||
getRaw = function(f, icon) {
|
||||
return {
|
||||
label : fm.escape(f.i18 || f.name),
|
||||
icon : icon,
|
||||
remain : false,
|
||||
callback : function() {
|
||||
var title = base.children('.ui-dialog-titlebar:first').find('span.elfinder-upload-target');
|
||||
targets = [ f.hash ];
|
||||
title.html(' - ' + fm.escape(f.i18 || f.name));
|
||||
$this.trigger('focus');
|
||||
},
|
||||
options : {
|
||||
className : (targets && targets.length && f.hash === targets[0])? 'ui-state-active' : '',
|
||||
iconClass : f.csscls || '',
|
||||
iconImg : f.icon || ''
|
||||
}
|
||||
};
|
||||
},
|
||||
raw = [ getRaw(targetDir, 'opendir'), '|' ];
|
||||
$.each(dirs, function(i, f) {
|
||||
raw.push(getRaw(f, 'dir'));
|
||||
});
|
||||
$this.trigger('blur');
|
||||
fm.trigger('contextmenu', {
|
||||
raw: raw,
|
||||
x: e.pageX || $(this).offset().left,
|
||||
y: e.pageY || $(this).offset().top,
|
||||
prevNode: base,
|
||||
fitHeight: true
|
||||
});
|
||||
}).append('<span class="elfinder-button-icon elfinder-button-icon-dir" ></span>');
|
||||
},
|
||||
inputButton = function(type, caption) {
|
||||
var button,
|
||||
input = $('<input type="file" ' + type + '/>')
|
||||
.on('click', function() {
|
||||
// for IE's bug
|
||||
if (fm.UA.IE) {
|
||||
setTimeout(function() {
|
||||
form.css('display', 'none').css('position', 'relative');
|
||||
requestAnimationFrame(function() {
|
||||
form.css('display', '').css('position', '');
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
})
|
||||
.on('change', function() {
|
||||
upload({input : input.get(0), type : 'files'});
|
||||
})
|
||||
.on('dragover', function(e) {
|
||||
e.originalEvent.dataTransfer.dropEffect = 'copy';
|
||||
}),
|
||||
form = $('<form></form>').append(input).on('click', function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
return $('<div class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only elfinder-tabstop elfinder-focus"><span class="ui-button-text">'+fm.i18n(caption)+'</span></div>')
|
||||
.append(form)
|
||||
.on('click', function(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
input.trigger('click');
|
||||
})
|
||||
.on('mouseenter mouseleave', function(e) {
|
||||
$(this).toggleClass(hover, e.type === 'mouseenter');
|
||||
});
|
||||
},
|
||||
dfrd = $.Deferred(),
|
||||
dialog, dropbox, pastebox, dropUpload, paste, dirs, spinner, uidialog;
|
||||
|
||||
dropUpload = function(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
var file = false,
|
||||
type = '',
|
||||
elfFrom = null,
|
||||
mycwd = '',
|
||||
data = null,
|
||||
target = e._target || null,
|
||||
trf = e.dataTransfer || null,
|
||||
kind = '',
|
||||
idx, errors;
|
||||
|
||||
if (trf) {
|
||||
if (trf.types && trf.types.length) {
|
||||
if ((idx = $.inArray('application/x-moz-file', trf.types)) !== -1) {
|
||||
kind = 'file';
|
||||
} else if ((idx = $.inArray('Files', trf.types)) !== -1) {
|
||||
kind = 'file';
|
||||
}
|
||||
}
|
||||
else if (trf.items && trf.items.length && trf.items[0].kind) {
|
||||
kind = trf.items[0].kind;
|
||||
}
|
||||
|
||||
try {
|
||||
elfFrom = trf.getData('elfinderfrom');
|
||||
if (elfFrom) {
|
||||
mycwd = window.location.href + fm.cwd().hash;
|
||||
if ((!target && elfFrom === mycwd) || target === mycwd) {
|
||||
dfrd.reject();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch(e) {}
|
||||
|
||||
if (kind === 'file' && (trf.items[idx].getAsEntry || trf.items[idx].webkitGetAsEntry || trf.items[idx].getAsFile)) {
|
||||
file = trf;
|
||||
type = 'data';
|
||||
} else if (kind !== 'string' && trf.files && trf.files.length && $.inArray('Text', trf.types) === -1) {
|
||||
file = trf.files;
|
||||
type = 'files';
|
||||
} else {
|
||||
try {
|
||||
if ((data = trf.getData('text/html')) && data.match(/<(?:img|a)/i)) {
|
||||
file = [ data ];
|
||||
type = 'html';
|
||||
}
|
||||
} catch(e) {}
|
||||
if (! file) {
|
||||
if (data = trf.getData('text')) {
|
||||
file = [ data ];
|
||||
type = 'text';
|
||||
} else if (trf && trf.files) {
|
||||
// maybe folder uploading but this UA dose not support it
|
||||
kind = 'file';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (file) {
|
||||
fmUpload({files : file, type : type, target : target, dropEvt : e});
|
||||
} else {
|
||||
errors = ['errUploadNoFiles'];
|
||||
if (kind === 'file') {
|
||||
errors.push('errFolderUpload');
|
||||
}
|
||||
fm.error(errors);
|
||||
dfrd.reject();
|
||||
}
|
||||
};
|
||||
|
||||
if (!targets && data) {
|
||||
if (data.input || data.files) {
|
||||
data.type = 'files';
|
||||
fmUpload(data);
|
||||
} else if (data.dropEvt) {
|
||||
dropUpload(data.dropEvt);
|
||||
}
|
||||
return dfrd;
|
||||
}
|
||||
|
||||
paste = function(ev) {
|
||||
var e = ev.originalEvent || ev;
|
||||
var files = [], items = [];
|
||||
var file;
|
||||
if (e.clipboardData) {
|
||||
if (e.clipboardData.items && e.clipboardData.items.length){
|
||||
items = e.clipboardData.items;
|
||||
for (var i=0; i < items.length; i++) {
|
||||
if (e.clipboardData.items[i].kind == 'file') {
|
||||
file = e.clipboardData.items[i].getAsFile();
|
||||
files.push(file);
|
||||
}
|
||||
}
|
||||
} else if (e.clipboardData.files && e.clipboardData.files.length) {
|
||||
files = e.clipboardData.files;
|
||||
}
|
||||
if (files.length) {
|
||||
upload({files : files, type : 'files', clipdata : true});
|
||||
return;
|
||||
}
|
||||
}
|
||||
var my = e.target || e.srcElement;
|
||||
requestAnimationFrame(function() {
|
||||
var type = 'text',
|
||||
src;
|
||||
if (my.innerHTML) {
|
||||
$(my).find('img').each(function(i, v){
|
||||
if (v.src.match(/^webkit-fake-url:\/\//)) {
|
||||
// For Safari's bug.
|
||||
// ref. https://bugs.webkit.org/show_bug.cgi?id=49141
|
||||
// https://dev.ckeditor.com/ticket/13029
|
||||
$(v).remove();
|
||||
}
|
||||
});
|
||||
|
||||
if ($(my).find('a,img').length) {
|
||||
type = 'html';
|
||||
}
|
||||
src = my.innerHTML;
|
||||
my.innerHTML = '';
|
||||
upload({files : [ src ], type : type});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
dialog = $('<div class="elfinder-upload-dialog-wrapper"></div>')
|
||||
.append(inputButton('multiple', 'selectForUpload'));
|
||||
|
||||
if (! fm.UA.Mobile && (function(input) {
|
||||
return (typeof input.webkitdirectory !== 'undefined' || typeof input.directory !== 'undefined');})(document.createElement('input'))) {
|
||||
dialog.append(inputButton('multiple webkitdirectory directory', 'selectFolder'));
|
||||
}
|
||||
|
||||
if (targetDir.dirs) {
|
||||
|
||||
if (targetDir.hash === cwdHash || fm.navHash2Elm(targetDir.hash).hasClass('elfinder-subtree-loaded')) {
|
||||
getSelector().appendTo(dialog);
|
||||
} else {
|
||||
spinner = $('<div class="elfinder-upload-dirselect" title="' + fm.i18n('nowLoading') + '"></div>')
|
||||
.append('<span class="elfinder-button-icon elfinder-button-icon-spinner" ></span>')
|
||||
.appendTo(dialog);
|
||||
fm.request({cmd : 'tree', target : targetDir.hash})
|
||||
.done(function() {
|
||||
fm.one('treedone', function() {
|
||||
spinner.replaceWith(getSelector());
|
||||
uidialog.elfinderdialog('tabstopsInit');
|
||||
});
|
||||
})
|
||||
.fail(function() {
|
||||
spinner.remove();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (fm.dragUpload) {
|
||||
dropbox = $('<div class="ui-corner-all elfinder-upload-dropbox elfinder-tabstop" contenteditable="true" data-ph="'+fm.i18n('dropPasteFiles')+'"></div>')
|
||||
.on('paste', function(e){
|
||||
paste(e);
|
||||
})
|
||||
.on('mousedown click', function(){
|
||||
$(this).trigger('focus');
|
||||
})
|
||||
.on('focus', function(){
|
||||
this.innerHTML = '';
|
||||
})
|
||||
.on('mouseover', function(){
|
||||
$(this).addClass(hover);
|
||||
})
|
||||
.on('mouseout', function(){
|
||||
$(this).removeClass(hover);
|
||||
})
|
||||
.on('dragenter', function(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
$(this).addClass(hover);
|
||||
})
|
||||
.on('dragleave', function(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
$(this).removeClass(hover);
|
||||
})
|
||||
.on('dragover', function(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
e.originalEvent.dataTransfer.dropEffect = 'copy';
|
||||
$(this).addClass(hover);
|
||||
})
|
||||
.on('drop', function(e) {
|
||||
dialog.elfinderdialog('close');
|
||||
targets && (e.originalEvent._target = targets[0]);
|
||||
dropUpload(e.originalEvent);
|
||||
})
|
||||
.prependTo(dialog)
|
||||
.after('<div class="elfinder-upload-dialog-or">'+fm.i18n('or')+'</div>')[0];
|
||||
|
||||
} else {
|
||||
pastebox = $('<div class="ui-corner-all elfinder-upload-dropbox" contenteditable="true">'+fm.i18n('dropFilesBrowser')+'</div>')
|
||||
.on('paste drop', function(e){
|
||||
paste(e);
|
||||
})
|
||||
.on('mousedown click', function(){
|
||||
$(this).trigger('focus');
|
||||
})
|
||||
.on('focus', function(){
|
||||
this.innerHTML = '';
|
||||
})
|
||||
.on('dragenter mouseover', function(){
|
||||
$(this).addClass(hover);
|
||||
})
|
||||
.on('dragleave mouseout', function(){
|
||||
$(this).removeClass(hover);
|
||||
})
|
||||
.prependTo(dialog)
|
||||
.after('<div class="elfinder-upload-dialog-or">'+fm.i18n('or')+'</div>')[0];
|
||||
|
||||
}
|
||||
|
||||
uidialog = this.fmDialog(dialog, {
|
||||
title : this.title + '<span class="elfinder-upload-target">' + (targetDir? ' - ' + fm.escape(targetDir.i18 || targetDir.name) : '') + '</span>',
|
||||
modal : true,
|
||||
resizable : false,
|
||||
destroyOnClose : true,
|
||||
propagationEvents : ['mousemove', 'mouseup', 'click'],
|
||||
close : function() {
|
||||
var cm = fm.getUI('contextmenu');
|
||||
if (cm.is(':visible')) {
|
||||
cm.click();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return dfrd;
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* @class elFinder command "view"
|
||||
* Change current directory view (icons/list)
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
elFinder.prototype.commands.view = function() {
|
||||
"use strict";
|
||||
var self = this,
|
||||
fm = this.fm,
|
||||
subMenuRaw;
|
||||
this.value = fm.viewType;
|
||||
this.alwaysEnabled = true;
|
||||
this.updateOnSelect = false;
|
||||
|
||||
this.options = { ui : 'viewbutton'};
|
||||
|
||||
this.getstate = function() {
|
||||
return 0;
|
||||
};
|
||||
|
||||
this.extra = {
|
||||
icon: 'menu',
|
||||
node: $('<span></span>')
|
||||
.attr({title: fm.i18n('viewtype')})
|
||||
.on('click touchstart', function(e){
|
||||
if (e.type === 'touchstart' && e.originalEvent.touches.length > 1) {
|
||||
return;
|
||||
}
|
||||
var node = $(this);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
fm.trigger('contextmenu', {
|
||||
raw: getSubMenuRaw(),
|
||||
x: node.offset().left,
|
||||
y: node.offset().top
|
||||
});
|
||||
})
|
||||
};
|
||||
|
||||
this.exec = function() {
|
||||
var self = this,
|
||||
value = this.value == 'list' ? 'icons' : 'list';
|
||||
|
||||
fm.storage('view', value);
|
||||
return fm.lazy(function() {
|
||||
fm.viewchange();
|
||||
self.update(void(0), value);
|
||||
this.resolve();
|
||||
});
|
||||
};
|
||||
|
||||
fm.bind('init', function() {
|
||||
subMenuRaw = (function() {
|
||||
var cwd = fm.getUI('cwd'),
|
||||
raws = [],
|
||||
sizeNames = fm.options.uiOptions.cwd.iconsView.sizeNames,
|
||||
max = fm.options.uiOptions.cwd.iconsView.sizeMax,
|
||||
i, size;
|
||||
for (i = 0; i <= max; i++) {
|
||||
raws.push(
|
||||
{
|
||||
label : fm.i18n(sizeNames[i] || ('Size-' + i + ' icons')),
|
||||
icon : 'view',
|
||||
callback : (function(s) {
|
||||
return function() {
|
||||
cwd.trigger('iconpref', {size: s});
|
||||
fm.storage('iconsize', s);
|
||||
if (self.value === 'list') {
|
||||
self.exec();
|
||||
}
|
||||
};
|
||||
})(i)
|
||||
}
|
||||
);
|
||||
}
|
||||
raws.push('|');
|
||||
raws.push(
|
||||
{
|
||||
label : fm.i18n('viewlist'),
|
||||
icon : 'view-list',
|
||||
callback : function() {
|
||||
if (self.value !== 'list') {
|
||||
self.exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
return raws;
|
||||
})();
|
||||
}).bind('contextmenucreate', function() {
|
||||
self.extra = {
|
||||
icon: 'menu',
|
||||
node: $('<span></span>')
|
||||
.attr({title: fm.i18n('cmdview')})
|
||||
.on('click touchstart', function(e){
|
||||
if (e.type === 'touchstart' && e.originalEvent.touches.length > 1) {
|
||||
return;
|
||||
}
|
||||
var node = $(this),
|
||||
raw = subMenuRaw.concat(),
|
||||
idx, i;
|
||||
if (self.value === 'list') {
|
||||
idx = subMenuRaw.length - 1;
|
||||
} else {
|
||||
idx = parseInt(fm.storage('iconsize') || 0);
|
||||
}
|
||||
for (i = 0; i < subMenuRaw.length; i++) {
|
||||
if (subMenuRaw[i] !== '|') {
|
||||
subMenuRaw[i].options = (i === idx? {'className': 'ui-state-active'} : void(0))
|
||||
;
|
||||
}
|
||||
}
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
fm.trigger('contextmenu', {
|
||||
raw: subMenuRaw,
|
||||
x: node.offset().left,
|
||||
y: node.offset().top
|
||||
});
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user