Part of Slepp's ProjectsPastebinTURLImagebinFilebin
Feedback -- English French German Japanese
Create Upload Newest Tools Donate
Sign In | Create Account

Advertising

Someone
Monday, May 21st, 2012 at 6:57:34am MDT 

  1. (function($) {
  2.  
  3.         /**
  4.          * @class  File manager (main controller)
  5.          * @author dio dio@std42.ru
  6.          **/
  7.         elFinder = function(el, o) {
  8.                 var self = this, id;
  9.                
  10.                 $(el).data('elfinder',this);
  11.                
  12.                 this.log = function(m) {
  13.                         window.console && window.console.log && window.console.log(m);
  14.                 }
  15.                 /**
  16.                  * Object. File manager configuration
  17.                  **/
  18.                 this.options.downloadLinkFormat = '/%s';
  19.                
  20.                 this.options = $.extend({}, this.options, o||{});
  21.                
  22.                 if(id = document.location.hash.replace(/^#(\.\/)?/,'').replace(/\??&.*$/,''))
  23.                         this.options.startDir = id;
  24.                
  25.                 if (!this.options.url) {
  26.                         alert('Invalid configuration! You have to set URL option.');
  27.                         return;
  28.                 }
  29.                
  30.                
  31.                 /**
  32.                  * String. element id, create random if not set;
  33.                  **/
  34.                 this.id = '';
  35.                 if ((id = $(el).attr('id'))) {
  36.                         this.id = id;
  37.                 } else {
  38.                         this.id = 'el-finder-'+Math.random().toString().substring(2);
  39.                 }
  40.                
  41.                 /**
  42.                  * String. Version number;
  43.                  **/
  44.                 this.version  = '1.1 RC3';
  45.                 /**
  46.                  * String. jQuery version;
  47.                  **/
  48.                 this.jquery = $.fn.jquery.split('.').join('');
  49.  
  50.                 /**
  51.                  * Object. Current Working Dir info
  52.                  **/
  53.                 this.cwd      = {};
  54.                 this.lockedFolders = {};
  55.                 /**
  56.                  * Object. Current Dir Content. Files/folders info
  57.                  **/
  58.                 this.cdc      = {};
  59.                 this.cdc_pos  = 0;
  60.                
  61.                 /**
  62.                  * Object. Current Tree Content.
  63.                  **/
  64.                 this.tree    = {};
  65.                
  66.                 /**
  67.                  * Object. Buffer for copied files
  68.                  **/
  69.                 this.buffer   = {};
  70.                 /**
  71.                  * Array. Selected files IDs
  72.                  **/
  73.                 this.selected = [];
  74.                 /**
  75.                  * Boolean. Enable/disable actions
  76.                  **/
  77.                 this.locked   = false;
  78.                 /**
  79.                  * Number. Max z-index on page + 1, need for contextmenu and quicklook
  80.                  **/
  81.                 this.zIndex = 2;
  82.                 /**
  83.                  * Object. Some options get from server
  84.                  **/
  85.                 this.params = { uplMaxSize : '' };
  86.                 this.vCookie = 'el-finder-view-'+this.id;
  87.                 this.oCookie = 'el-finder-order-'+this.id;
  88.                 /**
  89.                  * Object. View. After init we can accessel as this.view.win
  90.                  **/
  91.                 this.view = new this.view(this, el);
  92.                 /**
  93.                  * Object. User Iterface. Controller for commands/buttons/contextmenu
  94.                  **/
  95.                 this.ui = new this.ui(this);
  96.                 /**
  97.                  * Object. Set/update events
  98.                  **/
  99.                 this.eventsManager = new this.eventsManager(this);
  100.                 /**
  101.                  * Object. Quick Look like in MacOS X :)
  102.                  **/
  103.                 //this.quickLook = new this.quickLook(this);
  104.  
  105.                 /**
  106.                  * Set/get cookie value
  107.                  *
  108.                  * @param  String  name  cookie name
  109.                  * @param  String  value cookie value, null to unset
  110.                  **/
  111.                 this.cookie = function(name, value) {
  112.                         if (typeof value == 'undefined') {
  113.                                 if (document.cookie && document.cookie != '') {
  114.                                         var i, c = document.cookie.split(';');
  115.                                         name += '=';
  116.                                         for (i=0; i<c.length; i++) {
  117.                                                 c[i] = $.trim(c[i]);
  118.                                                 if (c[i].substring(0, name.length) == name) {
  119.                                                         return decodeURIComponent(c[i].substring(name.length));
  120.                                                 }
  121.                                         }
  122.                                 }
  123.                                 return '';
  124.                         } else {
  125.                                 var d, o = $.extend({}, this.options.cookie);
  126.                                 if (value===null) {
  127.                                         value = '';
  128.                                         o.expires = -1;
  129.                                 }
  130.                                 if (typeof(o.expires) == 'number') {
  131.                                         d = new Date();
  132.                                         d.setTime(d.getTime()+(o.expires * 24 * 60 * 60 * 1000));
  133.                                         o.expires = d;
  134.                                 }
  135.                                 document.cookie = name+'='+encodeURIComponent(value)+'; expires='+o.expires.toUTCString()+(o.path ? '; path='+o.path : '')+(o.domain ? '; domain='+o.domain : '')+(o.secure ? '; secure' : '');
  136.                         }
  137.                 }
  138.  
  139.                 this.options.order=this.cookie(this.oCookie)||'-name';
  140.                
  141.                 /**
  142.                  * Set/unset this.locked flag
  143.                  *
  144.                  * @param  Boolean  state
  145.                  **/
  146.                 this.lock = function(l) {
  147.                         this.view.spinner((this.locked = l||false));
  148.                         this.eventsManager.lock = this.locked;
  149.                 }
  150.  
  151.                 /**
  152.                  * Set/unset lock for keyboard shortcuts
  153.                  *
  154.                  * @param  Boolean  state
  155.                  **/
  156.                 this.lockShortcuts = function(l) {
  157.                         this.eventsManager.lock = l;
  158.                 }
  159.                
  160.                 /**
  161.                  * Set file manager view type (list|icon)
  162.                  *
  163.                  * @param  String  v  view name
  164.                  **/
  165.                 this.setView = function(v) {
  166.                         if (v == 'list' || v == 'icon') {
  167.                                 this.options.view = v;
  168.                                 this.cookie(this.vCookie, v);
  169.                         }
  170.                 }
  171.                
  172.                 this.setOrder = function(o) {
  173.                         var self=this;
  174.                         this.view.win.addClass('el-finder-disabled');
  175.                         var oo=this.options.order;
  176.                         var desc=(oo.match(/^-/) == '-' ? true : false);
  177.                         if(desc && oo.replace(/^-/,'')==o)oo=o;
  178.                         else if(oo==o)oo='-'+o;
  179.                         else oo=o;
  180.                         this.options.order = oo;
  181.                         this.cookie(this.oCookie, this.options.order);
  182.                         if(this.cdc_pos>0){
  183.                                 this.ajax({ cmd : 'open', target : this.cwd.hash, tree : false }, function(data) {
  184.                                         self.reload(data);
  185.                                 });
  186.                         }
  187.                         else {
  188.                                 var tmp=[];
  189.                                 for(var i in this.cdc)
  190.                                         tmp.push(this.cdc[i]);
  191.                                 function convText(mime, t){
  192.                                         return String(mime=='directory' ? (desc ? 0 : 1) : (desc ? 1 : 0)) + t;
  193.                                 }
  194.                                 function convNumeric(mime, t){
  195.                                         return (mime=='directory' ? (desc ? -0xfffffffffffffff0 : 0xfffffffffffffff0) : 0) + t;
  196.                                 }
  197.                                 switch(o){
  198.                                 default:
  199.                                         tmp = tmp.sort(function(a, b){ return convText(a.mime, a[o]).localeCompare(convText(b.mime, b[o]))*(desc ? 1 : -1); });
  200.                                         break;
  201.                                 case 'hits':
  202.                                 case 'size':
  203.                                         tmp = tmp.sort(function(a, b){ return (convNumeric(a.mime, a[o]) - convNumeric(b.mime, b[o]))*(desc ? 1 : -1); });
  204.                                         break;
  205.                                 }
  206.                                 this.reload({
  207.                                         cwd:this.cwd,
  208.                                         cdc:tmp,
  209.                                         cdc_pos:0,
  210.                                         cdc_append:false
  211.                                 });
  212.                                 this.lock(false);
  213.                                 /*
  214.                                 pl.sort(function(a, b) {
  215.                                         var _a = self.tree.find('a[key="'+a+'"]').text()||'',
  216.                                                 _b = self.tree.find('a[key="'+b+'"]').text()||'';
  217.                                         return _a.localeCompare(_b);
  218.                                 });*/
  219.                         }
  220.                 }
  221.                
  222.                 /**
  223.                  * make ajax request, show message on error, call callback on success
  224.                  *
  225.                  * @param  Object.  data for ajax request
  226.                  * @param  Function 
  227.                  * @param  Object   overrwrite some options
  228.                  */
  229.                 this.ajax = function(data, callback, options) {
  230.                         var self = this, opts = {
  231.                                 url      : this.options.url,
  232.                                 uploadUrl: this.options.url,
  233.                                 async    : true,
  234.                                 type     : 'POST',
  235.                                 data     : data,
  236.                                 dataType : 'html',
  237.                                 cache    : false,
  238.                                 lock     : true,
  239.                                 force    : false,
  240.                                 silent   : false
  241.                         }
  242.                         opts[this.options.session.type] = this.options.session.id;
  243.                         if (typeof(options) == 'object') {
  244.                                 opts = $.extend({}, opts, options);
  245.                         }
  246.                         if (!opts.silent) {
  247.                                 opts.error = self.view.fatal;
  248.                         }
  249.                         opts.success = function(data) {
  250.                                 try {
  251.                                         data=$.parseJSON(data);
  252.                                 }
  253.                                 catch(e){
  254.                                         alert('parseJSON: '+e+': '+data);
  255.                                 }
  256.                                 self.ajaxSuccess(opts, data, callback);
  257.                         }
  258.                         opts.lock && this.lock(true);
  259.                         opts.data.order = self.options.order;
  260.                         if(opts.data.cmd == 'open') {
  261.                                 var e = $(window),
  262.                                         w = e.width(),
  263.                                         h = e.height();
  264.                                 switch(this.options.view) {
  265.                                 case 'list':
  266.                                         opts.data.limit = Math.round((h/56)*4);
  267.                                         break;
  268.                                 case 'icon':
  269.                                         opts.data.limit = Math.round(((w/113)*((h/77)+1))*2);
  270.                                         //alert(w+'x'+h+' '+(w/113)+' x '+(h/77));
  271.                                         break;
  272.                                 }
  273.                         }
  274.                         if(!opts.data.init){
  275.                                 opts.data.tree_expanded = [];
  276.                                 this.view.tree.find('ul:visible:not(:first)').each(function(){
  277.                                         opts.data.tree_expanded.push($(this).parent().find('a').attr('key'));
  278.                                 });
  279.                         }
  280.                         if(!opts.data.startDir && this.options.startDir) opts.data.startDir = this.options.startDir;
  281.                        
  282.                         $.ajax(opts);
  283.                 }
  284.                
  285.                 /**
  286.                  * Blubb
  287.                  *
  288.                  * @return null
  289.                  **/
  290.                 this.ajaxSuccess = function(opts, data, callback) {
  291.                         var self = this;
  292.                         opts.lock && this.lock();
  293.                         data.debug && this.log(data.debug);
  294.                        
  295.                         if(data.run){
  296.                                 switch(data.run){
  297.                                 default:
  298.                                         this.view.error('Unknown run method: '+data.run);
  299.                                         break;
  300.                                 case 'page_reload':
  301.                                         setTimeout(function(){document.location = '/';}, 1500);
  302.                                         break;
  303.                                 case 'registered':
  304.                                         //$('[name=s_guest]').attr('name','s_user');
  305.                                         self.options.session.type='s_user';
  306.                                         this.ajax({cwd:'My_files',tree:true}, function(data) {
  307.                                                 self.reload(data);
  308.                                         });
  309.                                         break;
  310.                                 }
  311.                         }
  312.                        
  313.                         if (data.error) {
  314.                                 !opts.silent && this.view.error(data.error, data.errorData);
  315.                                 if (!opts.force && !data.force) {
  316.                                         return;
  317.                                 }
  318.                         }
  319.                         if(data.message && !opts.silent) this.view.message(data.message);
  320.                        
  321.                         if(data.session) $('[name=session]').val(data.session);
  322.                         if(data.startDir) self.options.startDir = data.startDir;
  323.                         callback && callback(data);
  324.                        
  325.                         delete data;
  326.                 }
  327.                
  328.                 /**
  329.                  * Update file manager content
  330.                  *
  331.                  * @param  Object  Data from server
  332.                  **/
  333.                 this.reload = function(data) {
  334.                         var i, currentDir;
  335.                         this.cwd = data.cwd;
  336.                        
  337.                         if(!this.cwd.columns)this.cwd.columns = {name:'Name', time:'Time', size:'Size', hits:'Hits', mime:'Kind'};
  338.                        
  339.                         this.cdc_pos = data.cdc_pos;
  340.                         if(!data.cdc_append) this.cdc = {};
  341.                        
  342.                         if(data.tree) {
  343.                                 this.view.renderNav(data);
  344.                                 this.eventsManager.updateNav();
  345.                         }
  346.                        
  347.                         switch(this.cwd.type) {
  348.                         default:
  349.                                 alert('elFinder.refresh('+this.cwd.type+') not implemented yet');
  350.                                 break;
  351.                         case 'folder':
  352.                                 for (i=0; i<data.cdc.length ; i++) {
  353.                                         this.cdc[data.cdc[i].hash] = data.cdc[i];
  354.                                         this.cwd.size += Number(data.cdc[i].size);
  355.                                 }
  356.                                 this.updateCwd();
  357.                                 if (data.select && data.select.length) {
  358.                                         var l = data.select.length;
  359.                                         while (l--) {
  360.                                                 this.cdc[data.select[l]] && this.selectById(data.select[l]);
  361.                                         }
  362.                                 }
  363.                                 break;
  364.                         case 'file':
  365.                                 this.cdc = {};
  366.                                 this.cdc[this.cwd.hash] = this.cwd;
  367.                                 this.updateCwd();
  368.                                 break;
  369.                         case 'template':
  370.                                 this.cdc = data.cdc;
  371.                                 this.updateCwd();
  372.                                 break;
  373.                         }
  374.                        
  375.                         if (this.options.autoReload>0) {
  376.                                 this.iID && clearInterval(this.iID);
  377.                                 this.iID = setInterval(function() {     !self.locked && self.ui.exec('reload'); }, this.options.autoReload*60000);
  378.                         }
  379.                        
  380.                         if(this.options.onChdir)this.options.onChdir(this);
  381.                 }
  382.                
  383.                 this.openHistory = function(opts) {
  384.                         if(window.History) {
  385.                                 window.History.pushState({
  386.                                         fn:'elfinder.go',
  387.                                         opts:{
  388.                                                 cmd:'open',
  389.                                                 target:opts.hash,
  390.                                                 tree:opts.tree,
  391.                                                 startDir:this.options.startDir
  392.                                         }
  393.                                 },
  394.                                 opts.name,
  395.                                 '/'+opts.hash);
  396.                         }
  397.                         else {
  398.                                 var self = this;
  399.                                 this.ajax({ cmd : 'open', target : opts.hash, tree: opts.tree }, function(data) { self.reload(data); });
  400.                         }
  401.                 }
  402.                 /**
  403.                  * Redraw current directory
  404.                  *
  405.                  */
  406.                 this.updateCwd = function() {
  407.                         this.lockShortcuts();
  408.                         this.selected = [];
  409.                         this.view.renderCwd();
  410.                         this.eventsManager.updateCwd();
  411.                         this.ui.update();
  412.                         this.view.tree.find('a[key="'+this.cwd.hash+'"]').trigger('select');
  413.                 }
  414.                
  415.                 /**
  416.                  * Execute after files was dropped onto folder
  417.                  *
  418.                  * @param  Object  drop event
  419.                  * @param  Object  drag helper object
  420.                  * @param  String  target folder ID
  421.                  */
  422.                 this.drop = function(e, ui, target) {
  423.                         /*if (ui.helper.find('[key="'+target+'"]').length) {
  424.                                 return self.view.error('Unable to copy into itself');
  425.                         }*/
  426.                         var ids = [], sel = this.getSelected(), cut = true, oldBuffer;
  427.                         for(var x in sel) {
  428.                                 ids.push(sel[x].hash);
  429.                                 if(!sel[x].rm) cut = false;
  430.                         }
  431.                         //ui.helper.hide();
  432.                         /*ui.helper.find('div:not(.noaccess):has(>label):not(:has(em[class="readonly"],em[class=""]))').each(function() {
  433.                                 ids.push($(this).hide().attr('key'));
  434.                         });*/
  435.                
  436.                         /*if (!ui.helper.find('div:has(>label):visible').length) {
  437.                                 ui.helper.hide();
  438.                         }*/
  439.                         if (ids.length) {
  440.                                 oldBuffer = self.buffer;
  441.                                 self.setBuffer(ids, e.shiftKey ? false : cut, target);
  442.                                 if (self.buffer.files) {
  443.                                         /* some strange jquery ui bug (in list view) */
  444.                                         setTimeout(function() { self.ui.exec('paste'); self.buffer = oldBuffer; }, 300);
  445.                                 }
  446.                         } else {
  447.                                 $(this).removeClass('el-finder-droppable');
  448.                         }
  449.                 }
  450.                
  451.                 /**
  452.                  * Return selected files data
  453.                  *
  454.                  * @param  Number  if set, returns only element with this index or empty object
  455.                  * @return Array|Object
  456.                  */
  457.                 this.getSelected = function(ndx) {
  458.                         var self = this;
  459.                         function getEl(hash) {
  460.                                 if(!hash) return;
  461.                                 else if(self.cdc[hash]) return self.cdc[hash];
  462.                                 else if(self.cwd.hash == hash) return self.cwd;
  463.                                 else if(self.tree[hash]) return self.tree[hash];
  464.                                 else throw new Exception('fm.getSelected(): key not found');
  465.                         }
  466.                         if (ndx>=0) {
  467.                                 return this.selected[ndx] && getEl(this.selected[ndx]) || {};
  468.                         }
  469.                         for (var i=0, s=[], e; i<this.selected.length; i++) {
  470.                                 e = getEl(this.selected[i]);
  471.                                 e && s.push(e);
  472.                         }
  473.                         return s;
  474.                 }
  475.                
  476.                 this.select = function(el, reset) {
  477.                         reset && $('.ui-selected', self.view.cwd).removeClass('ui-selected');
  478.                         el.addClass('ui-selected');
  479.                         self.updateSelect();
  480.                 }
  481.  
  482.                 this.selectById = function(id) {
  483.                         var el = $('[key="'+id+'"]', this.view.cwd);
  484.                         if (el.length) {
  485.                                 this.select(el);
  486.                                 this.checkSelectedPos();
  487.                         }
  488.                 }
  489.  
  490.                 this.unselect = function(el) {
  491.                         el.removeClass('ui-selected');
  492.                         self.updateSelect();
  493.                 }
  494.  
  495.                 this.toggleSelect = function(el) {
  496.                         el.toggleClass('ui-selected');
  497.                         this.updateSelect();
  498.                 }
  499.  
  500.                 this.selectAll = function() {
  501.                         $('.el-finder-list [key]', self.view.cwd).addClass('ui-selected')
  502.                         self.updateSelect();
  503.                 }
  504.  
  505.                 this.unselectAll = function() {
  506.                         $('.ui-selected', self.view.cwd).removeClass('ui-selected');
  507.                         self.updateSelect();
  508.                 }
  509.  
  510.                 this.updateSelect = function() {
  511.                         self.selected = [];
  512.                         $('.ui-selected', self.view.cwd).each(function() {
  513.                                 self.selected.push($(this).attr('key'));
  514.                         });
  515.                         self.ui.update();
  516.                         //self.quickLook.update();
  517.                 }
  518.  
  519.                 /**
  520.                  * Scroll selected element in visible position
  521.                  *
  522.                  * @param  Boolean  check last or first selected element?
  523.                  */
  524.                 this.checkSelectedPos = function(last) {
  525.                         var s = self.view.cwd.find('.ui-selected:'+(last ? 'last' : 'first')).eq(0),
  526.                                 e = $(window),
  527.                                 p = s.position(),
  528.                                 h = s.outerHeight(),
  529.                                 ph = e.height(),
  530.                                 pt = e.scrollTop();
  531.                         if (p.top - pt < 0) {
  532.                                 if(self.view.cwd.find('.el-finder-list [key]:first').eq(0).attr('key') === s.attr('key')) e.scrollTop(0);
  533.                                 else e.scrollTop(p.top);
  534.                         }
  535.                         else if (p.top + h*3 > pt + ph) e.scrollTop(p.top + h*3 - ph);
  536.                 }
  537.  
  538.                 /**
  539.                  * Add files to clipboard buffer
  540.                  *
  541.                  * @param  Array   files IDs
  542.                  * @param  Boolean copy or cut files?
  543.                  * @param  String  destination folder ID
  544.                  */
  545.                 this.setBuffer = function(files, cut, dst) {
  546.                         var i, id, f;
  547.                         this.buffer = {
  548.                                 src   : this.cwd.hash,
  549.                                 dst   : dst,
  550.                                 files : [],
  551.                                 names : [],
  552.                                 cut   : cut||0
  553.                         };
  554.                        
  555.                         for (i=0; i<files.length; i++) {
  556.                                 id = files[i];
  557.                                 f = this.cdc[id];
  558.                                 if(!f && id == this.cwd.hash) f = this.cwd;
  559.                                 if(!f && this.tree[id]) f = this.tree[id];
  560.                                 if (f && !f.system && f.read && f.type != 'link') {
  561.                                         this.buffer.files.push(f.hash);
  562.                                         this.buffer.names.push(f.name);
  563.                                 }
  564.                         }
  565.                        
  566.                         if (!this.buffer.files.length) {
  567.                                 this.buffer = {};
  568.                         }
  569.                 }
  570.                
  571.                 /**
  572.                  * Return true if file name is acceptable
  573.                  *
  574.                  * @param  String  file/folder name
  575.                  * @return Boolean
  576.                  */
  577.                 this.isValidName = function(n) {
  578.                         return n.match(/^[^\\\/\<\>:]+$/);
  579.                 }
  580.                
  581.                 /**
  582.                  * Return true if file with this name exists
  583.                  *
  584.                  * @param  String  file/folder name
  585.                  * @return Boolean
  586.                  */
  587.                 this.fileExists = function(n) {
  588.                         if(this.cdc.type != 'folder') return false;
  589.                         for (var i in this.cdc) {
  590.                                 if (this.cdc[i].name == n) {
  591.                                         return i;
  592.                                 }
  593.                         }
  594.                         return false;
  595.                 }
  596.                
  597.                 /**
  598.                  * Return name for new file/folder
  599.                  *
  600.                  * @param  String  base name (i18n)
  601.                  * @param  String  extension for file
  602.                  * @return String
  603.                  */
  604.                 this.uniqueName = function(n, ext) {
  605.                         n = self.i18n(n);
  606.                         var name = n, i = 0, ext = ext||'';
  607.  
  608.                         if (!this.fileExists(name+ext)) {
  609.                                 return name+ext;
  610.                         }
  611.  
  612.                         while (i++<100) {
  613.                                 if (!this.fileExists(name+i+ext)) {
  614.                                         return name+i+ext;
  615.                                 }
  616.                         }
  617.                         return name.replace('100', '')+Math.random()+ext;
  618.                 }
  619.  
  620.                 this.time = function() {
  621.                         return new Date().getMilliseconds();
  622.                 }
  623.                
  624.                 /* here we init file manager */
  625.                
  626.                 this.setView(this.cookie(this.vCookie));
  627.                
  628.                 //resize(self.options.width, self.options.height);
  629.                 //      w && self.view.win.width(w);
  630.                 //      h && self.view.nav.add(self.view.cwd).height(h);
  631.                
  632.                 this.ajax({
  633.                         cmd    : 'open',
  634.                         target : this.options.startDir,
  635.                         init   : true,
  636.                         tree   : true
  637.                         },
  638.                         function(data) {
  639.                                 //if (data.cwd) {
  640.                                         if((!self.options.startDir || data.cwd.hash!=self.options.startDir) && data.cwd.hash != 'Error'){
  641.                                                 document.location='/'+data.cwd.hash;
  642.                                                 //window.History.replaceState({fn:'elfinder.go', data:{cmd:'open',target:data.cwd.hash,tree:true}}, data.cwd.name, data.cwd.hash);
  643.                                                 //return;
  644.                                         }
  645.                                         self.eventsManager.init();
  646.                                         self.reload(data);
  647.                                         self.params = data.params;
  648.                                         // self.log(self.params)
  649.                                         $('*', document.body).each(function() {
  650.                                                 var z = parseInt($(this).css('z-index'));
  651.                                                 if (z >= self.zIndex) {
  652.                                                         self.zIndex = z+1;
  653.                                                 }
  654.                                         });
  655.                                         //if(window.History)window.History.pushState({fn:'elfinder.open',data:data},self.cwd.name,'/'+self.cwd.hash);
  656.                                         self.ui.init();
  657.                                 //}
  658.                 }, {force : true});
  659.         }
  660.        
  661.         /**
  662.          * Translate message into selected language
  663.          *
  664.          * @param  String  message in english
  665.          * @param  String  translated or original message
  666.          */
  667.         elFinder.prototype.i18n = function(m) {
  668.                 return this.options.i18n[this.options.lang] && this.options.i18n[this.options.lang][m] ? this.options.i18n[this.options.lang][m] :  m;
  669.         }
  670.        
  671.         /**
  672.          * Default config
  673.          *
  674.          */
  675.         elFinder.prototype.options = {
  676.                 /* connector url. Required! */
  677.                 url            : '',
  678.                 startDir           : '',
  679.                 templates          : {},
  680.                 /* interface language */
  681.                 lang           : 'en',
  682.                 /* additional css class for filemanager container */
  683.                 cssClass       : '',
  684.                 /* characters number to wrap file name in icon view. set to 0 to disable wrap */
  685.                 wrap           : 14,
  686.                 /* i18 messages. not set manually! */
  687.                 i18n           : {},
  688.                 /* fm view (icon|list) */
  689.                 view           : 'list',
  690.                 /* disable shortcuts exclude arrows/space */
  691.                 disableShortcuts : false,
  692.                 /* cookie options */
  693.                 cookie         : {
  694.                         expires : 30,
  695.                         domain  : '',
  696.                         path    : '/',
  697.                         secure  : false
  698.                 },
  699.                 /* buttons on toolbar */
  700.                 toolbar        : [
  701.                         //['back', 'reload'],
  702.                         ['select', 'open'],
  703.                         ['mkdir', 'mkfile', 'upload', 'remote'],
  704.                         ['copy', 'paste', 'rm'],
  705.                         ['rename', 'edit'],
  706.                         //['info', 'quicklook'],
  707.                         ['list', 'icon'],
  708.                         //['help']
  709.                 ],
  710.                 /* contextmenu commands */
  711.                 contextmenu : {
  712.                         'cwd'   : ['get_link', 'delim', 'reload', 'delim', 'mkdir', 'upload', 'remote', 'delim', 'paste', 'delim', 'info'],
  713.                         'file'  : ['get_link', 'delim', 'open', 'delim', 'copy', 'cut', 'rm', 'delim', 'duplicate', 'rename', 'delim', 'info'],
  714.                         'group' : ['get_link', 'delim', 'copy', 'cut', 'rm', 'delim', 'duplicate', 'delim', 'info']
  715.                 },
  716.                 /* auto reload time (min) */
  717.                 autoReload : 0
  718.         }
  719.  
  720.        
  721.         $.fn.elfinder = function(o) {
  722.                
  723.                 return this.each(function() {
  724.                        
  725.                         var cmd = typeof(o) == 'string' ? o : '';
  726.                         if (!this.elfinder) {
  727.                                 this.elfinder = new elFinder(this, typeof(o) == 'object' ? o : {})
  728.                         }
  729.                        
  730.                         switch(cmd) {
  731.                                 case 'close':
  732.                                 case 'hide':
  733.                                         this.elfinder.close();
  734.                                         break;
  735.                                        
  736.                                 case 'open':
  737.                                 case 'show':
  738.                                         this.elfinder.open();
  739.                                         break;
  740.                         }
  741.                        
  742.                 })
  743.         }
  744.        
  745. })(jQuery);
  746.  
  747.  
  748. /**
  749. * @class  Display stuff
  750. * @author dio dio@std42.ru
  751. **/
  752. (function($) {
  753. elFinder.prototype.view = function(fm, el) {
  754.         var self = this;
  755.         this.fm = fm;
  756.         /**
  757.          * Object. Mimetypes to kinds mapping
  758.          **/
  759.         this.kinds = {
  760.                 'unknown'                       : 'Unknown',
  761.                 'directory'                     : 'Folder',
  762.                 'symlink'                       : 'Alias',
  763.                 'symlink-broken'                : 'Broken alias',
  764.                 'application/x-empty'           : 'Plain text',
  765.                 'application/postscript'        : 'Postscript document',
  766.                 'application/octet-stream'      : 'Application',
  767.                 'application/vnd.ms-office'     : 'Microsoft Office document',
  768.                 'application/vnd.ms-word'       : 'Microsoft Word document'
  769.             'application/vnd.ms-excel'      : 'Microsoft Excel document',
  770.                 'application/vnd.ms-powerpoint' : 'Microsoft Powerpoint presentation',
  771.                 'application/pdf'               : 'Portable Document Format (PDF)',
  772.                 'application/vnd.oasis.opendocument.text' : 'Open Office document',
  773.                 'application/x-shockwave-flash' : 'Flash application',
  774.                 'application/xml'               : 'XML document',
  775.                 'application/x-bittorrent'      : 'Bittorrent file',
  776.                 'application/x-7z-compressed'   : '7z archive',
  777.                 'application/x-tar'             : 'TAR archive',
  778.             'application/x-gzip'            : 'GZIP archive',
  779.             'application/x-bzip2'           : 'BZIP archive',
  780.             'application/zip'               : 'ZIP archive'
  781.             'application/x-rar'             : 'RAR archive',
  782.                 'application/javascript'        : 'Javascript application',
  783.                 'text/plain'                    : 'Plain text',
  784.             'text/x-php'                    : 'PHP source',
  785.                 'text/html'                     : 'HTML document',
  786.                 'text/javascript'               : 'Javascript source',
  787.                 'text/css'                      : 'CSS style sheet'
  788.             'text/rtf'                      : 'Rich Text Format (RTF)',
  789.                 'text/rtfd'                     : 'RTF with attachments (RTFD)',
  790.                 'text/x-c'                      : 'C source',
  791.                 'text/x-c++'                    : 'C++ source',
  792.                 'text/x-shellscript'            : 'Unix shell script',
  793.             'text/x-python'                 : 'Python source',
  794.                 'text/x-java'                   : 'Java source',
  795.                 'text/x-ruby'                   : 'Ruby source',
  796.                 'text/x-perl'                   : 'Perl script',
  797.             'text/xml'                      : 'XML document',
  798.                 'image/x-ms-bmp'                : 'BMP image',
  799.             'image/jpeg'                    : 'JPEG image',   
  800.             'image/gif'                     : 'GIF Image',   
  801.             'image/png'                     : 'PNG image',
  802.                 'image/x-targa'                 : 'TGA image',
  803.             'image/tiff'                    : 'TIFF image',   
  804.             'image/vnd.adobe.photoshop'     : 'Adobe Photoshop image',
  805.                 'audio/mpeg'                    : 'MPEG audio'
  806.                 'audio/midi'                    : 'MIDI audio',
  807.                 'audio/ogg'                     : 'Ogg Vorbis audio',
  808.                 'audio/mp4'                     : 'MP4 audio',
  809.                 'audio/wav'                     : 'WAV audio',
  810.                 'video/x-dv'                    : 'DV video',
  811.                 'video/mp4'                     : 'MP4 video',
  812.                 'video/mpeg'                    : 'MPEG video'
  813.                 'video/x-msvideo'               : 'AVI video',
  814.                 'video/quicktime'               : 'Quicktime video',
  815.                 'video/x-ms-wmv'                : 'WM video',   
  816.                 'video/x-flv'                   : 'Flash video',
  817.                 'video/x-matroska'              : 'Matroska video'
  818.         }
  819.        
  820.         this.tlb = $('<ul />');
  821.  
  822.         this.nav = $('<div class="el-finder-nav"/>').resizable({handles : 'e', autoHide : true, minWidth : 200, maxWidth: 500});
  823.         this.cwd = $('<div class="el-finder-cwd"/>').attr('unselectable', 'on');
  824.         this.spn = $('<div class="el-finder-spinner"/>');
  825.         this.err = $('<p class="el-finder-err"><strong/></p>').click(function() { $(this).hide(); });
  826.         this.msg = $('<p class="el-finder-msg"><strong/></p>').click(function() { $(this).hide(); });
  827.         this.wrz = $('<div class="el-finder-workzone"/>')
  828.                 .append(this.nav)
  829.                 .append(this.cwd)
  830.                 .append(this.spn)
  831.                 .append(this.err)
  832.                 .append(this.msg)
  833.                 .append('<div style="clear:both"/>');
  834.         this.win = $(el).empty().attr('id', this.fm.id).addClass('el-finder '+(fm.options.cssClass||''))
  835.                 .append($('<div class="el-finder-toolbar"/>').append(this.tlb))
  836.                 .append(this.wrz);
  837.                 //.append(this.stb);
  838.  
  839.         this.tree = $('<ul class="el-finder-tree"></ul>').appendTo(this.nav);
  840.         this.uploads = $('#FileUploadFiles').detach().appendTo(this.nav).prepend('<hr/>');
  841.         this.nav.append('<div style="text-align:center;"><div style="width:160px;height:600px;background:#999;margin:0 auto;">Banner AD 160x600</div></div>');
  842.  
  843.  
  844.         /*
  845.          * Render ajax spinner
  846.         */
  847.         this.spinner = function(show) {
  848.                 this.win.toggleClass('el-finder-disabled', show);
  849.                 this.spn.toggle(show);
  850.         }
  851.        
  852.         /*
  853.          * Display ajax error
  854.         */
  855.         this.fatal = function(t) {
  856.                 self.error(t.status != '404' ? 'Invalid backend configuration' : 'Unable to connect to backend')
  857.         }
  858.        
  859.         /*
  860.          * Render error
  861.         */
  862.         this.error = function(err, data) {
  863.                 this.fm.lock();
  864.                 this.err.show().children('strong').html(this.fm.i18n(err)+' '+this.formatErrorData(data));
  865.                 setTimeout(function() { self.err.fadeOut('slow'); }, 4000);
  866.         }
  867.        
  868.         /*
  869.          * Render message
  870.         */
  871.         this.message = function(msg) {
  872.                 this.fm.lock();
  873.                 this.msg.show().children('strong').html(msg);
  874.                 setTimeout(function() { self.msg.fadeOut('slow'); }, 4000);
  875.         }
  876.        
  877.         /*
  878.          * Render navigation panel with dirs tree
  879.         */
  880.         this.renderNav = function(data) {
  881.                 var self = this;
  882.                
  883.                 if(!data.tree_expanded){
  884.                         data.tree_expanded = [];
  885.                         this.tree.find('ul:visible:not(:first)').each(function(){
  886.                                 data.tree_expanded.push($(this).parent().find('a').attr('key'));
  887.                         });
  888.                 }
  889.                 if(data.treeEntryPoint){
  890.                         x = this.tree.find('a[key='+data.treeEntryPoint+']');
  891.                         x.parent().find('a[key]').each(function(k, v){
  892.                                 delete self.fm.tree[v.getAttribute('key')];
  893.                         });
  894.                         x.parent().replaceWith(traverse(data.tree, false).find('li:first'));
  895.                 }
  896.                 else {
  897.                         this.fm.tree = {};
  898.                         this.tree.html(traverse(data.tree, true));
  899.                 }
  900.                 if(data.tree_expanded){
  901.                         for(var i in data.tree_expanded) {
  902.                                 this.tree.find('[key='+data.tree_expanded[i]+']').find('div').addClass('expanded').parent().next('ul').show();
  903.                         }
  904.                 }
  905.                
  906.                 function traverse(tree, root) {
  907.                         var i, hash, c, ul = $('<ul/>'), li;
  908.                         root || ul.css({display:'none'});
  909.                         for(i = 0; i < tree.length; i++) {
  910.                                 if(tree[i] == 'delim') {
  911.                                         $('<li><hr/></li>').appendTo(ul);
  912.                                         continue;
  913.                                 }
  914.                                 self.fm.tree[tree[i].hash] = tree[i];
  915.                                 c = '';
  916.                                 if(!tree[i].read && !tree[i].write) c = 'noaccess';
  917.                                 else if(!tree[i].read) c = 'dropbox';
  918.                                 else if(!tree[i].write) c = 'readonly';
  919.                                 if(tree[i].type == 'file') c += ' el-finder-nav-file';
  920.                                
  921.                                 li = $('<li><a href="/'+tree[i].hash+'" class="'+c+'" key="'+tree[i].hash+'"><div'+(tree[i].dirs.length ? ' class="collapsed"' : '')+'/>'+tree[i].name+'</a></li>');
  922.  
  923.                                 if (tree[i].dirs.length) {
  924.                                         li.append(traverse(tree[i].dirs));
  925.                                 }
  926.                                 //if(root && i == 0) li.append('<hr/>');
  927.                                 li.appendTo(ul);
  928.                         }
  929.                         return ul;
  930.                 }
  931.         }
  932.        
  933.         /*
  934.          * Render current directory
  935.         */
  936.         this.renderCwd = function() {
  937.                 this.cwd.empty();
  938.                
  939.                 switch(this.fm.cwd.type) {
  940.                 default:
  941.                         return alert('elFinder.renderCwd('+this.cwd.type+') not implemented yet');
  942.                 case 'file':
  943.                         return this.renderFile();
  944.                 case 'template':
  945.                         return this.renderTemplate();
  946.                 case 'folder':
  947.                         return this.renderFolder();
  948.                 }
  949.                
  950.                 /*var s = '', hash = this.fm.cwd.hash, e, i;
  951.                 for(;;) {
  952.                         i = this.tree.find('[key='+hash+']');
  953.                         if(!i.length) break;
  954.                         s = '/<a href="/'+hash+'/" key="'+hash+'">'+i.text()+'</a>'+s;
  955.                         i = i.parent('li').parent('ul').prev();
  956.                         hash = i.attr('key');
  957.                 }*/
  958.         }
  959.  
  960.         this.renderFile = function() {
  961.                 this.renderTemplate('cwd-info');
  962.                 this.renderTemplate('file');
  963.                 if(this.fm.cwd.session.init_status == 'wait') {
  964.                         var wait = this.fm.cwd.session.time_waiting,
  965.                                 interval = setInterval(function(){
  966.                                         if(--wait <= 0){
  967.                                                 clearInterval(interval);
  968.                                                 $('#WaitForDownloadTicket').hide().next().show();
  969.                                                 return;
  970.                                         }
  971.                                         $('#WaitForDownloadTicket span').html(wait);
  972.                                 }, 1000);
  973.                 }
  974.                 if(this.fm.cwd.session.init_status != 'ok') return;
  975.                 switch(this.fm.cwd.session.mime_class) {
  976.                 case 'txt':
  977.                         $('.text-tab').click(function(){{
  978.                                 $('.text-tab').removeClass('active');
  979.                                 $('.text-content').hide();
  980.                                 $(this).addClass('active');
  981.                                 $('#'+this.getAttribute('data-id')).show();
  982.                         }});
  983.                         $.getJSON(
  984.                                 this.fm.cwd.session.link_special+'?cb=?',
  985.                                 function(d){{
  986.                                         if(d.code)$('#text-code').html(unescape(d.code));
  987.                                         else $('.text-code').remove();
  988.                                         $('#text-plain,#text-edit textarea').html(unescape(d.plain));
  989.                                         $('.text-tab.text-'+(d.code?'code':'plain')).trigger('click');
  990.                                         $('#TextView')
  991.                                                 .tabs()
  992.                                                 .show();
  993.                                 }}
  994.                         );
  995.                         break;
  996.                 case 'flv':
  997.                 case 'mp4':
  998.                         var playlist = [];
  999.                         this.fm.cwd.session.splash && playlist.push({url:this.fm.cwd.session.splash, autoPlay:true});
  1000.                         playlist.push({url:this.fm.cwd.session.link_special, autoPlay:false});
  1001.                         $f('FlashVideoPlayer','/lib/swf/flowplayer-3.2.7.swf',{
  1002.                                 pageUrl:'/'+this.fm.cwd.hash,
  1003.                                 playlist:playlist,
  1004.                                 plugins:{
  1005.                                         flvseek:{url:'/lib/swf/flowplayer.pseudostreaming-3.2.7.swf'},
  1006.                                         controls:{url:'/lib/swf/flowplayer.controls-3.2.5.swf'},
  1007.                                         sharing:{
  1008.                                                 url:'/lib/swf/flowplayer.sharing-3.2.1.swf',
  1009.                                                 embed:false,
  1010.                                                 email:{subject:'Found a nice video on {BASE_DOMAIN}'}
  1011.                                         }
  1012.                                 }
  1013.                         });
  1014.                         break;
  1015.                 case 'mp3':
  1016.                         $f('FlashAudioPlayer','/lib/swf/flowplayer-3.2.7.swf',{
  1017.                                 clip:{
  1018.                                         url:this.fm.cwd.session.link_special,
  1019.                                         autoPlay:false
  1020.                                 },
  1021.                                 plugins:{
  1022.                                         controls:{
  1023.                                                 url:'/lib/swf/flowplayer.controls-3.2.5.swf',
  1024.                                                 fullscreen:false,
  1025.                                                 height:30,
  1026.                                                 autoHide:false
  1027.                                         },
  1028.                                         audio:{url:'/lib/swf/flowplayer.audio-3.2.2.swf'}
  1029.                                 }
  1030.                         });
  1031.                         break;
  1032.                 }
  1033.         }
  1034.         this.renderTemplate = function(name, opts) {
  1035.                 if(name == 'cwd-info' && typeof(this.fm.cwd.pth) == 'undefined') {
  1036.                         this.fm.cwd.pth = [];
  1037.                         var self = this, hash;
  1038.                         this.tree
  1039.                                 .find('[key='+this.fm.cwd.hash+']')
  1040.                                 .parents('ul').each(function(i, e) {
  1041.                                         hash = $(e).prev().attr('key');
  1042.                                         if(hash)self.fm.cwd.pth.push(hash);
  1043.                                 });
  1044.                         this.fm.cwd.pth.reverse();
  1045.                 }
  1046.                 var tmpl = $.tmpl('FM-'+(name||this.fm.cdc.template), $.extend({self:this, tree:this.fm.tree, cwd:this.fm.cwd, cdc:this.fm.cdc}, opts||{}))
  1047.                         .appendTo(this.cwd)
  1048.                         .wrap('<div class="el-finder-template"/>');
  1049.                 if(name == 'cwd-info') this.fm.eventsManager.updateCwdInfo(tmpl);
  1050.                 this.fm.eventsManager.updateCwdTemplate(tmpl);
  1051.         }
  1052.         this.renderFolder = function() {
  1053.                 if(!this.fm.cwd.system) this.renderTemplate('cwd-info');
  1054.                 var self = this,
  1055.                         num = 0,
  1056.                         size = 0,
  1057.                         t = $('<div class="el-finder-list"/>').append(this.renderTableHeader(this.fm.cwd.columns, true)),
  1058.                         u = this.fm.options.view == 'list' ? t.find('table') : t;
  1059.                 for (var hash in this.fm.cdc) {
  1060.                         size += Number(this.fm.cdc[hash].size);
  1061.                         this.renderItem(this.fm.options.view, this.fm.cdc[hash], num++%2).appendTo(u);
  1062.                 }
  1063.                 t.appendTo(this.cwd);
  1064.                
  1065.                 if(!num) {
  1066.                         t.hide();
  1067.                         this.fm.cwd.empty = true;
  1068.                         this.fm.cwd.write && this.renderTemplate('empty-folder');
  1069.                         return;
  1070.                 }
  1071.                 if(num == 1 && this.fm.options.view == 'icon') t.find('table').hide();
  1072.                
  1073.                 this.fm.eventsManager.updateCwdMore();
  1074.         }
  1075.        
  1076.        
  1077.        
  1078.         this.renderTableHeader = function(columns, order) {
  1079.                 var tmpl = $.tmpl(
  1080.                         'FM-item-table-header',
  1081.                         {
  1082.                                 self:this,
  1083.                                 cwd:this.fm.cwd,
  1084.                                 tableOrder:order
  1085.                         });
  1086.                 if(order) {
  1087.                         tmpl.find('th').css({cursor:'pointer'}).click(function(){self.fm.setOrder($(this).attr('orderCol'));})
  1088.                         tmpl.find('[orderCol='+this.fm.options.order.replace(/^-/,'')+']').addClass(this.fm.options.order.match(/^-/) ? 'desc' : 'asc');
  1089.                 }
  1090.                 return tmpl;
  1091.         }
  1092.        
  1093.         this.renderItem = function(tmpl, item, odd) {
  1094.                 return $.tmpl(
  1095.                         'FM-item-'+tmpl,
  1096.                         {
  1097.                                 self    : this,
  1098.                                 cwd          : this.fm.cwd,
  1099.                                 mimeSize: 'big',
  1100.                                 odd          : odd||false,
  1101.                                 f              : item,
  1102.                                 img          : item.ico||item.tmb||false,
  1103.                                 mimeStr : this.mime2class(item.mime)
  1104.                         });
  1105.         }
  1106.  
  1107.         /*
  1108.          * Re-render file (after editing)
  1109.         */
  1110.         this.updateFile = function(f) {
  1111.                 this.cwd.find('[key="'+f.hash+'"]').replaceWith(renderItem(this.fm.options.view, f, false));
  1112.         }
  1113.  
  1114.         /*
  1115.          * Return wraped file name if needed
  1116.         */
  1117.         this.formatName = function(n) {
  1118.                 var w = self.fm.options.wrap;
  1119.                 if (w>0) {
  1120.                         if (n.length > w*2) {
  1121.                                 return n.substr(0, w)+"&shy;"+n.substr(w, w-5)+"&hellip;"+n.substr(n.length-3);
  1122.                         } else if (n.length > w) {
  1123.                                 return n.substr(0, w)+"&shy;"+n.substr(w);
  1124.                         }
  1125.                 }
  1126.                 return n;
  1127.         }
  1128.  
  1129.         /*
  1130.          * Return error message
  1131.         */
  1132.         this.formatErrorData = function(data) {
  1133.                 var i, err = ''
  1134.                 if (typeof(data) == 'object') {
  1135.                         err = '<br />';
  1136.                         for (i in data) {
  1137.                                 err += i+' '+self.fm.i18n(data[i])+'<br />';
  1138.                         }
  1139.                 }
  1140.                 return err;
  1141.         }
  1142.  
  1143.         /*
  1144.          * Convert mimetype into css class
  1145.         */
  1146.         this.mime2class = function(mime) {
  1147.                 return String(mime).replace('/' , ' ').replace(/\./g, '-');
  1148.         }
  1149.  
  1150.         /*
  1151.          * Return localized date
  1152.         */
  1153.         this.formatTime = function(d) {
  1154.                 return d ? d.replace(/([a-z]+)\s/i, function(a1, a2) { return self.fm.i18n(a2)+' '; }) : '';
  1155.         }
  1156.  
  1157.         /*
  1158.          * Return formated file size
  1159.         */
  1160.         this.formatSize = function(s) {
  1161.                 if(!s) return 0;
  1162.                 var n = 1, u = '';
  1163.                 if (s > 1073741824) {
  1164.                         n = 1073741824;
  1165.                         u = 'Gb';
  1166.                 } else if (s > 1048576) {
  1167.             n = 1048576;
  1168.             u = 'Mb';
  1169.         } else if (s > 1024) {
  1170.             n = 1024;
  1171.             u = 'Kb';
  1172.         }
  1173.         return Math.round(s/n)+' '+u;
  1174.         }
  1175.  
  1176.         /*
  1177.          * Return kind of file
  1178.         */
  1179.         this.mime2kind = function(mime) {
  1180.                 return this.fm.i18n(this.kinds[mime]||'unknown');
  1181.         }
  1182.        
  1183. }
  1184. })(jQuery);
  1185.  
  1186.  
  1187. /**
  1188. * @class elFinder user Interface.
  1189. * @author dio dio@std42.ru
  1190. **/
  1191. (function($) {
  1192. elFinder.prototype.ui = function(fm) {
  1193.        
  1194.         var self        = this;
  1195.         this.fm         = fm;
  1196.         this.cmd        = {};
  1197.         this.buttons    = {};
  1198.         this.menu       = $('<div class="el-finder-contextmenu" />').appendTo(document.body).hide();
  1199.        
  1200.         this.exec = function(cmd, arg) {
  1201.                 if (this.cmd[cmd]) {
  1202.                         if (!this.fm.locked) {
  1203.                                 $('.el-finder-info').remove();
  1204.                                 this.cmd[cmd].exec(arg);
  1205.                                 this.update();
  1206.                         }
  1207.                 }
  1208.         }
  1209.        
  1210.         this.cmdName = function(cmd) {
  1211.                 if (this.cmd[cmd] && this.cmd[cmd].name) {
  1212.                         return this.fm.i18n(this.cmd[cmd].name);
  1213.                 }
  1214.                 return cmd;
  1215.         }
  1216.        
  1217.         this.isCmdAllowed = function(cmd) {
  1218.                 return self.cmd[cmd] && self.cmd[cmd].isAllowed();
  1219.         }
  1220.        
  1221.         this.execIfAllowed = function(cmd) {
  1222.                 this.isCmdAllowed(cmd) && this.exec(cmd);
  1223.         }
  1224.        
  1225.         this.includeInCm = function(cmd, t) {
  1226.                 return this.isCmdAllowed(cmd) && this.cmd[cmd].cm(t);
  1227.         }
  1228.        
  1229.         this.showMenu = function(e) {
  1230.                 var t, win, size, id = '';
  1231.                 this.hideMenu();
  1232.                
  1233.                 if (!self.fm.selected.length) {
  1234.                         t = 'cwd';
  1235.                 } else if (self.fm.selected.length == 1) {
  1236.                         t = 'file';
  1237.                 } else {
  1238.                         t = 'group';
  1239.                 }
  1240.                
  1241.                 menu(t);
  1242.                
  1243.                 win = $(window);
  1244.                 size = {
  1245.           sT     : win.scrollTop(),
  1246.           cW     : this.menu.width(),
  1247.           cH     : this.menu.height()
  1248.             };
  1249.                 this.menu
  1250.                         .css({
  1251.                                 left : ((e.clientX + size.cW) > size.width ? ( e.clientX - size.cW) : e.clientX),
  1252.                                 top  : ((e.clientY + size.cH) > size.height && e.clientY > size.cH ? (e.clientY + size.sT - size.cH) : e.clientY + size.sT)
  1253.                         })
  1254.                         .show()
  1255.                         .find('div[name]')
  1256.                         .hover(
  1257.                                 function() {
  1258.                                         var t = $(this), s = t.children('div'), w;
  1259.                                         t.addClass('hover');
  1260.                                         if (s.length) {
  1261.                                                 if (!s.attr('pos')) {
  1262.                                                         w  = t.outerWidth();
  1263.                                                         s.css($(window).width() - w - t.offset().left > s.width() ? 'left' : 'right', w-5).attr('pos', true);
  1264.                                                 }
  1265.                                                 s.show();
  1266.                                         }
  1267.                                 },
  1268.                                 function() { $(this).removeClass('hover').children('div').hide(); }
  1269.                         ).click(function(e) {
  1270.                                 e.stopPropagation();
  1271.                                 var t = $(this);
  1272.                                 if (!t.children('div').length) {
  1273.                                         self.hideMenu();
  1274.                                         self.exec(t.attr('name'), t.attr('argc'));
  1275.                                 }
  1276.                         });
  1277.                 // self.fm.log(self.menu.html())
  1278.                 function menu(t) {
  1279.                         var i, j, a, html, l, src = self.fm.options.contextmenu[t]||[];
  1280.                         for (i=0; i < src.length; i++) {
  1281.                                 if (src[i] == 'delim') {
  1282.                                         self.menu.children().length && !self.menu.children(':last').hasClass('delim') && self.menu.append('<div class="delim" />');
  1283.                                 } else if (self.fm.ui.includeInCm(src[i], t)) {
  1284.                                         a = self.cmd[src[i]].argc();
  1285.                                         html = '';
  1286.  
  1287.                                         if (a.length ) {
  1288.                                                 html = '<span/><div class="el-finder-contextmenu-sub" style="z-index:'+(parseInt(self.menu.css('z-index'))+1)+'">';
  1289.                                                 for (var j=0; j < a.length; j++) {
  1290.                                                         html += '<div name="'+src[i]+'" argc="'+a[j].argc+'" class="'+a[j]['class']+'">'+a[j].text+'</div>';
  1291.                                                 };
  1292.                                                 html += '</div>';
  1293.                                         }
  1294.                                         self.menu.append('<div class="'+src[i]+'" name="'+src[i]+'">'+html+self.cmdName(src[i])+'</div>');
  1295.                                 }
  1296.                         };
  1297.                 }
  1298.         }
  1299.        
  1300.         this.hideMenu = function() {
  1301.                 this.menu.hide().empty();
  1302.         }
  1303.        
  1304.         this.update = function() {
  1305.                 for (var i in this.buttons) {
  1306.                         this.buttons[i].toggleClass('disabled', !this.cmd[i].isAllowed());
  1307.                 }
  1308.         }
  1309.        
  1310.         this.init = function() {
  1311.                 var i, j, n, c=false, zindex = 2, z, fm=this.fm, t = fm.options.toolbar, name;
  1312.                 for (i in this.commands) {
  1313.                         this.commands[i].prototype = this.command.prototype;
  1314.                         this.cmd[i] = new this.commands[i](this.fm);
  1315.                 }
  1316.                 for (i=0; i<t.length; i++) {
  1317.                         if (c) {
  1318.                                 this.fm.view.tlb.append('<li class="delim"></li>');
  1319.                         }
  1320.                         c = false;
  1321.                         for (j=0; t[i] && j<t[i].length; j++) {
  1322.                                 n = t[i][j];
  1323.                                 if (this.cmd[n]) {
  1324.                                         c = true;
  1325.                                         name = this.cmdName(n);
  1326.                                         this.buttons[n] = $('<li class="'+n+'" name="'+n+'"><p/>'+name+'</li>')
  1327.                                                 .appendTo(this.fm.view.tlb)
  1328.                                                 .click(function(e) { e.stopPropagation(); })
  1329.                                                 .bind('click', (function(ui){ return function() { 
  1330.                                                                 !$(this).hasClass('disabled') && ui.exec($(this).attr('name'));
  1331.                                                         } })(this)
  1332.                                                 ).hover(
  1333.                                                         function() { !$(this).hasClass('disabled') && $(this).addClass('el-finder-tb-hover')},
  1334.                                                         function() { $(this).removeClass('el-finder-tb-hover')}
  1335.                                                 );
  1336.                                         if(n=='upload')
  1337.                                                 this.buttons[n].mouseover(function(){
  1338.                                                         if(fm.cwd.write && fm.cwd.type == 'folder')
  1339.                                                                 if($.browser.opera)fileinputFuckaround(this);
  1340.                                                 });
  1341.                                 }
  1342.                         }
  1343.                 }
  1344.                 this.update();
  1345.                 /* set z-index for context menu */
  1346.                 this.menu.css('z-index', this.fm.zIndex);
  1347.         }
  1348.  
  1349. }
  1350.  
  1351.  
  1352. /**
  1353. * @class elFinder user Interface Command.
  1354. * @author dio dio@std42.ru
  1355. **/
  1356. elFinder.prototype.ui.prototype.command = function(fm) {  }
  1357.  
  1358. /**
  1359. * Return true if command can be applied now
  1360. * @return Boolean
  1361. **/
  1362. elFinder.prototype.ui.prototype.command.prototype.isAllowed = function() {
  1363.         return true;
  1364. }
  1365.  
  1366. /**
  1367. * Return true if command can be included in contextmenu of required type
  1368. * @param  String  contextmenu type (cwd|group|file)
  1369. * @return Boolean
  1370. **/
  1371. elFinder.prototype.ui.prototype.command.prototype.cm = function(t) {
  1372.         return false;
  1373. }
  1374.  
  1375. /**
  1376. * Return not empty array if command required submenu in contextmenu
  1377. * @return Array
  1378. **/
  1379. elFinder.prototype.ui.prototype.command.prototype.argc = function(t) {
  1380.         return [];
  1381. }
  1382.  
  1383.  
  1384. elFinder.prototype.ui.prototype.commands = {
  1385.        
  1386.         /**
  1387.          * @class Go into previous folder
  1388.          * @param Object  elFinder
  1389.          **/
  1390.         back : function(fm) {
  1391.                 var self = this;
  1392.                 this.name = 'Back';
  1393.                 this.fm = fm;
  1394.                
  1395.                 this.exec = function() {
  1396.                         window.history.back();
  1397.                 }
  1398.                
  1399.                 this.isAllowed = function() {
  1400.                         return true;
  1401.                 }
  1402.                
  1403.         },
  1404.        
  1405.         /**
  1406.          * @class Reload current directory and navigation panel
  1407.          * @param Object  elFinder
  1408.          **/
  1409.         reload : function(fm) {
  1410.                 var self  = this;
  1411.                 this.name = 'Reload';
  1412.                 this.fm   = fm;
  1413.                
  1414.                 this.exec = function() {
  1415.                         this.fm.ajax({ cmd : 'open', target : this.fm.cwd.hash, tree : true }, function(data) {
  1416.                                 self.fm.reload(data);
  1417.                         });
  1418.                 }
  1419.                
  1420.                 this.cm = function(t) {
  1421.                         return t == 'cwd';
  1422.                 }
  1423.         },
  1424.        
  1425.         /**
  1426.          * @class Open file/folder
  1427.          * @param Object  elFinder
  1428.          **/
  1429.         open : function(fm) {
  1430.                 var self  = this;
  1431.                 this.name = 'Open';
  1432.                 this.fm   = fm;
  1433.                
  1434.                 /**
  1435.                  * Open file/folder
  1436.                  * @param String  file/folder id (only from click on nav tree)
  1437.                  **/
  1438.                 this.exec = function(dir) {
  1439.                         var t = null;
  1440.                         if (dir) {
  1441.                                 t = self.fm.tree[$(dir).attr('key')];
  1442.                         } else {
  1443.                                 t = this.fm.getSelected(0);
  1444.                         }
  1445.  
  1446.                         if (!t.hash) {
  1447.                                 return;
  1448.                         }
  1449.                         if (!t.read) {
  1450.                                 return this.fm.view.error('Access denied');
  1451.                         }
  1452.                         /*if (t.type == 'link' && !t.link) {
  1453.                                 return this.fm.view.error('Unable to open broken link');
  1454.                         }*/
  1455.                        
  1456.                         open(t);
  1457.                         /*if (t.mime == 'directory') {
  1458.                                 openDir(t.link||t.hash);
  1459.                         } else {
  1460.                                 openFile(t);
  1461.                         }*/
  1462.                        
  1463.                         function open(t) {
  1464.                                 /*for(x in t) alert(x+'='+t[x]+'; ');
  1465.                                 alert(''+self.fm.cwd.type+' = '+t+' = '+((self.fm.cwd.type == 'file' || t.type == 'file') ? true : false ))*/
  1466.                                 self.fm.openHistory({
  1467.                                         name:t.name,
  1468.                                         hash:t.hash,
  1469.                                         //tree:false
  1470.                                         tree:t.type != 'folder' || self.fm.cwd.type != 'folder'
  1471.                                 });
  1472.                         }
  1473.                        
  1474.                         function openFile(f) {
  1475.                                 window.open('/'+f.hash, false, 'top=50,left=50,scrollbars=yes,resizable=yes');
  1476.                                 return;
  1477.                                 var s, ws = '';
  1478.                                 if (f.dim) {
  1479.                                         s  = f.dim.split('x');
  1480.                                         ws = 'width='+(parseInt(s[0])+20)+',height='+(parseInt(s[1])+20)+',';
  1481.                                 }
  1482.                                 window.open(f.url);
  1483.                         }
  1484.                 }
  1485.        
  1486.                 this.isAllowed = function() {
  1487.                         return this.fm.selected.length == 1 && this.fm.getSelected(0).read && this.fm.getSelected(0).exec;
  1488.                 }
  1489.                
  1490.                 this.cm = function(t) {
  1491.                         return t == 'file';
  1492.                 }
  1493.                
  1494.         },
  1495.        
  1496.         /**
  1497.          * @class Display files/folders info in dialog window
  1498.          * @param Object  elFinder
  1499.          **/
  1500.         info : function(fm) {
  1501.                 var self  = this;
  1502.                 this.name = 'Get info';
  1503.                 this.fm   = fm;
  1504.                
  1505.                 /**
  1506.                  * Open dialog windows for each selected file/folder or for current folder
  1507.                  **/
  1508.                 this.exec = function() {
  1509.                         var f, s, cnt = this.fm.selected.length, w = $(window).width(), h = $(window).height();
  1510.                         this.fm.lockShortcuts(true);
  1511.                         if (!cnt) {
  1512.                                 /** nothing selected - show cwd info **/
  1513.                                 info(self.fm.cwd);
  1514.                         } else {
  1515.                                 /** show info for each selected obj **/
  1516.                                 $.each(this.fm.getSelected(), function() {
  1517.                                         info(this);
  1518.                                 });
  1519.                         }
  1520.                        
  1521.                         function info(f) {
  1522.                                 var p = ['50%', '50%'], x, y, d,
  1523.                                         tb = '<table cellspacing="0"><tr><td>'+self.fm.i18n('Name')+'</td><td>'+f.name+'</td></tr><tr><td>'+self.fm.i18n('Link')+'</td><td><a href="/'+f.hash+'">/'+f.hash+'</a></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.time)+'</td></tr><tr><td>'+self.fm.i18n('Hits')+'</td><td>'+(f.hits||0)+'</td></tr>';
  1524.                                
  1525.                                 if (f.link) {
  1526.                                         tb += '<tr><td>'+self.fm.i18n('Link to')+'</td><td>'+f.linkTo+'</td></tr>';
  1527.                                 }
  1528.                                 if (f.dim) {
  1529.                                         tb += '<tr><td>'+self.fm.i18n('Dimensions')+'</td><td>'+f.dim+' px.</td></tr>';
  1530.                                 }
  1531.                                 if (f.url) {
  1532.                                         tb += '<tr><td>'+self.fm.i18n('URL')+'</td><td><a href="'+f.url+'" target="_blank">'+f.url+'</a></td></tr>';
  1533.                                 }
  1534.  
  1535.                                 if (cnt>1) {
  1536.                                         d = $('.el-finder-dialog-info:last');
  1537.                                         if (!d.length) {
  1538.                                                 x = Math.round(((w-350)/2)-(cnt*10));
  1539.                                                 y = Math.round(((h-300)/2)-(cnt*10));
  1540.                                                 p = [x>20?x:20, y>20?y:20];
  1541.                                         } else {
  1542.                                                 x = d.offset().left+10;
  1543.                                                 y = d.offset().top+10;
  1544.                                                 p = [x<w-350 ? x : 20, y<h-300 ? y : 20];
  1545.                                         }
  1546.                                 }
  1547.  
  1548.                                 $('<div />').append(tb+'</table>').dialog({
  1549.                                         dialogClass : 'el-finder-dialog el-finder-dialog-info',
  1550.                                         width       : 390,
  1551.                                         position    : p,
  1552.                                         title       : self.fm.i18n(f.mime == 'directory' ? 'Folder info' : 'File info'),
  1553.                                         close       : function() { if (--cnt <= 0) { self.fm.lockShortcuts(); } $(this).dialog('destroy'); },
  1554.                                         buttons     : { Ok : function() { $(this).dialog('close'); }}
  1555.                                 });
  1556.                         }
  1557.                 }
  1558.        
  1559.                 this.cm = function(t) {
  1560.                         return this.fm.cwd.type == 'folder';
  1561.                 }
  1562.         },
  1563.        
  1564.         /**
  1565.          * @class Rename file/folder
  1566.          * @param Object elFinder
  1567.          **/
  1568.         rename : function(fm) {
  1569.                 var self  = this;
  1570.                 this.name = 'Rename';
  1571.                 this.fm   = fm;
  1572.                
  1573.                 this.exec = function() {
  1574.                         var s = this.fm.getSelected(), el, c, input, f, n;
  1575.                        
  1576.                         if (s.length == 1) {
  1577.                                 f  = s[0];
  1578.                                 el = this.fm.view.cwd.find('[key="'+f.hash+'"]');
  1579.                                 c  = this.fm.options.view == 'icon' ? el.children('label') : el.find('td').eq(1);
  1580.                                 n  = c.html();
  1581.                                 input = $('<input type="text" />').css({width:'100%'}).val(f.name).appendTo(c.empty())
  1582.                                         .bind('change blur', rename)
  1583.                                         .keydown(function(e) {
  1584.                                                 e.stopPropagation();
  1585.                                                 if (e.keyCode == 27) {
  1586.                                                         restore();
  1587.                                                 } else if (e.keyCode == 13) {
  1588.                                                         if (f.name == input.val()) {
  1589.                                                                 restore();
  1590.                                                         } else {
  1591.                                                                 $(this).trigger('change');
  1592.                                                         }
  1593.                                                 }
  1594.                                         })
  1595.                                         .click(function(e) { e.stopPropagation(); })
  1596.                                         .select()
  1597.                                         .focus();
  1598.                                 this.fm.lockShortcuts(true);
  1599.                         }
  1600.  
  1601.                         function restore() {
  1602.                                 c.html(n);
  1603.                                 self.fm.lockShortcuts();
  1604.                         }
  1605.                        
  1606.                         function rename() {
  1607.                                
  1608.                                 if (!self.fm.locked) {
  1609.                                         var err, name = input.val();
  1610.                                         if (f.name == input.val()) {
  1611.                                                 return restore();
  1612.                                         }
  1613.  
  1614.                                         if (!self.fm.isValidName(name)) {
  1615.                                                 err = 'Invalid name';
  1616.                                         }/* else if (self.fm.fileExists(name)) {
  1617.                                                 err = 'File or folder with the same name already exists';
  1618.                                         }*/
  1619.                                        
  1620.                                         if (err) {
  1621.                                                 self.fm.view.error(err);
  1622.                                                 el.addClass('ui-selected');
  1623.                                                 self.fm.lockShortcuts(true);
  1624.                                                 return input.select().focus();
  1625.                                         }
  1626.                                        
  1627.                                         self.fm.ajax({cmd : 'rename', current : self.fm.cwd.hash, target : f.hash, new_name : name}, function(data) {
  1628.                                                 if (data.error) {
  1629.                                                         restore();
  1630.                                                 } else {
  1631.                                                         self.fm.reload(data);
  1632.                                                 }
  1633.                                         }, { force : true });
  1634.                                 }
  1635.                         }
  1636.                 }
  1637.                
  1638.                 /**
  1639.                  * Return true if only one file selected and has write perms and current dir has write perms
  1640.                  * @return Boolean
  1641.                  */
  1642.                 this.isAllowed = function() {
  1643.                         return this.fm.cwd.write && this.fm.getSelected(0).write;
  1644.                 }
  1645.  
  1646.                 this.cm = function(t) {
  1647.                         return t == 'file';
  1648.                 }
  1649.         },
  1650.        
  1651.         /**
  1652.          * @class Copy file/folder to "clipboard"
  1653.          * @param Object elFinder
  1654.          **/
  1655.         copy : function(fm) {
  1656.                 this.name = 'Copy';
  1657.                 this.fm   = fm;
  1658.                
  1659.                 this.exec = function() {
  1660.                         this.fm.setBuffer(this.fm.selected);
  1661.                 }
  1662.                
  1663.                 this.isAllowed = function() {
  1664.                         if (this.fm.selected.length) {
  1665.                                 var s = this.fm.getSelected(), l = s.length;
  1666.                                 while (l--) {
  1667.                                         if (!s[l].system && s[l].read) {
  1668.                                                 return true;
  1669.                                         }
  1670.                                 }
  1671.                         }
  1672.                         return false;
  1673.                 }
  1674.                
  1675.                 this.cm = function(t) {
  1676.                         return t != 'cwd';
  1677.                 }
  1678.         },
  1679.        
  1680.         /**
  1681.          * @class Cut file/folder to "clipboard"
  1682.          * @param Object elFinder
  1683.          **/
  1684.         cut : function(fm) {
  1685.                 this.name = 'Cut';
  1686.                 this.fm   = fm;
  1687.                
  1688.                 this.exec = function() {
  1689.                         this.fm.setBuffer(this.fm.selected, 1);
  1690.                 }
  1691.                
  1692.                 this.isAllowed = function() {
  1693.                         if (this.fm.selected.length) {
  1694.                                 var s = this.fm.getSelected(), l = s.length;
  1695.                                 while (l--) {
  1696.                                         if (s[l].read && s[l].rm) {
  1697.                                                 return true;
  1698.                                         }
  1699.                                 }
  1700.                         }
  1701.                         return false;
  1702.                 }
  1703.                
  1704.                 this.cm = function(t) {
  1705.                         return t != 'cwd';
  1706.                 }
  1707.         },
  1708.        
  1709.         /**
  1710.          * @class Paste file/folder from "clipboard"
  1711.          * @param Object elFinder
  1712.          **/
  1713.         paste : function(fm) {
  1714.                 var self  = this;
  1715.                 this.name = 'Paste';
  1716.                 this.fm   = fm;
  1717.                
  1718.                 this.exec = function() {
  1719.                         var i, d, f, r, msg = '';
  1720.                        
  1721.                         if (!this.fm.buffer.dst) {
  1722.                                 this.fm.buffer.dst = this.fm.cwd.hash;
  1723.                         }
  1724.                         d = this.fm.view.tree.find('[key="'+this.fm.buffer.dst+'"]');
  1725.                         if (!d.length || d.hasClass('noaccess') || d.hasClass('readonly')) {
  1726.                                 return this.fm.view.error('Access denied');
  1727.                         }
  1728.                         var o = {
  1729.                                 cmd       : 'paste',
  1730.                                 current   : this.fm.cwd.hash,
  1731.                                 src       : this.fm.buffer.src,
  1732.                                 dst       : this.fm.buffer.dst,
  1733.                                 targets   : this.fm.buffer.files,
  1734.                                 cut       : this.fm.buffer.cut
  1735.                         };
  1736.                         this.fm.ajax(o, function(data) {
  1737.                                 data.cdc && self.fm.reload(data);
  1738.                         }, {force : true});
  1739.                 }
  1740.                
  1741.                 this.isAllowed = function() {
  1742.                         return this.fm.cwd.write && this.fm.cwd.type == 'folder' && this.fm.buffer.files;
  1743.                 }
  1744.                
  1745.                 this.cm = function(t) {
  1746.                         return t == 'cwd' && this.fm.cwd.write && this.fm.cwd.type == 'folder';
  1747.                 }
  1748.         },
  1749.        
  1750.         /**
  1751.          * @class Remove files/folders
  1752.          * @param Object elFinder
  1753.          **/
  1754.         rm : function(fm) {
  1755.                 var self  = this;
  1756.                 this.name = 'Remove';
  1757.                 this.fm   = fm;
  1758.                
  1759.                 this.exec = function() {
  1760.                         var i, ids = [], s =this.fm.getSelected();
  1761.                         for (var i=0; i < s.length; i++) {
  1762.                                 if (!s[i].rm) {
  1763.                                         return this.fm.view.error(s[i].name+': '+this.fm.i18n('Access denied'));
  1764.                                 }
  1765.                                 ids.push(s[i].hash);
  1766.                         };
  1767.                         if (ids.length) {
  1768.                                 this.fm.lockShortcuts(true);
  1769.                                 $('<div><div class="ui-state-error ui-corner-all"><span class="ui-icon ui-icon-alert"/><strong>'+this.fm.i18n('Are you shure you want to remove files?<br /> This cannot be undone!')+'</strong></div></div>')
  1770.                                         .dialog({
  1771.                                                 title       : this.fm.i18n('Confirmation required'),
  1772.                                                 dialogClass : 'el-finder-dialog',
  1773.                                                 width       : 350,
  1774.                                                 close       : function() { self.fm.lockShortcuts(); },
  1775.                                                 buttons     : {
  1776.                                                         Cancel : function() { $(this).dialog('close'); },
  1777.                                                         Ok     : function() {
  1778.                                                                 $(this).dialog('close');
  1779.                                                                 var o = { cmd : 'rm', current : self.fm.cwd.hash };
  1780.                                                                 if (self.fm.jquery > 132) {
  1781.                                                                         o.targets = ids;
  1782.                                                                 } else {
  1783.                                                                         o['targets[]'] = ids;
  1784.                                                                 }
  1785.                                                                 self.fm.ajax(o, function(data) { data.tree && self.fm.reload(data); }, {force : true});
  1786.                                                         }
  1787.                                                 }
  1788.                                         });
  1789.                         }
  1790.                 }
  1791.                
  1792.                 this.isAllowed = function(f) {
  1793.                         if (this.fm.selected.length) {
  1794.                                 var s = this.fm.getSelected(), l = s.length;
  1795.                                 while (l--) {
  1796.                                         if (s[l].rm) {
  1797.                                                 return true;
  1798.                                         }
  1799.                                 }
  1800.                         }
  1801.                         return false;
  1802.                 }
  1803.                
  1804.                 this.cm = function(t) {
  1805.                         return t != 'cwd';
  1806.                 }
  1807.         },
  1808.        
  1809.         /**
  1810.          * @class Create new folder
  1811.          * @param Object  elFinder
  1812.          **/
  1813.         mkdir : function(fm) {
  1814.                 var self  = this;
  1815.                 this.name = 'New folder';
  1816.                 this.fm   = fm;
  1817.                
  1818.                 this.exec = function() {
  1819.                         self.fm.unselectAll();
  1820.                         var n     = this.fm.uniqueName('Untitled folder');
  1821.                                 input = $('<input type="text"/>').val(n);
  1822.                                 prev  = this.fm.view.cwd.find('.el-finder-list .directory:last');
  1823.                                 f     = {name : n, hash : '', mime :'directory', read : true, write : true, date : '', size : 0},
  1824.                                 el    = this.fm.options.view == 'list'
  1825.                                                 ? $(this.fm.view.renderItem(this.fm.options.view, f)).children('td').eq(1).empty().append(input).end().end()
  1826.                                                 : this.fm.view.renderItem(this.fm.options.view, f).children('label').empty().append(input).end()
  1827.                         el.addClass('directory ui-selected');
  1828.                         if(this.fm.cwd.empty)this.fm.view.cwd.find('.el-finder-list').show();
  1829.                         //this.fm.view.cwd.find('el-finder-list').show();
  1830.                         if (prev.length) {
  1831.                                 el.insertAfter(prev);
  1832.                         } else if (this.fm.options.view == 'list') {
  1833.                                 el.insertAfter(this.fm.view.cwd.find('.el-finder-list tr').eq(0))
  1834.                         } else {
  1835.                                 el.insertAfter(this.fm.view.cwd.find('.el-finder-list table').eq(0));
  1836.                         }
  1837.                         self.fm.checkSelectedPos();
  1838.                         input.select().focus()
  1839.                                 .click(function(e) { e.stopPropagation(); })
  1840.                                 .bind('change blur', mkdir)
  1841.                                 .keydown(function(e) {
  1842.                                         e.stopPropagation();
  1843.                                         if (e.keyCode == 27) {
  1844.                                                 el.remove();
  1845.                                                 if(self.fm.cwd.empty)self.fm.view.cwd.find('.el-finder-list').hide();
  1846.                                                 self.fm.lockShortcuts();
  1847.                                         } else if (e.keyCode == 13) {
  1848.                                                 mkdir();
  1849.                                         }
  1850.                                 });
  1851.  
  1852.                         self.fm.lockShortcuts(true);
  1853.  
  1854.                         function mkdir() {
  1855.                                 if (!self.fm.locked) {
  1856.                                         var err, name = input.val();
  1857.                                         if (!self.fm.isValidName(name)) {
  1858.                                                 err = 'Invalid name';
  1859.                                         } else if (self.fm.fileExists(name)) {
  1860.                                                 err = 'File or folder with the same name already exists';
  1861.                                         }
  1862.                                         if (err) {
  1863.                                                 self.fm.view.error(err);
  1864.                                                 self.fm.lockShortcuts(true);
  1865.                                                 el.addClass('ui-selected');
  1866.                                                 return input.select().focus();
  1867.                                         }
  1868.                                        
  1869.                                         self.fm.ajax({cmd : 'mkdir', current : self.fm.cwd.hash, name : name}, function(data) {
  1870.                                                 if (data.error) {
  1871.                                                         el.addClass('ui-selected');
  1872.                                                         return input.select().focus();
  1873.                                                 }
  1874.                                                 self.fm.reload(data);
  1875.                                         }, {force : true});
  1876.                                 }
  1877.                         }
  1878.                 }
  1879.                
  1880.                 this.isAllowed = function() {
  1881.                         return this.fm.cwd.write && this.fm.cwd.write && this.fm.cwd.type == 'folder';
  1882.                 }
  1883.                
  1884.                 this.cm = function(t) {
  1885.                         return t == 'cwd' && this.fm.cwd.write && this.fm.cwd.type == 'folder';
  1886.                 }
  1887.         },
  1888.        
  1889.         /**
  1890.          * @class Upload files
  1891.          * @param Object  elFinder
  1892.          **/
  1893.         upload : function(fm) {
  1894.                 var self  = this;
  1895.                 this.name = 'Upload';
  1896.                 this.fm   = fm;
  1897.                
  1898.                 this.exec = function() {
  1899.                         if(!$.browser.opera)document.fileupload.file1.click();
  1900.                 }
  1901.                
  1902.                 this.isAllowed = function() {
  1903.                         return this.fm.cwd.write && this.fm.cwd.type == 'folder';
  1904.                 }
  1905.                
  1906.                 this.cm = function(t) {
  1907.                         return t == 'cwd' && this.fm.cwd.write && this.fm.cwd.type == 'folder';
  1908.                 }
  1909.         },
  1910.        
  1911.         /**
  1912.          * @class Upload files
  1913.          * @param Object  elFinder
  1914.          **/
  1915.         /*remote : function(fm) {
  1916.                 var self  = this;
  1917.                 this.name = 'Remote upload';
  1918.                 this.fm   = fm;
  1919.                
  1920.                 this.exec = function() {
  1921.                         var self = this;
  1922.                         this.fm.lockShortcuts(true);
  1923.                         $('<textarea/>')
  1924.                                 .html('Paste your links here and click ok')
  1925.                                 .focus(function(){this.select();})
  1926.                                 .dialog({
  1927.                                         width       : 617,
  1928.                                         title       : this.fm.i18n(this.name),
  1929.                                         dialogClass : 'el-finder-dialog',
  1930.                                         modal       : true,
  1931.                                         close       : function() { self.fm.lockShortcuts(); d.tabs('destroy').dialog('destroy').remove() },
  1932.                                         buttons     : {
  1933.                                                 Ok      : function() {
  1934.                                                         self.fm.ajax({
  1935.                                                                 cmd     : 'remote',
  1936.                                                                 current : self.fm.cwd.hash,
  1937.                                                                 links   : this.value
  1938.                                                         });
  1939.                                                         $(this).dialog('close');
  1940.                                                 },
  1941.                                                 Cancel  : function() { $(this).dialog('close'); }
  1942.                                         }
  1943.                                 })
  1944.                                 .css({width:'100%',height:'130px'});
  1945.                 }
  1946.                
  1947.                 this.isAllowed = function() {
  1948.                         return this.fm.cwd.write && this.fm.cwd.type == 'folder';
  1949.                 }
  1950.                
  1951.                 this.cm = function(t) {
  1952.                         return t == 'cwd' && this.fm.cwd.write && this.fm.cwd.type == 'folder';
  1953.                 }
  1954.         },*/
  1955.        
  1956.         /**
  1957.          * @class Make file/folder copy
  1958.          * @param Object  elFinder
  1959.          **/
  1960.         duplicate : function(fm) {
  1961.                 var self  = this;
  1962.                 this.name = 'Duplicate';
  1963.                 this.fm   = fm;
  1964.                
  1965.                 this.exec = function() {
  1966.                         var i, ids = [], s =this.fm.getSelected();
  1967.                         for (i=0; i < s.length; i++) {
  1968.                                 if(!s[i].read)return this.fm.view.error(s[i].name+': '+this.fm.i18n('Access denied'));
  1969.                                 ids.push(s[i].hash);
  1970.                         };
  1971.                         this.fm.ajax({
  1972.                                 cmd     : 'duplicate',
  1973.                                 current : this.fm.cwd.hash,
  1974.                                 targets : ids
  1975.                         },
  1976.                         function(data) {
  1977.                                 self.fm.reload(data);
  1978.                         });
  1979.                 }
  1980.                
  1981.                 this.isAllowed = function() {
  1982.                         return this.fm.cwd.write && this.fm.cwd.type == 'folder';
  1983.                 }
  1984.                
  1985.                 this.cm = function(t) {
  1986.                         return (t == 'file' || t == 'group') && this.fm.cwd.type == 'folder';
  1987.                 }
  1988.         },
  1989.        
  1990.         /**
  1991.          * @class Get downloadlink
  1992.          * @param Object  elFinder
  1993.          **/
  1994.         get_link : function(fm) {
  1995.                 var self  = this;
  1996.                 this.name = 'Get link';
  1997.                 this.fm   = fm;
  1998.                
  1999.                 this.exec = function() {
  2000.                         var i, links = [], s = this.fm.getSelected(), clip=null, clipDom=null;
  2001.                         this.fm.lockShortcuts(true);
  2002.                         if(!s.length)s=[this.fm.cwd];
  2003.                         if(!s.length)return this.fm.view.error(this.fm.i18n('No items selected'));
  2004.                         for (i=0; i < s.length; i++)
  2005.                                 links.push(this.fm.options.downloadLinkFormat.replace(/%s/,s[i].hash));
  2006.                         var d = $('<textarea/>')
  2007.                                 .html(links.join('\n'))
  2008.                                 .focus(function(){this.select()})
  2009.                                 .dialog({
  2010.                                         width       : 617,
  2011.                                         title       : this.fm.i18n('Downloadlinks'),
  2012.                                         dialogClass : 'el-finder-dialog',
  2013.                                         modal       : true,
  2014.                                         buttons     : [
  2015.                                                 {
  2016.                                                         id: 'get_link_dialog_clipboard',
  2017.                                                         text: 'Copy to clipboard',
  2018.                                                         click: function() { alert('Failed copying links to clipboard'); return false; }
  2019.                                                 },
  2020.                                                 {
  2021.                                                         id: 'get_link_dialog_ok',
  2022.                                                         text: 'Ok',
  2023.                                                         click: function() { $(this).dialog('close'); }
  2024.                                                 }
  2025.                                         ],
  2026.                                         open        : function(){
  2027.                                                 var d=$(this), p=d.parent(), t=p.find('#get_link_dialog_clipboard'),w=t.width(),h=t.height();
  2028.                                                 clip = new ZeroClipboard.Client()
  2029.                                                 clip.setHandCursor(true);
  2030.                                                 clip.addEventListener('mouseDown',function(){
  2031.                                                         clip.setText(d.val());
  2032.                                                 });
  2033.                                                 clip.addEventListener('onComplete',function(){
  2034.                                                         if(clip)clip.destroy();
  2035.                                                         d.dialog('close');
  2036.                                                 });
  2037.                                                 $('<div/>')
  2038.                                                         .html(clip.getHTML(w, h+10))
  2039.                                                         .css({
  2040.                                                                 position:'relative',
  2041.                                                                 marginBottom:-h,
  2042.                                                                 width:w,
  2043.                                                                 height:h,
  2044.                                                                 zIndex:1101
  2045.                                                         })
  2046.                                                 .insertBefore(t);
  2047.                                         },
  2048.                                         close       : function(){
  2049.                                                 self.fm.lockShortcuts();
  2050.                                                 if(clip)clip.destroy();
  2051.                                         }
  2052.                                 })
  2053.                                 .css({width:'100%',height:'130px'});
  2054.                 }
  2055.                
  2056.                 this.isAllowed = function() {
  2057.                         var s = this.fm.getSelected(0);
  2058.                         return s.read && s.exec && !s.system;
  2059.                 }
  2060.                
  2061.                 this.cm = function(t) {
  2062.                         return true;
  2063.                 }
  2064.         },
  2065.        
  2066.         /**
  2067.          * @class Switch elFinder into icon view
  2068.          * @param Object  elFinder
  2069.          **/
  2070.         icon : function(fm) {
  2071.                 this.name = 'View as icons';
  2072.                 this.fm   = fm;
  2073.                
  2074.                 this.exec = function() {
  2075.                         this.fm.view.win.addClass('el-finder-disabled');
  2076.                         this.fm.setView('icon');
  2077.                         this.fm.updateCwd();
  2078.                         this.fm.view.win.removeClass('el-finder-disabled');
  2079.                         //$('div.image', this.fm.view.cwd).length && this.fm.tmb();
  2080.                 }
  2081.                
  2082.                 this.isAllowed = function() {
  2083.                         return this.fm.options.view != 'icon' && this.fm.cwd.type == 'folder' && !this.fm.cwd.empty;
  2084.                 }
  2085.                
  2086.                 this.cm = function(t) {
  2087.                         return t == 'cwd';
  2088.                 }
  2089.         },
  2090.        
  2091.         /**
  2092.          * @class Switch elFinder into list view
  2093.          * @param Object  elFinder
  2094.          **/
  2095.         list : function(fm) {
  2096.                 this.name = 'View as list';
  2097.                 this.fm   = fm;
  2098.                
  2099.                 this.exec = function() {
  2100.                         this.fm.view.win.addClass('el-finder-disabled');
  2101.                         this.fm.setView('list');
  2102.                         this.fm.updateCwd();
  2103.                         this.fm.view.win.removeClass('el-finder-disabled');
  2104.                 }
  2105.                
  2106.                 this.isAllowed = function() {
  2107.                         return this.fm.options.view != 'list' && this.fm.cwd.type == 'folder' && !this.fm.cwd.empty;
  2108.                 }
  2109.                
  2110.                 this.cm = function(t) {
  2111.                         return t == 'cwd';
  2112.                 }
  2113.         },
  2114.        
  2115.         help : function(fm) {
  2116.                 this.name = 'Help';
  2117.                 this.fm   = fm;
  2118.                
  2119.                 this.exec = function() {
  2120.                         var h, ht = this.fm.i18n('helpText'), a, s, tabs, self = this;
  2121.                        
  2122.                         h = '<div class="el-finder-logo"/><strong>'+this.fm.i18n('elFinder: Web file manager')+'</strong><br/>'+this.fm.i18n('Version')+': '+this.fm.version+'<br clear="all"/>'
  2123.                                 +'<p><strong><a href="http://elrte.ru/donate?prod=elfinder&lang='+this.fm.options.lang+'" target="_blank">'+this.fm.i18n('Donate to support project development')+'</a></strong></p>'
  2124.                                 + '<p><a href="http://elrte.ru/redmine/wiki/elfinder/" target="_blank">'+this.fm.i18n('elFinder documentation')+'</a></p>';
  2125.                         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>';
  2126.                         h += '<p>'
  2127.                                 + '<strong>'+this.fm.i18n('elFinder support following shortcuts')+':</strong><ul>'
  2128.                                 + '<li><kbd>Ctrl+A</kbd> - '+this.fm.i18n('Select all files')+'</li>'
  2129.                                 + '<li><kbd>Ctrl+C/Ctrl+X/Ctrl+V</kbd> - '+this.fm.i18n('Copy/Cut/Paste files')+'</li>'
  2130.                                 + '<li><kbd>Enter</kbd> - '+this.fm.i18n('Open selected file/folder')+'</li>'
  2131.                                 //+ '<li><kbd>Space</kbd> - '+this.fm.i18n('Open/close QuickLook window')+'</li>'
  2132.                                 + '<li><kbd>Delete/Cmd+Backspace</kbd> - '+this.fm.i18n('Remove selected files')+'</li>'
  2133.                                 + '<li><kbd>Ctrl+I</kbd> - '+this.fm.i18n('Selected files or current directory info')+'</li>'
  2134.                                 + '<li><kbd>Ctrl+N</kbd> - '+this.fm.i18n('Create new directory')+'</li>'
  2135.                                 + '<li><kbd>Ctrl+U</kbd> - '+this.fm.i18n('Open upload files form')+'</li>'
  2136.                                 + '<li><kbd>Left arrow</kbd> - '+this.fm.i18n('Select previous file')+'</li>'
  2137.                                 + '<li><kbd>Right arrow </kbd> - '+this.fm.i18n('Select next file')+'</li>'
  2138.                                 + '<li><kbd>Ctrl+Right arrow</kbd> - '+this.fm.i18n('Open selected file/folder')+'</li>'
  2139.                                 + '<li><kbd>Ctrl+Left arrow</kbd> - '+this.fm.i18n('Return into previous folder')+'</li>'
  2140.                                 + '<li><kbd>Shift+arrows</kbd> - '+this.fm.i18n('Increase/decrease files selection')+'</li></ul>'
  2141.                                 + '</p><p>'
  2142.                                 + this.fm.i18n('Contacts us if you need help integrating elFinder in you products')+': dev@std42.ru</p>';
  2143.  
  2144.                         a = '<div class="el-finder-help-std"/>'
  2145.                                 +'<p>'+this.fm.i18n('Javascripts/PHP programming: Dmitry (dio) Levashov, dio@std42.ru')+'</p>'
  2146.                                 +'<p>'+this.fm.i18n('Python programming, techsupport: Troex Nevelin, troex@fury.scancode.ru')+'</p>'
  2147.                                 +'<p>'+this.fm.i18n('Design: Valentin Razumnih')+'</p>'
  2148.                                 +'<p>'+this.fm.i18n('Spanish localization')+': Alex (xand) Vavilin, xand@xand.es, <a href="http://xand.es" target="_blank">http://xand.es</a></p>'
  2149.                                 +'<p>'+this.fm.i18n('Icons')+': <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>'
  2150.                                 +'<p>'+this.fm.i18n('Copyright: <a href="http://www.std42.ru" target="_blank">Studio 42 LTD</a>')+'</p>'
  2151.                                 +'<p>'+this.fm.i18n('License: BSD License')+'</p>'
  2152.                                 +'<p>'+this.fm.i18n('Web site: <a href="http://www.elrte.ru/elfinder/" target="_blank">elrte.ru</a>')+'</p>';
  2153.                        
  2154.                         s = '<div class="el-finder-logo"/><strong><a href="http://www.eldorado-cms.ru" target="_blank">ELDORADO.CMS</a></strong><br/>'
  2155.                                 +this.fm.i18n('Simple and usefull Content Management System')
  2156.                                 +'<hr/>'
  2157.                                 + this.fm.i18n('Support project development and we will place here info about you');
  2158.                        
  2159.                         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>'
  2160.                                         +'<div id="el-finder-help-h"><p>'+h+'</p></div>'
  2161.                                         +'<div id="el-finder-help-a"><p>'+a+'</p></div>'
  2162.                                         +'<div id="el-finder-help-sp"><p>'+s+'</p></div>';
  2163.                        
  2164.                         this.fm.lockShortcuts(true);
  2165.                         var d = $('<div/>').html(tabs).dialog({
  2166.                                 width       : 617,
  2167.                                 title       : this.fm.i18n('Help'),
  2168.                                 dialogClass : 'el-finder-dialog',
  2169.                                 modal       : true,
  2170.                                 close       : function() { self.fm.lockShortcuts(); d.tabs('destroy').dialog('destroy').remove() },
  2171.                                 buttons     : {
  2172.                                         Ok : function() { $(this).dialog('close'); }
  2173.                                 }
  2174.                         }).tabs()
  2175.                 }
  2176.  
  2177.  
  2178.                 this.cm = function(t) {
  2179.                         return t == 'cwd';
  2180.                 }
  2181.         }
  2182. }
  2183.  
  2184. })(jQuery);
  2185.  
  2186.  
  2187. /**
  2188. * @class  Bind/update events
  2189. * @author dio dio@std42.ru
  2190. **/
  2191. (function($) {
  2192. elFinder.prototype.eventsManager = function(fm, el) {
  2193.         var self   = this;
  2194.         this.lock  = false;
  2195.         this.fm    = fm;
  2196.         this.ui    = fm.ui;
  2197.         this.tree  = fm.view.tree
  2198.         this.cwd   = fm.view.cwd;
  2199.         this.pointer = '';
  2200.        
  2201.         /**
  2202.          * Initial events binding
  2203.          *
  2204.          **/
  2205.         this.init = function() {
  2206.                 this.cwd
  2207.                         .bind('click', function(e) {
  2208.                                 var t = $(e.target);
  2209.                                 if (t.hasClass('ui-selected')) {
  2210.                                         self.fm.unselectAll();
  2211.                                 } else {
  2212.                                         if (!t.attr('key')) {
  2213.                                                 t = t.parent('[key]');
  2214.                                         }
  2215.                                         if (e.ctrlKey || e.metaKey) {
  2216.                                                 self.fm.toggleSelect(t);
  2217.                                         } else {
  2218.                                                 self.fm.select(t, true);
  2219.                                         }
  2220.                                 }
  2221.                         })
  2222.                         .bind(window.opera?'click':'contextmenu', function(e) {
  2223.                                 if (window.opera && !e.ctrlKey) {
  2224.                                         return;
  2225.                                 }
  2226.                                 var t = $(e.target);
  2227.                                 if(t.is('input'))return;
  2228.                                 e.preventDefault();
  2229.                                 e.stopPropagation()
  2230.                                 if (t.hasClass('el-finder-cwd')) {
  2231.                                         self.fm.unselectAll();
  2232.                                 } else {
  2233.                                         self.fm.select(t.attr('key') ? t : t.parents('[key]'));
  2234.                                 }
  2235.                                 self.fm.ui.showMenu(e);
  2236.                         });
  2237.                         $('html').selectable({
  2238.                                 filter : '.el-finder-list [key]',
  2239.                                 //cancel : '.el-finder-template',
  2240.                                 delay  : 300,
  2241.                                 stop   : function() { self.fm.updateSelect() }
  2242.                         });
  2243.                        
  2244.                 $(document).bind('click', function() {
  2245.                         self.fm.ui.hideMenu();
  2246.                         $('input', self.cwd).trigger('change');
  2247.                 });
  2248.  
  2249.  
  2250.                 /* open parents dir in tree */
  2251.                 this.tree.bind('select', function(e) {
  2252.                         self.tree.find('a').removeClass('selected');
  2253.                         $(e.target).addClass('selected').parents('li:has(ul)').children('ul').show().prev().children('div').addClass('expanded');
  2254.                 });
  2255.                
  2256.                 /* bind shortcuts */
  2257.                
  2258.                 $(document).bind($.browser.mozilla || $.browser.opera ? 'keypress' : 'keydown', function(e) {
  2259.                         var meta = e.ctrlKey||e.metaKey;
  2260.                        
  2261.                         if (self.lock) {
  2262.                                 return;
  2263.                         }
  2264.                         switch(e.keyCode) {
  2265.                                 /* arrows left/up. with Ctrl - exec "back", w/o - move selection */
  2266.                                 case 37:
  2267.                                 case 38:
  2268.                                         e.stopPropagation();
  2269.                                         e.preventDefault();
  2270.                                         if (e.keyCode == 37 && meta) {
  2271.                                                 self.ui.execIfAllowed('back');
  2272.                                         } else {
  2273.                                                 moveSelection(false, !e.shiftKey);
  2274.                                         }
  2275.                                         break;
  2276.                                 /* arrows right/down. with Ctrl - exec "open", w/o - move selection  */
  2277.                                 case 39:
  2278.                                 case 40:
  2279.                                         e.stopPropagation();
  2280.                                         e.preventDefault();
  2281.                                         if (meta) {
  2282.                                                 self.ui.execIfAllowed('open');
  2283.                                         } else {
  2284.                                                 moveSelection(true, !e.shiftKey);
  2285.                                         }
  2286.                                         break;
  2287.                         }
  2288.                 });
  2289.                
  2290.  
  2291.                 $(document).bind($.browser.opera ? 'keypress' : 'keydown', function(e) {
  2292.  
  2293.                         if (self.lock) {
  2294.                                 return;
  2295.                         }
  2296.                         switch(e.keyCode) {
  2297.                                 /* Space - QuickLook */
  2298.                                 /*case 32:
  2299.                                         e.preventDefault();
  2300.                                         e.stopPropagation();
  2301.                                         self.fm.quickLook.toggle();
  2302.                                         break;*/
  2303.                                 /* Esc */       
  2304.                                 /*case 27:
  2305.                                         self.fm.quickLook.hide();
  2306.                                         break;*/
  2307.                         }
  2308.                 });
  2309.                
  2310.                 if (!this.fm.options.disableShortcuts) {
  2311.                        
  2312.                         $(document).bind('keydown', function(e) {
  2313.                                 var meta = e.ctrlKey||e.metaKey;
  2314.  
  2315.                                 if (self.lock) {
  2316.                                         return;
  2317.                                 }
  2318.                                 if($(e.target).is('input,select'))return;
  2319.                                 //e.target
  2320.                                 //e.srcElement
  2321.  
  2322.                                 switch (e.keyCode) {
  2323.                                         /* Meta+Backspace - delete */
  2324.                                         case 8:
  2325.                                                 if (meta && self.ui.isCmdAllowed('rm')) {
  2326.                                                         e.preventDefault();
  2327.                                                         self.ui.exec('rm');
  2328.                                                 }
  2329.                                                 break;
  2330.                                         /* Enter - exec "select" command if enabled, otherwise exec "open" */   
  2331.                                         case 13:
  2332.                                                 if (self.ui.isCmdAllowed('select')) {
  2333.                                                         return self.ui.exec('select');
  2334.                                                 }
  2335.                                                 self.ui.execIfAllowed('open');
  2336.                                                 break;
  2337.                                         /* Delete */
  2338.                                         case 46:
  2339.                                                 self.ui.execIfAllowed('rm');
  2340.                                                 break;
  2341.                                         /* Ctrl+A */
  2342.                                         case 65:
  2343.                                                 if (meta) {
  2344.                                                         e.preventDefault();
  2345.                                                         self.fm.selectAll();
  2346.                                                 }
  2347.                                                 break;
  2348.                                         /* Ctrl+C */
  2349.                                         case 67:
  2350.                                                 meta && self.ui.execIfAllowed('copy');
  2351.                                                 break;
  2352.                                         /* Ctrl+I - get info */ 
  2353.                                         case 73:
  2354.                                                 if (meta) {
  2355.                                                         e.preventDefault();
  2356.                                                         self.ui.exec('info');
  2357.                                                 }
  2358.                                                 break;
  2359.                                         /* Ctrl+N - new folder */
  2360.                                         case 78:
  2361.                                                 if (meta) {
  2362.                                                         e.preventDefault();
  2363.                                                         self.ui.execIfAllowed('mkdir');
  2364.                                                 }
  2365.                                                 break;
  2366.                                         /* Ctrl+U - upload files */
  2367.                                         case 85:
  2368.                                        
  2369.                                                 if (meta) {
  2370.                                                         e.preventDefault();
  2371.                                                         self.ui.execIfAllowed('upload');
  2372.                                                 }
  2373.                                                 break;
  2374.                                         /* Ctrl+V */
  2375.                                         case 86:
  2376.                                                 meta && self.ui.execIfAllowed('paste');
  2377.                                                 break;
  2378.                                         /* Ctrl+X */
  2379.                                         case 88:
  2380.                                                 meta && self.ui.execIfAllowed('cut');
  2381.                                                 break;
  2382.                                                
  2383.                                         case 113:
  2384.                                                 self.ui.execIfAllowed('rename');
  2385.                                                 break;
  2386.                                                
  2387.                                 }
  2388.  
  2389.                         });
  2390.                        
  2391.                 }
  2392.                
  2393.         }
  2394.        
  2395.         /**
  2396.          * Update navigation droppable/draggable
  2397.          *
  2398.          **/
  2399.         this.updateNav = function() {
  2400.                 $('a:not(.iClick)', this.tree)
  2401.                         .addClass('iClick')
  2402.                         .click(function(e) {
  2403.                                 e.preventDefault();
  2404.                                 var t = $(this), c;
  2405.                                 if (e.target.nodeName == 'DIV' && $(e.target).hasClass('collapsed')) {
  2406.                                         $(e.target).toggleClass('expanded').parent().next('ul').toggle(300);
  2407.                                         setTimeout(function(){
  2408.                                                 self.fm.ajax({cmd:'silent'}, false, {lock:false})
  2409.                                         }, 350);
  2410.                                 } else if (t.attr('key') != self.fm.cwd.hash) {
  2411.                                         if (t.hasClass('noaccess') || t.hasClass('dropbox')) {
  2412.                                                 self.fm.view.error('Access denied');
  2413.                                         } else {
  2414.                                                 self.ui.exec('open', t.trigger('select')[0]);
  2415.                                         }
  2416.                                 } else {
  2417.                                         c = t.children('.collapsed');
  2418.                                         if (c.length) {
  2419.                                                 c.toggleClass('expanded');
  2420.                                                 t.next('ul').toggle(300);
  2421.                                         }
  2422.                                 }
  2423.                         });
  2424.                
  2425.                 $('a:not(.noaccess,.readonly,.iDrop)', this.tree)
  2426.                         .addClass('iDrop')
  2427.                         .droppable({
  2428.                                 tolerance : 'pointer',
  2429.                                 accept : '(div,tr)[key]',
  2430.                                 over   : function() { $(this).addClass('el-finder-droppable'); },
  2431.                                 out    : function() { $(this).removeClass('el-finder-droppable'); },
  2432.                                 drop   : function(e, ui) { $(this).removeClass('el-finder-droppable'); self.fm.drop(e, ui, $(this).attr('key')); }
  2433.                         });
  2434.         }
  2435.        
  2436.         /**
  2437.          * Update folders droppable & files/folders draggable
  2438.          **/
  2439.         this.updateCwd = function() {
  2440.                 //var overTimeout;
  2441.                 $('a[key]', this.cwd)
  2442.                         .bind('click', function(e) {
  2443.                                 $(this).trigger('dblclick');
  2444.                                 return false;
  2445.                         });
  2446.                 var items=$('[key]', this.cwd)
  2447.                         /*.mouseover(function(e){
  2448.                                 if(e.ctrlKey || e.metaKey) return;
  2449.                                 if(overTimeout) clearTimeout(overTimeout);
  2450.                                 if(self.fm.selected.length > 1) return;
  2451.                                 var el = this;
  2452.                                 overTimeout = setTimeout(function(){self.fm.select($(el), true);overTimeout = null;}, 500);
  2453.                         })
  2454.                         .mouseout(function(e){
  2455.                                 if(overTimeout){
  2456.                                         clearTimeout(overTimeout);
  2457.                                         overTimeout = null;
  2458.                                 }
  2459.                         })*/
  2460.                         .bind('click', function(e) {
  2461.                                 if(e.shiftKey||e.ctrlKey)return;
  2462.                                 self.fm.select($(this), true);
  2463.                                 self.ui.exec(self.ui.isCmdAllowed('select') ? 'select' : 'open');
  2464.                         })
  2465.                         .draggable({
  2466.                                 delay      : 3,
  2467.                                 addClasses : false,
  2468.                                 appendTo   : '.el-finder-cwd',
  2469.                                 cursorAt   : {top:0,left:0},
  2470.                                 revert     : true,
  2471.                                 revertDuration: 200,
  2472.                                 start      : function(e, ui) {
  2473.                                         if(e.shiftKey||e.ctrlKey)return false;
  2474.                                 },
  2475.                                 drag       : function(e, ui) {
  2476.                                         ui.helper.toggleClass('el-finder-drag-copy', e.shiftKey||e.ctrlKey);
  2477.                                 },
  2478.                                 helper     : function() {
  2479.                                         var t = $(this),
  2480.                                                 h = $('<div class="el-finder-drag-helper"/>'),
  2481.                                                 num
  2482.                                                 c = 0;
  2483.                                         !t.hasClass('ui-selected') && self.fm.select(t, true);
  2484.  
  2485.                                         /*self.cwd.find('.ui-selected').each(function(i) {
  2486.                                                 var el = $(self.fm.view.renderIcon(self.fm.cdc[$(this).attr('key')]));
  2487.                                                 //var el = self.fm.options.view == 'icon' ? $(this).clone().removeClass('ui-selected') : $(self.fm.view.renderIcon(self.fm.cdc[$(this).attr('key')]))
  2488.                                                 if (c++ == 0 || c%7 == 0) {
  2489.                                                         el.css('margin-left', 0);
  2490.                                                 }
  2491.                                                 h.append(el);
  2492.                                         });*/
  2493.                                         c = self.cwd.find('.ui-selected').length;
  2494.                                         h.html('Dragging '+c+' '+(c == 1 ? 'item' : 'items'));
  2495.                                         return h;
  2496.                                         //return h.css('width', (c<=12 ? 85+(c-1)*29 : 387)+'px');
  2497.                                         //return h.css('width', (c<=7 ? 180+(c-1)*50 : 450)+'px');
  2498.                                 }
  2499.                         });
  2500.                 items
  2501.                         .filter('.directory')//TODO: filter readonly, noaccess
  2502.                         .droppable({
  2503.                                 tolerance : 'pointer',
  2504.                                 accept    : '(div,tr)[key]',
  2505.                                 over      : function() { $(this).addClass('el-finder-droppable')},
  2506.                                 out       : function() { $(this).removeClass('el-finder-droppable'); },
  2507.                                 drop      : function(e, ui) { $(this).removeClass('el-finder-droppable'); self.fm.drop(e, ui, $(this).attr('key')); }
  2508.                         });
  2509.                 items
  2510.                         .find('.controls a')
  2511.                         .click(function(){
  2512.                                 self.fm.select($(this).parents('[key]'),true);
  2513.                                 self.ui.exec(this.name);
  2514.                                 return false;
  2515.                         });
  2516.                        
  2517.                 if ($.browser.msie) {
  2518.                         $('[key]', this.cwd)
  2519.                                 .bind('dragstart', function() { self.cwd.selectable('disable').removeClass('ui-state-disabled ui-selectable-disabled'); })
  2520.                                 .bind('dragstop', function() { self.cwd.selectable('enable'); });
  2521.                         $('*:not(input,select,button)', this.cwd).attr('unselectable', 'on');
  2522.                 }
  2523.  
  2524.         }
  2525.        
  2526.         this.updateCwdInfo = function(tmpl) {
  2527.                 var self = this;
  2528.                 $('.share-facebook', tmpl).click(function(){
  2529.                         window.open('http://facebook.com/sharer.php?u='+encodeURIComponent('http://file.loc/'+self.fm.cwd.hash));
  2530.                         return false;
  2531.                 });
  2532.                 $('.share-twitter', tmpl).click(function(){
  2533.                         window.open('http://twitter.com/intent/tweet?text='+encodeURIComponent('Check out '+(self.fm.cwd.type === 'file' ? 'this file' : 'these files')+', http://file.loc/'+self.fm.cwd.hash));
  2534.                         return false;
  2535.                 });
  2536.                 $('.share-email', tmpl).click(function(){
  2537.                         ps.set('/sendmail', {sharename: share.name, share:ps.location(), sharetype:util.shareType(share), filescount:share.files.length});
  2538.                 });
  2539.                 $('#QuickSearch input', tmpl)
  2540.                         .focus(function(){
  2541.                                 if(this.value === 'Quick search') this.value = '';
  2542.                         })
  2543.                         .blur(function(){
  2544.                                 if(this.value === '') this.value = 'Quick search';
  2545.                         });
  2546.         }
  2547.         this.updateCwdTemplate = function(tmpl) {
  2548.                 var self = this;
  2549.                 tmpl
  2550.                         .find('form')
  2551.                         .submit(function(){
  2552.                                 var frm = {};
  2553.                                 $.map($(this).serializeArray(), function(n, i){ frm[n['name']] = n['value']; });
  2554.                                 self.fm.ajax($.extend({cmd:'open', target:self.fm.cwd.hash, tree:false}, frm), function(data) {
  2555.                                         self.fm.reload(data);
  2556.                                 });
  2557.                                 return false;
  2558.                         });
  2559.         }
  2560.         this.updateCwdMore = function() {
  2561.                 var self = this, w = $(window), e = $('.el-finder-more-files');
  2562.                 function cdc_more_scrolling() {
  2563.                         var w = $(window), e = $('.el-finder-more-files');
  2564.                         if(e.position().top <= w.height() + w.scrollTop()){
  2565.                                 w.unbind('scroll', cdc_more_scrolling);
  2566.                                 e.click();
  2567.                                 return true;
  2568.                         }
  2569.                 }
  2570.                 w.unbind('scroll', cdc_more_scrolling);
  2571.                 if(this.fm.cdc_pos){
  2572.                         $('<button class="el-finder-more-files">More</button>')
  2573.                                 .appendTo(this.fm.view.cwd)
  2574.                                 .click(function(){
  2575.                                         var t=$(this).replaceWith('<div class="el-finder-more-files-loading">Loading...</div>');
  2576.                                         self.fm.ajax({cmd:'open', target:self.fm.cwd.hash, tree:false, start:self.fm.cdc_pos}, function(data) {
  2577.                                                 self.fm.reload(data);
  2578.                                         },
  2579.                                         {lock:false});
  2580.                                 });
  2581.                         cdc_more_scrolling() || w.bind('scroll', cdc_more_scrolling);
  2582.                 }
  2583.         }
  2584.        
  2585.        
  2586.         /**
  2587.          * Move selection in current dir
  2588.          *
  2589.          * @param Boolean  move forward?
  2590.          * @param Boolean  clear current selection?
  2591.          **/
  2592.         function moveSelection(forward, reset) {
  2593.                 var p, _p, cur, cwd = self.cwd.find('.el-finder-list');
  2594.                
  2595.                 if (!$('[key]', cwd).length) {
  2596.                         return;
  2597.                 }
  2598.                
  2599.                 if (self.fm.selected.length == 0) {
  2600.                         p = $('[key]:'+(forward ? 'first' : 'last'), cwd);
  2601.                         self.fm.select(p);
  2602.                 } else if (reset) {
  2603.                         p  = $('.ui-selected:'+(forward ? 'last' : 'first'), cwd);
  2604.                         _p = p[forward ? 'next' : 'prev']('[key]');
  2605.                         if (_p.length) {
  2606.                                 p = _p;
  2607.                         }
  2608.                         self.fm.select(p, true);
  2609.                 } else {
  2610.                         if (self.pointer) {
  2611.                                 cur = $('[key="'+self.pointer+'"].ui-selected', cwd);
  2612.                         }
  2613.                         if (!cur || !cur.length) {
  2614.                                 cur = $('.ui-selected:'+(forward ? 'last' : 'first'), cwd);
  2615.                         }
  2616.                         p = cur[forward ? 'next' : 'prev']('[key]');
  2617.  
  2618.                         if (!p.length) {
  2619.                                 p = cur;
  2620.                         } else {
  2621.                                 if (!p.hasClass('ui-selected')) {
  2622.                                         self.fm.select(p);
  2623.                                 } else {
  2624.                                         if (!cur.hasClass('ui-selected')) {
  2625.                                                 self.fm.unselect(p);
  2626.                                         } else {
  2627.                                                 _p = cur[forward ? 'prev' : 'next']('[key]')
  2628.                                                 if (!_p.length || !_p.hasClass('ui-selected')) {
  2629.                                                         self.fm.unselect(cur);
  2630.                                                 } else {
  2631.                                                         while ((_p = forward ? p.next('[key]') : p.prev('[key]')) && p.hasClass('ui-selected')) {
  2632.                                                                 p = _p;
  2633.                                                         }
  2634.                                                         self.fm.select(p);
  2635.                                                 }
  2636.                                         }
  2637.                                 }
  2638.                         }
  2639.                 }
  2640.                 self.pointer = p.attr('key');
  2641.                 self.fm.checkSelectedPos(forward);
  2642.         }
  2643.        
  2644. }
  2645.  
  2646. })(jQuery);

advertising

Update the Post

Either update this post and resubmit it with changes, or make a new post.

You may also comment on this post.

update paste below
details of the post (optional)

Note: Only the paste content is required, though the following information can be useful to others.

Save name / title?

(space separated, optional)



Please note that information posted here will expire by default in one month. If you do not want it to expire, please set the expiry time above. If it is set to expire, web search engines will not be allowed to index it prior to it expiring. Items that are not marked to expire will be indexable by search engines. Be careful with your passwords. All illegal activities will be reported and any information will be handed over to the authorities, so be good.

worth-right
fantasy-obligation