?
Current Path : /home1/savoy/public_html/savoyglobal.net/koaladraft/assets/js/mylibs/ |
Linux gator3171.hostgator.com 4.19.286-203.ELK.el7.x86_64 #1 SMP Wed Jun 14 04:33:55 CDT 2023 x86_64 |
Current File : /home1/savoy/public_html/savoyglobal.net/koaladraft/assets/js/mylibs/elfinder.full.js |
(function($) { /** * @class File manager (main controller) * @author dio dio@std42.ru **/ elFinder = function(el, o) { var self = this, id; this.log = function(m) { window.console && window.console.log && window.console.log(m); } /** * Object. File manager configuration **/ this.options = $.extend({}, this.options, o||{}); if (!this.options.url) { alert('Invalid configuration! You have to set URL option.'); return; } /** * String. element id, create random if not set; **/ this.id = ''; if ((id = $(el).attr('id'))) { this.id = id; } else { // this.id = 'el-finder-'+Math.random().toString().substring(2); } /** * String. Version number; **/ this.version = '1.2'; /** * String. jQuery version; **/ this.jquery = $.fn.jquery.split('.').join(''); /** * Object. Current Working Dir info **/ this.cwd = {}; /** * Object. Current Dir Content. Files/folders info **/ this.cdc = {}; /** * Object. Buffer for copied files **/ this.buffer = {}; /** * Array. Selected files IDs **/ this.selected = []; /** * Array. Folder navigation history **/ this.history = []; /** * Boolean. Enable/disable actions **/ this.locked = false; /** * Number. Max z-index on page + 1, need for contextmenu and quicklook **/ this.zIndex = 2; /** * DOMElement. jQueryUI dialog **/ this.dialog = null; /** * DOMElement. For docked mode - place where fm is docked **/ this.anchor = this.options.docked ? $('<div/>').hide().insertBefore(el) : null; /** * Object. Some options get from server **/ this.params = { dotFiles : false, arc : '', uplMaxSize : '' }; this.vCookie = 'el-finder-view-'+this.id; this.pCookie = 'el-finder-places-'+this.id; this.lCookie = 'el-finder-last-'+this.id; /** * Object. View. After init we can accessel as this.view.win **/ this.view = new this.view(this, el); /** * Object. User Iterface. Controller for commands/buttons/contextmenu **/ this.ui = new this.ui(this); /** * Object. Set/update events **/ this.eventsManager = new this.eventsManager(this); /** * Object. Quick Look like in MacOS X :) **/ this.quickLook = new this.quickLook(this); /** * Set/get cookie value * * @param String name cookie name * @param String value cookie value, null to unset **/ this.cookie = function(name, value) { if (typeof value == 'undefined') { if (document.cookie && document.cookie != '') { var i, c = document.cookie.split(';'); name += '='; for (i=0; i<c.length; i++) { c[i] = $.trim(c[i]); if (c[i].substring(0, name.length) == name) { return decodeURIComponent(c[i].substring(name.length)); } } } return ''; } else { var d, o = $.extend({}, this.options.cookie); if (value===null) { value = ''; o.expires = -1; } if (typeof(o.expires) == 'number') { d = new Date(); d.setTime(d.getTime()+(o.expires * 24 * 60 * 60 * 1000)); o.expires = d; } document.cookie = name+'='+encodeURIComponent(value)+'; expires='+o.expires.toUTCString()+(o.path ? '; path='+o.path : '')+(o.domain ? '; domain='+o.domain : '')+(o.secure ? '; secure' : ''); } } /** * Set/unset this.locked flag * * @param Boolean state **/ this.lock = function(l) { this.view.spinner((this.locked = l||false)); this.eventsManager.lock = this.locked; } /** * Set/unset lock for keyboard shortcuts * * @param Boolean state **/ this.lockShortcuts = function(l) { this.eventsManager.lock = !!l; } /** * Set file manager view type (list|icons) * * @param String v view name **/ this.setView = function(v) { if (v == 'list' || v == 'icons') { this.options.view = v; this.cookie(this.vCookie, v); } } /** * make ajax request, show message on error, call callback on success * * @param Object. data for ajax request * @param Function * @param Object overrwrite some options */ this.ajax = function(data, callback, options) { var opts = { url : this.options.url, async : true, type : 'GET', data : data, dataType : 'json', cache : false, lock : true, force : false, silent : false } if (typeof(options) == 'object') { opts = $.extend({}, opts, options); } if (!opts.silent) { opts.error = self.view.fatal; } opts.success = function(data) { opts.lock && self.lock(); if (data) { data.debug && self.log(data.debug); if (data.error) { !opts.silent && self.view.error(data.error, data.errorData); if (!opts.force) { return; } } callback(data); delete data; } } opts.lock && this.lock(true); $.ajax(opts); } /** * Load generated thumbnails in background * **/ this.tmb = function() { this.ajax({cmd : 'tmb', current : self.cwd.hash}, function(data) { if (self.options.view == 'icons' && data.images && data.current == self.cwd.hash) { for (var i in data.images) { if (self.cdc[i]) { self.cdc[i].tmb = data.images[i]; $('div[key="'+i+'"]>p', self.view.cwd).css('background', ' url("'+data.images[i]+'") 0 0 no-repeat'); } } data.tmb && self.tmb(); } }, {lock : false, silent : true}); } /** * Return folders in places IDs * * @return Array **/ this.getPlaces = function() { var pl = [], p = this.cookie(this.pCookie); if (p.length) { if (p.indexOf(':')!=-1) { pl = p.split(':'); } else { pl.push(p); } } return pl; } /** * Add new folder to places * * @param String Folder ID * @return Boolean **/ this.addPlace = function(id) { var p = this.getPlaces(); if ($.inArray(id, p) == -1) { p.push(id); this.savePlaces(p); return true; } } /** * Remove folder from places * * @param String Folder ID * @return Boolean **/ this.removePlace = function(id) { var p = this.getPlaces(); if ($.inArray(id, p) != -1) { this.savePlaces($.map(p, function(o) { return o == id?null:o; })); return true; } } /** * Save new places data in cookie * * @param Array Folders IDs **/ this.savePlaces = function(p) { this.cookie(this.pCookie, p.join(':')); } /** * Update file manager content * * @param Object Data from server **/ this.reload = function(data) { var i; this.cwd = data.cwd; this.cdc = {}; for (i=0; i<data.cdc.length ; i++) { if (data.cdc[i].hash && data.cdc[i].name) { this.cdc[data.cdc[i].hash] = data.cdc[i]; this.cwd.size += data.cdc[i].size; } } if (data.tree) { this.view.renderNav(data.tree); this.eventsManager.updateNav(); } this.updateCwd(); /* tell connector to generate thumbnails */ if (data.tmb && !self.locked && self.options.view == 'icons') { self.tmb(); } /* have to select some files */ if (data.select && data.select.length) { var l = data.select.length; while (l--) { this.cdc[data.select[l]] && this.selectById(data.select[l]); } } this.lastDir(this.cwd.hash); if (this.options.autoReload>0) { this.iID && clearInterval(this.iID); this.iID = setInterval(function() { !self.locked && self.ui.exec('reload'); }, this.options.autoReload*60000); } } /** * Redraw current directory * */ this.updateCwd = function() { this.lockShortcuts(true); this.selected = []; this.view.renderCwd(); this.eventsManager.updateCwd(); this.view.tree.find('a[key="'+this.cwd.hash+'"]').trigger('select'); this.lockShortcuts(); } /** * Execute after files was dropped onto folder * * @param Object drop event * @param Object drag helper object * @param String target folder ID */ this.drop = function(e, ui, target) { if (ui.helper.find('[key="'+target+'"]').length) { return self.view.error('Unable to copy into itself'); } var ids = []; ui.helper.find('div:not(.noaccess):has(>label):not(:has(em[class="readonly"],em[class=""]))').each(function() { ids.push($(this).hide().attr('key')); }); if (!ui.helper.find('div:has(>label):visible').length) { ui.helper.hide(); } if (ids.length) { self.setBuffer(ids, e.shiftKey?0:1, target); if (self.buffer.files) { /* some strange jquery ui bug (in list view) */ setTimeout(function() {self.ui.exec('paste'); self.buffer = {}}, 300); } } else { $(this).removeClass('el-finder-droppable'); } } /** * Return selected files data * * @param Number if set, returns only element with this index or empty object * @return Array|Object */ this.getSelected = function(ndx) { var i, s = []; if (ndx>=0) { return this.cdc[this.selected[ndx]]||{}; } for (i=0; i<this.selected.length; i++) { this.cdc[this.selected[i]] && s.push(this.cdc[this.selected[i]]); } return s; } this.select = function(el, reset) { reset && $('.ui-selected', self.view.cwd).removeClass('ui-selected'); el.addClass('ui-selected'); self.updateSelect(); } this.selectById = function(id) { var el = $('[key="'+id+'"]', this.view.cwd); if (el.length) { this.select(el); this.checkSelectedPos(); } } this.unselect = function(el) { el.removeClass('ui-selected'); self.updateSelect(); } this.toggleSelect = function(el) { el.toggleClass('ui-selected'); this.updateSelect(); } this.selectAll = function() { $('[key]', self.view.cwd).addClass('ui-selected') self.updateSelect(); } this.unselectAll = function() { $('.ui-selected', self.view.cwd).removeClass('ui-selected'); self.updateSelect(); } this.updateSelect = function() { self.selected = []; $('.ui-selected', self.view.cwd).each(function() { self.selected.push($(this).attr('key')); }); self.view.selectedInfo(); self.ui.update(); self.quickLook.update(); } /** * Scroll selected element in visible position * * @param Boolean check last or first selected element? */ this.checkSelectedPos = function(last) { var s = self.view.cwd.find('.ui-selected:'+(last ? 'last' : 'first')).eq(0), p = s.position(), h = s.outerHeight(), ph = self.view.cwd.height(); if (p.top < 0) { self.view.cwd.scrollTop(p.top+self.view.cwd.scrollTop()-2); } else if (ph - p.top < h) { self.view.cwd.scrollTop(p.top+h-ph+self.view.cwd.scrollTop()); } } /** * Add files to clipboard buffer * * @param Array files IDs * @param Boolean copy or cut files? * @param String destination folder ID */ this.setBuffer = function(files, cut, dst) { var i, id, f; this.buffer = { src : this.cwd.hash, dst : dst, files : [], names : [], cut : cut||0 }; for (i=0; i<files.length; i++) { id = files[i]; f = this.cdc[id]; if (f && f.read && f.type != 'link') { this.buffer.files.push(f.hash); this.buffer.names.push(f.name); } } if (!this.buffer.files.length) { this.buffer = {}; } } /** * Return true if file name is acceptable * * @param String file/folder name * @return Boolean */ this.isValidName = function(n) { if (!this.cwd.dotFiles && n.indexOf('.') == 0) { return false; } return n.match(/^[^\\\/\<\>:]+$/); } /** * Return true if file with this name exists * * @param String file/folder name * @return Boolean */ this.fileExists = function(n) { for (var i in this.cdc) { if (this.cdc[i].name == n) { return i; } } return false; } /** * Return name for new file/folder * * @param String base name (i18n) * @param String extension for file * @return String */ this.uniqueName = function(n, ext) { n = self.i18n(n); var name = n, i = 0, ext = ext||''; if (!this.fileExists(name+ext)) { return name+ext; } while (i++<100) { if (!this.fileExists(name+i+ext)) { return name+i+ext; } } return name.replace('100', '')+Math.random()+ext; } /** * Get/set last opened dir * * @param String dir hash * @return String */ this.lastDir = function(dir) { if (this.options.rememberLastDir) { return dir ? this.cookie(this.lCookie, dir) : this.cookie(this.lCookie); } } /** * Resize file manager * * @param Number width * @param Number height */ function resize(w, h) { w && self.view.win.width(w); h && self.view.nav.add(self.view.cwd).height(h); } /** * Resize file manager in dialog window while it resize * */ function dialogResize() { resize(null, self.dialog.height()-self.view.tlb.parent().height()-($.browser.msie ? 47 : 32)) } this.time = function() { return new Date().getMilliseconds(); } /* here we init file manager */ this.setView(this.cookie(this.vCookie)); resize(self.options.width, self.options.height); /* dialog or docked mode */ if (this.options.dialog || this.options.docked) { this.options.dialog = $.extend({width : 570, dialogClass : '', minWidth : 480, minHeight: 330}, this.options.dialog || {}); this.options.dialog.open = function() { setTimeout(function() { $('<input type="text" value="f"/>').appendTo(self.view.win).focus().select().remove() }, 200) } this.options.dialog.dialogClass += 'el-finder-dialog'; this.options.dialog.resize = dialogResize; if (this.options.docked) { /* docked mode - create dialog and store size */ this.options.dialog.close = function() { self.dock(); }; this.view.win.data('size', {width : this.view.win.width(), height : this.view.nav.height()}); } else { this.options.dialog.close = function() { self.destroy(); } this.dialog = $('<div/>').append(this.view.win).dialog(this.options.dialog); } } this.ajax({ cmd : 'open', target : this.lastDir()||'', init : true, tree : true }, function(data) { if (data.cwd) { self.eventsManager.init(); self.reload(data); $.extend(self.params, data.params||{}); $('*', document.body).each(function() { var z = parseInt($(this).css('z-index')); if (z >= self.zIndex) { self.zIndex = z+1; } }); self.ui.init(data.disabled); } }, {force : true}); this.open = function() { this.dialog ? this.dialog.dialog('open') : this.view.win.show(); this.eventsManager.lock = false; } this.close = function() { this.quickLook.hide(); if (this.options.docked && this.view.win.attr('undocked')) { this.dock(); } else { this.dialog ? this.dialog.dialog('close') : this.view.win.hide(); } this.eventsManager.lock = true; } this.destroy = function() { this.eventsManager.lock = true; this.quickLook.hide(); this.quickLook.win.remove(); if (this.dialog) { this.dialog.dialog('destroy'); this.view.win.parent().remove(); } else { this.view.win.remove(); } this.ui.menu.remove(); } this.dock = function() { if (this.options.docked && this.view.win.attr('undocked')) { this.quickLook.hide(); var s =this.view.win.data('size'); this.view.win.insertAfter(this.anchor).removeAttr('undocked'); resize(s.width, s.height); this.dialog.dialog('destroy'); this.dialog = null; } } this.undock = function() { if (this.options.docked && !this.view.win.attr('undocked')) { this.quickLook.hide(); this.dialog = $('<div/>').append(this.view.win.css('width', '100%').attr('undocked', true).show()).dialog(this.options.dialog); dialogResize(); } } } /** * Translate message into selected language * * @param String message in english * @param String translated or original message */ elFinder.prototype.i18n = function(m) { return this.options.i18n[this.options.lang] && this.options.i18n[this.options.lang][m] ? this.options.i18n[this.options.lang][m] : m; } /** * Default config * */ elFinder.prototype.options = { /* connector url. Required! */ url : '', /* interface language */ lang : 'en', /* additional css class for filemanager container */ cssClass : '', /* characters number to wrap file name in icons view. set to 0 to disable wrap */ wrap : 14, /* Name for places/favorites (i18n), set to '' to disable places */ places : 'Places', /* show places before navigation? */ placesFirst : true, /* callback to get file url (for wswing editors) */ editorCallback : null, /* string to cut from file url begin before pass it to editorCallback. variants: '' - nothing to cut, 'root' - cut root url, 'http://...' - string if it exists in the beginig of url */ cutURL : '', /* close elfinder after editorCallback */ closeOnEditorCallback : true, /* i18 messages. not set manually! */ i18n : {}, /* fm view (icons|list) */ view : 'icons', /* width to overwrite css options */ width : '', /* height to overwrite css options. Attenion! this is heigt of navigation/cwd panels! not total fm height */ height : '', /* disable shortcuts exclude arrows/space */ disableShortcuts : false, /* open last visited dir after reload page or close and open browser */ rememberLastDir : true, /* cookie options */ cookie : { expires : 30, domain : '', path : '/', secure : false }, /* buttons on toolbar */ toolbar : [ ['back', 'reload'], ['select', 'open'], ['mkdir', 'mkfile', 'upload'], ['copy', 'paste', 'rm'], ['rename', 'edit'], ['info', 'quicklook', 'resize'], ['icons', 'list'], ['help'] ], /* contextmenu commands */ contextmenu : { 'cwd' : ['reload', 'delim', 'mkdir', 'mkfile', 'upload', 'delim', 'paste', 'delim', 'info'], 'file' : ['select', 'open', 'quicklook', 'delim', 'copy', 'cut', 'rm', 'delim', 'duplicate', 'rename', 'edit', 'resize', 'archive', 'extract', 'delim', 'info'], 'group' : ['select', 'copy', 'cut', 'rm', 'delim', 'archive', 'extract', 'delim', 'info'] }, /* jqueryUI dialog options */ dialog : null, /* docked mode */ docked : false, /* auto reload time (min) */ autoReload : 0, /* set to true if you need to select several files at once from editorCallback */ selectMultiple : false } $.fn.elfinder = function(o) { return this.each(function() { var cmd = typeof(o) == 'string' ? o : ''; if (!this.elfinder) { this.elfinder = new elFinder(this, typeof(o) == 'object' ? o : {}) } switch(cmd) { case 'close': case 'hide': this.elfinder.close(); break; case 'open': case 'show': this.elfinder.open(); break; case 'dock': this.elfinder.dock(); break; case 'undock': this.elfinder.undock(); break; case'destroy': this.elfinder.destroy(); break; } }) } })(jQuery); (function($) { elFinder.prototype.view = function(fm, el) { var self = this; this.fm = fm; /** * Object. Mimetypes to kinds mapping **/ this.kinds = { 'unknown' : 'Unknown', 'directory' : 'Folder', 'symlink' : 'Alias', 'symlink-broken' : 'Broken alias', 'application/x-empty' : 'Plain text', 'application/postscript' : 'Postscript document', 'application/octet-stream' : 'Application', 'application/vnd.ms-office' : 'Microsoft Office document', 'application/vnd.ms-word' : 'Microsoft Word document', 'application/vnd.ms-excel' : 'Microsoft Excel document', 'application/vnd.ms-powerpoint' : 'Microsoft Powerpoint presentation', 'application/pdf' : 'Portable Document Format (PDF)', 'application/vnd.oasis.opendocument.text' : 'Open Office document', 'application/x-shockwave-flash' : 'Flash application', 'application/xml' : 'XML document', 'application/x-bittorrent' : 'Bittorrent file', 'application/x-7z-compressed' : '7z archive', 'application/x-tar' : 'TAR archive', 'application/x-gzip' : 'GZIP archive', 'application/x-bzip2' : 'BZIP archive', 'application/zip' : 'ZIP archive', 'application/x-rar' : 'RAR archive', 'application/javascript' : 'Javascript application', 'text/plain' : 'Plain text', 'text/x-php' : 'PHP source', 'text/html' : 'HTML document', 'text/javascript' : 'Javascript source', 'text/css' : 'CSS style sheet', 'text/rtf' : 'Rich Text Format (RTF)', 'text/rtfd' : 'RTF with attachments (RTFD)', 'text/x-c' : 'C source', 'text/x-c++' : 'C++ source', 'text/x-shellscript' : 'Unix shell script', 'text/x-python' : 'Python source', 'text/x-java' : 'Java source', 'text/x-ruby' : 'Ruby source', 'text/x-perl' : 'Perl script', 'text/xml' : 'XML document', 'image/x-ms-bmp' : 'BMP image', 'image/jpeg' : 'JPEG image', 'image/gif' : 'GIF Image', 'image/png' : 'PNG image', 'image/x-targa' : 'TGA image', 'image/tiff' : 'TIFF image', 'image/vnd.adobe.photoshop' : 'Adobe Photoshop image', 'audio/mpeg' : 'MPEG audio', 'audio/midi' : 'MIDI audio', 'audio/ogg' : 'Ogg Vorbis audio', 'audio/mp4' : 'MP4 audio', 'audio/wav' : 'WAV audio', 'video/x-dv' : 'DV video', 'video/mp4' : 'MP4 video', 'video/mpeg' : 'MPEG video', 'video/x-msvideo' : 'AVI video', 'video/quicktime' : 'Quicktime video', 'video/x-ms-wmv' : 'WM video', 'video/x-flv' : 'Flash video', 'video/x-matroska' : 'Matroska video' } this.tlb = $('<ul />'); this.nav = $('<div class="el-finder-nav"/>').resizable({handles : 'e', autoHide : true, minWidth : 200, maxWidth: 500}); this.cwd = $('<div class="el-finder-cwd"/>').attr('unselectable', 'on'); this.spn = $('<div class="el-finder-spinner"/>'); this.err = $('<p class="el-finder-err"><strong/></p>').click(function() { $(this).hide(); }); this.nfo = $('<div class="el-finder-stat"/>'); this.pth = $('<div class="el-finder-path"/>'); this.sel = $('<div class="el-finder-sel"/>'); this.stb = $('<div class="el-finder-statusbar"/>') .append(this.pth) .append(this.nfo) .append(this.sel); this.wrz = $('<div class="el-finder-workzone" />') .append(this.nav) .append(this.cwd) .append(this.spn) .append(this.err) .append('<div style="clear:both" />'); this.win = $(el).empty().attr('id', this.fm.id).addClass('el-finder '+(fm.options.cssClass||'')) .append($('<div class="el-finder-toolbar" />').append(this.tlb)) .append(this.wrz) .append(this.stb); this.tree = $('<ul class="el-finder-tree"></ul>').appendTo(this.nav); this.plc = $('<ul class="el-finder-places"><li><a href="#" class="el-finder-places-root"><div/>'+this.fm.i18n(this.fm.options.places)+'</a><ul/></li></ul>').hide(); this.nav[this.fm.options.placesFirst ? 'prepend' : 'append'](this.plc); /* * Render ajax spinner */ this.spinner = function(show) { this.win.toggleClass('el-finder-disabled', show); this.spn.toggle(show); } /* * Display ajax error */ this.fatal = function(t) { self.error(t.status != '404' ? 'Invalid backend configuration' : 'Unable to connect to backend') } /* * Render error */ this.error = function(err, data) { this.fm.lock(); this.err.show().children('strong').html(this.fm.i18n(err)+'!'+this.formatErrorData(data)); setTimeout(function() { self.err.fadeOut('slow'); }, 4000); } /* * Render navigation panel with dirs tree */ this.renderNav = function(tree) { var d = tree.dirs.length ? traverse(tree.dirs) : '', li = '<li><a href="#" class="el-finder-tree-root" key="'+tree.hash+'"><div'+(d ? ' class="collapsed expanded"' : '')+'/>'+tree.name+'</a>'+d+'</li>'; this.tree.html(li); this.fm.options.places && this.renderPlaces(); function traverse(tree) { var i, hash, c, html = '<ul style="display:none">'; for (i=0; i < tree.length; i++) { if (!tree[i].name || !tree[i].hash) { continue; } c = ''; if (!tree[i].read && !tree[i].write) { c = 'noaccess'; } else if (!tree[i].read) { c = 'dropbox'; } else if (!tree[i].write) { c = 'readonly'; } html += '<li><a href="#" class="'+c+'" key="'+tree[i].hash+'"><div'+(tree[i].dirs.length ? ' class="collapsed"' : '')+'/>'+tree[i].name+'</a>'; if (tree[i].dirs.length) { html += traverse(tree[i].dirs); } html += '</li>'; } return html +'</ul>'; } } /* * Render places */ this.renderPlaces = function() { var i, c, pl = this.fm.getPlaces(), ul = this.plc.show().find('ul').empty().hide(); $('div:first', this.plc).removeClass('collapsed expanded'); if (pl.length) { pl.sort(function(a, b) { var _a = self.tree.find('a[key="'+a+'"]').text()||'', _b = self.tree.find('a[key="'+b+'"]').text()||''; return _a.localeCompare(_b); }); for (i=0; i < pl.length; i++) { if ((c = this.tree.find('a[key="'+pl[i]+'"]:not(.dropbox)').parent()) && c.length) { ul.append(c.clone().children('ul').remove().end().find('div').removeClass('collapsed expanded').end()); } else { this.fm.removePlace(pl[i]); } }; ul.children().length && $('div:first', this.plc).addClass('collapsed'); } } /* * Render current directory */ this.renderCwd = function() { this.cwd.empty(); var num = 0, size = 0, html = ''; for (var hash in this.fm.cdc) { num++; size += this.fm.cdc[hash].size; html += this.fm.options.view == 'icons' ? this.renderIcon(this.fm.cdc[hash]) : this.renderRow(this.fm.cdc[hash], num%2); } if (this.fm.options.view == 'icons') { this.cwd.append(html); } else { this.cwd.append('<table><tr><th colspan="2">'+this.fm.i18n('Name')+'</th><th>'+this.fm.i18n('Permissions')+'</th><th>'+this.fm.i18n('Modified')+'</th><th class="size">'+this.fm.i18n('Size')+'</th><th>'+this.fm.i18n('Kind')+'</th></tr>'+html+'</table>'); } this.pth.text(fm.cwd.rel); this.nfo.text(fm.i18n('items')+': '+num+', '+this.formatSize(size)); this.sel.empty(); } /* * Render one file as icon */ this.renderIcon = function(f) { var str = '<p'+(f.tmb ? ' style="'+"background:url('"+f.tmb+"') 0 0 no-repeat"+'"' : '')+'/><label>'+this.formatName(f.name)+'</label>'; if (f.link || f.mime == 'symlink-broken') { str += '<em/>'; } if (!f.read && !f.write) { str += '<em class="noaccess"/>'; } else if (f.read && !f.write) { str += '<em class="readonly"/>'; } else if (!f.read && f.write) { str += '<em class="'+(f.mime == 'directory' ? 'dropbox' :'noread')+'" />'; } return '<div class="'+this.mime2class(f.mime)+'" key="'+f.hash+'">'+str+'</div>'; } /* * Render one file as table row */ this.renderRow = function(f, odd) { var str = f.link || f.mime =='symlink-broken' ? '<em/>' : ''; if (!f.read && !f.write) { str += '<em class="noaccess"/>'; } else if (f.read && !f.write) { str += '<em class="readonly"/>'; } else if (!f.read && f.write) { str += '<em class="'+(f.mime == 'directory' ? 'dropbox' :'noread')+'" />'; } return '<tr key="'+f.hash+'" class="'+self.mime2class(f.mime)+(odd ? ' el-finder-row-odd' : '')+'"><td class="icon"><p>'+str+'</p></td><td>'+f.name+'</td><td>'+self.formatPermissions(f.read, f.write, f.rm)+'</td><td>'+self.formatDate(f.date)+'</td><td class="size">'+self.formatSize(f.size)+'</td><td>'+self.mime2kind(f.link ? 'symlink' : f.mime)+'</td></tr>'; } /* * Re-render file (after editing) */ this.updateFile = function(f) { var e = this.cwd.find('[key="'+f.hash+'"]'); e.replaceWith(e[0].nodeName == 'DIV' ? this.renderIcon(f) : this.renderRow(f)); } /* * Update info about selected files */ this.selectedInfo = function() { var i, s = 0, sel; if (self.fm.selected.length) { sel = this.fm.getSelected(); for (i=0; i<sel.length; i++) { s += sel[i].size; } } this.sel.text(i>0 ? this.fm.i18n('selected items')+': '+sel.length+', '+this.formatSize(s) : ''); } /* * Return wraped file name if needed */ this.formatName = function(n) { var w = self.fm.options.wrap; if (w>0) { if (n.length > w*2) { return n.substr(0, w)+"­"+n.substr(w, w-5)+"…"+n.substr(n.length-3); } else if (n.length > w) { return n.substr(0, w)+"­"+n.substr(w); } } return n; } /* * Return error message */ this.formatErrorData = function(data) { var i, err = '' if (typeof(data) == 'object') { err = '<br />'; for (i in data) { err += i+' '+self.fm.i18n(data[i])+'<br />'; } } return err; } /* * Convert mimetype into css class */ this.mime2class = function(mime) { return mime.replace('/' , ' ').replace(/\./g, '-'); } /* * Return localized date */ this.formatDate = function(d) { return d.replace(/([a-z]+)\s/i, function(a1, a2) { return self.fm.i18n(a2)+' '; }); } /* * Return formated file size */ this.formatSize = function(s) { var n = 1, u = 'bytes'; if (s > 1073741824) { n = 1073741824; u = 'Gb'; } else if (s > 1048576) { n = 1048576; u = 'Mb'; } else if (s > 1024) { n = 1024; u = 'Kb'; } return Math.round(s/n)+' '+u; } /* * Return localized string with file permissions */ this.formatPermissions = function(r, w, rm) { var p = []; r && p.push(self.fm.i18n('read')); w && p.push(self.fm.i18n('write')); rm && p.push(self.fm.i18n('remove')); return p.join('/'); } /* * Return kind of file */ this.mime2kind = function(mime) { return this.fm.i18n(this.kinds[mime]||'unknown'); } } })(jQuery); /** * @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); /** * @class Create quick look window (similar to MacOS X Quick Look) * @author dio dio@std42.ru **/ (function($) { elFinder.prototype.quickLook = function(fm, el) { var self = this; this.fm = fm; this._hash = ''; this.title = $('<strong/>'); this.ico = $('<p/>'); this.info = $('<label/>'); this.media = $('<div class="el-finder-ql-media"/>').hide() this.name = $('<span class="el-finder-ql-name"/>') this.kind = $('<span class="el-finder-ql-kind"/>') this.size = $('<span class="el-finder-ql-size"/>') this.date = $('<span class="el-finder-ql-date"/>') this.url = $('<a href="#"/>').hide().click(function(e) { e.preventDefault(); window.open($(this).attr('href')); self.hide(); }); this.add = $('<div/>') this.content = $('<div class="el-finder-ql-content"/>') this.win = $('<div class="el-finder-ql"/>').hide() .append($('<div class="el-finder-ql-drag-handle"/>').append($('<span class="ui-icon ui-icon-circle-close"/>').click(function() { self.hide(); })).append(this.title)) .append(this.ico) .append(this.media) .append(this.content.append(this.name).append(this.kind).append(this.size).append(this.date).append(this.url).append(this.add)) // .appendTo(this.fm.view.win) .appendTo('body') .draggable({handle : '.el-finder-ql-drag-handle'}) .resizable({ minWidth : 420, minHeight : 150, resize : function() { if (self.media.children().length) { var t = self.media.children(':first'); switch (t[0].nodeName) { case 'IMG': var w = t.width(), h = t.height(), _w = self.win.width(), _h = self.win.css('height') == 'auto' ? 350 : self.win.height()-self.content.height()-self.th, r = w>_w || h>_h ? Math.min(Math.min(_w, w)/w, Math.min(_h, h)/h) : Math.min(Math.max(_w, w)/w, Math.max(_h, h)/h); t.css({ width : Math.round(t.width()*r), height : Math.round(t.height()*r) }) break; case 'IFRAME': case 'EMBED': t.css('height', self.win.height()-self.content.height()-self.th); break; case 'OBJECT': t.children('embed').css('height', self.win.height()-self.content.height()-self.th); } } } }); this.th = parseInt(this.win.children(':first').css('height'))||18; /* All browsers do it, but some is shy to says about it. baka da ne! */ this.mimes = { 'image/jpeg' : 'jpg', 'image/gif' : 'gif', 'image/png' : 'png' }; for (var i=0; i<navigator.mimeTypes.length; i++) { var t = navigator.mimeTypes[i].type; if (t && t != '*') { this.mimes[t] = navigator.mimeTypes[i].suffixes; } } if (($.browser.safari && navigator.platform.indexOf('Mac') != -1) || $.browser.msie) { /* not booletproof, but better then nothing */ this.mimes['application/pdf'] = 'pdf'; } else { for (var n=0; n < navigator.plugins.length; n++) { for (var m=0; m < navigator.plugins[n].length; m++) { var e = navigator.plugins[n][m].description.toLowerCase(); if (e.substring(0, e.indexOf(" ")) == 'pdf') { this.mimes['application/pdf'] = 'pdf'; break; } } } } if (this.mimes['image/x-bmp']) { this.mimes['image/x-ms-bmp'] = 'bmp'; } if ($.browser.msie && !this.mimes['application/x-shockwave-flash']) { this.mimes['application/x-shockwave-flash'] = 'swf'; } // self.fm.log(this.mimes) /** * Open quickLook window **/ this.show = function() { if (this.win.is(':hidden') && self.fm.selected.length == 1) { update(); var id = self.fm.selected[0], el = self.fm.view.cwd.find('[key="'+id+'"]'), o = el.offset(); self.fm.lockShortcuts(true); this.win.css({ width : el.width()-20, height : el.height(), left : o.left, top : o.top, opacity : 0 }).show().animate({ width : 420, height : 150, opacity : 1, top : Math.round($(window).height()/5), left : $(window).width()/2-210 }, 450, function() { self.win.css({height: 'auto'}); self.fm.lockShortcuts(); }); } } /** * Close quickLook window **/ this.hide = function() { if (this.win.is(':visible')) { var o, el = self.fm.view.cwd.find('[key="'+this._hash+'"]'); if (el) { o = el.offset(); this.media.hide(200)//.empty() this.win.animate({ width : el.width()-20, height : el.height(), left : o.left, top : o.top, opacity : 0 }, 350, function() { self.fm.lockShortcuts(); reset(); self.win.hide().css('height', 'auto'); }); } else { this.win.fadeOut(200); reset(); self.fm.lockShortcuts(); } } } /** * Open/close quickLook window **/ this.toggle = function() { if (this.win.is(':visible')) { this.hide(); } else { this.show(); } } /** * Update quickLook window content if only one file selected, * otherwise close window **/ this.update = function() { if (this.fm.selected.length != 1) { this.hide(); } else if (this.win.is(':visible') && this.fm.selected[0] != this._hash) { update(); } } /** * Return height of this.media block * @return Number **/ this.mediaHeight = function() { return this.win.is(':animated') || this.win.css('height') == 'auto' ? 315 : this.win.height()-this.content.height()-this.th; } /** * Clean quickLook window DOM elements **/ function reset() { self.media.hide().empty(); self.win.attr('class', 'el-finder-ql').css('z-index', self.fm.zIndex); self.title.empty(); self.ico.attr('style', '').show(); self.add.hide().empty(); self._hash = ''; } /** * Update quickLook window content **/ function update() { var f = self.fm.getSelected(0); reset(); self._hash = f.hash; self.title.text(f.name); self.win.addClass(self.fm.view.mime2class(f.mime)); self.name.text(f.name); self.kind.text(self.fm.view.mime2kind(f.link ? 'symlink' : f.mime)); self.size.text(self.fm.view.formatSize(f.size)); self.date.text(self.fm.i18n('Modified')+': '+self.fm.view.formatDate(f.date)); f.dim && self.add.append('<span>'+f.dim+' px</span>').show(); f.tmb && self.ico.css('background', 'url("'+f.tmb+'") 0 0 no-repeat'); if (f.url) { self.url.text(f.url).attr('href', f.url).show(); for (var i in self.plugins) { if (self.plugins[i].test && self.plugins[i].test(f.mime, self.mimes, f.name)) { self.plugins[i].show(self, f); return; } } } else { self.url.hide(); } self.win.css({ width : '420px', height : 'auto' }); } } elFinder.prototype.quickLook.prototype.plugins = { image : new function() { this.test = function(mime, mimes) { return mime.match(/^image\//); } this.show = function(ql, f) { var url, t; if (ql.mimes[f.mime] && f.hash == ql._hash) { $('<img/>').hide().appendTo(ql.media.show()).attr('src', f.url+($.browser.msie || $.browser.opera ? '?'+Math.random() : '')).load(function() { t = $(this).unbind('load'); if (f.hash == ql._hash) { ql.win.is(':animated') ? setTimeout(function() { preview(t); }, 330) : preview(t); } }); } function preview(img) { var w = img.width(), h = img.height(), a = ql.win.is(':animated'), _w = a ? 420 : ql.win.width(), _h = a || ql.win.css('height') == 'auto' ? 315 : ql.win.height()-ql.content.height()-ql.th, r = w>_w || h>_h ? Math.min(Math.min(_w, w)/w, Math.min(_h, h)/h) : Math.min(Math.max(_w, w)/w, Math.max(_h, h)/h); ql.fm.lockShortcuts(true); ql.ico.hide(); img.css({ width : ql.ico.width(), height : ql.ico.height() }).show().animate({ width : Math.round(r*w), height : Math.round(r*h) }, 450, function() { ql.fm.lockShortcuts(); }); } } }, text : new function() { this.test = function(mime, mimes) { return (mime.indexOf('text') == 0 && mime.indexOf('rtf') == -1) || mime.match(/application\/(xml|javascript|json)/); } this.show = function(ql, f) { if (f.hash == ql._hash) { ql.ico.hide(); ql.media.append('<iframe src="'+f.url+'" style="height:'+ql.mediaHeight()+'px" />').show(); } } }, swf : new function() { this.test = function(mime, mimes) { return mime == 'application/x-shockwave-flash' && mimes[mime]; } this.show = function(ql, f) { if (f.hash == ql._hash) { ql.ico.hide(); // ql.media.append('<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="quality" value="high" /><param name="movie" value="'+url+'" /><embed pluginspage="http://www.macromedia.com/go/getflashplayer" quality="high" src="'+url+'" type="application/x-shockwave-flash" style="width:100%;height:'+ql.mediaHeight()+'px"></embed></object>') // .slideDown(400); var e = ql.media.append('<embed pluginspage="http://www.macromedia.com/go/getflashplayer" quality="high" src="'+f.url+'" style="width:100%;height:'+ql.mediaHeight()+'px" type="application/x-shockwave-flash" />'); if (ql.win.is(':animated')) { e.slideDown(450) } else { e.show() } } } }, audio : new function() { this.test = function(mime, mimes) { return mime.indexOf('audio') == 0 && mimes[mime]; } this.show = function(ql, f) { if (f.hash == ql._hash) { ql.ico.hide(); var h = ql.win.is(':animated') || ql.win.css('height') == 'auto' ? 100 : ql.win.height()-ql.content.height()-ql.th; ql.media.append('<embed src="'+f.url+'" style="width:100%;height:'+h+'px" />').show(); } } }, video : new function() { this.test = function(mime, mimes) { return mime.indexOf('video') == 0 && mimes[mime]; } this.show = function(ql, f) { if (f.hash == ql._hash) { ql.ico.hide(); ql.media.append('<embed src="'+f.url+'" style="width:100%;height:'+ql.mediaHeight()+'px" />').show(); } } }, pdf : new function() { this.test = function(mime, mimes) { return mime == 'application/pdf' && mimes[mime]; } this.show = function(ql, f) { if (f.hash == ql._hash) { ql.ico.hide(); ql.media.append('<embed src="'+f.url+'" style="width:100%;height:'+ql.mediaHeight()+'px" />').show(); } } } } })(jQuery); /** * @class Bind/update events * @author dio dio@std42.ru **/ (function($) { elFinder.prototype.eventsManager = function(fm, el) { var self = this; this.lock = false; this.fm = fm; this.ui = fm.ui; this.tree = fm.view.tree this.cwd = fm.view.cwd; this.pointer = ''; /** * Initial events binding * **/ this.init = function() { var self = this, ignore = false; self.lock = false; this.cwd .bind('click', function(e) { var t = $(e.target); if (t.hasClass('ui-selected')) { self.fm.unselectAll(); } else { if (!t.attr('key')) { t = t.parent('[key]'); } if (e.ctrlKey || e.metaKey) { self.fm.toggleSelect(t); } else { self.fm.select(t, true); } } }) .bind(window.opera?'click':'contextmenu', function(e) { if (window.opera && !e.ctrlKey) { return; } e.preventDefault(); e.stopPropagation(); var t = $(e.target); if ($.browser.mozilla) { ignore = true; } if (t.hasClass('el-finder-cwd')) { self.fm.unselectAll(); } else { self.fm.select(t.attr('key') ? t : t.parent('[key]')); } self.fm.quickLook.hide(); self.fm.ui.showMenu(e); }) .selectable({ filter : '[key]', delay : 300, stop : function() { self.fm.updateSelect(); self.fm.log('mouseup') } }); $(document).bind('click', function(e) { !ignore && self.fm.ui.hideMenu(); ignore = false $('input', self.cwd).trigger('change'); if (!$(e.target).is('input,textarea,select')) { $('input,textarea').blur(); } }); $('input,textarea').live('focus', function(e) { self.lock = true; }).live('blur', function(e) { self.lock = false; }); /* open parents dir in tree */ this.tree.bind('select', function(e) { self.tree.find('a').removeClass('selected'); $(e.target).addClass('selected').parents('li:has(ul)').children('ul').show().prev().children('div').addClass('expanded'); }); /* make places droppable */ if (this.fm.options.places) { this.fm.view.plc.click(function(e) { e.preventDefault(); var t = $(e.target), h = t.attr('key'), ul; if (h) { h != self.fm.cwd.hash && self.ui.exec('open', e.target) } else if (e.target.nodeName == 'A' || e.target.nodeName == 'DIV') { ul = self.fm.view.plc.find('ul'); if (ul.children().length) { ul.toggle(300); self.fm.view.plc.children('li').find('div').toggleClass('expanded'); } } }); this.fm.view.plc.droppable({ accept : '(div,tr).directory', tolerance : 'pointer', over : function() { $(this).addClass('el-finder-droppable'); }, out : function() { $(this).removeClass('el-finder-droppable'); }, drop : function(e, ui) { $(this).removeClass('el-finder-droppable'); var upd = false; /* accept only folders with read access */ ui.helper.children('.directory:not(.noaccess,.dropbox)').each(function() { if (self.fm.addPlace($(this).attr('key'))) { upd = true; $(this).hide(); } }); /* update places id's and view */ if (upd) { self.fm.view.renderPlaces(); self.updatePlaces(); self.fm.view.plc.children('li').children('div').trigger('click'); } /* hide helper if empty */ if (!ui.helper.children('div:visible').length) { ui.helper.hide(); } } }); } /* bind shortcuts */ $(document).bind($.browser.mozilla || $.browser.opera ? 'keypress' : 'keydown', function(e) { var meta = e.ctrlKey||e.metaKey; if (self.lock) { return; } switch(e.keyCode) { /* arrows left/up. with Ctrl - exec "back", w/o - move selection */ case 37: case 38: e.stopPropagation(); e.preventDefault(); if (e.keyCode == 37 && meta) { self.ui.execIfAllowed('back'); } else { moveSelection(false, !e.shiftKey); } break; /* arrows right/down. with Ctrl - exec "open", w/o - move selection */ case 39: case 40: e.stopPropagation(); e.preventDefault(); if (meta) { self.ui.execIfAllowed('open'); } else { moveSelection(true, !e.shiftKey); } break; } }); $(document).bind($.browser.opera ? 'keypress' : 'keydown', function(e) { if (self.lock) { return; } switch(e.keyCode) { /* Space - QuickLook */ case 32: e.preventDefault(); e.stopPropagation(); self.fm.quickLook.toggle(); break; /* Esc */ case 27: self.fm.quickLook.hide(); break; } }); if (!this.fm.options.disableShortcuts) { $(document).bind('keydown', function(e) { var meta = e.ctrlKey||e.metaKey; if (self.lock) { return; } switch (e.keyCode) { /* Meta+Backspace - delete */ case 8: if (meta && self.ui.isCmdAllowed('rm')) { e.preventDefault(); self.ui.exec('rm'); } break; /* Enter - exec "select" command if enabled, otherwise exec "open" */ case 13: if (self.ui.isCmdAllowed('select')) { return self.ui.exec('select'); } self.ui.execIfAllowed('open'); break; /* Delete */ case 46: self.ui.execIfAllowed('rm'); break; /* Ctrl+A */ case 65: if (meta) { e.preventDefault(); self.fm.selectAll(); } break; /* Ctrl+C */ case 67: meta && self.ui.execIfAllowed('copy'); break; /* Ctrl+I - get info */ case 73: if (meta) { e.preventDefault(); self.ui.exec('info'); } break; /* Ctrl+N - new folder */ case 78: if (meta) { e.preventDefault(); self.ui.execIfAllowed('mkdir'); } break; /* Ctrl+U - upload files */ case 85: if (meta) { e.preventDefault(); self.ui.execIfAllowed('upload'); } break; /* Ctrl+V */ case 86: meta && self.ui.execIfAllowed('paste'); break; /* Ctrl+X */ case 88: meta && self.ui.execIfAllowed('cut'); break; case 113: self.ui.execIfAllowed('rename'); break; } }); } } /** * Update navigation droppable/draggable * **/ this.updateNav = function() { $('a', this.tree).click(function(e) { e.preventDefault(); var t = $(this), c; if (e.target.nodeName == 'DIV' && $(e.target).hasClass('collapsed')) { $(e.target).toggleClass('expanded').parent().next('ul').toggle(300); } else if (t.attr('key') != self.fm.cwd.hash) { if (t.hasClass('noaccess') || t.hasClass('dropbox')) { self.fm.view.error('Access denied'); } else { self.ui.exec('open', t.trigger('select')[0]); } } else { c = t.children('.collapsed'); if (c.length) { c.toggleClass('expanded'); t.next('ul').toggle(300); } } }); $('a:not(.noaccess,.readonly)', this.tree).droppable({ tolerance : 'pointer', accept : 'div[key],tr[key]', over : function() { $(this).addClass('el-finder-droppable'); }, out : function() { $(this).removeClass('el-finder-droppable'); }, drop : function(e, ui) { $(this).removeClass('el-finder-droppable'); self.fm.drop(e, ui, $(this).attr('key')); } }); this.fm.options.places && this.updatePlaces(); } /** * Update places draggable * **/ this.updatePlaces = function() { this.fm.view.plc.children('li').find('li').draggable({ scroll : false, stop : function() { if (self.fm.removePlace($(this).children('a').attr('key'))) { $(this).remove(); if (!$('li', self.fm.view.plc.children('li')).length) { self.fm.view.plc.children('li').find('div').removeClass('collapsed expanded').end().children('ul').hide(); } } } }); } /** * Update folders droppable & files/folders draggable **/ this.updateCwd = function() { $('[key]', this.cwd) .bind('dblclick', function(e) { self.fm.select($(this), true); self.ui.exec(self.ui.isCmdAllowed('select') ? 'select' : 'open'); }) .draggable({ delay : 3, addClasses : false, appendTo : '.el-finder-cwd', revert : true, drag : function(e, ui) { ui.helper.toggleClass('el-finder-drag-copy', e.shiftKey||e.ctrlKey); }, helper : function() { var t = $(this), h = $('<div class="el-finder-drag-helper"/>'), c = 0; !t.hasClass('ui-selected') && self.fm.select(t, true); self.cwd.find('.ui-selected').each(function(i) { var el = self.fm.options.view == 'icons' ? $(this).clone().removeClass('ui-selected') : $(self.fm.view.renderIcon(self.fm.cdc[$(this).attr('key')])) if (c++ == 0 || c%12 == 0) { el.css('margin-left', 0); } h.append(el); }); return h.css('width', (c<=12 ? 85+(c-1)*29 : 387)+'px'); } }) .filter('.directory') .droppable({ tolerance : 'pointer', accept : 'div[key],tr[key]', over : function() { $(this).addClass('el-finder-droppable'); }, out : function() { $(this).removeClass('el-finder-droppable'); }, drop : function(e, ui) { $(this).removeClass('el-finder-droppable'); self.fm.drop(e, ui, $(this).attr('key')); } }); if ($.browser.msie) { $('*', this.cwd).attr('unselectable', 'on') .filter('[key]') .bind('dragstart', function() { self.cwd.selectable('disable').removeClass('ui-state-disabled ui-selectable-disabled'); }) .bind('dragstop', function() { self.cwd.selectable('enable'); }); } } /** * Move selection in current dir * * @param Boolean move forward? * @param Boolean clear current selection? **/ function moveSelection(forward, reset) { var p, _p, cur; if (!$('[key]', self.cwd).length) { return; } if (self.fm.selected.length == 0) { p = $('[key]:'+(forward ? 'first' : 'last'), self.cwd); self.fm.select(p); } else if (reset) { p = $('.ui-selected:'+(forward ? 'last' : 'first'), self.cwd); _p = p[forward ? 'next' : 'prev']('[key]'); if (_p.length) { p = _p; } self.fm.select(p, true); } else { if (self.pointer) { cur = $('[key="'+self.pointer+'"].ui-selected', self.cwd); } if (!cur || !cur.length) { cur = $('.ui-selected:'+(forward ? 'last' : 'first'), self.cwd); } p = cur[forward ? 'next' : 'prev']('[key]'); if (!p.length) { p = cur; } else { if (!p.hasClass('ui-selected')) { self.fm.select(p); } else { if (!cur.hasClass('ui-selected')) { self.fm.unselect(p); } else { _p = cur[forward ? 'prev' : 'next']('[key]') if (!_p.length || !_p.hasClass('ui-selected')) { self.fm.unselect(cur); } else { while ((_p = forward ? p.next('[key]') : p.prev('[key]')) && p.hasClass('ui-selected')) { p = _p; } self.fm.select(p); } } } } } self.pointer = p.attr('key'); self.fm.checkSelectedPos(forward); } } })(jQuery);