aDriv4 - MANAGER
Edit File: elFinder.ui.js
/** * @class elFinder user Interface. * @author dio dio@std42.ru **/ (function($) { elFinder.prototype.ui = function(fm) { var self = this; this.fm = fm; this.cmd = {}; this.buttons = {}; this.menu = $('<div class="el-finder-contextmenu" />').appendTo(document.body).hide(); this.dockButton = $('<div class="el-finder-dock-button" title="'+self.fm.i18n('Dock/undock filemanager window')+'" />'); this.exec = function(cmd, arg) { if (this.cmd[cmd]) { if (cmd != 'open' && !this.cmd[cmd].isAllowed()) { return this.fm.view.error('Command not allowed'); } if (!this.fm.locked) { this.fm.quickLook.hide(); $('.el-finder-info').remove(); this.cmd[cmd].exec(arg); this.update(); } } } this.cmdName = function(cmd) { if (this.cmd[cmd] && this.cmd[cmd].name) { return cmd == 'archive' && this.fm.params.archives.length == 1 ? this.fm.i18n('Create')+' '+this.fm.view.mime2kind(this.fm.params.archives[0]).toLowerCase() : this.fm.i18n(this.cmd[cmd].name); } return cmd; } this.isCmdAllowed = function(cmd) { return self.cmd[cmd] && self.cmd[cmd].isAllowed(); } this.execIfAllowed = function(cmd) { this.isCmdAllowed(cmd) && this.exec(cmd); } this.includeInCm = function(cmd, t) { return this.isCmdAllowed(cmd) && this.cmd[cmd].cm(t); } this.showMenu = function(e) { var t, win, size, id = ''; this.hideMenu(); if (!self.fm.selected.length) { t = 'cwd'; } else if (self.fm.selected.length == 1) { t = 'file'; } else { t = 'group'; } menu(t); win = $(window); size = { height : win.height(), width : win.width(), sT : win.scrollTop(), cW : this.menu.width(), cH : this.menu.height() }; this.menu.css({ left : ((e.clientX + size.cW) > size.width ? ( e.clientX - size.cW) : e.clientX), top : ((e.clientY + size.cH) > size.height && e.clientY > size.cH ? (e.clientY + size.sT - size.cH) : e.clientY + size.sT) }) .show() .find('div[name]') .hover( function() { var t = $(this), s = t.children('div'), w; t.addClass('hover'); if (s.length) { if (!s.attr('pos')) { w = t.outerWidth(); s.css($(window).width() - w - t.offset().left > s.width() ? 'left' : 'right', w-5).attr('pos', true); } s.show(); } }, function() { $(this).removeClass('hover').children('div').hide(); } ).click(function(e) { e.stopPropagation(); var t = $(this); if (!t.children('div').length) { self.hideMenu(); self.exec(t.attr('name'), t.attr('argc')); } }); function menu(t) { var i, j, a, html, l, src = self.fm.options.contextmenu[t]||[]; for (i=0; i < src.length; i++) { if (src[i] == 'delim') { self.menu.children().length && !self.menu.children(':last').hasClass('delim') && self.menu.append('<div class="delim" />'); } else if (self.fm.ui.includeInCm(src[i], t)) { a = self.cmd[src[i]].argc(); html = ''; if (a.length) { html = '<span/><div class="el-finder-contextmenu-sub" style="z-index:'+(parseInt(self.menu.css('z-index'))+1)+'">'; for (var j=0; j < a.length; j++) { html += '<div name="'+src[i]+'" argc="'+a[j].argc+'" class="'+a[j]['class']+'">'+a[j].text+'</div>'; }; html += '</div>'; } self.menu.append('<div class="'+src[i]+'" name="'+src[i]+'">'+html+self.cmdName(src[i])+'</div>'); } }; } } this.hideMenu = function() { this.menu.hide().empty(); } this.update = function() { for (var i in this.buttons) { this.buttons[i].toggleClass('disabled', !this.cmd[i].isAllowed()); } } this.init = function(disabled) { var i, j, n, c=false, zindex = 2, z, t = this.fm.options.toolbar; /* disable select command if there is no callback for it */ if (!this.fm.options.editorCallback) { disabled.push('select'); } /* disable archive command if no archivers enabled */ if (!this.fm.params.archives.length && $.inArray('archive', disabled) == -1) { disabled.push('archive'); } for (i in this.commands) { if ($.inArray(i, disabled) == -1) { this.commands[i].prototype = this.command.prototype; this.cmd[i] = new this.commands[i](this.fm); } } for (i=0; i<t.length; i++) { if (c) { this.fm.view.tlb.append('<li class="delim" />'); } c = false; for (j=0; j<t[i].length; j++) { n = t[i][j]; if (this.cmd[n]) { c = true; this.buttons[n] = $('<li class="'+n+'" title="'+this.cmdName(n)+'" name="'+n+'" />') .appendTo(this.fm.view.tlb) .click(function(e) { e.stopPropagation(); }) .bind('click', (function(ui){ return function() { !$(this).hasClass('disabled') && ui.exec($(this).attr('name')); } })(this) ).hover( function() { !$(this).hasClass('disabled') && $(this).addClass('el-finder-tb-hover')}, function() { $(this).removeClass('el-finder-tb-hover')} ); } } } this.update(); /* set z-index for context menu */ this.menu.css('z-index', this.fm.zIndex); if (this.fm.options.docked) { this.dockButton.hover( function() { $(this).addClass('el-finder-dock-button-hover')}, function() { $(this).removeClass('el-finder-dock-button-hover')} ).click(function() { self.fm.view.win.attr('undocked') ? self.fm.dock() : self.fm.undock(); $(this).trigger('mouseout'); }).prependTo(this.fm.view.tlb); } } } /** * @class elFinder user Interface Command. * @author dio dio@std42.ru **/ elFinder.prototype.ui.prototype.command = function(fm) { } /** * Return true if command can be applied now * @return Boolean **/ elFinder.prototype.ui.prototype.command.prototype.isAllowed = function() { return true; } /** * Return true if command can be included in contextmenu of required type * @param String contextmenu type (cwd|group|file) * @return Boolean **/ elFinder.prototype.ui.prototype.command.prototype.cm = function(t) { return false; } /** * Return not empty array if command required submenu in contextmenu * @return Array **/ elFinder.prototype.ui.prototype.command.prototype.argc = function(t) { return []; } elFinder.prototype.ui.prototype.commands = { /** * @class Go into previous folder * @param Object elFinder **/ back : function(fm) { var self = this; this.name = 'Back'; this.fm = fm; this.exec = function() { if (this.fm.history.length) { this.fm.ajax({ cmd : 'open', target : this.fm.history.pop() }, function(data) { self.fm.reload(data); }); } } this.isAllowed = function() { return this.fm.history.length } }, /** * @class Reload current directory and navigation panel * @param Object elFinder **/ reload : function(fm) { var self = this; this.name = 'Reload'; this.fm = fm; this.exec = function() { this.fm.ajax({ cmd : 'open', target : this.fm.cwd.hash, tree : true }, function(data) { self.fm.reload(data); }); } this.cm = function(t) { return t == 'cwd'; } }, /** * @class Open file/folder * @param Object elFinder **/ open : function(fm) { var self = this; this.name = 'Open'; this.fm = fm; /** * Open file/folder * @param String file/folder id (only from click on nav tree) **/ this.exec = function(dir) { var t = null; if (dir) { t = { hash : $(dir).attr('key'), mime : 'directory', read : !$(dir).hasClass('noaccess') && !$(dir).hasClass('dropbox') } } else { t = this.fm.getSelected(0); } if (!t.hash) { return; } if (!t.read) { return this.fm.view.error('Access denied'); } if (t.type == 'link' && !t.link) { return this.fm.view.error('Unable to open broken link'); } if (t.mime == 'directory') { openDir(t.link||t.hash); } else { openFile(t); } function openDir(id) { self.fm.history.push(self.fm.cwd.hash); self.fm.ajax({ cmd : 'open', target : id }, function(data) { self.fm.reload(data); }); } function openFile(f) { var s, ws = ''; if (f.dim) { s = f.dim.split('x'); ws = 'width='+(parseInt(s[0])+20)+',height='+(parseInt(s[1])+20)+','; } window.open(f.url||self.fm.options.url+'?cmd=open¤t='+(f.parent||self.fm.cwd.hash)+'&target='+(f.link||f.hash), false, 'top=50,left=50,'+ws+'scrollbars=yes,resizable=yes'); } } this.isAllowed = function() { return this.fm.selected.length == 1 && this.fm.getSelected(0).read; } this.cm = function(t) { return t == 'file'; } }, /** * @class. Return file url * @param Object elFinder **/ select : function(fm) { this.name = 'Select file'; this.fm = fm; if (fm.options.selectMultiple) { this.exec = function() { var selected = $(fm.getSelected()).map(function() { return fm.options.cutURL == 'root' ? this.url.substr(fm.params.url.length) : this.url.replace(new RegExp('^('+fm.options.cutURL+')'), ''); }); fm.options.editorCallback(selected); if (fm.options.closeOnEditorCallback) { fm.dock(); fm.close(); } } } else { this.exec = function() { var f = this.fm.getSelected(0); if (!f.url) { return this.fm.view.error('File URL disabled by connector config'); } this.fm.options.editorCallback(this.fm.options.cutURL == 'root' ? f.url.substr(this.fm.params.url.length) : f.url.replace(new RegExp('^('+this.fm.options.cutURL+')'), '')); if (this.fm.options.closeOnEditorCallback) { this.fm.dock(); this.fm.close(); this.fm.destroy(); } } } this.isAllowed = function() { return ((this.fm.options.selectMultiple && this.fm.selected.length >= 1) || this.fm.selected.length == 1) && !/(symlink\-broken|directory)/.test(this.fm.getSelected(0).mime); } this.cm = function(t) { return t != 'cwd'; // return t == 'file'; } }, /** * @class. Open/close quickLook window * @param Object elFinder **/ quicklook : function(fm) { var self = this; this.name = 'Preview with Quick Look'; this.fm = fm; this.exec = function() { self.fm.quickLook.toggle(); } this.isAllowed = function() { return this.fm.selected.length == 1; } this.cm = function() { return true; } }, /** * @class Display files/folders info in dialog window * @param Object elFinder **/ info : function(fm) { var self = this; this.name = 'Get info'; this.fm = fm; /** * Open dialog windows for each selected file/folder or for current folder **/ this.exec = function() { var f, s, cnt = this.fm.selected.length, w = $(window).width(), h = $(window).height(); this.fm.lockShortcuts(true); if (!cnt) { /** nothing selected - show cwd info **/ info(self.fm.cwd); } else { /** show info for each selected obj **/ $.each(this.fm.getSelected(), function() { info(this); }); } function info(f) { var p = ['50%', '50%'], x, y, d, tb = '<table cellspacing="0"><tr><td>'+self.fm.i18n('Name')+'</td><td>'+f.name+'</td></tr><tr><td>'+self.fm.i18n('Kind')+'</td><td>'+self.fm.view.mime2kind(f.link ? 'symlink' : f.mime)+'</td></tr><tr><td>'+self.fm.i18n('Size')+'</td><td>'+self.fm.view.formatSize(f.size)+'</td></tr><tr><td>'+self.fm.i18n('Modified')+'</td><td>'+self.fm.view.formatDate(f.date)+'</td></tr><tr><td>'+self.fm.i18n('Permissions')+'</td><td>'+self.fm.view.formatPermissions(f.read, f.write, f.rm)+'</td></tr>'; if (f.link) { tb += '<tr><td>'+self.fm.i18n('Link to')+'</td><td>'+f.linkTo+'</td></tr>'; } if (f.dim) { tb += '<tr><td>'+self.fm.i18n('Dimensions')+'</td><td>'+f.dim+' px.</td></tr>'; } if (f.url) { tb += '<tr><td>'+self.fm.i18n('URL')+'</td><td><a href="'+f.url+'" target="_blank">'+f.url+'</a></td></tr>'; } if (cnt>1) { d = $('.el-finder-dialog-info:last'); if (!d.length) { x = Math.round(((w-350)/2)-(cnt*10)); y = Math.round(((h-300)/2)-(cnt*10)); p = [x>20?x:20, y>20?y:20]; } else { x = d.offset().left+10; y = d.offset().top+10; p = [x<w-350 ? x : 20, y<h-300 ? y : 20]; } } $('<div />').append(tb+'</table>').dialog({ dialogClass : 'el-finder-dialog el-finder-dialog-info', width : 390, position : p, title : self.fm.i18n(f.mime == 'directory' ? 'Folder info' : 'File info'), close : function() { if (--cnt <= 0) { self.fm.lockShortcuts(); } $(this).dialog('destroy'); }, buttons : { Ok : function() { $(this).dialog('close'); }} }); } } this.cm = function(t) { return true; } }, /** * @class Rename file/folder * @param Object elFinder **/ rename : function(fm) { var self = this; this.name = 'Rename'; this.fm = fm; this.exec = function() { var s = this.fm.getSelected(), el, c, input, f, n; if (s.length == 1) { f = s[0]; el = this.fm.view.cwd.find('[key="'+f.hash+'"]'); c = this.fm.options.view == 'icons' ? el.children('label') : el.find('td').eq(1); n = c.html(); input = $('<input type="text" />').val(f.name).appendTo(c.empty()) .bind('change blur', rename) .keydown(function(e) { e.stopPropagation(); if (e.keyCode == 27) { restore(); } else if (e.keyCode == 13) { if (f.name == input.val()) { restore(); } else { $(this).trigger('change'); } } }) .click(function(e) { e.stopPropagation(); }) .select() .focus(); this.fm.lockShortcuts(true); } function restore() { c.html(n); self.fm.lockShortcuts(); } function rename() { if (!self.fm.locked) { var err, name = input.val(); if (f.name == input.val()) { return restore(); } if (!self.fm.isValidName(name)) { err = 'Invalid name'; } else if (self.fm.fileExists(name)) { err = 'File or folder with the same name already exists'; } if (err) { self.fm.view.error(err); el.addClass('ui-selected'); self.fm.lockShortcuts(true); return input.select().focus(); } self.fm.ajax({cmd : 'rename', current : self.fm.cwd.hash, target : f.hash, name : name}, function(data) { if (data.error) { restore(); } else { f.mime == 'directory' && self.fm.removePlace(f.hash) && self.fm.addPlace(data.target); self.fm.reload(data); } }, { force : true }); } } } /** * Return true if only one file selected and has write perms and current dir has write perms * @return Boolean */ this.isAllowed = function() { return this.fm.cwd.write && this.fm.getSelected(0).write; } this.cm = function(t) { return t == 'file'; } }, /** * @class Copy file/folder to "clipboard" * @param Object elFinder **/ copy : function(fm) { this.name = 'Copy'; this.fm = fm; this.exec = function() { this.fm.setBuffer(this.fm.selected); } this.isAllowed = function() { if (this.fm.selected.length) { var s = this.fm.getSelected(), l = s.length; while (l--) { if (s[l].read) { return true; } } } return false; } this.cm = function(t) { return t != 'cwd'; } }, /** * @class Cut file/folder to "clipboard" * @param Object elFinder **/ cut : function(fm) { this.name = 'Cut'; this.fm = fm; this.exec = function() { this.fm.setBuffer(this.fm.selected, 1); } this.isAllowed = function() { if (this.fm.selected.length) { var s = this.fm.getSelected(), l = s.length; while (l--) { if (s[l].read && s[l].rm) { return true; } } } return false; } this.cm = function(t) { return t != 'cwd'; } }, /** * @class Paste file/folder from "clipboard" * @param Object elFinder **/ paste : function(fm) { var self = this; this.name = 'Paste'; this.fm = fm; this.exec = function() { var i, d, f, r, msg = ''; if (!this.fm.buffer.dst) { this.fm.buffer.dst = this.fm.cwd.hash; } d = this.fm.view.tree.find('[key="'+this.fm.buffer.dst+'"]'); if (!d.length || d.hasClass('noaccess') || d.hasClass('readonly')) { return this.fm.view.error('Access denied'); } if (this.fm.buffer.src == this.fm.buffer.dst) { return this.fm.view.error('Unable to copy into itself'); } var o = { cmd : 'paste', current : this.fm.cwd.hash, src : this.fm.buffer.src, dst : this.fm.buffer.dst, cut : this.fm.buffer.cut }; if (this.fm.jquery>132) { o.targets = this.fm.buffer.files; } else { o['targets[]'] = this.fm.buffer.files; } this.fm.ajax(o, function(data) { data.cdc && self.fm.reload(data); }, {force : true}); } this.isAllowed = function() { return this.fm.buffer.files; } this.cm = function(t) { return t == 'cwd'; } }, /** * @class Remove files/folders * @param Object elFinder **/ rm : function(fm) { var self = this; this.name = 'Remove'; this.fm = fm; this.exec = function() { var i, ids = [], s =this.fm.getSelected(); for (var i=0; i < s.length; i++) { if (!s[i].rm) { return this.fm.view.error(s[i].name+': '+this.fm.i18n('Access denied')); } ids.push(s[i].hash); }; if (ids.length) { this.fm.lockShortcuts(true); $('<div><div class="ui-state-error ui-corner-all"><span class="ui-icon ui-icon-alert"/><strong>'+this.fm.i18n('Are you sure you want to remove files?<br /> This cannot be undone!')+'</strong></div></div>') .dialog({ title : this.fm.i18n('Confirmation required'), dialogClass : 'el-finder-dialog', width : 350, close : function() { self.fm.lockShortcuts(); }, buttons : { Cancel : function() { $(this).dialog('close'); }, Ok : function() { $(this).dialog('close'); var o = { cmd : 'rm', current : self.fm.cwd.hash }; if (self.fm.jquery > 132) { o.targets = ids; } else { o['targets[]'] = ids; } self.fm.ajax(o, function(data) { data.tree && self.fm.reload(data); }, {force : true}); } } }); } } this.isAllowed = function(f) { if (this.fm.selected.length) { var s = this.fm.getSelected(), l = s.length; while (l--) { if (s[l].rm) { return true; } } } return false; } this.cm = function(t) { return t != 'cwd'; } }, /** * @class Create new folder * @param Object elFinder **/ mkdir : function(fm) { var self = this; this.name = 'New folder'; this.fm = fm; this.exec = function() { self.fm.unselectAll(); var n = this.fm.uniqueName('untitled folder'); input = $('<input type="text"/>').val(n); prev = this.fm.view.cwd.find('.directory:last'); f = {name : n, hash : '', mime :'directory', read : true, write : true, date : '', size : 0}, el = this.fm.options.view == 'list' ? $(this.fm.view.renderRow(f)).children('td').eq(1).empty().append(input).end().end() : $(this.fm.view.renderIcon(f)).children('label').empty().append(input).end() el.addClass('directory ui-selected'); if (prev.length) { el.insertAfter(prev); } else if (this.fm.options.view == 'list') { el.insertAfter(this.fm.view.cwd.find('tr').eq(0)) } else { el.prependTo(this.fm.view.cwd) } self.fm.checkSelectedPos(); input.select().focus() .click(function(e) { e.stopPropagation(); }) .bind('change blur', mkdir) .keydown(function(e) { e.stopPropagation(); if (e.keyCode == 27) { el.remove(); self.fm.lockShortcuts(); } else if (e.keyCode == 13) { mkdir(); } }); self.fm.lockShortcuts(true); function mkdir() { if (!self.fm.locked) { var err, name = input.val(); if (!self.fm.isValidName(name)) { err = 'Invalid name'; } else if (self.fm.fileExists(name)) { err = 'File or folder with the same name already exists'; } if (err) { self.fm.view.error(err); self.fm.lockShortcuts(true); el.addClass('ui-selected'); return input.select().focus(); } self.fm.ajax({cmd : 'mkdir', current : self.fm.cwd.hash, name : name}, function(data) { if (data.error) { el.addClass('ui-selected'); return input.select().focus(); } self.fm.reload(data); }, {force : true}); } } } this.isAllowed = function() { return this.fm.cwd.write; } this.cm = function(t) { return t == 'cwd'; } }, /** * @class Create new text file * @param Object elFinder **/ mkfile : function(fm) { var self = this; this.name = 'New text file'; this.fm = fm; this.exec = function() { self.fm.unselectAll(); var n = this.fm.uniqueName('untitled file', '.txt'), input = $('<input type="text"/>').val(n), f = {name : n, hash : '', mime :'text/plain', read : true, write : true, date : '', size : 0}, el = this.fm.options.view == 'list' ? $(this.fm.view.renderRow(f)).children('td').eq(1).empty().append(input).end().end() : $(this.fm.view.renderIcon(f)).children('label').empty().append(input).end(); el.addClass('text ui-selected').appendTo(this.fm.options.view == 'list' ? self.fm.view.cwd.children('table') : self.fm.view.cwd); input.select().focus() .bind('change blur', mkfile) .click(function(e) { e.stopPropagation(); }) .keydown(function(e) { e.stopPropagation(); if (e.keyCode == 27) { el.remove(); self.fm.lockShortcuts(); } else if (e.keyCode == 13) { mkfile(); } }); self.fm.lockShortcuts(true); function mkfile() { if (!self.fm.locked) { var err, name = input.val(); if (!self.fm.isValidName(name)) { err = 'Invalid name'; } else if (self.fm.fileExists(name)) { err = 'File or folder with the same name already exists'; } if (err) { self.fm.view.error(err); self.fm.lockShortcuts(true); el.addClass('ui-selected'); return input.select().focus(); } self.fm.ajax({cmd : 'mkfile', current : self.fm.cwd.hash, name : name}, function(data) { if (data.error) { el.addClass('ui-selected'); return input.select().focus(); } self.fm.reload(data); }, {force : true }); } } } this.isAllowed = function(f) { return this.fm.cwd.write; } this.cm = function(t) { return t == 'cwd'; } }, /** * @class Upload files * @param Object elFinder **/ upload : function(fm) { var self = this; this.name = 'Upload files'; this.fm = fm; this.exec = function() { var id = 'el-finder-io-'+(new Date().getTime()), e = $('<div class="ui-state-error ui-corner-all"><span class="ui-icon ui-icon-alert"/><div/></div>'), m = this.fm.params.uplMaxSize ? '<p>'+this.fm.i18n('Maximum allowed files size')+': '+this.fm.params.uplMaxSize+'</p>' : '', b = $('<p class="el-finder-add-field"><span class="ui-state-default ui-corner-all"><em class="ui-icon ui-icon-circle-plus"/></span>'+this.fm.i18n('Add field')+'</p>') .click(function() { $(this).before('<p><input type="file" name="upload[]"/></p>'); }), f = '<form method="post" enctype="multipart/form-data" action="'+self.fm.options.url+'" target="'+id+'"><input type="hidden" name="cmd" value="upload" /><input type="hidden" name="current" value="'+self.fm.cwd.hash+'" />', d = $('<div/>'), i = 3; while (i--) { f += '<p><input type="file" name="upload[]"/></p>'; } // Rails csrf meta tag (for XSS protection), see #256 var rails_csrf_token = $('meta[name=csrf-token]').attr('content'); var rails_csrf_param = $('meta[name=csrf-param]').attr('content'); if (rails_csrf_param != null && rails_csrf_token != null) { f += '<input name="'+rails_csrf_param+'" value="'+rails_csrf_token+'" type="hidden" />'; } f = $(f+'</form>'); d.append(f.append(e.hide()).prepend(m).append(b)).dialog({ dialogClass : 'el-finder-dialog', title : self.fm.i18n('Upload files'), modal : true, resizable : false, close : function() { self.fm.lockShortcuts(); }, buttons : { Cancel : function() { $(this).dialog('close'); }, Ok : function() { if (!$(':file[value]', f).length) { return error(self.fm.i18n('Select at least one file to upload')); } setTimeout(function() { self.fm.lock(); if ($.browser.safari) { $.ajax({ url : self.fm.options.url, data : {cmd : 'ping'}, error : submit, success : submit }); } else { submit(); } }); $(this).dialog('close'); } } }); self.fm.lockShortcuts(true); function error(err) { e.show().find('div').empty().text(err); } function submit() { var $io = $('<iframe name="'+id+'" name="'+id+'" src="about:blank"/>'), io = $io[0], cnt = 50, doc, html, data; $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' }) .appendTo('body').bind('load', function() { $io.unbind('load'); result(); }); self.fm.lock(true); f.submit(); function result() { try { doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document; /* opera */ if (doc.body == null || doc.body.innerHTML == '') { if (--cnt) { return setTimeout(result, 100); } else { complite(); return self.fm.view.error('Unable to access iframe DOM after 50 tries'); } } /* get server response */ html = $(doc.body).html(); if (self.fm.jquery>=141) { data = $.parseJSON(html); } else if ( /^[\],:{}\s]*$/.test(html.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@") .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]") .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) { /* get from jQuery 1.4 */ data = window.JSON && window.JSON.parse ? window.JSON.parse(html) : (new Function("return " + html))(); } else { data = { error : 'Unable to parse server response' }; } } catch(e) { data = { error : 'Unable to parse server response' }; } complite(); data.error && self.fm.view.error(data.error, data.errorData); data.cwd && self.fm.reload(data); data.tmb && self.fm.tmb(); } function complite() { self.fm.lock(); $io.remove(); } } } this.isAllowed = function() { return this.fm.cwd.write; } this.cm = function(t) { return t == 'cwd'; } }, /** * @class Make file/folder copy * @param Object elFinder **/ duplicate : function(fm) { var self = this; this.name = 'Duplicate'; this.fm = fm; this.exec = function() { this.fm.ajax({ cmd : 'duplicate', current : this.fm.cwd.hash, target : this.fm.selected[0] }, function(data) { self.fm.reload(data); }); } this.isAllowed = function() { return this.fm.cwd.write && this.fm.selected.length == 1 && this.fm.getSelected()[0].read; } this.cm = function(t) { return t == 'file'; } }, /** * @class Edit text file * @param Object elFinder **/ edit : function(fm) { var self = this; this.name = 'Edit text file'; this.fm = fm; this.exec = function() { var f = this.fm.getSelected(0); this.fm.lockShortcuts(true); this.fm.ajax({ cmd : 'read', current : this.fm.cwd.hash, target : f.hash }, function(data) { self.fm.lockShortcuts(true); var ta = $('<textarea/>').val(data.content||'').keydown(function(e) { e.stopPropagation(); if (e.keyCode == 9) { e.preventDefault(); if ($.browser.msie) { var r = document.selection.createRange(); r.text = "\t"+r.text; this.focus(); } else { var before = this.value.substr(0, this.selectionStart), after = this.value.substr(this.selectionEnd); this.value = before+"\t"+after; this.setSelectionRange(before.length+1, before.length+1); } } }); $('<div/>').append(ta) .dialog({ dialogClass : 'el-finder-dialog', title : self.fm.i18n(self.name), modal : true, width : 500, close : function() { self.fm.lockShortcuts(); }, buttons : { Cancel : function() { $(this).dialog('close'); }, Ok : function() { var c = ta.val(); $(this).dialog('close'); self.fm.ajax({ cmd : 'edit', current : self.fm.cwd.hash, target : f.hash, content : c }, function(data) { if (data.target) { self.fm.cdc[data.target.hash] = data.target; self.fm.view.updateFile(data.target); self.fm.selectById(data.target.hash); } }, {type : 'POST'}); } } }); }); } this.isAllowed = function() { if (self.fm.selected.length == 1) { var f = this.fm.getSelected()[0]; return f.write && f.read && (f.mime.indexOf('text') == 0 || f.mime == 'application/x-empty' || f.mime == 'application/xml'); } } this.cm = function(t) { return t == 'file'; } }, /** * @class Create archive * @param Object elFinder **/ archive : function(fm) { var self = this; this.name = 'Create archive'; this.fm = fm; this.exec = function(t) { var o = { cmd : 'archive', current : self.fm.cwd.hash, type : $.inArray(t, this.fm.params.archives) != -1 ? t : this.fm.params.archives[0], name : self.fm.i18n('Archive') }; if (this.fm.jquery>132) { o.targets = self.fm.selected; } else { o['targets[]'] = self.fm.selected; } this.fm.ajax(o, function(data) { self.fm.reload(data); }); } this.isAllowed = function() { if (this.fm.cwd.write && this.fm.selected.length) { var s = this.fm.getSelected(), l = s.length; while (l--) { if (s[l].read) { return true; } } } return false; } this.cm = function(t) { return t != 'cwd'; } this.argc = function() { var i, v = []; for (i=0; i < self.fm.params.archives.length; i++) { v.push({ 'class' : 'archive', 'argc' : self.fm.params.archives[i], 'text' : self.fm.view.mime2kind(self.fm.params.archives[i]) }); }; return v; } }, /** * @class Extract files from archive * @param Object elFinder **/ extract : function(fm) { var self = this; this.name = 'Uncompress archive'; this.fm = fm; this.exec = function() { this.fm.ajax({ cmd : 'extract', current : this.fm.cwd.hash, target : this.fm.getSelected(0).hash }, function(data) { self.fm.reload(data); }) } this.isAllowed = function() { var extract = this.fm.params.extract, cnt = extract && extract.length; return this.fm.cwd.write && this.fm.selected.length == 1 && this.fm.getSelected(0).read && cnt && $.inArray(this.fm.getSelected(0).mime, extract) != -1; } this.cm = function(t) { return t == 'file'; } }, /** * @class Resize image * @param Object elFinder **/ resize : function(fm) { var self = this; this.name = 'Resize image'; this.fm = fm; this.exec = function() { var s = this.fm.getSelected(); if (s[0] && s[0].write && s[0].dim) { var size = s[0].dim.split('x'), w = parseInt(size[0]), h = parseInt(size[1]), rel = w/h iw = $('<input type="text" size="9" value="'+w+'" name="width"/>'), ih = $('<input type="text" size="9" value="'+h+'" name="height"/>'), f = $('<form/>').append(iw).append(' x ').append(ih).append(' px'); iw.add(ih).bind('change', calc); self.fm.lockShortcuts(true); var d = $('<div/>').append($('<div/>').text(self.fm.i18n('Dimensions')+':')).append(f).dialog({ title : self.fm.i18n('Resize image'), dialogClass : 'el-finder-dialog', width : 230, modal : true, close : function() { self.fm.lockShortcuts(); }, buttons : { Cancel : function() { $(this).dialog('close'); }, Ok : function() { var _w = parseInt(iw.val()) || 0, _h = parseInt(ih.val()) || 0; if (_w>0 && _w != w && _h>0 && _h != h) { self.fm.ajax({ cmd : 'resize', current : self.fm.cwd.hash, target : s[0].hash, width : _w, height : _h }, function (data) { self.fm.reload(data); }); } $(this).dialog('close'); } } }); } function calc() { var _w = parseInt(iw.val()) || 0, _h = parseInt(ih.val()) || 0; if (_w<=0 || _h<=0) { _w = w; _h = h; } else if (this == iw.get(0)) { _h = parseInt(_w/rel); } else { _w = parseInt(_h*rel); } iw.val(_w); ih.val(_h); } } this.isAllowed = function() { return this.fm.selected.length == 1 && this.fm.cdc[this.fm.selected[0]].write && this.fm.cdc[this.fm.selected[0]].read && this.fm.cdc[this.fm.selected[0]].resize; } this.cm = function(t) { return t == 'file'; } }, /** * @class Switch elFinder into icon view * @param Object elFinder **/ icons : function(fm) { this.name = 'View as icons'; this.fm = fm; this.exec = function() { this.fm.view.win.addClass('el-finder-disabled'); this.fm.setView('icons'); this.fm.updateCwd(); this.fm.view.win.removeClass('el-finder-disabled'); $('div.image', this.fm.view.cwd).length && this.fm.tmb(); } this.isAllowed = function() { return this.fm.options.view != 'icons'; } this.cm = function(t) { return t == 'cwd'; } }, /** * @class Switch elFinder into list view * @param Object elFinder **/ list : function(fm) { this.name = 'View as list'; this.fm = fm; this.exec = function() { this.fm.view.win.addClass('el-finder-disabled'); this.fm.setView('list'); this.fm.updateCwd(); this.fm.view.win.removeClass('el-finder-disabled'); } this.isAllowed = function() { return this.fm.options.view != 'list'; } this.cm = function(t) { return t == 'cwd'; } }, help : function(fm) { this.name = 'Help'; this.fm = fm; this.exec = function() { var h, ht = this.fm.i18n('helpText'), a, s, tabs; h = '<div class="el-finder-logo"/><strong>'+this.fm.i18n('elFinder: Web file manager')+'</strong><br/>'+this.fm.i18n('Version')+': '+this.fm.version+'<br/>' +'jQuery/jQueryUI: '+$().jquery+'/'+$.ui.version+'<br clear="all"/>' +'<p><strong><a href="http://elrte.org/'+this.fm.options.lang+'/elfinder" target="_blank">'+this.fm.i18n('Donate to support project development')+'</a></strong></p>' + '<p><a href="http://elrte.org/redmine/projects/elfinder/wiki" target="_blank">'+this.fm.i18n('elFinder documentation')+'</a></p>'; h += '<p>'+(ht != 'helpText' ? ht : 'elFinder works similar to file manager on your computer. <br /> To make actions on files/folders use icons on top panel. If icon action it is not clear for you, hold mouse cursor over it to see the hint. <br /> Manipulations with existing files/folders can be done through the context menu (mouse right-click).<br/> To copy/delete a group of files/folders, select them using Shift/Alt(Command) + mouse left-click.')+'</p>'; h += '<p>' + '<strong>'+this.fm.i18n('elFinder support following shortcuts')+':</strong><ul>' + '<li><kbd>Ctrl+A</kbd> - '+this.fm.i18n('Select all files')+'</li>' + '<li><kbd>Ctrl+C/Ctrl+X/Ctrl+V</kbd> - '+this.fm.i18n('Copy/Cut/Paste files')+'</li>' + '<li><kbd>Enter</kbd> - '+this.fm.i18n('Open selected file/folder')+'</li>' + '<li><kbd>Space</kbd> - '+this.fm.i18n('Open/close QuickLook window')+'</li>' + '<li><kbd>Delete/Cmd+Backspace</kbd> - '+this.fm.i18n('Remove selected files')+'</li>' + '<li><kbd>Ctrl+I</kbd> - '+this.fm.i18n('Selected files or current directory info')+'</li>' + '<li><kbd>Ctrl+N</kbd> - '+this.fm.i18n('Create new directory')+'</li>' + '<li><kbd>Ctrl+U</kbd> - '+this.fm.i18n('Open upload files form')+'</li>' + '<li><kbd>Left arrow</kbd> - '+this.fm.i18n('Select previous file')+'</li>' + '<li><kbd>Right arrow </kbd> - '+this.fm.i18n('Select next file')+'</li>' + '<li><kbd>Ctrl+Right arrow</kbd> - '+this.fm.i18n('Open selected file/folder')+'</li>' + '<li><kbd>Ctrl+Left arrow</kbd> - '+this.fm.i18n('Return into previous folder')+'</li>' + '<li><kbd>Shift+arrows</kbd> - '+this.fm.i18n('Increase/decrease files selection')+'</li></ul>' + '</p><p>' + this.fm.i18n('Contacts us if you need help integrating elFinder in you products')+': dev@std42.ru</p>'; a = '<div class="el-finder-help-std"/>' +'<p>'+this.fm.i18n('Javascripts/PHP programming: Dmitry (dio) Levashov, dio@std42.ru')+'</p>' +'<p>'+this.fm.i18n('Python programming, techsupport: Troex Nevelin, troex@fury.scancode.ru')+'</p>' +'<p>'+this.fm.i18n('Design: Valentin Razumnih')+'</p>' +'<p>'+this.fm.i18n('Chezh localization')+': Roman Matěna, info@romanmatena.cz</p>' +'<p>'+this.fm.i18n('Chinese (traditional) localization')+': Tad, tad0616@gmail.com</p>' +'<p>'+this.fm.i18n('Dutch localization')+': Kurt Aerts, <a href="http://ilabsolutions.net/" target="_blank">http://ilabsolutions.net</a></p>' +'<p>'+this.fm.i18n('Greek localization')+': Panagiotis Skarvelis</p>' +'<p>'+this.fm.i18n('Hungarian localization')+': Viktor Tamas, tamas.viktor@totalstudio.hu</p>' +'<p>'+this.fm.i18n('Italian localization')+': Ugo Punzolo, sadraczerouno@gmail.com</p>' +'<p>'+this.fm.i18n('Latvian localization')+': Uldis Plotiņš, uldis.plotins@gmail.com</p>' +'<p>'+this.fm.i18n('Poland localization')+': Darek Wapiński, darek@wapinski.us</p>' +'<p>'+this.fm.i18n('Spanish localization')+': Alex (xand) Vavilin, xand@xand.es, <a href="http://xand.es" target="_blank">http://xand.es</a></p>' +'<p>'+this.fm.i18n('Icons')+': <a href="http://pixelmixer.ru/" target="_blank">pixelmixer</a>, <a href="http://www.famfamfam.com/lab/icons/silk/" target="_blank">Famfam silk icons</a>, <a href="http://www.fatcow.com/free-icons/" target="_blank">Fatcow icons</a>'+'</p>' +'<p>'+this.fm.i18n('Copyright: <a href="http://www.std42.ru" target="_blank">Studio 42 LTD</a>')+'</p>' +'<p>'+this.fm.i18n('License: BSD License')+'</p>' +'<p>'+this.fm.i18n('Web site: <a href="http://elrte.org/elfinder/" target="_blank">elrte.org/elfinder</a>')+'</p>'; s = '<div class="el-finder-logo"/><strong><a href="http://www.eldorado-cms.ru" target="_blank">ELDORADO.CMS</a></strong><br/>' +this.fm.i18n('Simple and usefull Content Management System') +'<hr/>' + this.fm.i18n('Support project development and we will place here info about you'); tabs = '<ul><li><a href="#el-finder-help-h">'+this.fm.i18n('Help')+'</a></li><li><a href="#el-finder-help-a">'+this.fm.i18n('Authors')+'</a><li><a href="#el-finder-help-sp">'+this.fm.i18n('Sponsors')+'</a></li></ul>' +'<div id="el-finder-help-h"><p>'+h+'</p></div>' +'<div id="el-finder-help-a"><p>'+a+'</p></div>' +'<div id="el-finder-help-sp"><p>'+s+'</p></div>'; var d = $('<div/>').html(tabs).dialog({ width : 617, title : this.fm.i18n('Help'), dialogClass : 'el-finder-dialog', modal : true, close : function() { d.tabs('destroy').dialog('destroy').remove() }, buttons : { Ok : function() { $(this).dialog('close'); } } }).tabs() } this.cm = function(t) { return t == 'cwd'; } } } })(jQuery);