|
@@ -0,0 +1,11519 @@
|
|
|
+/*!
|
|
|
+ * elFinder - file manager for web
|
|
|
+ * Version 2.1 (Nightly: 093d077) (2013-12-05)
|
|
|
+ * http://elfinder.org
|
|
|
+ *
|
|
|
+ * Copyright 2009-2013, Studio 42
|
|
|
+ * Licensed under a 3 clauses BSD license
|
|
|
+ */
|
|
|
+(function($) {
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/elFinder.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder - file manager for web
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+window.elFinder = function(node, opts) {
|
|
|
+ this.time('load');
|
|
|
+
|
|
|
+ var self = this,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Node on which elfinder creating
|
|
|
+ *
|
|
|
+ * @type jQuery
|
|
|
+ **/
|
|
|
+ node = $(node),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Store node contents.
|
|
|
+ *
|
|
|
+ * @see this.destroy
|
|
|
+ * @type jQuery
|
|
|
+ **/
|
|
|
+ prevContent = $('<div/>').append(node.contents()),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Store node inline styles
|
|
|
+ *
|
|
|
+ * @see this.destroy
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ prevStyle = node.attr('style'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Instance ID. Required to get/set cookie
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ id = node.attr('id') || '',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Events namespace
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ namespace = 'elfinder-'+(id || Math.random().toString().substr(2, 7)),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Mousedown event
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ mousedown = 'mousedown.'+namespace,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Keydown event
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ keydown = 'keydown.'+namespace,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Keypress event
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ keypress = 'keypress.'+namespace,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Is shortcuts/commands enabled
|
|
|
+ *
|
|
|
+ * @type Boolean
|
|
|
+ **/
|
|
|
+ enabled = true,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Store enabled value before ajax requiest
|
|
|
+ *
|
|
|
+ * @type Boolean
|
|
|
+ **/
|
|
|
+ prevEnabled = true,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * List of build-in events which mapped into methods with same names
|
|
|
+ *
|
|
|
+ * @type Array
|
|
|
+ **/
|
|
|
+ events = ['enable', 'disable', 'load', 'open', 'reload', 'select', 'add', 'remove', 'change', 'dblclick', 'getfile', 'lockfiles', 'unlockfiles', 'dragstart', 'dragstop'],
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Rules to validate data from backend
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ rules = {},
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Current working directory hash
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ cwd = '',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Current working directory options
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ cwdOptions = {
|
|
|
+ path : '',
|
|
|
+ url : '',
|
|
|
+ tmbUrl : '',
|
|
|
+ disabled : [],
|
|
|
+ separator : '/',
|
|
|
+ archives : [],
|
|
|
+ extract : [],
|
|
|
+ copyOverwrite : true,
|
|
|
+ uploadMaxSize : 0,
|
|
|
+ tmb : false // old API
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Files/dirs cache
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ files = {},
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Selected files hashes
|
|
|
+ *
|
|
|
+ * @type Array
|
|
|
+ **/
|
|
|
+ selected = [],
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Events listeners
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ listeners = {},
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Shortcuts
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ shortcuts = {},
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Buffer for copied files
|
|
|
+ *
|
|
|
+ * @type Array
|
|
|
+ **/
|
|
|
+ clipboard = [],
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Copied/cuted files hashes
|
|
|
+ * Prevent from remove its from cache.
|
|
|
+ * Required for dispaly correct files names in error messages
|
|
|
+ *
|
|
|
+ * @type Array
|
|
|
+ **/
|
|
|
+ remember = [],
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Queue for 'open' requests
|
|
|
+ *
|
|
|
+ * @type Array
|
|
|
+ **/
|
|
|
+ queue = [],
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Commands prototype
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ base = new self.command(self),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * elFinder node width
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ * @default "auto"
|
|
|
+ **/
|
|
|
+ width = 'auto',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * elFinder node height
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ * @default 400
|
|
|
+ **/
|
|
|
+ height = 400,
|
|
|
+
|
|
|
+ beeper = $(document.createElement('audio')).hide().appendTo('body')[0],
|
|
|
+
|
|
|
+ syncInterval,
|
|
|
+
|
|
|
+ open = function(data) {
|
|
|
+ if (data.init) {
|
|
|
+ // init - reset cache
|
|
|
+ files = {};
|
|
|
+ } else {
|
|
|
+ // remove only files from prev cwd
|
|
|
+ for (var i in files) {
|
|
|
+ if (files.hasOwnProperty(i)
|
|
|
+ && files[i].mime != 'directory'
|
|
|
+ && files[i].phash == cwd
|
|
|
+ && $.inArray(i, remember) === -1) {
|
|
|
+ delete files[i];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ cwd = data.cwd.hash;
|
|
|
+ cache(data.files);
|
|
|
+ if (!files[cwd]) {
|
|
|
+ cache([data.cwd]);
|
|
|
+ }
|
|
|
+ self.lastDir(cwd);
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Store info about files/dirs in "files" object.
|
|
|
+ *
|
|
|
+ * @param Array files
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ cache = function(data) {
|
|
|
+ var l = data.length, f;
|
|
|
+
|
|
|
+ while (l--) {
|
|
|
+ f = data[l];
|
|
|
+ if (f.name && f.hash && f.mime) {
|
|
|
+ if (!f.phash) {
|
|
|
+ var name = 'volume_'+f.name,
|
|
|
+ i18 = self.i18n(name);
|
|
|
+
|
|
|
+ if (name != i18) {
|
|
|
+ f.i18 = i18;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ files[f.hash] = f;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Exec shortcut
|
|
|
+ *
|
|
|
+ * @param jQuery.Event keydown/keypress event
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ execShortcut = function(e) {
|
|
|
+ var code = e.keyCode,
|
|
|
+ ctrlKey = !!(e.ctrlKey || e.metaKey);
|
|
|
+
|
|
|
+ if (enabled) {
|
|
|
+
|
|
|
+ $.each(shortcuts, function(i, shortcut) {
|
|
|
+ if (shortcut.type == e.type
|
|
|
+ && shortcut.keyCode == code
|
|
|
+ && shortcut.shiftKey == e.shiftKey
|
|
|
+ && shortcut.ctrlKey == ctrlKey
|
|
|
+ && shortcut.altKey == e.altKey) {
|
|
|
+ e.preventDefault()
|
|
|
+ e.stopPropagation();
|
|
|
+ shortcut.callback(e, self);
|
|
|
+ self.debug('shortcut-exec', i+' : '+shortcut.description);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // prevent tab out of elfinder
|
|
|
+ if (code == 9 && !$(e.target).is(':input')) {
|
|
|
+ e.preventDefault();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ },
|
|
|
+ date = new Date(),
|
|
|
+ utc,
|
|
|
+ i18n
|
|
|
+ ;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Protocol version
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ this.api = null;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * elFinder use new api
|
|
|
+ *
|
|
|
+ * @type Boolean
|
|
|
+ **/
|
|
|
+ this.newAPI = false;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * elFinder use old api
|
|
|
+ *
|
|
|
+ * @type Boolean
|
|
|
+ **/
|
|
|
+ this.oldAPI = false;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * User os. Required to bind native shortcuts for open/rename
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ this.OS = navigator.userAgent.indexOf('Mac') !== -1 ? 'mac' : navigator.userAgent.indexOf('Win') !== -1 ? 'win' : 'other';
|
|
|
+
|
|
|
+ /**
|
|
|
+ * User browser UA.
|
|
|
+ * jQuery.browser: version deprecated: 1.3, removed: 1.9
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ this.UA = (function(){
|
|
|
+ var webkit = !document.uniqueID && !window.opera && !window.sidebar && window.localStorage && typeof window.orientation == "undefined";
|
|
|
+ return {
|
|
|
+ // Browser IE <= IE 6
|
|
|
+ ltIE6:typeof window.addEventListener == "undefined" && typeof document.documentElement.style.maxHeight == "undefined",
|
|
|
+ // Browser IE <= IE 7
|
|
|
+ ltIE7:typeof window.addEventListener == "undefined" && typeof document.querySelectorAll == "undefined",
|
|
|
+ // Browser IE <= IE 8
|
|
|
+ ltIE8:typeof window.addEventListener == "undefined" && typeof document.getElementsByClassName == "undefined",
|
|
|
+ IE:document.uniqueID,
|
|
|
+ Firefox:window.sidebar,
|
|
|
+ Opera:window.opera,
|
|
|
+ Webkit:webkit,
|
|
|
+ Chrome:webkit && window.chrome,
|
|
|
+ Safari:webkit && !window.chrome,
|
|
|
+ Mobile:typeof window.orientation != "undefined"
|
|
|
+ }
|
|
|
+ })();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Configuration options
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ this.options = $.extend(true, {}, this._options, opts||{});
|
|
|
+
|
|
|
+ if (opts.ui) {
|
|
|
+ this.options.ui = opts.ui;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (opts.commands) {
|
|
|
+ this.options.commands = opts.commands;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (opts.uiOptions && opts.uiOptions.toolbar) {
|
|
|
+ this.options.uiOptions.toolbar = opts.uiOptions.toolbar;
|
|
|
+ }
|
|
|
+
|
|
|
+ $.extend(this.options.contextmenu, opts.contextmenu);
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Ajax request type
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ * @default "get"
|
|
|
+ **/
|
|
|
+ this.requestType = /^(get|post)$/i.test(this.options.requestType) ? this.options.requestType.toLowerCase() : 'get',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Any data to send across every ajax request
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ * @default {}
|
|
|
+ **/
|
|
|
+ this.customData = $.isPlainObject(this.options.customData) ? this.options.customData : {};
|
|
|
+
|
|
|
+ /**
|
|
|
+ * ID. Required to create unique cookie name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ this.id = id;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * URL to upload files
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ this.uploadURL = opts.urlUpload || opts.url;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Events namespace
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ this.namespace = namespace;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Interface language
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ * @default "en"
|
|
|
+ **/
|
|
|
+ this.lang = this.i18[this.options.lang] && this.i18[this.options.lang].messages ? this.options.lang : 'en';
|
|
|
+
|
|
|
+ i18n = this.lang == 'en'
|
|
|
+ ? this.i18['en']
|
|
|
+ : $.extend(true, {}, this.i18['en'], this.i18[this.lang]);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Interface direction
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ * @default "ltr"
|
|
|
+ **/
|
|
|
+ this.direction = i18n.direction;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * i18 messages
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ this.messages = i18n.messages;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Date/time format
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ * @default "m.d.Y"
|
|
|
+ **/
|
|
|
+ this.dateFormat = this.options.dateFormat || i18n.dateFormat;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Date format like "Yesterday 10:20:12"
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ * @default "{day} {time}"
|
|
|
+ **/
|
|
|
+ this.fancyFormat = this.options.fancyDateFormat || i18n.fancyDateFormat;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Today timestamp
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ **/
|
|
|
+ this.today = (new Date(date.getFullYear(), date.getMonth(), date.getDate())).getTime()/1000;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Yesterday timestamp
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ **/
|
|
|
+ this.yesterday = this.today - 86400;
|
|
|
+
|
|
|
+ utc = this.options.UTCDate ? 'UTC' : '';
|
|
|
+
|
|
|
+ this.getHours = 'get'+utc+'Hours';
|
|
|
+ this.getMinutes = 'get'+utc+'Minutes';
|
|
|
+ this.getSeconds = 'get'+utc+'Seconds';
|
|
|
+ this.getDate = 'get'+utc+'Date';
|
|
|
+ this.getDay = 'get'+utc+'Day';
|
|
|
+ this.getMonth = 'get'+utc+'Month';
|
|
|
+ this.getFullYear = 'get'+utc+'FullYear';
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Css classes
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ this.cssClass = 'ui-helper-reset ui-helper-clearfix ui-widget ui-widget-content ui-corner-all elfinder elfinder-'+(this.direction == 'rtl' ? 'rtl' : 'ltr')+' '+this.options.cssClass;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Method to store/fetch data
|
|
|
+ *
|
|
|
+ * @type Function
|
|
|
+ **/
|
|
|
+ this.storage = (function() {
|
|
|
+ try {
|
|
|
+ return 'localStorage' in window && window['localStorage'] !== null ? self.localStorage : self.cookie;
|
|
|
+ } catch (e) {
|
|
|
+ return self.cookie;
|
|
|
+ }
|
|
|
+ })();
|
|
|
+
|
|
|
+ this.viewType = this.storage('view') || this.options.defaultView || 'icons';
|
|
|
+
|
|
|
+ this.sortType = this.storage('sortType') || this.options.sortType || 'name';
|
|
|
+
|
|
|
+ this.sortOrder = this.storage('sortOrder') || this.options.sortOrder || 'asc';
|
|
|
+
|
|
|
+ this.sortStickFolders = this.storage('sortStickFolders');
|
|
|
+
|
|
|
+ if (this.sortStickFolders === null) {
|
|
|
+ this.sortStickFolders = !!this.options.sortStickFolders;
|
|
|
+ } else {
|
|
|
+ this.sortStickFolders = !!this.sortStickFolders
|
|
|
+ }
|
|
|
+
|
|
|
+ this.sortRules = $.extend(true, {}, this._sortRules, this.options.sortsRules);
|
|
|
+
|
|
|
+ $.each(this.sortRules, function(name, method) {
|
|
|
+ if (typeof method != 'function') {
|
|
|
+ delete self.sortRules[name];
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ this.compare = $.proxy(this.compare, this);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Delay in ms before open notification dialog
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ * @default 500
|
|
|
+ **/
|
|
|
+ this.notifyDelay = this.options.notifyDelay > 0 ? parseInt(this.options.notifyDelay) : 500;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Base draggable options
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ this.draggable = {
|
|
|
+ appendTo : 'body',
|
|
|
+ addClasses : true,
|
|
|
+ delay : 30,
|
|
|
+ revert : true,
|
|
|
+ refreshPositions : true,
|
|
|
+ cursor : 'move',
|
|
|
+ cursorAt : {left : 50, top : 47},
|
|
|
+ drag : function(e, ui) {
|
|
|
+ if (! ui.helper.data('locked')) {
|
|
|
+ ui.helper.toggleClass('elfinder-drag-helper-plus', e.shiftKey||e.ctrlKey||e.metaKey);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ start : function(e, ui) {
|
|
|
+ var targets = $.map(ui.helper.data('files')||[], function(h) { return h || null ;}),
|
|
|
+ cnt, h;
|
|
|
+ cnt = targets.length;
|
|
|
+ while (cnt--) {
|
|
|
+ h = targets[cnt];
|
|
|
+ if (files[h].locked) {
|
|
|
+ ui.helper.addClass('elfinder-drag-helper-plus').data('locked', true);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ stop : function() { self.trigger('focus').trigger('dragstop'); },
|
|
|
+ helper : function(e, ui) {
|
|
|
+ var element = this.id ? $(this) : $(this).parents('[id]:first'),
|
|
|
+ helper = $('<div class="elfinder-drag-helper"><span class="elfinder-drag-helper-icon-plus"/></div>'),
|
|
|
+ icon = function(mime) { return '<div class="elfinder-cwd-icon '+self.mime2class(mime)+' ui-corner-all"/>'; },
|
|
|
+ hashes, l;
|
|
|
+
|
|
|
+ self.trigger('dragstart', {target : element[0], originalEvent : e});
|
|
|
+
|
|
|
+ hashes = element.is('.'+self.res('class', 'cwdfile'))
|
|
|
+ ? self.selected()
|
|
|
+ : [self.navId2Hash(element.attr('id'))];
|
|
|
+
|
|
|
+ helper.append(icon(files[hashes[0]].mime)).data('files', hashes).data('locked', false);
|
|
|
+
|
|
|
+ if ((l = hashes.length) > 1) {
|
|
|
+ helper.append(icon(files[hashes[l-1]].mime) + '<span class="elfinder-drag-num">'+l+'</span>');
|
|
|
+ }
|
|
|
+
|
|
|
+ return helper;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Base droppable options
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ this.droppable = {
|
|
|
+ // greedy : true,
|
|
|
+ tolerance : 'pointer',
|
|
|
+ accept : '.elfinder-cwd-file-wrapper,.elfinder-navbar-dir,.elfinder-cwd-file',
|
|
|
+ hoverClass : this.res('class', 'adroppable'),
|
|
|
+ drop : function(e, ui) {
|
|
|
+ var dst = $(this),
|
|
|
+ targets = $.map(ui.helper.data('files')||[], function(h) { return h || null }),
|
|
|
+ result = [],
|
|
|
+ c = 'class',
|
|
|
+ cnt, hash, i, h;
|
|
|
+
|
|
|
+ if (dst.is('.'+self.res(c, 'cwd'))) {
|
|
|
+ hash = cwd;
|
|
|
+ } else if (dst.is('.'+self.res(c, 'cwdfile'))) {
|
|
|
+ hash = dst.attr('id');
|
|
|
+ } else if (dst.is('.'+self.res(c, 'navdir'))) {
|
|
|
+ hash = self.navId2Hash(dst.attr('id'));
|
|
|
+ }
|
|
|
+
|
|
|
+ cnt = targets.length;
|
|
|
+
|
|
|
+ while (cnt--) {
|
|
|
+ h = targets[cnt];
|
|
|
+ // ignore drop into itself or in own location
|
|
|
+ h != hash && files[h].phash != hash && result.push(h);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (result.length) {
|
|
|
+ ui.helper.hide();
|
|
|
+ self.clipboard(result, !(e.ctrlKey||e.shiftKey||e.metaKey||ui.helper.data('locked')));
|
|
|
+ self.exec('paste', hash);
|
|
|
+ self.trigger('drop', {files : targets});
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return true if filemanager is active
|
|
|
+ *
|
|
|
+ * @return Boolean
|
|
|
+ **/
|
|
|
+ this.enabled = function() {
|
|
|
+ return node.is(':visible') && enabled;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return true if filemanager is visible
|
|
|
+ *
|
|
|
+ * @return Boolean
|
|
|
+ **/
|
|
|
+ this.visible = function() {
|
|
|
+ return node.is(':visible');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return root dir hash for current working directory
|
|
|
+ *
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ this.root = function(hash) {
|
|
|
+ var dir = files[hash || cwd], i;
|
|
|
+
|
|
|
+ while (dir && dir.phash) {
|
|
|
+ dir = files[dir.phash]
|
|
|
+ }
|
|
|
+ if (dir) {
|
|
|
+ return dir.hash;
|
|
|
+ }
|
|
|
+
|
|
|
+ while (i in files && files.hasOwnProperty(i)) {
|
|
|
+ dir = files[i]
|
|
|
+ if (!dir.phash && !dir.mime == 'directory' && dir.read) {
|
|
|
+ return dir.hash
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return current working directory info
|
|
|
+ *
|
|
|
+ * @return Object
|
|
|
+ */
|
|
|
+ this.cwd = function() {
|
|
|
+ return files[cwd] || {};
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return required cwd option
|
|
|
+ *
|
|
|
+ * @param String option name
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ this.option = function(name) {
|
|
|
+ return cwdOptions[name]||'';
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return file data from current dir or tree by it's hash
|
|
|
+ *
|
|
|
+ * @param String file hash
|
|
|
+ * @return Object
|
|
|
+ */
|
|
|
+ this.file = function(hash) {
|
|
|
+ return files[hash];
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return all cached files
|
|
|
+ *
|
|
|
+ * @return Array
|
|
|
+ */
|
|
|
+ this.files = function() {
|
|
|
+ return $.extend(true, {}, files);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return list of file parents hashes include file hash
|
|
|
+ *
|
|
|
+ * @param String file hash
|
|
|
+ * @return Array
|
|
|
+ */
|
|
|
+ this.parents = function(hash) {
|
|
|
+ var parents = [],
|
|
|
+ dir;
|
|
|
+
|
|
|
+ while ((dir = this.file(hash))) {
|
|
|
+ parents.unshift(dir.hash);
|
|
|
+ hash = dir.phash;
|
|
|
+ }
|
|
|
+ return parents;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.path2array = function(hash, i18) {
|
|
|
+ var file,
|
|
|
+ path = [];
|
|
|
+
|
|
|
+ while (hash && (file = files[hash]) && file.hash) {
|
|
|
+ path.unshift(i18 && file.i18 ? file.i18 : file.name);
|
|
|
+ hash = file.phash;
|
|
|
+ }
|
|
|
+
|
|
|
+ return path;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return file path
|
|
|
+ *
|
|
|
+ * @param Object file
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ this.path = function(hash, i18) {
|
|
|
+ return files[hash] && files[hash].path
|
|
|
+ ? files[hash].path
|
|
|
+ : this.path2array(hash, i18).join(cwdOptions.separator);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return file url if set
|
|
|
+ *
|
|
|
+ * @param Object file
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ this.url = function(hash) {
|
|
|
+ var file = files[hash];
|
|
|
+
|
|
|
+ if (!file || !file.read) {
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+
|
|
|
+ if (file.url) {
|
|
|
+ return file.url;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cwdOptions.url) {
|
|
|
+ return cwdOptions.url + $.map(this.path2array(hash), function(n) { return encodeURIComponent(n); }).slice(1).join('/')
|
|
|
+ }
|
|
|
+
|
|
|
+ var params = $.extend({}, this.customData, {
|
|
|
+ cmd: 'file',
|
|
|
+ target: file.hash
|
|
|
+ });
|
|
|
+ if (this.oldAPI) {
|
|
|
+ params.cmd = 'open';
|
|
|
+ params.current = file.phash;
|
|
|
+ }
|
|
|
+ return this.options.url + (this.options.url.indexOf('?') === -1 ? '?' : '&') + $.param(params, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return thumbnail url
|
|
|
+ *
|
|
|
+ * @param String file hash
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ this.tmb = function(hash) {
|
|
|
+ var file = files[hash],
|
|
|
+ url = file && file.tmb && file.tmb != 1 ? cwdOptions['tmbUrl'] + file.tmb : '';
|
|
|
+
|
|
|
+ if (url && (this.UA.Opera || this.UA.IE)) {
|
|
|
+ url += '?_=' + new Date().getTime();
|
|
|
+ }
|
|
|
+ return url;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return selected files hashes
|
|
|
+ *
|
|
|
+ * @return Array
|
|
|
+ **/
|
|
|
+ this.selected = function() {
|
|
|
+ return selected.slice(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return selected files info
|
|
|
+ *
|
|
|
+ * @return Array
|
|
|
+ */
|
|
|
+ this.selectedFiles = function() {
|
|
|
+ return $.map(selected, function(hash) { return files[hash] ? $.extend({}, files[hash]) : null });
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return true if file with required name existsin required folder
|
|
|
+ *
|
|
|
+ * @param String file name
|
|
|
+ * @param String parent folder hash
|
|
|
+ * @return Boolean
|
|
|
+ */
|
|
|
+ this.fileByName = function(name, phash) {
|
|
|
+ var hash;
|
|
|
+
|
|
|
+ for (hash in files) {
|
|
|
+ if (files.hasOwnProperty(hash) && files[hash].phash == phash && files[hash].name == name) {
|
|
|
+ return files[hash];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Valid data for required command based on rules
|
|
|
+ *
|
|
|
+ * @param String command name
|
|
|
+ * @param Object cammand's data
|
|
|
+ * @return Boolean
|
|
|
+ */
|
|
|
+ this.validResponse = function(cmd, data) {
|
|
|
+ return data.error || this.rules[this.rules[cmd] ? cmd : 'defaults'](data);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return bytes from ini formated size
|
|
|
+ *
|
|
|
+ * @param String ini formated size
|
|
|
+ * @return Integer
|
|
|
+ */
|
|
|
+ this.returnBytes = function(val) {
|
|
|
+ if (val == '-1') val = 0;
|
|
|
+ if (val) {
|
|
|
+ // for ex. 1mb, 1KB
|
|
|
+ val = val.replace(/b$/i, '');
|
|
|
+ var last = val.charAt(val.length - 1).toLowerCase();
|
|
|
+ val = val.replace(/[gmk]$/i, '');
|
|
|
+ if (last == 'g') {
|
|
|
+ val = val * 1024 * 1024 * 1024;
|
|
|
+ } else if (last == 'm') {
|
|
|
+ val = val * 1024 * 1024;
|
|
|
+ } else if (last == 'k') {
|
|
|
+ val = val * 1024;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return val;
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Proccess ajax request.
|
|
|
+ * Fired events :
|
|
|
+ * @todo
|
|
|
+ * @example
|
|
|
+ * @todo
|
|
|
+ * @return $.Deferred
|
|
|
+ */
|
|
|
+ this.request = function(options) {
|
|
|
+ var self = this,
|
|
|
+ o = this.options,
|
|
|
+ dfrd = $.Deferred(),
|
|
|
+ // request data
|
|
|
+ data = $.extend({}, o.customData, {mimes : o.onlyMimes}, options.data || options),
|
|
|
+ // command name
|
|
|
+ cmd = data.cmd,
|
|
|
+ // call default fail callback (display error dialog) ?
|
|
|
+ deffail = !(options.preventDefault || options.preventFail),
|
|
|
+ // call default success callback ?
|
|
|
+ defdone = !(options.preventDefault || options.preventDone),
|
|
|
+ // options for notify dialog
|
|
|
+ notify = $.extend({}, options.notify),
|
|
|
+ // do not normalize data - return as is
|
|
|
+ raw = !!options.raw,
|
|
|
+ // sync files on request fail
|
|
|
+ syncOnFail = options.syncOnFail,
|
|
|
+ // open notify dialog timeout
|
|
|
+ timeout,
|
|
|
+ // request options
|
|
|
+ options = $.extend({
|
|
|
+ url : o.url,
|
|
|
+ async : true,
|
|
|
+ type : this.requestType,
|
|
|
+ dataType : 'json',
|
|
|
+ cache : false,
|
|
|
+ // timeout : 100,
|
|
|
+ data : data
|
|
|
+ }, options.options || {}),
|
|
|
+ /**
|
|
|
+ * Default success handler.
|
|
|
+ * Call default data handlers and fire event with command name.
|
|
|
+ *
|
|
|
+ * @param Object normalized response data
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ done = function(data) {
|
|
|
+ data.warning && self.error(data.warning);
|
|
|
+
|
|
|
+ cmd == 'open' && open($.extend(true, {}, data));
|
|
|
+
|
|
|
+ // fire some event to update cache/ui
|
|
|
+ data.removed && data.removed.length && self.remove(data);
|
|
|
+ data.added && data.added.length && self.add(data);
|
|
|
+ data.changed && data.changed.length && self.change(data);
|
|
|
+
|
|
|
+ // fire event with command name
|
|
|
+ self.trigger(cmd, data);
|
|
|
+
|
|
|
+ // force update content
|
|
|
+ data.sync && self.sync();
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * Request error handler. Reject dfrd with correct error message.
|
|
|
+ *
|
|
|
+ * @param jqxhr request object
|
|
|
+ * @param String request status
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ error = function(xhr, status) {
|
|
|
+ var error;
|
|
|
+
|
|
|
+ switch (status) {
|
|
|
+ case 'abort':
|
|
|
+ error = xhr.quiet ? '' : ['errConnect', 'errAbort'];
|
|
|
+ break;
|
|
|
+ case 'timeout':
|
|
|
+ error = ['errConnect', 'errTimeout'];
|
|
|
+ break;
|
|
|
+ case 'parsererror':
|
|
|
+ error = ['errResponse', 'errDataNotJSON'];
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ if (xhr.status == 403) {
|
|
|
+ error = ['errConnect', 'errAccess'];
|
|
|
+ } else if (xhr.status == 404) {
|
|
|
+ error = ['errConnect', 'errNotFound'];
|
|
|
+ } else {
|
|
|
+ error = 'errConnect';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ dfrd.reject(error, xhr, status);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * Request success handler. Valid response data and reject/resolve dfrd.
|
|
|
+ *
|
|
|
+ * @param Object response data
|
|
|
+ * @param String request status
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ success = function(response) {
|
|
|
+ if (raw) {
|
|
|
+ return dfrd.resolve(response);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!response) {
|
|
|
+ return dfrd.reject(['errResponse', 'errDataEmpty'], xhr);
|
|
|
+ } else if (!$.isPlainObject(response)) {
|
|
|
+ return dfrd.reject(['errResponse', 'errDataNotJSON'], xhr);
|
|
|
+ } else if (response.error) {
|
|
|
+ return dfrd.reject(response.error, xhr);
|
|
|
+ } else if (!self.validResponse(cmd, response)) {
|
|
|
+ return dfrd.reject('errResponse', xhr);
|
|
|
+ }
|
|
|
+
|
|
|
+ response = self.normalize(response);
|
|
|
+
|
|
|
+ if (!self.api) {
|
|
|
+ self.api = response.api || 1;
|
|
|
+ self.newAPI = self.api >= 2;
|
|
|
+ self.oldAPI = !self.newAPI;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (response.options) {
|
|
|
+ cwdOptions = $.extend({}, cwdOptions, response.options);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (response.netDrivers) {
|
|
|
+ self.netDrivers = response.netDrivers;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmd == 'open' && !!data.init) {
|
|
|
+ self.uplMaxSize = self.returnBytes(response.uplMaxSize);
|
|
|
+ self.uplMaxFile = !!response.uplMaxFile? parseInt(response.uplMaxFile) : 20;
|
|
|
+ }
|
|
|
+
|
|
|
+ dfrd.resolve(response);
|
|
|
+ response.debug && self.debug('backend-debug', response.debug);
|
|
|
+ },
|
|
|
+ xhr, _xhr
|
|
|
+ ;
|
|
|
+
|
|
|
+ defdone && dfrd.done(done);
|
|
|
+ dfrd.fail(function(error) {
|
|
|
+ if (error) {
|
|
|
+ deffail ? self.error(error) : self.debug('error', self.i18n(error));
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ if (!cmd) {
|
|
|
+ return dfrd.reject('errCmdReq');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (syncOnFail) {
|
|
|
+ dfrd.fail(function(error) {
|
|
|
+ error && self.sync();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (notify.type && notify.cnt) {
|
|
|
+ timeout = setTimeout(function() {
|
|
|
+ self.notify(notify);
|
|
|
+ dfrd.always(function() {
|
|
|
+ notify.cnt = -(parseInt(notify.cnt)||0);
|
|
|
+ self.notify(notify);
|
|
|
+ })
|
|
|
+ }, self.notifyDelay)
|
|
|
+
|
|
|
+ dfrd.always(function() {
|
|
|
+ clearTimeout(timeout);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // quiet abort not completed "open" requests
|
|
|
+ if (cmd == 'open') {
|
|
|
+ while ((_xhr = queue.pop())) {
|
|
|
+ if (_xhr.state() == 'pending') {
|
|
|
+ _xhr.quiet = true;
|
|
|
+ _xhr.abort();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ delete options.preventFail
|
|
|
+
|
|
|
+ xhr = this.transport.send(options).fail(error).done(success);
|
|
|
+
|
|
|
+ // this.transport.send(options)
|
|
|
+
|
|
|
+ // add "open" xhr into queue
|
|
|
+ if (cmd == 'open') {
|
|
|
+ queue.unshift(xhr);
|
|
|
+ dfrd.always(function() {
|
|
|
+ var ndx = $.inArray(xhr, queue);
|
|
|
+
|
|
|
+ ndx !== -1 && queue.splice(ndx, 1);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ return dfrd;
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Compare current files cache with new files and return diff
|
|
|
+ *
|
|
|
+ * @param Array new files
|
|
|
+ * @return Object
|
|
|
+ */
|
|
|
+ this.diff = function(incoming) {
|
|
|
+ var raw = {},
|
|
|
+ added = [],
|
|
|
+ removed = [],
|
|
|
+ changed = [],
|
|
|
+ isChanged = function(hash) {
|
|
|
+ var l = changed.length;
|
|
|
+
|
|
|
+ while (l--) {
|
|
|
+ if (changed[l].hash == hash) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ $.each(incoming, function(i, f) {
|
|
|
+ raw[f.hash] = f;
|
|
|
+ });
|
|
|
+
|
|
|
+ // find removed
|
|
|
+ $.each(files, function(hash, f) {
|
|
|
+ !raw[hash] && removed.push(hash);
|
|
|
+ });
|
|
|
+
|
|
|
+ // compare files
|
|
|
+ $.each(raw, function(hash, file) {
|
|
|
+ var origin = files[hash];
|
|
|
+
|
|
|
+ if (!origin) {
|
|
|
+ added.push(file);
|
|
|
+ } else {
|
|
|
+ $.each(file, function(prop) {
|
|
|
+ if (file[prop] != origin[prop]) {
|
|
|
+ changed.push(file)
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // parents of removed dirs mark as changed (required for tree correct work)
|
|
|
+ $.each(removed, function(i, hash) {
|
|
|
+ var file = files[hash],
|
|
|
+ phash = file.phash;
|
|
|
+
|
|
|
+ if (phash
|
|
|
+ && file.mime == 'directory'
|
|
|
+ && $.inArray(phash, removed) === -1
|
|
|
+ && raw[phash]
|
|
|
+ && !isChanged(phash)) {
|
|
|
+ changed.push(raw[phash]);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return {
|
|
|
+ added : added,
|
|
|
+ removed : removed,
|
|
|
+ changed : changed
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Sync content
|
|
|
+ *
|
|
|
+ * @return jQuery.Deferred
|
|
|
+ */
|
|
|
+ this.sync = function() {
|
|
|
+ var self = this,
|
|
|
+ dfrd = $.Deferred().done(function() { self.trigger('sync'); }),
|
|
|
+ opts1 = {
|
|
|
+ data : {cmd : 'open', init : 1, target : cwd, tree : this.ui.tree ? 1 : 0},
|
|
|
+ preventDefault : true
|
|
|
+ },
|
|
|
+ opts2 = {
|
|
|
+ data : {cmd : 'tree', target : (cwd == this.root())? cwd : this.file(cwd).phash},
|
|
|
+ preventDefault : true
|
|
|
+ };
|
|
|
+
|
|
|
+ $.when(
|
|
|
+ this.request(opts1),
|
|
|
+ this.request(opts2)
|
|
|
+ )
|
|
|
+ .fail(function(error) {
|
|
|
+ dfrd.reject(error);
|
|
|
+ error && self.request({
|
|
|
+ data : {cmd : 'open', target : self.lastDir(''), tree : 1, init : 1},
|
|
|
+ notify : {type : 'open', cnt : 1, hideCnt : true},
|
|
|
+ preventDefault : true
|
|
|
+ });
|
|
|
+ })
|
|
|
+ .done(function(odata, pdata) {
|
|
|
+ var diff = self.diff(odata.files.concat(pdata && pdata.tree ? pdata.tree : []));
|
|
|
+
|
|
|
+ diff.added.push(odata.cwd)
|
|
|
+ diff.removed.length && self.remove(diff);
|
|
|
+ diff.added.length && self.add(diff);
|
|
|
+ diff.changed.length && self.change(diff);
|
|
|
+ return dfrd.resolve(diff);
|
|
|
+ });
|
|
|
+
|
|
|
+ return dfrd;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.upload = function(files) {
|
|
|
+ return this.transport.upload(files, this);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Attach listener to events
|
|
|
+ * To bind to multiply events at once, separate events names by space
|
|
|
+ *
|
|
|
+ * @param String event(s) name(s)
|
|
|
+ * @param Object event handler
|
|
|
+ * @return elFinder
|
|
|
+ */
|
|
|
+ this.bind = function(event, callback) {
|
|
|
+ var i;
|
|
|
+
|
|
|
+ if (typeof(callback) == 'function') {
|
|
|
+ event = ('' + event).toLowerCase().split(/\s+/);
|
|
|
+
|
|
|
+ for (i = 0; i < event.length; i++) {
|
|
|
+ if (listeners[event[i]] === void(0)) {
|
|
|
+ listeners[event[i]] = [];
|
|
|
+ }
|
|
|
+ listeners[event[i]].push(callback);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Remove event listener if exists
|
|
|
+ *
|
|
|
+ * @param String event name
|
|
|
+ * @param Function callback
|
|
|
+ * @return elFinder
|
|
|
+ */
|
|
|
+ this.unbind = function(event, callback) {
|
|
|
+ var l = listeners[('' + event).toLowerCase()] || [],
|
|
|
+ i = l.indexOf(callback);
|
|
|
+
|
|
|
+ i > -1 && l.splice(i, 1);
|
|
|
+ //delete callback; // need this?
|
|
|
+ callback = null
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Fire event - send notification to all event listeners
|
|
|
+ *
|
|
|
+ * @param String event type
|
|
|
+ * @param Object data to send across event
|
|
|
+ * @return elFinder
|
|
|
+ */
|
|
|
+ this.trigger = function(event, data) {
|
|
|
+ var event = event.toLowerCase(),
|
|
|
+ handlers = listeners[event] || [], i, j;
|
|
|
+
|
|
|
+ this.debug('event-'+event, data)
|
|
|
+
|
|
|
+ if (handlers.length) {
|
|
|
+ event = $.Event(event);
|
|
|
+
|
|
|
+ for (i = 0; i < handlers.length; i++) {
|
|
|
+ // to avoid data modifications. remember about "sharing" passing arguments in js :)
|
|
|
+ event.data = $.extend(true, {}, data);
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (handlers[i](event, this) === false
|
|
|
+ || event.isDefaultPrevented()) {
|
|
|
+ this.debug('event-stoped', event.type);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } catch (ex) {
|
|
|
+ window.console && window.console.log && window.console.log(ex);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Bind keybord shortcut to keydown event
|
|
|
+ *
|
|
|
+ * @example
|
|
|
+ * elfinder.shortcut({
|
|
|
+ * pattern : 'ctrl+a',
|
|
|
+ * description : 'Select all files',
|
|
|
+ * callback : function(e) { ... },
|
|
|
+ * keypress : true|false (bind to keypress instead of keydown)
|
|
|
+ * })
|
|
|
+ *
|
|
|
+ * @param Object shortcut config
|
|
|
+ * @return elFinder
|
|
|
+ */
|
|
|
+ this.shortcut = function(s) {
|
|
|
+ var patterns, pattern, code, i, parts;
|
|
|
+
|
|
|
+ if (this.options.allowShortcuts && s.pattern && $.isFunction(s.callback)) {
|
|
|
+ patterns = s.pattern.toUpperCase().split(/\s+/);
|
|
|
+
|
|
|
+ for (i= 0; i < patterns.length; i++) {
|
|
|
+ pattern = patterns[i]
|
|
|
+ parts = pattern.split('+');
|
|
|
+ code = (code = parts.pop()).length == 1
|
|
|
+ ? code > 0 ? code : code.charCodeAt(0)
|
|
|
+ : $.ui.keyCode[code];
|
|
|
+
|
|
|
+ if (code && !shortcuts[pattern]) {
|
|
|
+ shortcuts[pattern] = {
|
|
|
+ keyCode : code,
|
|
|
+ altKey : $.inArray('ALT', parts) != -1,
|
|
|
+ ctrlKey : $.inArray('CTRL', parts) != -1,
|
|
|
+ shiftKey : $.inArray('SHIFT', parts) != -1,
|
|
|
+ type : s.type || 'keydown',
|
|
|
+ callback : s.callback,
|
|
|
+ description : s.description,
|
|
|
+ pattern : pattern
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Registered shortcuts
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ this.shortcuts = function() {
|
|
|
+ var ret = [];
|
|
|
+
|
|
|
+ $.each(shortcuts, function(i, s) {
|
|
|
+ ret.push([s.pattern, self.i18n(s.description)]);
|
|
|
+ });
|
|
|
+ return ret;
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get/set clipboard content.
|
|
|
+ * Return new clipboard content.
|
|
|
+ *
|
|
|
+ * @example
|
|
|
+ * this.clipboard([]) - clean clipboard
|
|
|
+ * this.clipboard([{...}, {...}], true) - put 2 files in clipboard and mark it as cutted
|
|
|
+ *
|
|
|
+ * @param Array new files hashes
|
|
|
+ * @param Boolean cut files?
|
|
|
+ * @return Array
|
|
|
+ */
|
|
|
+ this.clipboard = function(hashes, cut) {
|
|
|
+ var map = function() { return $.map(clipboard, function(f) { return f.hash }); }
|
|
|
+
|
|
|
+ if (hashes !== void(0)) {
|
|
|
+ clipboard.length && this.trigger('unlockfiles', {files : map()});
|
|
|
+ remember = [];
|
|
|
+
|
|
|
+ clipboard = $.map(hashes||[], function(hash) {
|
|
|
+ var file = files[hash];
|
|
|
+ if (file) {
|
|
|
+
|
|
|
+ remember.push(hash);
|
|
|
+
|
|
|
+ return {
|
|
|
+ hash : hash,
|
|
|
+ phash : file.phash,
|
|
|
+ name : file.name,
|
|
|
+ mime : file.mime,
|
|
|
+ read : file.read,
|
|
|
+ locked : file.locked,
|
|
|
+ cut : !!cut
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ });
|
|
|
+ this.trigger('changeclipboard', {clipboard : clipboard.slice(0, clipboard.length)});
|
|
|
+ cut && this.trigger('lockfiles', {files : map()});
|
|
|
+ }
|
|
|
+
|
|
|
+ // return copy of clipboard instead of refrence
|
|
|
+ return clipboard.slice(0, clipboard.length);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return true if command enabled
|
|
|
+ *
|
|
|
+ * @param String command name
|
|
|
+ * @return Boolean
|
|
|
+ */
|
|
|
+ this.isCommandEnabled = function(name) {
|
|
|
+ return this._commands[name] ? $.inArray(name, cwdOptions.disabled) === -1 : false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Exec command and return result;
|
|
|
+ *
|
|
|
+ * @param String command name
|
|
|
+ * @param String|Array usualy files hashes
|
|
|
+ * @param String|Array command options
|
|
|
+ * @return $.Deferred
|
|
|
+ */
|
|
|
+ this.exec = function(cmd, files, opts) {
|
|
|
+ return this._commands[cmd] && this.isCommandEnabled(cmd)
|
|
|
+ ? this._commands[cmd].exec(files, opts)
|
|
|
+ : $.Deferred().reject('No such command');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create and return dialog.
|
|
|
+ *
|
|
|
+ * @param String|DOMElement dialog content
|
|
|
+ * @param Object dialog options
|
|
|
+ * @return jQuery
|
|
|
+ */
|
|
|
+ this.dialog = function(content, options) {
|
|
|
+ return $('<div/>').append(content).appendTo(node).elfinderdialog(options);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return UI widget or node
|
|
|
+ *
|
|
|
+ * @param String ui name
|
|
|
+ * @return jQuery
|
|
|
+ */
|
|
|
+ this.getUI = function(ui) {
|
|
|
+ return this.ui[ui] || node;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.command = function(name) {
|
|
|
+ return name === void(0) ? this._commands : this._commands[name];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Resize elfinder node
|
|
|
+ *
|
|
|
+ * @param String|Number width
|
|
|
+ * @param Number height
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ this.resize = function(w, h) {
|
|
|
+ node.css('width', w).height(h).trigger('resize');
|
|
|
+ this.trigger('resize', {width : node.width(), height : node.height()});
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Restore elfinder node size
|
|
|
+ *
|
|
|
+ * @return elFinder
|
|
|
+ */
|
|
|
+ this.restoreSize = function() {
|
|
|
+ this.resize(width, height);
|
|
|
+ }
|
|
|
+
|
|
|
+ this.show = function() {
|
|
|
+ node.show();
|
|
|
+ this.enable().trigger('show');
|
|
|
+ }
|
|
|
+
|
|
|
+ this.hide = function() {
|
|
|
+ this.disable().trigger('hide');
|
|
|
+ node.hide();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Destroy this elFinder instance
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ this.destroy = function() {
|
|
|
+ if (node && node[0].elfinder) {
|
|
|
+ this.trigger('destroy').disable();
|
|
|
+ listeners = {};
|
|
|
+ shortcuts = {};
|
|
|
+ $(document).add(node).unbind('.'+this.namespace);
|
|
|
+ self.trigger = function() { }
|
|
|
+ node.children().remove();
|
|
|
+ node.append(prevContent.contents()).removeClass(this.cssClass).attr('style', prevStyle);
|
|
|
+ node[0].elfinder = null;
|
|
|
+ if (syncInterval) {
|
|
|
+ clearInterval(syncInterval);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /************* init stuffs ****************/
|
|
|
+
|
|
|
+ // check jquery ui
|
|
|
+ if (!($.fn.selectable && $.fn.draggable && $.fn.droppable)) {
|
|
|
+ return alert(this.i18n('errJqui'));
|
|
|
+ }
|
|
|
+
|
|
|
+ // check node
|
|
|
+ if (!node.length) {
|
|
|
+ return alert(this.i18n('errNode'));
|
|
|
+ }
|
|
|
+ // check connector url
|
|
|
+ if (!this.options.url) {
|
|
|
+ return alert(this.i18n('errURL'));
|
|
|
+ }
|
|
|
+
|
|
|
+ $.extend($.ui.keyCode, {
|
|
|
+ 'F1' : 112,
|
|
|
+ 'F2' : 113,
|
|
|
+ 'F3' : 114,
|
|
|
+ 'F4' : 115,
|
|
|
+ 'F5' : 116,
|
|
|
+ 'F6' : 117,
|
|
|
+ 'F7' : 118,
|
|
|
+ 'F8' : 119,
|
|
|
+ 'F9' : 120
|
|
|
+ });
|
|
|
+
|
|
|
+ this.dragUpload = false;
|
|
|
+ this.xhrUpload = (typeof XMLHttpRequestUpload != 'undefined' || typeof XMLHttpRequestEventTarget != 'undefined') && typeof File != 'undefined' && typeof FormData != 'undefined';
|
|
|
+
|
|
|
+ // configure transport object
|
|
|
+ this.transport = {}
|
|
|
+
|
|
|
+ if (typeof(this.options.transport) == 'object') {
|
|
|
+ this.transport = this.options.transport;
|
|
|
+ if (typeof(this.transport.init) == 'function') {
|
|
|
+ this.transport.init(this)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (typeof(this.transport.send) != 'function') {
|
|
|
+ this.transport.send = function(opts) { return $.ajax(opts); }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.transport.upload == 'iframe') {
|
|
|
+ this.transport.upload = $.proxy(this.uploads.iframe, this);
|
|
|
+ } else if (typeof(this.transport.upload) == 'function') {
|
|
|
+ this.dragUpload = !!this.options.dragUploadAllow;
|
|
|
+ } else if (this.xhrUpload && !!this.options.dragUploadAllow) {
|
|
|
+ this.transport.upload = $.proxy(this.uploads.xhr, this);
|
|
|
+ this.dragUpload = true;
|
|
|
+ } else {
|
|
|
+ this.transport.upload = $.proxy(this.uploads.iframe, this);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Alias for this.trigger('error', {error : 'message'})
|
|
|
+ *
|
|
|
+ * @param String error message
|
|
|
+ * @return elFinder
|
|
|
+ **/
|
|
|
+ this.error = function() {
|
|
|
+ var arg = arguments[0];
|
|
|
+ return arguments.length == 1 && typeof(arg) == 'function'
|
|
|
+ ? self.bind('error', arg)
|
|
|
+ : self.trigger('error', {error : arg});
|
|
|
+ }
|
|
|
+
|
|
|
+ // create bind/trigger aliases for build-in events
|
|
|
+ $.each(['enable', 'disable', 'load', 'open', 'reload', 'select', 'add', 'remove', 'change', 'dblclick', 'getfile', 'lockfiles', 'unlockfiles', 'dragstart', 'dragstop', 'search', 'searchend', 'viewchange'], function(i, name) {
|
|
|
+ self[name] = function() {
|
|
|
+ var arg = arguments[0];
|
|
|
+ return arguments.length == 1 && typeof(arg) == 'function'
|
|
|
+ ? self.bind(name, arg)
|
|
|
+ : self.trigger(name, $.isPlainObject(arg) ? arg : {});
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // bind core event handlers
|
|
|
+ this
|
|
|
+ .enable(function() {
|
|
|
+ if (!enabled && self.visible() && self.ui.overlay.is(':hidden')) {
|
|
|
+ enabled = true;
|
|
|
+ $('texarea:focus,input:focus,button').blur();
|
|
|
+ node.removeClass('elfinder-disabled');
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .disable(function() {
|
|
|
+ prevEnabled = enabled;
|
|
|
+ enabled = false;
|
|
|
+ node.addClass('elfinder-disabled');
|
|
|
+ })
|
|
|
+ .open(function() {
|
|
|
+ selected = [];
|
|
|
+ })
|
|
|
+ .select(function(e) {
|
|
|
+ selected = $.map(e.data.selected || e.data.value|| [], function(hash) { return files[hash] ? hash : null; });
|
|
|
+ })
|
|
|
+ .error(function(e) {
|
|
|
+ var opts = {
|
|
|
+ cssClass : 'elfinder-dialog-error',
|
|
|
+ title : self.i18n(self.i18n('error')),
|
|
|
+ resizable : false,
|
|
|
+ destroyOnClose : true,
|
|
|
+ buttons : {}
|
|
|
+ };
|
|
|
+
|
|
|
+ opts.buttons[self.i18n(self.i18n('btnClose'))] = function() { $(this).elfinderdialog('close'); };
|
|
|
+
|
|
|
+ self.dialog('<span class="elfinder-dialog-icon elfinder-dialog-icon-error"/>'+self.i18n(e.data.error), opts);
|
|
|
+ })
|
|
|
+ .bind('tree parents', function(e) {
|
|
|
+ cache(e.data.tree || []);
|
|
|
+ })
|
|
|
+ .bind('tmb', function(e) {
|
|
|
+ $.each(e.data.images||[], function(hash, tmb) {
|
|
|
+ if (files[hash]) {
|
|
|
+ files[hash].tmb = tmb;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ .add(function(e) {
|
|
|
+ cache(e.data.added||[]);
|
|
|
+ })
|
|
|
+ .change(function(e) {
|
|
|
+ $.each(e.data.changed||[], function(i, file) {
|
|
|
+ var hash = file.hash;
|
|
|
+ if ((files[hash].width && !file.width) || (files[hash].height && !file.height)) {
|
|
|
+ files[hash].width = undefined;
|
|
|
+ files[hash].height = undefined;
|
|
|
+ }
|
|
|
+ files[hash] = files[hash] ? $.extend(files[hash], file) : file;
|
|
|
+ });
|
|
|
+ })
|
|
|
+ .remove(function(e) {
|
|
|
+ var removed = e.data.removed||[],
|
|
|
+ l = removed.length,
|
|
|
+ rm = function(hash) {
|
|
|
+ var file = files[hash];
|
|
|
+ if (file) {
|
|
|
+ if (file.mime == 'directory' && file.dirs) {
|
|
|
+ $.each(files, function(h, f) {
|
|
|
+ f.phash == hash && rm(h);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ delete files[hash];
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ while (l--) {
|
|
|
+ rm(removed[l]);
|
|
|
+ }
|
|
|
+
|
|
|
+ })
|
|
|
+ .bind('search', function(e) {
|
|
|
+ cache(e.data.files);
|
|
|
+ })
|
|
|
+ .bind('rm', function(e) {
|
|
|
+ var play = beeper.canPlayType && beeper.canPlayType('audio/wav; codecs="1"');
|
|
|
+
|
|
|
+ play && play != '' && play != 'no' && $(beeper).html('<source src="./sounds/rm.wav" type="audio/wav">')[0].play()
|
|
|
+ })
|
|
|
+
|
|
|
+ ;
|
|
|
+
|
|
|
+ // bind external event handlers
|
|
|
+ $.each(this.options.handlers, function(event, callback) {
|
|
|
+ self.bind(event, callback);
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * History object. Store visited folders
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ this.history = new this.history(this);
|
|
|
+
|
|
|
+ // in getFileCallback set - change default actions on double click/enter/ctrl+enter
|
|
|
+ if (typeof(this.options.getFileCallback) == 'function' && this.commands.getfile) {
|
|
|
+ this.bind('dblclick', function(e) {
|
|
|
+ e.preventDefault();
|
|
|
+ self.exec('getfile').fail(function() {
|
|
|
+ self.exec('open');
|
|
|
+ });
|
|
|
+ });
|
|
|
+ this.shortcut({
|
|
|
+ pattern : 'enter',
|
|
|
+ description : this.i18n('cmdgetfile'),
|
|
|
+ callback : function() { self.exec('getfile').fail(function() { self.exec(self.OS == 'mac' ? 'rename' : 'open') }) }
|
|
|
+ })
|
|
|
+ .shortcut({
|
|
|
+ pattern : 'ctrl+enter',
|
|
|
+ description : this.i18n(this.OS == 'mac' ? 'cmdrename' : 'cmdopen'),
|
|
|
+ callback : function() { self.exec(self.OS == 'mac' ? 'rename' : 'open') }
|
|
|
+ });
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Loaded commands
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ this._commands = {};
|
|
|
+
|
|
|
+ if (!$.isArray(this.options.commands)) {
|
|
|
+ this.options.commands = [];
|
|
|
+ }
|
|
|
+ // check required commands
|
|
|
+ $.each(['open', 'reload', 'back', 'forward', 'up', 'home', 'info', 'quicklook', 'getfile', 'help'], function(i, cmd) {
|
|
|
+ $.inArray(cmd, self.options.commands) === -1 && self.options.commands.push(cmd);
|
|
|
+ });
|
|
|
+
|
|
|
+ // load commands
|
|
|
+ $.each(this.options.commands, function(i, name) {
|
|
|
+ var cmd = self.commands[name];
|
|
|
+ if ($.isFunction(cmd) && !self._commands[name]) {
|
|
|
+ cmd.prototype = base;
|
|
|
+ self._commands[name] = new cmd();
|
|
|
+ self._commands[name].setup(name, self.options.commandsOptions[name]||{});
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // prepare node
|
|
|
+ node.addClass(this.cssClass)
|
|
|
+ .bind(mousedown, function() {
|
|
|
+ !enabled && self.enable();
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * UI nodes
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ this.ui = {
|
|
|
+ // container for nav panel and current folder container
|
|
|
+ workzone : $('<div/>').appendTo(node).elfinderworkzone(this),
|
|
|
+ // container for folders tree / places
|
|
|
+ navbar : $('<div/>').appendTo(node).elfindernavbar(this, this.options.uiOptions.navbar || {}),
|
|
|
+ // contextmenu
|
|
|
+ contextmenu : $('<div/>').appendTo(node).elfindercontextmenu(this),
|
|
|
+ // overlay
|
|
|
+ overlay : $('<div/>').appendTo(node).elfinderoverlay({
|
|
|
+ show : function() { self.disable(); },
|
|
|
+ hide : function() { prevEnabled && self.enable(); }
|
|
|
+ }),
|
|
|
+ // current folder container
|
|
|
+ cwd : $('<div/>').appendTo(node).elfindercwd(this, this.options.uiOptions.cwd || {}),
|
|
|
+ // notification dialog window
|
|
|
+ notify : this.dialog('', {
|
|
|
+ cssClass : 'elfinder-dialog-notify',
|
|
|
+ position : {top : '12px', right : '12px'},
|
|
|
+ resizable : false,
|
|
|
+ autoOpen : false,
|
|
|
+ title : ' ',
|
|
|
+ width : 280
|
|
|
+ }),
|
|
|
+ statusbar : $('<div class="ui-widget-header ui-helper-clearfix ui-corner-bottom elfinder-statusbar"/>').hide().appendTo(node)
|
|
|
+ }
|
|
|
+
|
|
|
+ // load required ui
|
|
|
+ $.each(this.options.ui || [], function(i, ui) {
|
|
|
+ var name = 'elfinder'+ui,
|
|
|
+ opts = self.options.uiOptions[ui] || {};
|
|
|
+
|
|
|
+ if (!self.ui[ui] && $.fn[name]) {
|
|
|
+ self.ui[ui] = $('<'+(opts.tag || 'div')+'/>').appendTo(node)[name](self, opts);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // store instance in node
|
|
|
+ node[0].elfinder = this;
|
|
|
+
|
|
|
+ // make node resizable
|
|
|
+ this.options.resizable
|
|
|
+ && $.fn.resizable
|
|
|
+ && node.resizable({
|
|
|
+ handles : 'se',
|
|
|
+ minWidth : 300,
|
|
|
+ minHeight : 200
|
|
|
+ });
|
|
|
+
|
|
|
+ if (this.options.width) {
|
|
|
+ width = this.options.width;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.options.height) {
|
|
|
+ height = parseInt(this.options.height);
|
|
|
+ }
|
|
|
+
|
|
|
+ // update size
|
|
|
+ self.resize(width, height);
|
|
|
+
|
|
|
+ // attach events to document
|
|
|
+ $(document)
|
|
|
+ // disable elfinder on click outside elfinder
|
|
|
+ .bind('click.'+this.namespace, function(e) { enabled && !$(e.target).closest(node).length && self.disable(); })
|
|
|
+ // exec shortcuts
|
|
|
+ .bind(keydown+' '+keypress, execShortcut);
|
|
|
+
|
|
|
+ // send initial request and start to pray >_<
|
|
|
+ this.trigger('init')
|
|
|
+ .request({
|
|
|
+ data : {cmd : 'open', target : self.lastDir(), init : 1, tree : this.ui.tree ? 1 : 0},
|
|
|
+ preventDone : true,
|
|
|
+ notify : {type : 'open', cnt : 1, hideCnt : true},
|
|
|
+ freeze : true
|
|
|
+ })
|
|
|
+ .fail(function() {
|
|
|
+ self.trigger('fail').disable().lastDir('');
|
|
|
+ listeners = {};
|
|
|
+ shortcuts = {};
|
|
|
+ $(document).add(node).unbind('.'+this.namespace);
|
|
|
+ self.trigger = function() { };
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ self.load().debug('api', self.api);
|
|
|
+ data = $.extend(true, {}, data);
|
|
|
+ open(data);
|
|
|
+ self.trigger('open', data);
|
|
|
+ });
|
|
|
+
|
|
|
+ // update ui's size after init
|
|
|
+ this.one('load', function() {
|
|
|
+ node.trigger('resize');
|
|
|
+ if (self.options.sync > 1000) {
|
|
|
+ syncInterval = setInterval(function() {
|
|
|
+ self.sync();
|
|
|
+ }, self.options.sync)
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+ // self.timeEnd('load');
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Prototype
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ */
|
|
|
+elFinder.prototype = {
|
|
|
+
|
|
|
+ res : function(type, id) {
|
|
|
+ return this.resources[type] && this.resources[type][id];
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Internationalization object
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ */
|
|
|
+ i18 : {
|
|
|
+ en : {
|
|
|
+ translator : '',
|
|
|
+ language : 'English',
|
|
|
+ direction : 'ltr',
|
|
|
+ dateFormat : 'd.m.Y H:i',
|
|
|
+ fancyDateFormat : '$1 H:i',
|
|
|
+ messages : {}
|
|
|
+ },
|
|
|
+ months : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
|
|
+ monthsShort : ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
|
|
+
|
|
|
+ days : ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
|
|
+ daysShort : ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * File mimetype to kind mapping
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ */
|
|
|
+ kinds : {
|
|
|
+ 'unknown' : 'Unknown',
|
|
|
+ 'directory' : 'Folder',
|
|
|
+ 'symlink' : 'Alias',
|
|
|
+ 'symlink-broken' : 'AliasBroken',
|
|
|
+ 'application/x-empty' : 'TextPlain',
|
|
|
+ 'application/postscript' : 'Postscript',
|
|
|
+ 'application/vnd.ms-office' : 'MsOffice',
|
|
|
+ 'application/vnd.ms-word' : 'MsWord',
|
|
|
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' : 'MsWord',
|
|
|
+ 'application/vnd.ms-word.document.macroEnabled.12' : 'MsWord',
|
|
|
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' : 'MsWord',
|
|
|
+ 'application/vnd.ms-word.template.macroEnabled.12' : 'MsWord',
|
|
|
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' : 'MsWord',
|
|
|
+ 'application/vnd.ms-excel' : 'MsExcel',
|
|
|
+ 'application/vnd.ms-excel.sheet.macroEnabled.12' : 'MsExcel',
|
|
|
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' : 'MsExcel',
|
|
|
+ 'application/vnd.ms-excel.template.macroEnabled.12' : 'MsExcel',
|
|
|
+ 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' : 'MsExcel',
|
|
|
+ 'application/vnd.ms-excel.addin.macroEnabled.12' : 'MsExcel',
|
|
|
+ 'application/vnd.ms-powerpoint' : 'MsPP',
|
|
|
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation' : 'MsPP',
|
|
|
+ 'application/vnd.ms-powerpoint.presentation.macroEnabled.12' : 'MsPP',
|
|
|
+ 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' : 'MsPP',
|
|
|
+ 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' : 'MsPP',
|
|
|
+ 'application/vnd.openxmlformats-officedocument.presentationml.template' : 'MsPP',
|
|
|
+ 'application/vnd.ms-powerpoint.template.macroEnabled.12' : 'MsPP',
|
|
|
+ 'application/vnd.ms-powerpoint.addin.macroEnabled.12' : 'MsPP',
|
|
|
+ 'application/vnd.openxmlformats-officedocument.presentationml.slide' : 'MsPP',
|
|
|
+ 'application/vnd.ms-powerpoint.slide.macroEnabled.12' : 'MsPP',
|
|
|
+ 'application/pdf' : 'PDF',
|
|
|
+ 'application/xml' : 'XML',
|
|
|
+ 'application/vnd.oasis.opendocument.text' : 'OO',
|
|
|
+ 'application/vnd.oasis.opendocument.text-template' : 'OO',
|
|
|
+ 'application/vnd.oasis.opendocument.text-web' : 'OO',
|
|
|
+ 'application/vnd.oasis.opendocument.text-master' : 'OO',
|
|
|
+ 'application/vnd.oasis.opendocument.graphics' : 'OO',
|
|
|
+ 'application/vnd.oasis.opendocument.graphics-template' : 'OO',
|
|
|
+ 'application/vnd.oasis.opendocument.presentation' : 'OO',
|
|
|
+ 'application/vnd.oasis.opendocument.presentation-template' : 'OO',
|
|
|
+ 'application/vnd.oasis.opendocument.spreadsheet' : 'OO',
|
|
|
+ 'application/vnd.oasis.opendocument.spreadsheet-template' : 'OO',
|
|
|
+ 'application/vnd.oasis.opendocument.chart' : 'OO',
|
|
|
+ 'application/vnd.oasis.opendocument.formula' : 'OO',
|
|
|
+ 'application/vnd.oasis.opendocument.database' : 'OO',
|
|
|
+ 'application/vnd.oasis.opendocument.image' : 'OO',
|
|
|
+ 'application/vnd.openofficeorg.extension' : 'OO',
|
|
|
+ 'application/x-shockwave-flash' : 'AppFlash',
|
|
|
+ 'application/flash-video' : 'Flash video',
|
|
|
+ 'application/x-bittorrent' : 'Torrent',
|
|
|
+ 'application/javascript' : 'JS',
|
|
|
+ 'application/rtf' : 'RTF',
|
|
|
+ 'application/rtfd' : 'RTF',
|
|
|
+ 'application/x-font-ttf' : 'TTF',
|
|
|
+ 'application/x-font-otf' : 'OTF',
|
|
|
+ 'application/x-rpm' : 'RPM',
|
|
|
+ 'application/x-web-config' : 'TextPlain',
|
|
|
+ 'application/xhtml+xml' : 'HTML',
|
|
|
+ 'application/docbook+xml' : 'DOCBOOK',
|
|
|
+ 'application/x-awk' : 'AWK',
|
|
|
+ 'application/x-gzip' : 'GZIP',
|
|
|
+ 'application/x-bzip2' : 'BZIP',
|
|
|
+ 'application/zip' : 'ZIP',
|
|
|
+ 'application/x-zip' : 'ZIP',
|
|
|
+ 'application/x-rar' : 'RAR',
|
|
|
+ 'application/x-tar' : 'TAR',
|
|
|
+ 'application/x-7z-compressed' : '7z',
|
|
|
+ 'application/x-jar' : 'JAR',
|
|
|
+ 'text/plain' : 'TextPlain',
|
|
|
+ 'text/x-php' : 'PHP',
|
|
|
+ 'text/html' : 'HTML',
|
|
|
+ 'text/javascript' : 'JS',
|
|
|
+ 'text/css' : 'CSS',
|
|
|
+ 'text/rtf' : 'RTF',
|
|
|
+ 'text/rtfd' : 'RTF',
|
|
|
+ 'text/x-c' : 'C',
|
|
|
+ 'text/x-csrc' : 'C',
|
|
|
+ 'text/x-chdr' : 'CHeader',
|
|
|
+ 'text/x-c++' : 'CPP',
|
|
|
+ 'text/x-c++src' : 'CPP',
|
|
|
+ 'text/x-c++hdr' : 'CPPHeader',
|
|
|
+ 'text/x-shellscript' : 'Shell',
|
|
|
+ 'application/x-csh' : 'Shell',
|
|
|
+ 'text/x-python' : 'Python',
|
|
|
+ 'text/x-java' : 'Java',
|
|
|
+ 'text/x-java-source' : 'Java',
|
|
|
+ 'text/x-ruby' : 'Ruby',
|
|
|
+ 'text/x-perl' : 'Perl',
|
|
|
+ 'text/x-sql' : 'SQL',
|
|
|
+ 'text/xml' : 'XML',
|
|
|
+ 'text/x-comma-separated-values' : 'CSV',
|
|
|
+ 'image/x-ms-bmp' : 'BMP',
|
|
|
+ 'image/jpeg' : 'JPEG',
|
|
|
+ 'image/gif' : 'GIF',
|
|
|
+ 'image/png' : 'PNG',
|
|
|
+ 'image/tiff' : 'TIFF',
|
|
|
+ 'image/x-targa' : 'TGA',
|
|
|
+ 'image/vnd.adobe.photoshop' : 'PSD',
|
|
|
+ 'image/xbm' : 'XBITMAP',
|
|
|
+ 'image/pxm' : 'PXM',
|
|
|
+ 'audio/mpeg' : 'AudioMPEG',
|
|
|
+ 'audio/midi' : 'AudioMIDI',
|
|
|
+ 'audio/ogg' : 'AudioOGG',
|
|
|
+ 'audio/mp4' : 'AudioMPEG4',
|
|
|
+ 'audio/x-m4a' : 'AudioMPEG4',
|
|
|
+ 'audio/wav' : 'AudioWAV',
|
|
|
+ 'audio/x-mp3-playlist' : 'AudioPlaylist',
|
|
|
+ 'video/x-dv' : 'VideoDV',
|
|
|
+ 'video/mp4' : 'VideoMPEG4',
|
|
|
+ 'video/mpeg' : 'VideoMPEG',
|
|
|
+ 'video/x-msvideo' : 'VideoAVI',
|
|
|
+ 'video/quicktime' : 'VideoMOV',
|
|
|
+ 'video/x-ms-wmv' : 'VideoWM',
|
|
|
+ 'video/x-flv' : 'VideoFlash',
|
|
|
+ 'video/x-matroska' : 'VideoMKV',
|
|
|
+ 'video/ogg' : 'VideoOGG'
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Ajax request data validation rules
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ */
|
|
|
+ rules : {
|
|
|
+ defaults : function(data) {
|
|
|
+ if (!data
|
|
|
+ || (data.added && !$.isArray(data.added))
|
|
|
+ || (data.removed && !$.isArray(data.removed))
|
|
|
+ || (data.changed && !$.isArray(data.changed))) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+ open : function(data) { return data && data.cwd && data.files && $.isPlainObject(data.cwd) && $.isArray(data.files); },
|
|
|
+ tree : function(data) { return data && data.tree && $.isArray(data.tree); },
|
|
|
+ parents : function(data) { return data && data.tree && $.isArray(data.tree); },
|
|
|
+ tmb : function(data) { return data && data.images && ($.isPlainObject(data.images) || $.isArray(data.images)); },
|
|
|
+ upload : function(data) { return data && ($.isPlainObject(data.added) || $.isArray(data.added));},
|
|
|
+ search : function(data) { return data && data.files && $.isArray(data.files)}
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Commands costructors
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ */
|
|
|
+ commands : {},
|
|
|
+
|
|
|
+ parseUploadData : function(text) {
|
|
|
+ var data;
|
|
|
+
|
|
|
+ if (!$.trim(text)) {
|
|
|
+ return {error : ['errResponse', 'errDataEmpty']};
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ data = $.parseJSON(text);
|
|
|
+ } catch (e) {
|
|
|
+ return {error : ['errResponse', 'errDataNotJSON']}
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this.validResponse('upload', data)) {
|
|
|
+ return {error : ['errResponse']};
|
|
|
+ }
|
|
|
+ data = this.normalize(data);
|
|
|
+ data.removed = $.map(data.added||[], function(f) { return f.hash; })
|
|
|
+ return data;
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ iframeCnt : 0,
|
|
|
+
|
|
|
+ uploads : {
|
|
|
+ // check droped contents
|
|
|
+ checkFile : function(data, fm) {
|
|
|
+ if (!!data.checked || data.type == 'files') {
|
|
|
+ return data.files;
|
|
|
+ } else if (data.type == 'data') {
|
|
|
+ var dfrd = $.Deferred(),
|
|
|
+ files = [],
|
|
|
+ paths = [],
|
|
|
+ dirctorys = [],
|
|
|
+ entries = [],
|
|
|
+ processing = 0,
|
|
|
+
|
|
|
+ readEntries = function(dirReader) {
|
|
|
+ var toArray = function(list) {
|
|
|
+ return Array.prototype.slice.call(list || []);
|
|
|
+ };
|
|
|
+ var readFile = function(fileEntry, callback) {
|
|
|
+ var dfrd = $.Deferred();
|
|
|
+ if (typeof fileEntry == 'undefined') {
|
|
|
+ dfrd.reject('empty');
|
|
|
+ } else if (fileEntry.isFile) {
|
|
|
+ fileEntry.file(function (file) {
|
|
|
+ dfrd.resolve(file);
|
|
|
+ }, function(e){
|
|
|
+ dfrd.reject();
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ dfrd.reject('dirctory');
|
|
|
+ }
|
|
|
+ return dfrd.promise();
|
|
|
+ };
|
|
|
+
|
|
|
+ dirReader.readEntries(function (results) {
|
|
|
+ if (!results.length) {
|
|
|
+ var len = entries.length - 1;
|
|
|
+ var read = function(i) {
|
|
|
+ readFile(entries[i]).done(function(file){
|
|
|
+ if (! (fm.OS == 'win' && file.name.match(/^(?:desktop\.ini|thumbs\.db)$/i))
|
|
|
+ &&
|
|
|
+ ! (fm.OS == 'mac' && file.name.match(/^\.ds_store$/i))) {
|
|
|
+ paths.push(entries[i].fullPath);
|
|
|
+ files.push(file);
|
|
|
+ }
|
|
|
+ }).fail(function(e){
|
|
|
+ if (e == 'dirctory') {
|
|
|
+ // dirctory
|
|
|
+ dirctorys.push(entries[i]);
|
|
|
+ } else if (e == 'empty') {
|
|
|
+ // dirctory is empty
|
|
|
+ } else {
|
|
|
+ // why fail?
|
|
|
+ }
|
|
|
+ }).always(function(){
|
|
|
+ processing--;
|
|
|
+ if (i < len) {
|
|
|
+ processing++;
|
|
|
+ read(++i);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+ processing++;
|
|
|
+ read(0);
|
|
|
+ processing--;
|
|
|
+ } else {
|
|
|
+ entries = entries.concat(toArray(results));
|
|
|
+ readEntries(dirReader);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ doScan = function(items, isEntry) {
|
|
|
+ var dirReader, entry;
|
|
|
+ entries = [];
|
|
|
+ var length = items.length;
|
|
|
+ for (var i = 0; i < length; i++) {
|
|
|
+ if (! isEntry) {
|
|
|
+ entry = !!items[i].getAsEntry? items[i].getAsEntry() : items[i].webkitGetAsEntry();
|
|
|
+ } else {
|
|
|
+ entry = items[i];
|
|
|
+ }
|
|
|
+ if (entry) {
|
|
|
+ if (entry.isFile) {
|
|
|
+ paths.push('');
|
|
|
+ files.push(data.files.items[i].getAsFile());
|
|
|
+ } else if (entry.isDirectory) {
|
|
|
+ if (processing > 0) {
|
|
|
+ dirctorys.push(entry);
|
|
|
+ } else {
|
|
|
+ processing = 0;
|
|
|
+ dirReader = entry.createReader();
|
|
|
+ processing++;
|
|
|
+ readEntries(dirReader);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ doScan(data.files.items);
|
|
|
+
|
|
|
+ setTimeout(function wait() {
|
|
|
+ if (processing > 0) {
|
|
|
+ setTimeout(wait, 10);
|
|
|
+ } else {
|
|
|
+ if (dirctorys.length > 0) {
|
|
|
+ doScan([dirctorys.shift()], true);
|
|
|
+ setTimeout(wait, 10);
|
|
|
+ } else {
|
|
|
+ dfrd.resolve([files, paths]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, 10);
|
|
|
+
|
|
|
+ return dfrd.promise();
|
|
|
+ } else {
|
|
|
+ var ret = [];
|
|
|
+ var regex;
|
|
|
+ var str = data.files[0];
|
|
|
+ if (data.type == 'html') {
|
|
|
+ regex = /<img[^>]+src=["']?([^"'> ]+)/ig;
|
|
|
+ var m = [];
|
|
|
+ var url = '';
|
|
|
+ var links;
|
|
|
+ while (m = regex.exec(str)) {
|
|
|
+ url = m[1].replace(/&/g, '&');
|
|
|
+ if (url.match(/^http|data:/) && $.inArray(url, ret) == -1) ret.push(url);
|
|
|
+ }
|
|
|
+ links = str.match(/<\/a>/i);
|
|
|
+ if (links && links.length == 1) {
|
|
|
+ regex = /<a[^>]+href=["']?([^"'> ]+)((?:.|\s)+)<\/a>/i;
|
|
|
+ if (m = regex.exec(str)) {
|
|
|
+ if (! m[2].match(/<img/i)) {
|
|
|
+ url = m[1].replace(/&/g, '&');
|
|
|
+ if (url.match(/^http/) && $.inArray(url, ret) == -1) ret.push(url);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ regex = /(http[^<>"{}|\\^\[\]`\s]+)/ig;
|
|
|
+ while (m = regex.exec(str)) {
|
|
|
+ url = m[1].replace(/&/g, '&');
|
|
|
+ if ($.inArray(url, ret) == -1) ret.push(url);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // upload transport using iframe
|
|
|
+ iframe : function(data, fm) {
|
|
|
+ var self = fm ? fm : this,
|
|
|
+ input = data.input? data.input : false,
|
|
|
+ files = !input ? self.uploads.checkFile(data, self) : false,
|
|
|
+ dfrd = $.Deferred()
|
|
|
+ .fail(function(error) {
|
|
|
+ error && self.error(error);
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ data.warning && self.error(data.warning);
|
|
|
+ data.removed && self.remove(data);
|
|
|
+ data.added && self.add(data);
|
|
|
+ data.changed && self.change(data);
|
|
|
+ self.trigger('upload', data);
|
|
|
+ data.sync && self.sync();
|
|
|
+ }),
|
|
|
+ name = 'iframe-'+self.namespace+(++self.iframeCnt),
|
|
|
+ form = $('<form action="'+self.uploadURL+'" method="post" enctype="multipart/form-data" encoding="multipart/form-data" target="'+name+'" style="display:none"><input type="hidden" name="cmd" value="upload" /></form>'),
|
|
|
+ msie = this.UA.IE,
|
|
|
+ // clear timeouts, close notification dialog, remove form/iframe
|
|
|
+ onload = function() {
|
|
|
+ abortto && clearTimeout(abortto);
|
|
|
+ notifyto && clearTimeout(notifyto);
|
|
|
+ notify && self.notify({type : 'upload', cnt : -cnt});
|
|
|
+
|
|
|
+ setTimeout(function() {
|
|
|
+ msie && $('<iframe src="javascript:false;"/>').appendTo(form);
|
|
|
+ form.remove();
|
|
|
+ iframe.remove();
|
|
|
+ }, 100);
|
|
|
+ },
|
|
|
+ iframe = $('<iframe src="'+(msie ? 'javascript:false;' : 'about:blank')+'" name="'+name+'" style="position:absolute;left:-1000px;top:-1000px" />')
|
|
|
+ .bind('load', function() {
|
|
|
+ iframe.unbind('load')
|
|
|
+ .bind('load', function() {
|
|
|
+ var data = self.parseUploadData(iframe.contents().text());
|
|
|
+
|
|
|
+ onload();
|
|
|
+ data.error ? dfrd.reject(data.error) : dfrd.resolve(data);
|
|
|
+ });
|
|
|
+
|
|
|
+ // notify dialog
|
|
|
+ notifyto = setTimeout(function() {
|
|
|
+ notify = true;
|
|
|
+ self.notify({type : 'upload', cnt : cnt});
|
|
|
+ }, self.options.notifyDelay);
|
|
|
+
|
|
|
+ // emulate abort on timeout
|
|
|
+ if (self.options.iframeTimeout > 0) {
|
|
|
+ abortto = setTimeout(function() {
|
|
|
+ onload();
|
|
|
+ dfrd.reject([errors.connect, errors.timeout]);
|
|
|
+ }, self.options.iframeTimeout);
|
|
|
+ }
|
|
|
+
|
|
|
+ form.submit();
|
|
|
+ }),
|
|
|
+ cnt, notify, notifyto, abortto
|
|
|
+
|
|
|
+ ;
|
|
|
+
|
|
|
+ if (files && files.length) {
|
|
|
+ $.each(files, function(i, val) {
|
|
|
+ form.append('<input type="hidden" name="upload[]" value="'+val+'"/>');
|
|
|
+ });
|
|
|
+ cnt = 1;
|
|
|
+ } else if (input && $(input).is(':file') && $(input).val()) {
|
|
|
+ form.append(input);
|
|
|
+ cnt = input.files ? input.files.length : 1;
|
|
|
+ } else {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ form.append('<input type="hidden" name="'+(self.newAPI ? 'target' : 'current')+'" value="'+self.cwd().hash+'"/>')
|
|
|
+ .append('<input type="hidden" name="html" value="1"/>')
|
|
|
+ .append($(input).attr('name', 'upload[]'));
|
|
|
+
|
|
|
+ $.each(self.options.onlyMimes||[], function(i, mime) {
|
|
|
+ form.append('<input type="hidden" name="mimes[]" value="'+mime+'"/>');
|
|
|
+ });
|
|
|
+
|
|
|
+ $.each(self.options.customData, function(key, val) {
|
|
|
+ form.append('<input type="hidden" name="'+key+'" value="'+val+'"/>');
|
|
|
+ });
|
|
|
+
|
|
|
+ form.appendTo('body');
|
|
|
+ iframe.appendTo('body');
|
|
|
+
|
|
|
+ return dfrd;
|
|
|
+ },
|
|
|
+ // upload transport using XMLHttpRequest
|
|
|
+ xhr : function(data, fm) {
|
|
|
+ var self = fm ? fm : this,
|
|
|
+ dfrd = $.Deferred()
|
|
|
+ .fail(function(error) {
|
|
|
+ error && self.error(error);
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ data.warning && self.error(data.warning);
|
|
|
+ data.removed && self.remove(data);
|
|
|
+ data.added && self.add(data);
|
|
|
+ data.changed && self.change(data);
|
|
|
+ self.trigger('upload', data);
|
|
|
+ data.sync && self.sync();
|
|
|
+ })
|
|
|
+ .always(function() {
|
|
|
+ notifyto && clearTimeout(notifyto);
|
|
|
+ ! data.checked && notify && self.notify({type : 'upload', cnt : -cnt, progress : 100*cnt});
|
|
|
+ }),
|
|
|
+ xhr = new XMLHttpRequest(),
|
|
|
+ formData = new FormData(),
|
|
|
+ isDataType = (data.type == 'data'),
|
|
|
+ files = data.input ? data.input.files : self.uploads.checkFile(data, self),
|
|
|
+ cnt = data.checked? (isDataType? files[0].length : files.length) : files.length,
|
|
|
+ loaded = 5,
|
|
|
+ notify = false,
|
|
|
+ startNotify = function() {
|
|
|
+ return setTimeout(function() {
|
|
|
+ notify = true;
|
|
|
+ self.notify({type : 'upload', cnt : cnt, progress : loaded*cnt});
|
|
|
+ }, self.options.notifyDelay);
|
|
|
+ },
|
|
|
+ notifyto, notifyto2;
|
|
|
+
|
|
|
+ if (!isDataType && !cnt) {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ xhr.addEventListener('error', function() {
|
|
|
+ dfrd.reject('errConnect');
|
|
|
+ }, false);
|
|
|
+
|
|
|
+ xhr.addEventListener('abort', function() {
|
|
|
+ dfrd.reject(['errConnect', 'errAbort']);
|
|
|
+ }, false);
|
|
|
+
|
|
|
+ xhr.addEventListener('load', function() {
|
|
|
+ var status = xhr.status, data;
|
|
|
+
|
|
|
+ if (status > 500) {
|
|
|
+ return dfrd.reject('errResponse');
|
|
|
+ }
|
|
|
+ if (status != 200) {
|
|
|
+ return dfrd.reject('errConnect');
|
|
|
+ }
|
|
|
+ if (xhr.readyState != 4) {
|
|
|
+ return dfrd.reject(['errConnect', 'errTimeout']); // am i right?
|
|
|
+ }
|
|
|
+ if (!xhr.responseText) {
|
|
|
+ return dfrd.reject(['errResponse', 'errDataEmpty']);
|
|
|
+ }
|
|
|
+
|
|
|
+ data = self.parseUploadData(xhr.responseText);
|
|
|
+ data.error ? dfrd.reject(data.error) : dfrd.resolve(data);
|
|
|
+ }, false);
|
|
|
+
|
|
|
+ xhr.upload.addEventListener('progress', function(e) {
|
|
|
+ var prev = loaded, curr;
|
|
|
+
|
|
|
+ if (e.lengthComputable) {
|
|
|
+
|
|
|
+ curr = parseInt(e.loaded*100 / e.total);
|
|
|
+
|
|
|
+ // to avoid strange bug in safari (not in chrome) with drag&drop.
|
|
|
+ // bug: macos finder opened in any folder,
|
|
|
+ // reset safari cache (option+command+e), reload elfinder page,
|
|
|
+ // drop file from finder
|
|
|
+ // on first attempt request starts (progress callback called ones) but never ends.
|
|
|
+ // any next drop - successfull.
|
|
|
+ if (!data.checked && curr > 0 && !notifyto) {
|
|
|
+ notifyto = startNotify();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (curr - prev > 4) {
|
|
|
+ loaded = curr;
|
|
|
+ (data.checked || notify) && self.notify({type : 'upload', cnt : 0, progress : (loaded - prev)*cnt});
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, false);
|
|
|
+
|
|
|
+ var send = function(files, paths){
|
|
|
+ var size = 0, fcnt = 1, sfiles = [], c = 0, total = cnt, maxFileSize;
|
|
|
+ if (! data.checked) {
|
|
|
+ maxFileSize = fm.option('uploadMaxSize')? fm.option('uploadMaxSize') : fm.uplMaxSize;
|
|
|
+ for (var i=0; i < files.length; i++) {
|
|
|
+ if (maxFileSize && files[i].size >= maxFileSize) {
|
|
|
+ self.error(self.i18n('errUploadFile', files[i].name) + ' ' + self.i18n('errUploadFileSize'));
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if ((fm.uplMaxSize && size + files[i].size >= fm.uplMaxSize) || fcnt > fm.uplMaxFile) {
|
|
|
+ size = 0;
|
|
|
+ fcnt = 1;
|
|
|
+ c++;
|
|
|
+ }
|
|
|
+ if (typeof sfiles[c] == 'undefined') {
|
|
|
+ sfiles[c] = [];
|
|
|
+ if (isDataType) {
|
|
|
+ sfiles[c][0] = [];
|
|
|
+ sfiles[c][1] = [];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (isDataType) {
|
|
|
+ sfiles[c][0].push(files[i]);
|
|
|
+ sfiles[c][1].push(paths[i]);
|
|
|
+ } else {
|
|
|
+ sfiles[c].push(files[i]);
|
|
|
+ }
|
|
|
+ size += files[i].size;
|
|
|
+ fcnt++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sfiles.length == 0) {
|
|
|
+ data.checked = true;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sfiles.length > 1) {
|
|
|
+ notifyto = startNotify();
|
|
|
+ for (var i=0; i < sfiles.length; i++) {
|
|
|
+ fm.exec('upload', {type: data.type, files: sfiles[i], checked: true}).always(function() {
|
|
|
+ if (notify) {
|
|
|
+ var _cnt = (isDataType? this[0] : this).length;
|
|
|
+ total -= _cnt;
|
|
|
+ if (total < 1) {
|
|
|
+ notifyto && clearTimeout(notifyto);
|
|
|
+ self.notify({type : 'upload', cnt : -cnt, progress : 100 * cnt});
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }.bind(sfiles[i]));
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isDataType) {
|
|
|
+ files = sfiles[0][0];
|
|
|
+ paths = sfiles[0][1];
|
|
|
+ } else {
|
|
|
+ files = sfiles[0];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ xhr.open('POST', self.uploadURL, true);
|
|
|
+ formData.append('cmd', 'upload');
|
|
|
+ formData.append(self.newAPI ? 'target' : 'current', self.cwd().hash);
|
|
|
+ $.each(self.options.customData, function(key, val) {
|
|
|
+ formData.append(key, val);
|
|
|
+ });
|
|
|
+ $.each(self.options.onlyMimes, function(i, mime) {
|
|
|
+ formData.append('mimes['+i+']', mime);
|
|
|
+ });
|
|
|
+
|
|
|
+ $.each(files, function(i, file) {
|
|
|
+ formData.append('upload[]', file);
|
|
|
+ });
|
|
|
+
|
|
|
+ if (isDataType) {
|
|
|
+ $.each(paths, function(i, path) {
|
|
|
+ formData.append('upload_path[]', path);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ xhr.onreadystatechange = function() {
|
|
|
+ if (xhr.readyState == 4 && xhr.status == 0) {
|
|
|
+ // ff bug while send zero sized file
|
|
|
+ // for safari - send directory
|
|
|
+ dfrd.reject(['errConnect', 'errAbort']);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ xhr.send(formData);
|
|
|
+
|
|
|
+ return true;
|
|
|
+ };
|
|
|
+
|
|
|
+ if (! isDataType) {
|
|
|
+ if (! send(files)) {
|
|
|
+ dfrd.reject();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (!! data.checked) {
|
|
|
+ send(files[0], files[1]);
|
|
|
+ } else {
|
|
|
+ notifyto2 = setTimeout(function() {
|
|
|
+ self.notify({type : 'readdir', cnt : 1, hideCnt: true});
|
|
|
+ }, self.options.notifyDelay);
|
|
|
+ files.done(function(result){
|
|
|
+ notifyto2 && clearTimeout(notifyto2);
|
|
|
+ self.notify({type : 'readdir', cnt : -1});
|
|
|
+ cnt = result[0].length;
|
|
|
+ send(result[0], result[1]);
|
|
|
+ }).fail(function(){
|
|
|
+ dfrd.reject();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!isDataType && !data.checked && (!this.UA.Safari || !data.files)) {
|
|
|
+ notifyto = startNotify();
|
|
|
+ }
|
|
|
+
|
|
|
+ return dfrd;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Bind callback to event(s) The callback is executed at most once per event.
|
|
|
+ * To bind to multiply events at once, separate events names by space
|
|
|
+ *
|
|
|
+ * @param String event name
|
|
|
+ * @param Function callback
|
|
|
+ * @return elFinder
|
|
|
+ */
|
|
|
+ one : function(event, callback) {
|
|
|
+ var self = this,
|
|
|
+ h = $.proxy(callback, function(event) {
|
|
|
+ setTimeout(function() {self.unbind(event.type, h);}, 3);
|
|
|
+ return callback.apply(this, arguments);
|
|
|
+ });
|
|
|
+ return this.bind(event, h);
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Set/get data into/from localStorage
|
|
|
+ *
|
|
|
+ * @param String key
|
|
|
+ * @param String|void value
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ localStorage : function(key, val) {
|
|
|
+ var s = window.localStorage;
|
|
|
+
|
|
|
+ key = 'elfinder-'+key+this.id;
|
|
|
+
|
|
|
+ if (val === null) {
|
|
|
+ console.log('remove', key)
|
|
|
+ return s.removeItem(key);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (val !== void(0)) {
|
|
|
+ try {
|
|
|
+ s.setItem(key, val);
|
|
|
+ } catch (e) {
|
|
|
+ s.clear();
|
|
|
+ s.setItem(key, val);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return s.getItem(key);
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get/set cookie
|
|
|
+ *
|
|
|
+ * @param String cookie name
|
|
|
+ * @param String|void cookie value
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ cookie : function(name, value) {
|
|
|
+ var d, o, c, i;
|
|
|
+
|
|
|
+ name = 'elfinder-'+name+this.id;
|
|
|
+
|
|
|
+ if (value === void(0)) {
|
|
|
+ if (document.cookie && document.cookie != '') {
|
|
|
+ c = document.cookie.split(';');
|
|
|
+ name += '=';
|
|
|
+ for (i=0; i<c.length; i++) {
|
|
|
+ c[i] = $.trim(c[i]);
|
|
|
+ if (c[i].substring(0, name.length) == name) {
|
|
|
+ return decodeURIComponent(c[i].substring(name.length));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+
|
|
|
+ o = $.extend({}, this.options.cookie);
|
|
|
+ if (value === null) {
|
|
|
+ value = '';
|
|
|
+ o.expires = -1;
|
|
|
+ }
|
|
|
+ if (typeof(o.expires) == 'number') {
|
|
|
+ d = new Date();
|
|
|
+ d.setTime(d.getTime()+(o.expires * 86400000));
|
|
|
+ o.expires = d;
|
|
|
+ }
|
|
|
+ document.cookie = name+'='+encodeURIComponent(value)+'; expires='+o.expires.toUTCString()+(o.path ? '; path='+o.path : '')+(o.domain ? '; domain='+o.domain : '')+(o.secure ? '; secure' : '');
|
|
|
+ return value;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get/set last opened directory
|
|
|
+ *
|
|
|
+ * @param String|undefined dir hash
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ lastDir : function(hash) {
|
|
|
+ return this.options.rememberLastDir ? this.storage('lastdir', hash) : '';
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Node for escape html entities in texts
|
|
|
+ *
|
|
|
+ * @type jQuery
|
|
|
+ */
|
|
|
+ _node : $('<span/>'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Replace not html-safe symbols to html entities
|
|
|
+ *
|
|
|
+ * @param String text to escape
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ escape : function(name) {
|
|
|
+ return this._node.text(name).html();
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Cleanup ajax data.
|
|
|
+ * For old api convert data into new api format
|
|
|
+ *
|
|
|
+ * @param String command name
|
|
|
+ * @param Object data from backend
|
|
|
+ * @return Object
|
|
|
+ */
|
|
|
+ normalize : function(data) {
|
|
|
+ var filter = function(file) {
|
|
|
+
|
|
|
+ if (file && file.hash && file.name && file.mime) {
|
|
|
+ if (file.mime == 'application/x-empty') {
|
|
|
+ file.mime = 'text/plain';
|
|
|
+ }
|
|
|
+ return file;
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ return file && file.hash && file.name && file.mime ? file : null;
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ if (data.files) {
|
|
|
+ data.files = $.map(data.files, filter);
|
|
|
+ }
|
|
|
+ if (data.tree) {
|
|
|
+ data.tree = $.map(data.tree, filter);
|
|
|
+ }
|
|
|
+ if (data.added) {
|
|
|
+ data.added = $.map(data.added, filter);
|
|
|
+ }
|
|
|
+ if (data.changed) {
|
|
|
+ data.changed = $.map(data.changed, filter);
|
|
|
+ }
|
|
|
+ if (data.api) {
|
|
|
+ data.init = true;
|
|
|
+ }
|
|
|
+ return data;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Update sort options
|
|
|
+ *
|
|
|
+ * @param {String} sort type
|
|
|
+ * @param {String} sort order
|
|
|
+ * @param {Boolean} show folder first
|
|
|
+ */
|
|
|
+ setSort : function(type, order, stickFolders) {
|
|
|
+ this.storage('sortType', (this.sortType = this.sortRules[type] ? type : 'name'));
|
|
|
+ this.storage('sortOrder', (this.sortOrder = /asc|desc/.test(order) ? order : 'asc'));
|
|
|
+ this.storage('sortStickFolders', (this.sortStickFolders = !!stickFolders) ? 1 : '');
|
|
|
+ this.trigger('sortchange');
|
|
|
+ },
|
|
|
+
|
|
|
+ _sortRules : {
|
|
|
+ name : function(file1, file2) { return file1.name.toLowerCase().localeCompare(file2.name.toLowerCase()); },
|
|
|
+ size : function(file1, file2) {
|
|
|
+ var size1 = parseInt(file1.size) || 0,
|
|
|
+ size2 = parseInt(file2.size) || 0;
|
|
|
+
|
|
|
+ return size1 == size2 ? 0 : size1 > size2 ? 1 : -1;
|
|
|
+ return (parseInt(file1.size) || 0) > (parseInt(file2.size) || 0) ? 1 : -1; },
|
|
|
+ kind : function(file1, file2) { return file1.mime.localeCompare(file2.mime); },
|
|
|
+ date : function(file1, file2) {
|
|
|
+ var date1 = file1.ts || file1.date,
|
|
|
+ date2 = file2.ts || file2.date;
|
|
|
+
|
|
|
+ return date1 == date2 ? 0 : date1 > date2 ? 1 : -1
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Compare files based on elFinder.sort
|
|
|
+ *
|
|
|
+ * @param Object file
|
|
|
+ * @param Object file
|
|
|
+ * @return Number
|
|
|
+ */
|
|
|
+ compare : function(file1, file2) {
|
|
|
+ var self = this,
|
|
|
+ type = self.sortType,
|
|
|
+ asc = self.sortOrder == 'asc',
|
|
|
+ stick = self.sortStickFolders,
|
|
|
+ rules = self.sortRules,
|
|
|
+ sort = rules[type],
|
|
|
+ d1 = file1.mime == 'directory',
|
|
|
+ d2 = file2.mime == 'directory',
|
|
|
+ res;
|
|
|
+
|
|
|
+ if (stick) {
|
|
|
+ if (d1 && !d2) {
|
|
|
+ return -1;
|
|
|
+ } else if (!d1 && d2) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ res = asc ? sort(file1, file2) : sort(file2, file1);
|
|
|
+
|
|
|
+ return type != 'name' && res == 0
|
|
|
+ ? res = asc ? rules.name(file1, file2) : rules.name(file2, file1)
|
|
|
+ : res;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Sort files based on config
|
|
|
+ *
|
|
|
+ * @param Array files
|
|
|
+ * @return Array
|
|
|
+ */
|
|
|
+ sortFiles : function(files) {
|
|
|
+ return files.sort(this.compare);
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Open notification dialog
|
|
|
+ * and append/update message for required notification type.
|
|
|
+ *
|
|
|
+ * @param Object options
|
|
|
+ * @example
|
|
|
+ * this.notify({
|
|
|
+ * type : 'copy',
|
|
|
+ * msg : 'Copy files', // not required for known types @see this.notifyType
|
|
|
+ * cnt : 3,
|
|
|
+ * hideCnt : false, // true for not show count
|
|
|
+ * progress : 10 // progress bar percents (use cnt : 0 to update progress bar)
|
|
|
+ * })
|
|
|
+ * @return elFinder
|
|
|
+ */
|
|
|
+ notify : function(opts) {
|
|
|
+ var type = opts.type,
|
|
|
+ msg = this.messages['ntf'+type] ? this.i18n('ntf'+type) : this.i18n('ntfsmth'),
|
|
|
+ ndialog = this.ui.notify,
|
|
|
+ notify = ndialog.children('.elfinder-notify-'+type),
|
|
|
+ ntpl = '<div class="elfinder-notify elfinder-notify-{type}"><span class="elfinder-dialog-icon elfinder-dialog-icon-{type}"/><span class="elfinder-notify-msg">{msg}</span> <span class="elfinder-notify-cnt"/><div class="elfinder-notify-progressbar"><div class="elfinder-notify-progress"/></div></div>',
|
|
|
+ delta = opts.cnt,
|
|
|
+ progress = opts.progress >= 0 ? opts.progress : 0,
|
|
|
+ cnt, total, prc;
|
|
|
+
|
|
|
+ if (!type) {
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!notify.length) {
|
|
|
+ notify = $(ntpl.replace(/\{type\}/g, type).replace(/\{msg\}/g, msg))
|
|
|
+ .appendTo(ndialog)
|
|
|
+ .data('cnt', 0);
|
|
|
+
|
|
|
+ if (progress) {
|
|
|
+ notify.data({progress : 0, total : 0});
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ cnt = delta + parseInt(notify.data('cnt'));
|
|
|
+
|
|
|
+ if (cnt > 0) {
|
|
|
+ !opts.hideCnt && notify.children('.elfinder-notify-cnt').text('('+cnt+')');
|
|
|
+ ndialog.is(':hidden') && ndialog.elfinderdialog('open');
|
|
|
+ notify.data('cnt', cnt);
|
|
|
+
|
|
|
+ if (progress
|
|
|
+ && (total = notify.data('total')) >= 0
|
|
|
+ && (prc = notify.data('progress')) >= 0) {
|
|
|
+
|
|
|
+ total = delta + parseInt(notify.data('total'));
|
|
|
+ prc = progress + prc;
|
|
|
+ progress = parseInt(prc/total);
|
|
|
+ notify.data({progress : prc, total : total});
|
|
|
+
|
|
|
+ ndialog.find('.elfinder-notify-progress')
|
|
|
+ .animate({
|
|
|
+ width : (progress < 100 ? progress : 100)+'%'
|
|
|
+ }, 20);
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ notify.remove();
|
|
|
+ !ndialog.children().length && ndialog.elfinderdialog('close');
|
|
|
+ }
|
|
|
+
|
|
|
+ return this;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Open confirmation dialog
|
|
|
+ *
|
|
|
+ * @param Object options
|
|
|
+ * @example
|
|
|
+ * this.confirm({
|
|
|
+ * title : 'Remove files',
|
|
|
+ * text : 'Here is question text',
|
|
|
+ * accept : { // accept callback - required
|
|
|
+ * label : 'Continue',
|
|
|
+ * callback : function(applyToAll) { fm.log('Ok') }
|
|
|
+ * },
|
|
|
+ * cancel : { // cancel callback - required
|
|
|
+ * label : 'Cancel',
|
|
|
+ * callback : function() { fm.log('Cancel')}
|
|
|
+ * },
|
|
|
+ * reject : { // reject callback - optionally
|
|
|
+ * label : 'No',
|
|
|
+ * callback : function(applyToAll) { fm.log('No')}
|
|
|
+ * },
|
|
|
+ * all : true // display checkbox "Apply to all"
|
|
|
+ * })
|
|
|
+ * @return elFinder
|
|
|
+ */
|
|
|
+ confirm : function(opts) {
|
|
|
+ var complete = false,
|
|
|
+ options = {
|
|
|
+ cssClass : 'elfinder-dialog-confirm',
|
|
|
+ modal : true,
|
|
|
+ resizable : false,
|
|
|
+ title : this.i18n(opts.title || 'confirmReq'),
|
|
|
+ buttons : {},
|
|
|
+ close : function() {
|
|
|
+ !complete && opts.cancel.callback();
|
|
|
+ $(this).elfinderdialog('destroy');
|
|
|
+ }
|
|
|
+ },
|
|
|
+ apply = this.i18n('apllyAll'),
|
|
|
+ label, checkbox;
|
|
|
+
|
|
|
+
|
|
|
+ if (opts.reject) {
|
|
|
+ options.buttons[this.i18n(opts.reject.label)] = function() {
|
|
|
+ opts.reject.callback(!!(checkbox && checkbox.prop('checked')))
|
|
|
+ complete = true;
|
|
|
+ $(this).elfinderdialog('close')
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ options.buttons[this.i18n(opts.accept.label)] = function() {
|
|
|
+ opts.accept.callback(!!(checkbox && checkbox.prop('checked')))
|
|
|
+ complete = true;
|
|
|
+ $(this).elfinderdialog('close')
|
|
|
+ };
|
|
|
+
|
|
|
+ options.buttons[this.i18n(opts.cancel.label)] = function() {
|
|
|
+ $(this).elfinderdialog('close')
|
|
|
+ };
|
|
|
+
|
|
|
+ if (opts.all) {
|
|
|
+ if (opts.reject) {
|
|
|
+ options.width = 370;
|
|
|
+ }
|
|
|
+ options.create = function() {
|
|
|
+ checkbox = $('<input type="checkbox" />');
|
|
|
+ $(this).next().children().before($('<label>'+apply+'</label>').prepend(checkbox));
|
|
|
+ }
|
|
|
+
|
|
|
+ options.open = function() {
|
|
|
+ var pane = $(this).next(),
|
|
|
+ width = parseInt(pane.children(':first').outerWidth() + pane.children(':last').outerWidth());
|
|
|
+
|
|
|
+ if (width > parseInt(pane.width())) {
|
|
|
+ $(this).closest('.elfinder-dialog').width(width+30);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return this.dialog('<span class="elfinder-dialog-icon elfinder-dialog-icon-confirm"/>' + this.i18n(opts.text), options);
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create unique file name in required dir
|
|
|
+ *
|
|
|
+ * @param String file name
|
|
|
+ * @param String parent dir hash
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ uniqueName : function(prefix, phash) {
|
|
|
+ var i = 0, ext = '', p, name;
|
|
|
+
|
|
|
+ prefix = this.i18n(prefix);
|
|
|
+ phash = phash || this.cwd().hash;
|
|
|
+
|
|
|
+ if ((p = prefix.indexOf('.txt')) != -1) {
|
|
|
+ ext = '.txt';
|
|
|
+ prefix = prefix.substr(0, p);
|
|
|
+ }
|
|
|
+
|
|
|
+ name = prefix+ext;
|
|
|
+
|
|
|
+ if (!this.fileByName(name, phash)) {
|
|
|
+ return name;
|
|
|
+ }
|
|
|
+ while (i < 10000) {
|
|
|
+ name = prefix + ' ' + (++i) + ext;
|
|
|
+ if (!this.fileByName(name, phash)) {
|
|
|
+ return name;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return prefix + Math.random() + ext;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return message translated onto current language
|
|
|
+ *
|
|
|
+ * @param String|Array message[s]
|
|
|
+ * @return String
|
|
|
+ **/
|
|
|
+ i18n : function() {
|
|
|
+ var self = this,
|
|
|
+ messages = this.messages,
|
|
|
+ input = [],
|
|
|
+ ignore = [],
|
|
|
+ message = function(m) {
|
|
|
+ var file;
|
|
|
+ if (m.indexOf('#') === 0) {
|
|
|
+ if ((file = self.file(m.substr(1)))) {
|
|
|
+ return file.name;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return m;
|
|
|
+ },
|
|
|
+ i, j, m;
|
|
|
+
|
|
|
+ for (i = 0; i< arguments.length; i++) {
|
|
|
+ m = arguments[i];
|
|
|
+
|
|
|
+ if (typeof m == 'string') {
|
|
|
+ input.push(message(m));
|
|
|
+ } else if ($.isArray(m)) {
|
|
|
+ for (j = 0; j < m.length; j++) {
|
|
|
+ if (typeof m[j] == 'string') {
|
|
|
+ input.push(message(m[j]));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < input.length; i++) {
|
|
|
+ // dont translate placeholders
|
|
|
+ if ($.inArray(i, ignore) !== -1) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ m = input[i];
|
|
|
+ // translate message
|
|
|
+ m = messages[m] || m;
|
|
|
+ // replace placeholders in message
|
|
|
+ m = m.replace(/\$(\d+)/g, function(match, placeholder) {
|
|
|
+ placeholder = i + parseInt(placeholder);
|
|
|
+ if (placeholder > 0 && input[placeholder]) {
|
|
|
+ ignore.push(placeholder)
|
|
|
+ }
|
|
|
+ return input[placeholder] || '';
|
|
|
+ });
|
|
|
+
|
|
|
+ input[i] = m;
|
|
|
+ }
|
|
|
+
|
|
|
+ return $.map(input, function(m, i) { return $.inArray(i, ignore) === -1 ? m : null; }).join('<br>');
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Convert mimetype into css classes
|
|
|
+ *
|
|
|
+ * @param String file mimetype
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ mime2class : function(mime) {
|
|
|
+ var prefix = 'elfinder-cwd-icon-';
|
|
|
+
|
|
|
+ mime = mime.split('/');
|
|
|
+
|
|
|
+ return prefix+mime[0]+(mime[0] != 'image' && mime[1] ? ' '+prefix+mime[1].replace(/(\.|\+)/g, '-') : '');
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return localized kind of file
|
|
|
+ *
|
|
|
+ * @param Object|String file or file mimetype
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ mime2kind : function(f) {
|
|
|
+ var mime = typeof(f) == 'object' ? f.mime : f, kind;
|
|
|
+
|
|
|
+ if (f.alias) {
|
|
|
+ kind = 'Alias';
|
|
|
+ } else if (this.kinds[mime]) {
|
|
|
+ kind = this.kinds[mime];
|
|
|
+ } else {
|
|
|
+ if (mime.indexOf('text') === 0) {
|
|
|
+ kind = 'Text';
|
|
|
+ } else if (mime.indexOf('image') === 0) {
|
|
|
+ kind = 'Image';
|
|
|
+ } else if (mime.indexOf('audio') === 0) {
|
|
|
+ kind = 'Audio';
|
|
|
+ } else if (mime.indexOf('video') === 0) {
|
|
|
+ kind = 'Video';
|
|
|
+ } else if (mime.indexOf('application') === 0) {
|
|
|
+ kind = 'App';
|
|
|
+ } else {
|
|
|
+ kind = mime;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return this.messages['kind'+kind] ? this.i18n('kind'+kind) : mime;
|
|
|
+
|
|
|
+ var mime = typeof(f) == 'object' ? f.mime : f,
|
|
|
+ kind = this.kinds[mime]||'unknown';
|
|
|
+
|
|
|
+ if (f.alias) {
|
|
|
+ kind = 'Alias';
|
|
|
+ } else if (kind == 'unknown') {
|
|
|
+ if (mime.indexOf('text') === 0) {
|
|
|
+ kind = 'Text';
|
|
|
+ } else if (mime.indexOf('image') === 0) {
|
|
|
+ kind = 'Image';
|
|
|
+ } else if (mime.indexOf('audio') === 0) {
|
|
|
+ kind = 'Audio';
|
|
|
+ } else if (mime.indexOf('video') === 0) {
|
|
|
+ kind = 'Video';
|
|
|
+ } else if (mime.indexOf('application') === 0) {
|
|
|
+ kind = 'Application';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return this.i18n(kind);
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return localized date
|
|
|
+ *
|
|
|
+ * @param Object file object
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ formatDate : function(file, ts) {
|
|
|
+ var self = this,
|
|
|
+ ts = ts || file.ts,
|
|
|
+ i18 = self.i18,
|
|
|
+ date, format, output, d, dw, m, y, h, g, i, s;
|
|
|
+
|
|
|
+ if (self.options.clientFormatDate && ts > 0) {
|
|
|
+
|
|
|
+ date = new Date(ts*1000);
|
|
|
+
|
|
|
+ h = date[self.getHours]();
|
|
|
+ g = h > 12 ? h - 12 : h;
|
|
|
+ i = date[self.getMinutes]();
|
|
|
+ s = date[self.getSeconds]();
|
|
|
+ d = date[self.getDate]();
|
|
|
+ dw = date[self.getDay]();
|
|
|
+ m = date[self.getMonth]() + 1;
|
|
|
+ y = date[self.getFullYear]();
|
|
|
+
|
|
|
+ format = ts >= this.yesterday
|
|
|
+ ? this.fancyFormat
|
|
|
+ : this.dateFormat;
|
|
|
+
|
|
|
+ output = format.replace(/[a-z]/gi, function(val) {
|
|
|
+ switch (val) {
|
|
|
+ case 'd': return d > 9 ? d : '0'+d;
|
|
|
+ case 'j': return d;
|
|
|
+ case 'D': return self.i18n(i18.daysShort[dw]);
|
|
|
+ case 'l': return self.i18n(i18.days[dw]);
|
|
|
+ case 'm': return m > 9 ? m : '0'+m;
|
|
|
+ case 'n': return m;
|
|
|
+ case 'M': return self.i18n(i18.monthsShort[m-1]);
|
|
|
+ case 'F': return self.i18n(i18.months[m-1]);
|
|
|
+ case 'Y': return y;
|
|
|
+ case 'y': return (''+y).substr(2);
|
|
|
+ case 'H': return h > 9 ? h : '0'+h;
|
|
|
+ case 'G': return h;
|
|
|
+ case 'g': return g;
|
|
|
+ case 'h': return g > 9 ? g : '0'+g;
|
|
|
+ case 'a': return h > 12 ? 'pm' : 'am';
|
|
|
+ case 'A': return h > 12 ? 'PM' : 'AM';
|
|
|
+ case 'i': return i > 9 ? i : '0'+i;
|
|
|
+ case 's': return s > 9 ? s : '0'+s;
|
|
|
+ }
|
|
|
+ return val;
|
|
|
+ });
|
|
|
+
|
|
|
+ return ts >= this.yesterday
|
|
|
+ ? output.replace('$1', this.i18n(ts >= this.today ? 'Today' : 'Yesterday'))
|
|
|
+ : output;
|
|
|
+ } else if (file.date) {
|
|
|
+ return file.date.replace(/([a-z]+)\s/i, function(a1, a2) { return self.i18n(a2)+' '; });
|
|
|
+ }
|
|
|
+
|
|
|
+ return self.i18n('dateUnknown');
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return css class marks file permissions
|
|
|
+ *
|
|
|
+ * @param Object file
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ perms2class : function(o) {
|
|
|
+ var c = '';
|
|
|
+
|
|
|
+ if (!o.read && !o.write) {
|
|
|
+ c = 'elfinder-na';
|
|
|
+ } else if (!o.read) {
|
|
|
+ c = 'elfinder-wo';
|
|
|
+ } else if (!o.write) {
|
|
|
+ c = 'elfinder-ro';
|
|
|
+ }
|
|
|
+ return c;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return localized string with file permissions
|
|
|
+ *
|
|
|
+ * @param Object file
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ formatPermissions : function(f) {
|
|
|
+ var p = [];
|
|
|
+
|
|
|
+ f.read && p.push(this.i18n('read'));
|
|
|
+ f.write && p.push(this.i18n('write'));
|
|
|
+
|
|
|
+ return p.length ? p.join(' '+this.i18n('and')+' ') : this.i18n('noaccess');
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return formated file size
|
|
|
+ *
|
|
|
+ * @param Number file size
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ formatSize : function(s) {
|
|
|
+ var n = 1, u = 'b';
|
|
|
+
|
|
|
+ if (s == 'unknown') {
|
|
|
+ return this.i18n('unknown');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (s > 1073741824) {
|
|
|
+ n = 1073741824;
|
|
|
+ u = 'GB';
|
|
|
+ } else if (s > 1048576) {
|
|
|
+ n = 1048576;
|
|
|
+ u = 'MB';
|
|
|
+ } else if (s > 1024) {
|
|
|
+ n = 1024;
|
|
|
+ u = 'KB';
|
|
|
+ }
|
|
|
+ s = s/n;
|
|
|
+ return (s > 0 ? n >= 1048576 ? s.toFixed(2) : Math.round(s) : 0) +' '+u;
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ navHash2Id : function(hash) {
|
|
|
+ return 'nav-'+hash;
|
|
|
+ },
|
|
|
+
|
|
|
+ navId2Hash : function(id) {
|
|
|
+ return typeof(id) == 'string' ? id.substr(4) : false;
|
|
|
+ },
|
|
|
+
|
|
|
+ log : function(m) { window.console && window.console.log && window.console.log(m); return this; },
|
|
|
+
|
|
|
+ debug : function(type, m) {
|
|
|
+ var d = this.options.debug;
|
|
|
+
|
|
|
+ if (d == 'all' || d === true || ($.isArray(d) && $.inArray(type, d) != -1)) {
|
|
|
+ window.console && window.console.log && window.console.log('elfinder debug: ['+type+'] ['+this.id+']', m);
|
|
|
+ }
|
|
|
+ return this;
|
|
|
+ },
|
|
|
+ time : function(l) { window.console && window.console.time && window.console.time(l); },
|
|
|
+ timeEnd : function(l) { window.console && window.console.timeEnd && window.console.timeEnd(l); }
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/elFinder.version.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * Application version
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+elFinder.prototype.version = '2.1 (Nightly: 093d077)';
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/jquery.elfinder.js
|
|
|
+ */
|
|
|
+
|
|
|
+$.fn.elfinder = function(o) {
|
|
|
+
|
|
|
+ if (o == 'instance') {
|
|
|
+ return this.getElFinder();
|
|
|
+ }
|
|
|
+
|
|
|
+ return this.each(function() {
|
|
|
+
|
|
|
+ var cmd = typeof(o) == 'string' ? o : '';
|
|
|
+ if (!this.elfinder) {
|
|
|
+ new elFinder(this, typeof(o) == 'object' ? o : {})
|
|
|
+ }
|
|
|
+
|
|
|
+ switch(cmd) {
|
|
|
+ case 'close':
|
|
|
+ case 'hide':
|
|
|
+ this.elfinder.hide();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'open':
|
|
|
+ case 'show':
|
|
|
+ this.elfinder.show();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case'destroy':
|
|
|
+ this.elfinder.destroy();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+$.fn.getElFinder = function() {
|
|
|
+ var instance;
|
|
|
+
|
|
|
+ this.each(function() {
|
|
|
+ if (this.elfinder) {
|
|
|
+ instance = this.elfinder;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return instance;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/elFinder.options.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * Default elFinder config
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ * @autor Dmitry (dio) Levashov
|
|
|
+ */
|
|
|
+elFinder.prototype._options = {
|
|
|
+ /**
|
|
|
+ * Connector url. Required!
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ url : '',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Ajax request type.
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ * @default "get"
|
|
|
+ */
|
|
|
+ requestType : 'get',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Transport to send request to backend.
|
|
|
+ * Required for future extensions using websockets/webdav etc.
|
|
|
+ * Must be an object with "send" method.
|
|
|
+ * transport.send must return $.Deferred() object
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ * @default null
|
|
|
+ * @example
|
|
|
+ * transport : {
|
|
|
+ * init : function(elfinderInstance) { },
|
|
|
+ * send : function(options) {
|
|
|
+ * var dfrd = $.Deferred();
|
|
|
+ * // connect to backend ...
|
|
|
+ * return dfrd;
|
|
|
+ * },
|
|
|
+ * upload : function(data) {
|
|
|
+ * var dfrd = $.Deferred();
|
|
|
+ * // upload ...
|
|
|
+ * return dfrd;
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * }
|
|
|
+ **/
|
|
|
+ transport : {},
|
|
|
+
|
|
|
+ /**
|
|
|
+ * URL to upload file to.
|
|
|
+ * If not set - connector URL will be used
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ * @default ''
|
|
|
+ */
|
|
|
+ urlUpload : '',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allow to drag and drop to upload files
|
|
|
+ *
|
|
|
+ * @type Boolean|String
|
|
|
+ * @default 'auto'
|
|
|
+ */
|
|
|
+ dragUploadAllow : 'auto',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Timeout for upload using iframe
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ * @default 0 - no timeout
|
|
|
+ */
|
|
|
+ iframeTimeout : 0,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Data to append to all requests and to upload files
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ * @default {}
|
|
|
+ */
|
|
|
+ customData : {},
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Event listeners to bind on elFinder init
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ * @default {}
|
|
|
+ */
|
|
|
+ handlers : {},
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Interface language
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ * @default "en"
|
|
|
+ */
|
|
|
+ lang : 'en',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Additional css class for filemanager node.
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ cssClass : '',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Active commands list
|
|
|
+ * If some required commands will be missed here, elFinder will add its
|
|
|
+ *
|
|
|
+ * @type Array
|
|
|
+ */
|
|
|
+ commands : [
|
|
|
+ 'open', 'reload', 'home', 'up', 'back', 'forward', 'getfile', 'quicklook',
|
|
|
+ 'download', 'rm', 'duplicate', 'rename', 'mkdir', 'mkfile', 'upload', 'copy',
|
|
|
+ 'cut', 'paste', 'edit', 'extract', 'archive', 'search', 'info', 'view', 'help', 'resize', 'sort', 'netmount'
|
|
|
+ ],
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Commands options.
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ commandsOptions : {
|
|
|
+ // "getfile" command options.
|
|
|
+ getfile : {
|
|
|
+ onlyURL : false,
|
|
|
+ // allow to return multiple files info
|
|
|
+ multiple : false,
|
|
|
+ // allow to return filers info
|
|
|
+ folders : false,
|
|
|
+ // action after callback (""/"close"/"destroy")
|
|
|
+ oncomplete : ''
|
|
|
+ },
|
|
|
+ // "upload" command options.
|
|
|
+ upload : {
|
|
|
+ ui : 'uploadbutton'
|
|
|
+ },
|
|
|
+ // "quicklook" command options.
|
|
|
+ quicklook : {
|
|
|
+ autoplay : true,
|
|
|
+ jplayer : 'extensions/jplayer'
|
|
|
+ },
|
|
|
+ // "quicklook" command options.
|
|
|
+ edit : {
|
|
|
+ // list of allowed mimetypes to edit
|
|
|
+ // if empty - any text files can be edited
|
|
|
+ mimes : [],
|
|
|
+ // edit files in wysisyg's
|
|
|
+ editors : [
|
|
|
+ // {
|
|
|
+ // /**
|
|
|
+ // * files mimetypes allowed to edit in current wysisyg
|
|
|
+ // * @type Array
|
|
|
+ // */
|
|
|
+ // mimes : ['text/html'],
|
|
|
+ // /**
|
|
|
+ // * Called when "edit" dialog loaded.
|
|
|
+ // * Place to init wysisyg.
|
|
|
+ // * Can return wysisyg instance
|
|
|
+ // *
|
|
|
+ // * @param DOMElement textarea node
|
|
|
+ // * @return Object
|
|
|
+ // */
|
|
|
+ // load : function(textarea) { },
|
|
|
+ // /**
|
|
|
+ // * Called before "edit" dialog closed.
|
|
|
+ // * Place to destroy wysisyg instance.
|
|
|
+ // *
|
|
|
+ // * @param DOMElement textarea node
|
|
|
+ // * @param Object wysisyg instance (if was returned by "load" callback)
|
|
|
+ // * @return void
|
|
|
+ // */
|
|
|
+ // close : function(textarea, instance) { },
|
|
|
+ // /**
|
|
|
+ // * Called before file content send to backend.
|
|
|
+ // * Place to update textarea content if needed.
|
|
|
+ // *
|
|
|
+ // * @param DOMElement textarea node
|
|
|
+ // * @param Object wysisyg instance (if was returned by "load" callback)
|
|
|
+ // * @return void
|
|
|
+ // */
|
|
|
+ // save : function(textarea, editor) {}
|
|
|
+ //
|
|
|
+ // }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ help : {view : ['about', 'shortcuts', 'help']}
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Callback for "getfile" commands.
|
|
|
+ * Required to use elFinder with WYSIWYG editors etc..
|
|
|
+ *
|
|
|
+ * @type Function
|
|
|
+ * @default null (command not active)
|
|
|
+ */
|
|
|
+ getFileCallback : null,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Default directory view. icons/list
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ * @default "icons"
|
|
|
+ */
|
|
|
+ defaultView : 'icons',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * UI plugins to load.
|
|
|
+ * Current dir ui and dialogs loads always.
|
|
|
+ * Here set not required plugins as folders tree/toolbar/statusbar etc.
|
|
|
+ *
|
|
|
+ * @type Array
|
|
|
+ * @default ['toolbar', 'tree', 'path', 'stat']
|
|
|
+ * @full ['toolbar', 'places', 'tree', 'path', 'stat']
|
|
|
+ */
|
|
|
+ ui : ['toolbar', 'tree', 'path', 'stat'],
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Some UI plugins options.
|
|
|
+ * @type Object
|
|
|
+ */
|
|
|
+ uiOptions : {
|
|
|
+ // toolbar configuration
|
|
|
+ toolbar : [
|
|
|
+ ['back', 'forward'],
|
|
|
+ ['netmount'],
|
|
|
+ // ['reload'],
|
|
|
+ // ['home', 'up'],
|
|
|
+ ['mkdir', 'mkfile', 'upload'],
|
|
|
+ ['open', 'download', 'getfile'],
|
|
|
+ ['info'],
|
|
|
+ ['quicklook'],
|
|
|
+ ['copy', 'cut', 'paste'],
|
|
|
+ ['rm'],
|
|
|
+ ['duplicate', 'rename', 'edit', 'resize'],
|
|
|
+ ['extract', 'archive'],
|
|
|
+ ['search'],
|
|
|
+ ['view', 'sort'],
|
|
|
+ ['help']
|
|
|
+ ],
|
|
|
+ // directories tree options
|
|
|
+ tree : {
|
|
|
+ // expand current root on init
|
|
|
+ openRootOnLoad : true,
|
|
|
+ // auto load current dir parents
|
|
|
+ syncTree : true
|
|
|
+ },
|
|
|
+ // navbar options
|
|
|
+ navbar : {
|
|
|
+ minWidth : 150,
|
|
|
+ maxWidth : 500
|
|
|
+ },
|
|
|
+ cwd : {
|
|
|
+ // display parent folder with ".." name :)
|
|
|
+ oldSchool : false
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Display only required files by types
|
|
|
+ *
|
|
|
+ * @type Array
|
|
|
+ * @default []
|
|
|
+ * @example
|
|
|
+ * onlyMimes : ["image"] - display all images
|
|
|
+ * onlyMimes : ["image/png", "application/x-shockwave-flash"] - display png and flash
|
|
|
+ */
|
|
|
+ onlyMimes : [],
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Custom files sort rules.
|
|
|
+ * All default rules (name/size/kind/date) set in elFinder._sortRules
|
|
|
+ *
|
|
|
+ * @type {Object}
|
|
|
+ * @example
|
|
|
+ * sortRules : {
|
|
|
+ * name : function(file1, file2) { return file1.name.toLowerCase().localeCompare(file2.name.toLowerCase()); }
|
|
|
+ * }
|
|
|
+ */
|
|
|
+ sortRules : {},
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Default sort type.
|
|
|
+ *
|
|
|
+ * @type {String}
|
|
|
+ */
|
|
|
+ sortType : 'name',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Default sort order.
|
|
|
+ *
|
|
|
+ * @type {String}
|
|
|
+ * @default "asc"
|
|
|
+ */
|
|
|
+ sortOrder : 'asc',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Display folders first?
|
|
|
+ *
|
|
|
+ * @type {Boolean}
|
|
|
+ * @default true
|
|
|
+ */
|
|
|
+ sortStickFolders : true,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * If true - elFinder will formating dates itself,
|
|
|
+ * otherwise - backend date will be used.
|
|
|
+ *
|
|
|
+ * @type Boolean
|
|
|
+ */
|
|
|
+ clientFormatDate : true,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Show UTC dates.
|
|
|
+ * Required set clientFormatDate to true
|
|
|
+ *
|
|
|
+ * @type Boolean
|
|
|
+ */
|
|
|
+ UTCDate : false,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * File modification datetime format.
|
|
|
+ * Value from selected language data is used by default.
|
|
|
+ * Set format here to overwrite it.
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ * @default ""
|
|
|
+ */
|
|
|
+ dateFormat : '',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * File modification datetime format in form "Yesterday 12:23:01".
|
|
|
+ * Value from selected language data is used by default.
|
|
|
+ * Set format here to overwrite it.
|
|
|
+ * Use $1 for "Today"/"Yesterday" placeholder
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ * @default ""
|
|
|
+ * @example "$1 H:m:i"
|
|
|
+ */
|
|
|
+ fancyDateFormat : '',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * elFinder width
|
|
|
+ *
|
|
|
+ * @type String|Number
|
|
|
+ * @default "auto"
|
|
|
+ */
|
|
|
+ width : 'auto',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * elFinder height
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ * @default "auto"
|
|
|
+ */
|
|
|
+ height : 400,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Make elFinder resizable if jquery ui resizable available
|
|
|
+ *
|
|
|
+ * @type Boolean
|
|
|
+ * @default true
|
|
|
+ */
|
|
|
+ resizable : true,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Timeout before open notifications dialogs
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ * @default 500 (.5 sec)
|
|
|
+ */
|
|
|
+ notifyDelay : 500,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allow shortcuts
|
|
|
+ *
|
|
|
+ * @type Boolean
|
|
|
+ * @default true
|
|
|
+ */
|
|
|
+ allowShortcuts : true,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Remeber last opened dir to open it after reload or in next session
|
|
|
+ *
|
|
|
+ * @type Boolean
|
|
|
+ * @default true
|
|
|
+ */
|
|
|
+ rememberLastDir : true,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Lazy load config.
|
|
|
+ * How many files display at once?
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ * @default 50
|
|
|
+ */
|
|
|
+ showFiles : 30,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Lazy load config.
|
|
|
+ * Distance in px to cwd bottom edge to start display files
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ * @default 50
|
|
|
+ */
|
|
|
+ showThreshold : 50,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Additional rule to valid new file name.
|
|
|
+ * By default not allowed empty names or '..'
|
|
|
+ *
|
|
|
+ * @type false|RegExp|function
|
|
|
+ * @default false
|
|
|
+ * @example
|
|
|
+ * disable names with spaces:
|
|
|
+ * validName : /^[^\s]$/
|
|
|
+ */
|
|
|
+ validName : false,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Sync content interval
|
|
|
+ * @todo - fix in elFinder
|
|
|
+ * @type Number
|
|
|
+ * @default 0 (do not sync)
|
|
|
+ */
|
|
|
+ sync : 0,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * How many thumbnails create in one request
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ * @default 5
|
|
|
+ */
|
|
|
+ loadTmbs : 5,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Cookie option for browsersdoes not suppot localStorage
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ */
|
|
|
+ cookie : {
|
|
|
+ expires : 30,
|
|
|
+ domain : '',
|
|
|
+ path : '/',
|
|
|
+ secure : false
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Contextmenu config
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ */
|
|
|
+ contextmenu : {
|
|
|
+ // navbarfolder menu
|
|
|
+ navbar : ['open', '|', 'copy', 'cut', 'paste', 'duplicate', '|', 'rm', '|', 'info'],
|
|
|
+ // current directory menu
|
|
|
+ cwd : ['reload', 'back', '|', 'upload', 'mkdir', 'mkfile', 'paste', '|', 'sort', '|', 'info'],
|
|
|
+ // current directory file menu
|
|
|
+ files : ['getfile', '|','open', 'quicklook', '|', 'download', '|', 'copy', 'cut', 'paste', 'duplicate', '|', 'rm', '|', 'edit', 'rename', 'resize', '|', 'archive', 'extract', '|', 'info']
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Debug config
|
|
|
+ *
|
|
|
+ * @type Array|Boolean
|
|
|
+ */
|
|
|
+ // debug : true
|
|
|
+ debug : ['error', 'warning', 'event-destroy']
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/elFinder.history.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder.history
|
|
|
+ * Store visited folders
|
|
|
+ * and provide "back" and "forward" methods
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ */
|
|
|
+elFinder.prototype.history = function(fm) {
|
|
|
+ var self = this,
|
|
|
+ /**
|
|
|
+ * Update history on "open" event?
|
|
|
+ *
|
|
|
+ * @type Boolean
|
|
|
+ */
|
|
|
+ update = true,
|
|
|
+ /**
|
|
|
+ * Directories hashes storage
|
|
|
+ *
|
|
|
+ * @type Array
|
|
|
+ */
|
|
|
+ history = [],
|
|
|
+ /**
|
|
|
+ * Current directory index in history
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ */
|
|
|
+ current,
|
|
|
+ /**
|
|
|
+ * Clear history
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ reset = function() {
|
|
|
+ history = [fm.cwd().hash];
|
|
|
+ current = 0;
|
|
|
+ update = true;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * Open prev/next folder
|
|
|
+ *
|
|
|
+ * @Boolen open next folder?
|
|
|
+ * @return jQuery.Deferred
|
|
|
+ */
|
|
|
+ go = function(fwd) {
|
|
|
+ if ((fwd && self.canForward()) || (!fwd && self.canBack())) {
|
|
|
+ update = false;
|
|
|
+ return fm.exec('open', history[fwd ? ++current : --current]).fail(reset);
|
|
|
+ }
|
|
|
+ return $.Deferred().reject();
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return true if there is previous visited directories
|
|
|
+ *
|
|
|
+ * @return Boolen
|
|
|
+ */
|
|
|
+ this.canBack = function() {
|
|
|
+ return current > 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return true if can go forward
|
|
|
+ *
|
|
|
+ * @return Boolen
|
|
|
+ */
|
|
|
+ this.canForward = function() {
|
|
|
+ return current < history.length - 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Go back
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ this.back = go;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Go forward
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ this.forward = function() {
|
|
|
+ return go(true);
|
|
|
+ }
|
|
|
+
|
|
|
+ // bind to elfinder events
|
|
|
+ fm.open(function(e) {
|
|
|
+ var l = history.length,
|
|
|
+ cwd = fm.cwd().hash;
|
|
|
+
|
|
|
+ if (update) {
|
|
|
+ current >= 0 && l > current + 1 && history.splice(current+1);
|
|
|
+ history[history.length-1] != cwd && history.push(cwd);
|
|
|
+ current = history.length - 1;
|
|
|
+ }
|
|
|
+ update = true;
|
|
|
+ })
|
|
|
+ .reload(reset);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/elFinder.command.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * elFinder command prototype
|
|
|
+ *
|
|
|
+ * @type elFinder.command
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ */
|
|
|
+elFinder.prototype.command = function(fm) {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * elFinder instance
|
|
|
+ *
|
|
|
+ * @type elFinder
|
|
|
+ */
|
|
|
+ this.fm = fm;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Command name, same as class name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ this.name = '';
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Short command description
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ this.title = '';
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Current command state
|
|
|
+ *
|
|
|
+ * @example
|
|
|
+ * this.state = -1; // command disabled
|
|
|
+ * this.state = 0; // command enabled
|
|
|
+ * this.state = 1; // command active (for example "fullscreen" command while elfinder in fullscreen mode)
|
|
|
+ * @default -1
|
|
|
+ * @type Number
|
|
|
+ */
|
|
|
+ this.state = -1;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * If true, command can not be disabled by connector.
|
|
|
+ * @see this.update()
|
|
|
+ *
|
|
|
+ * @type Boolen
|
|
|
+ */
|
|
|
+ this.alwaysEnabled = false;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * If true, this means command was disabled by connector.
|
|
|
+ * @see this.update()
|
|
|
+ *
|
|
|
+ * @type Boolen
|
|
|
+ */
|
|
|
+ this._disabled = false;
|
|
|
+
|
|
|
+ this.disableOnSearch = false;
|
|
|
+
|
|
|
+ this.updateOnSelect = true;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * elFinder events defaults handlers.
|
|
|
+ * Inside handlers "this" is current command object
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ */
|
|
|
+ this._handlers = {
|
|
|
+ enable : function() { this.update(void(0), this.value); },
|
|
|
+ disable : function() { this.update(-1, this.value); },
|
|
|
+ 'open reload load' : function(e) {
|
|
|
+ this._disabled = !(this.alwaysEnabled || this.fm.isCommandEnabled(this.name));
|
|
|
+ this.update(void(0), this.value)
|
|
|
+ this.change();
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * elFinder events handlers.
|
|
|
+ * Inside handlers "this" is current command object
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ */
|
|
|
+ this.handlers = {}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Shortcuts
|
|
|
+ *
|
|
|
+ * @type Array
|
|
|
+ */
|
|
|
+ this.shortcuts = [];
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Command options
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ */
|
|
|
+ this.options = {ui : 'button'};
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Prepare object -
|
|
|
+ * bind events and shortcuts
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ this.setup = function(name, opts) {
|
|
|
+ var self = this,
|
|
|
+ fm = this.fm, i, s;
|
|
|
+
|
|
|
+ this.name = name;
|
|
|
+ this.title = fm.messages['cmd'+name] ? fm.i18n('cmd'+name) : name,
|
|
|
+ this.options = $.extend({}, this.options, opts);
|
|
|
+ this.listeners = [];
|
|
|
+
|
|
|
+ if (this.updateOnSelect) {
|
|
|
+ this._handlers.select = function() { this.update(void(0), this.value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ $.each($.extend({}, self._handlers, self.handlers), function(cmd, handler) {
|
|
|
+ fm.bind(cmd, $.proxy(handler, self));
|
|
|
+ });
|
|
|
+
|
|
|
+ for (i = 0; i < this.shortcuts.length; i++) {
|
|
|
+ s = this.shortcuts[i];
|
|
|
+ s.callback = $.proxy(s.callback || function() { this.exec() }, this);
|
|
|
+ !s.description && (s.description = this.title);
|
|
|
+ fm.shortcut(s);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.disableOnSearch) {
|
|
|
+ fm.bind('search searchend', function(e) {
|
|
|
+ self._disabled = e.type == 'search';
|
|
|
+ self.update(void(0), self.value);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ this.init();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Command specific init stuffs
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ this.init = function() { }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Exec command
|
|
|
+ *
|
|
|
+ * @param Array target files hashes
|
|
|
+ * @param Array|Object command value
|
|
|
+ * @return $.Deferred
|
|
|
+ */
|
|
|
+ this.exec = function(files, opts) {
|
|
|
+ return $.Deferred().reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return true if command disabled.
|
|
|
+ *
|
|
|
+ * @return Boolen
|
|
|
+ */
|
|
|
+ this.disabled = function() {
|
|
|
+ return this.state < 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return true if command enabled.
|
|
|
+ *
|
|
|
+ * @return Boolen
|
|
|
+ */
|
|
|
+ this.enabled = function() {
|
|
|
+ return this.state > -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return true if command active.
|
|
|
+ *
|
|
|
+ * @return Boolen
|
|
|
+ */
|
|
|
+ this.active = function() {
|
|
|
+ return this.state > 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return current command state.
|
|
|
+ * Must be overloaded in most commands
|
|
|
+ *
|
|
|
+ * @return Number
|
|
|
+ */
|
|
|
+ this.getstate = function() {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Update command state/value
|
|
|
+ * and rize 'change' event if smth changed
|
|
|
+ *
|
|
|
+ * @param Number new state or undefined to auto update state
|
|
|
+ * @param mixed new value
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ this.update = function(s, v) {
|
|
|
+ var state = this.state,
|
|
|
+ value = this.value;
|
|
|
+
|
|
|
+ if (this._disabled) {
|
|
|
+ this.state = -1;
|
|
|
+ } else {
|
|
|
+ this.state = s !== void(0) ? s : this.getstate();
|
|
|
+ }
|
|
|
+
|
|
|
+ this.value = v;
|
|
|
+
|
|
|
+ if (state != this.state || value != this.value) {
|
|
|
+ this.change();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Bind handler / fire 'change' event.
|
|
|
+ *
|
|
|
+ * @param Function|undefined event callback
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ this.change = function(c) {
|
|
|
+ var cmd, i;
|
|
|
+
|
|
|
+ if (typeof(c) === 'function') {
|
|
|
+ this.listeners.push(c);
|
|
|
+ } else {
|
|
|
+ for (i = 0; i < this.listeners.length; i++) {
|
|
|
+ cmd = this.listeners[i];
|
|
|
+ try {
|
|
|
+ cmd(this.state, this.value);
|
|
|
+ } catch (e) {
|
|
|
+ this.fm.debug('error', e)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * With argument check given files hashes and return list of existed files hashes.
|
|
|
+ * Without argument return selected files hashes.
|
|
|
+ *
|
|
|
+ * @param Array|String|void hashes
|
|
|
+ * @return Array
|
|
|
+ */
|
|
|
+ this.hashes = function(hashes) {
|
|
|
+ return hashes
|
|
|
+ ? $.map($.isArray(hashes) ? hashes : [hashes], function(hash) { return fm.file(hash) ? hash : null; })
|
|
|
+ : fm.selected();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return only existed files from given fils hashes | selected files
|
|
|
+ *
|
|
|
+ * @param Array|String|void hashes
|
|
|
+ * @return Array
|
|
|
+ */
|
|
|
+ this.files = function(hashes) {
|
|
|
+ var fm = this.fm;
|
|
|
+
|
|
|
+ return hashes
|
|
|
+ ? $.map($.isArray(hashes) ? hashes : [hashes], function(hash) { return fm.file(hash) || null })
|
|
|
+ : fm.selectedFiles();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/elFinder.resources.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * elFinder resources registry.
|
|
|
+ * Store shared data
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.resources = {
|
|
|
+ 'class' : {
|
|
|
+ hover : 'ui-state-hover',
|
|
|
+ active : 'ui-state-active',
|
|
|
+ disabled : 'ui-state-disabled',
|
|
|
+ draggable : 'ui-draggable',
|
|
|
+ droppable : 'ui-droppable',
|
|
|
+ adroppable : 'elfinder-droppable-active',
|
|
|
+ cwdfile : 'elfinder-cwd-file',
|
|
|
+ cwd : 'elfinder-cwd',
|
|
|
+ tree : 'elfinder-tree',
|
|
|
+ treeroot : 'elfinder-navbar-root',
|
|
|
+ navdir : 'elfinder-navbar-dir',
|
|
|
+ navdirwrap : 'elfinder-navbar-dir-wrapper',
|
|
|
+ navarrow : 'elfinder-navbar-arrow',
|
|
|
+ navsubtree : 'elfinder-navbar-subtree',
|
|
|
+ navcollapse : 'elfinder-navbar-collapsed',
|
|
|
+ navexpand : 'elfinder-navbar-expanded',
|
|
|
+ treedir : 'elfinder-tree-dir',
|
|
|
+ placedir : 'elfinder-place-dir',
|
|
|
+ searchbtn : 'elfinder-button-search'
|
|
|
+ },
|
|
|
+ tpl : {
|
|
|
+ perms : '<span class="elfinder-perms"/>',
|
|
|
+ symlink : '<span class="elfinder-symlink"/>',
|
|
|
+ navicon : '<span class="elfinder-nav-icon"/>',
|
|
|
+ navspinner : '<span class="elfinder-navbar-spinner"/>',
|
|
|
+ navdir : '<div class="elfinder-navbar-wrapper"><span id="{id}" class="ui-corner-all elfinder-navbar-dir {cssclass}"><span class="elfinder-navbar-arrow"/><span class="elfinder-navbar-icon"/>{symlink}{permissions}{name}</span><div class="elfinder-navbar-subtree"/></div>'
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ mimes : {
|
|
|
+ text : [
|
|
|
+ 'application/x-empty',
|
|
|
+ 'application/javascript',
|
|
|
+ 'application/xhtml+xml',
|
|
|
+ 'audio/x-mp3-playlist',
|
|
|
+ 'application/x-web-config',
|
|
|
+ 'application/docbook+xml',
|
|
|
+ 'application/x-php',
|
|
|
+ 'application/x-perl',
|
|
|
+ 'application/x-awk',
|
|
|
+ 'application/x-config',
|
|
|
+ 'application/x-csh',
|
|
|
+ 'application/xml'
|
|
|
+ ]
|
|
|
+ },
|
|
|
+
|
|
|
+ mixin : {
|
|
|
+ make : function() {
|
|
|
+ var fm = this.fm,
|
|
|
+ cmd = this.name,
|
|
|
+ cwd = fm.getUI('cwd'),
|
|
|
+ dfrd = $.Deferred()
|
|
|
+ .fail(function(error) {
|
|
|
+ cwd.trigger('unselectall');
|
|
|
+ error && fm.error(error);
|
|
|
+ })
|
|
|
+ .always(function() {
|
|
|
+ input.remove();
|
|
|
+ node.remove();
|
|
|
+ fm.enable();
|
|
|
+ }),
|
|
|
+ id = 'tmp_'+parseInt(Math.random()*100000),
|
|
|
+ phash = fm.cwd().hash,
|
|
|
+ date = new Date(),
|
|
|
+ file = {
|
|
|
+ hash : id,
|
|
|
+ name : fm.uniqueName(this.prefix),
|
|
|
+ mime : this.mime,
|
|
|
+ read : true,
|
|
|
+ write : true,
|
|
|
+ date : 'Today '+date.getHours()+':'+date.getMinutes()
|
|
|
+ },
|
|
|
+ node = cwd.trigger('create.'+fm.namespace, file).find('#'+id),
|
|
|
+ input = $('<input type="text"/>')
|
|
|
+ .keydown(function(e) {
|
|
|
+ e.stopImmediatePropagation();
|
|
|
+
|
|
|
+ if (e.keyCode == $.ui.keyCode.ESCAPE) {
|
|
|
+ dfrd.reject();
|
|
|
+ } else if (e.keyCode == $.ui.keyCode.ENTER) {
|
|
|
+ input.blur();
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .mousedown(function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+ })
|
|
|
+ .blur(function() {
|
|
|
+ var name = $.trim(input.val()),
|
|
|
+ parent = input.parent();
|
|
|
+
|
|
|
+ if (parent.length) {
|
|
|
+
|
|
|
+ if (!name) {
|
|
|
+ return dfrd.reject('errInvName');
|
|
|
+ }
|
|
|
+ if (fm.fileByName(name, phash)) {
|
|
|
+ return dfrd.reject(['errExists', name]);
|
|
|
+ }
|
|
|
+
|
|
|
+ parent.html(fm.escape(name));
|
|
|
+
|
|
|
+ fm.lockfiles({files : [id]});
|
|
|
+
|
|
|
+ fm.request({
|
|
|
+ data : {cmd : cmd, name : name, target : phash},
|
|
|
+ notify : {type : cmd, cnt : 1},
|
|
|
+ preventFail : true,
|
|
|
+ syncOnFail : true
|
|
|
+ })
|
|
|
+ .fail(function(error) {
|
|
|
+ dfrd.reject(error);
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ dfrd.resolve(data);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ if (this.disabled() || !node.length) {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ fm.disable();
|
|
|
+ node.find('.elfinder-cwd-filename').empty('').append(input.val(file.name));
|
|
|
+ input.select().focus();
|
|
|
+ input[0].setSelectionRange && input[0].setSelectionRange(0, file.name.replace(/\..+$/, '').length);
|
|
|
+
|
|
|
+ return dfrd;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/jquery.dialogelfinder.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class dialogelfinder - open elFinder in dialog window
|
|
|
+ *
|
|
|
+ * @param Object elFinder options with dialog options
|
|
|
+ * @example
|
|
|
+ * $(selector).dialogelfinder({
|
|
|
+ * // some elfinder options
|
|
|
+ * title : 'My files', // dialog title, default = "Files"
|
|
|
+ * width : 850, // dialog width, default 840
|
|
|
+ * autoOpen : false, // if false - dialog will not be opened after init, default = true
|
|
|
+ * destroyOnClose : true // destroy elFinder on close dialog, default = false
|
|
|
+ * })
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.dialogelfinder = function(opts) {
|
|
|
+ var position = 'elfinderPosition',
|
|
|
+ destroy = 'elfinderDestroyOnClose';
|
|
|
+
|
|
|
+ this.not('.elfinder').each(function() {
|
|
|
+
|
|
|
+
|
|
|
+ var doc = $(document),
|
|
|
+ toolbar = $('<div class="ui-widget-header dialogelfinder-drag ui-corner-top">'+(opts.title || 'Files')+'</div>'),
|
|
|
+ button = $('<a href="#" class="dialogelfinder-drag-close ui-corner-all"><span class="ui-icon ui-icon-closethick"/></a>')
|
|
|
+ .appendTo(toolbar)
|
|
|
+ .click(function(e) {
|
|
|
+ e.preventDefault();
|
|
|
+
|
|
|
+ node.dialogelfinder('close');
|
|
|
+ }),
|
|
|
+ node = $(this).addClass('dialogelfinder')
|
|
|
+ .css('position', 'absolute')
|
|
|
+ .hide()
|
|
|
+ .appendTo('body')
|
|
|
+ .draggable({ handle : '.dialogelfinder-drag',
|
|
|
+ containment : 'window' })
|
|
|
+ .elfinder(opts)
|
|
|
+ .prepend(toolbar),
|
|
|
+ elfinder = node.elfinder('instance');
|
|
|
+
|
|
|
+
|
|
|
+ node.width(parseInt(node.width()) || 840) // fix width if set to "auto"
|
|
|
+ .data(destroy, !!opts.destroyOnClose)
|
|
|
+ .find('.elfinder-toolbar').removeClass('ui-corner-top');
|
|
|
+
|
|
|
+ opts.position && node.data(position, opts.position);
|
|
|
+
|
|
|
+ opts.autoOpen !== false && $(this).dialogelfinder('open');
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+ if (opts == 'open') {
|
|
|
+ var node = $(this),
|
|
|
+ pos = node.data(position) || {
|
|
|
+ top : parseInt($(document).scrollTop() + ($(window).height() < node.height() ? 2 : ($(window).height() - node.height())/2)),
|
|
|
+ left : parseInt($(document).scrollLeft() + ($(window).width() < node.width() ? 2 : ($(window).width() - node.width())/2))
|
|
|
+ },
|
|
|
+ zindex = 100;
|
|
|
+
|
|
|
+ if (node.is(':hidden')) {
|
|
|
+
|
|
|
+ $('body').find(':visible').each(function() {
|
|
|
+ var $this = $(this), z;
|
|
|
+
|
|
|
+ if (this !== node[0] && $this.css('position') == 'absolute' && (z = parseInt($this.zIndex())) > zindex) {
|
|
|
+ zindex = z + 1;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ node.zIndex(zindex).css(pos).show().trigger('resize')
|
|
|
+
|
|
|
+ setTimeout(function() {
|
|
|
+ // fix resize icon position and make elfinder active
|
|
|
+ node.trigger('resize').mousedown();
|
|
|
+ }, 200);
|
|
|
+ }
|
|
|
+ } else if (opts == 'close') {
|
|
|
+ var node = $(this);
|
|
|
+
|
|
|
+ if (node.is(':visible')) {
|
|
|
+ !!node.data(destroy)
|
|
|
+ ? node.elfinder('destroy').remove()
|
|
|
+ : node.elfinder('close');
|
|
|
+ }
|
|
|
+ } else if (opts == 'instance') {
|
|
|
+ return $(this).getElFinder();
|
|
|
+ }
|
|
|
+
|
|
|
+ return this;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/i18n/elfinder.en.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * English translation
|
|
|
+ * @author Troex Nevelin <troex@fury.scancode.ru>
|
|
|
+ * @version 2013-07-03
|
|
|
+ */
|
|
|
+if (elFinder && elFinder.prototype && typeof(elFinder.prototype.i18) == 'object') {
|
|
|
+ elFinder.prototype.i18.en = {
|
|
|
+ translator : 'Troex Nevelin <troex@fury.scancode.ru>',
|
|
|
+ language : 'English',
|
|
|
+ direction : 'ltr',
|
|
|
+ dateFormat : 'M d, Y h:i A', // Mar 13, 2012 05:27 PM
|
|
|
+ fancyDateFormat : '$1 h:i A', // will produce smth like: Today 12:25 PM
|
|
|
+ messages : {
|
|
|
+
|
|
|
+ /********************************** errors **********************************/
|
|
|
+ 'error' : 'Error',
|
|
|
+ 'errUnknown' : 'Unknown error.',
|
|
|
+ 'errUnknownCmd' : 'Unknown command.',
|
|
|
+ 'errJqui' : 'Invalid jQuery UI configuration. Selectable, draggable and droppable components must be included.',
|
|
|
+ 'errNode' : 'elFinder requires DOM Element to be created.',
|
|
|
+ 'errURL' : 'Invalid elFinder configuration! URL option is not set.',
|
|
|
+ 'errAccess' : 'Access denied.',
|
|
|
+ 'errConnect' : 'Unable to connect to backend.',
|
|
|
+ 'errAbort' : 'Connection aborted.',
|
|
|
+ 'errTimeout' : 'Connection timeout.',
|
|
|
+ 'errNotFound' : 'Backend not found.',
|
|
|
+ 'errResponse' : 'Invalid backend response.',
|
|
|
+ 'errConf' : 'Invalid backend configuration.',
|
|
|
+ 'errJSON' : 'PHP JSON module not installed.',
|
|
|
+ 'errNoVolumes' : 'Readable volumes not available.',
|
|
|
+ 'errCmdParams' : 'Invalid parameters for command "$1".',
|
|
|
+ 'errDataNotJSON' : 'Data is not JSON.',
|
|
|
+ 'errDataEmpty' : 'Data is empty.',
|
|
|
+ 'errCmdReq' : 'Backend request requires command name.',
|
|
|
+ 'errOpen' : 'Unable to open "$1".',
|
|
|
+ 'errNotFolder' : 'Object is not a folder.',
|
|
|
+ 'errNotFile' : 'Object is not a file.',
|
|
|
+ 'errRead' : 'Unable to read "$1".',
|
|
|
+ 'errWrite' : 'Unable to write into "$1".',
|
|
|
+ 'errPerm' : 'Permission denied.',
|
|
|
+ 'errLocked' : '"$1" is locked and can not be renamed, moved or removed.',
|
|
|
+ 'errExists' : 'File named "$1" already exists.',
|
|
|
+ 'errInvName' : 'Invalid file name.',
|
|
|
+ 'errFolderNotFound' : 'Folder not found.',
|
|
|
+ 'errFileNotFound' : 'File not found.',
|
|
|
+ 'errTrgFolderNotFound' : 'Target folder "$1" not found.',
|
|
|
+ 'errPopup' : 'Browser prevented opening popup window. To open file enable it in browser options.',
|
|
|
+ 'errMkdir' : 'Unable to create folder "$1".',
|
|
|
+ 'errMkfile' : 'Unable to create file "$1".',
|
|
|
+ 'errRename' : 'Unable to rename "$1".',
|
|
|
+ 'errCopyFrom' : 'Copying files from volume "$1" not allowed.',
|
|
|
+ 'errCopyTo' : 'Copying files to volume "$1" not allowed.',
|
|
|
+ 'errUpload' : 'Upload error.', // old name - errUploadCommon
|
|
|
+ 'errUploadFile' : 'Unable to upload "$1".', // old name - errUpload
|
|
|
+ 'errUploadNoFiles' : 'No files found for upload.',
|
|
|
+ 'errUploadTotalSize' : 'Data exceeds the maximum allowed size.', // old name - errMaxSize
|
|
|
+ 'errUploadFileSize' : 'File exceeds maximum allowed size.', // old name - errFileMaxSize
|
|
|
+ 'errUploadMime' : 'File type not allowed.',
|
|
|
+ 'errUploadTransfer' : '"$1" transfer error.',
|
|
|
+ 'errNotReplace' : 'Object "$1" already exists at this location and can not be replaced by object with another type.', // new
|
|
|
+ 'errReplace' : 'Unable to replace "$1".',
|
|
|
+ 'errSave' : 'Unable to save "$1".',
|
|
|
+ 'errCopy' : 'Unable to copy "$1".',
|
|
|
+ 'errMove' : 'Unable to move "$1".',
|
|
|
+ 'errCopyInItself' : 'Unable to copy "$1" into itself.',
|
|
|
+ 'errRm' : 'Unable to remove "$1".',
|
|
|
+ 'errRmSrc' : 'Unable remove source file(s).',
|
|
|
+ 'errExtract' : 'Unable to extract files from "$1".',
|
|
|
+ 'errArchive' : 'Unable to create archive.',
|
|
|
+ 'errArcType' : 'Unsupported archive type.',
|
|
|
+ 'errNoArchive' : 'File is not archive or has unsupported archive type.',
|
|
|
+ 'errCmdNoSupport' : 'Backend does not support this command.',
|
|
|
+ 'errReplByChild' : 'The folder “$1” can’t be replaced by an item it contains.',
|
|
|
+ 'errArcSymlinks' : 'For security reason denied to unpack archives contains symlinks or files with not allowed names.', // edited 24.06.2012
|
|
|
+ 'errArcMaxSize' : 'Archive files exceeds maximum allowed size.',
|
|
|
+ 'errResize' : 'Unable to resize "$1".',
|
|
|
+ 'errResizeDegree' : 'Invalid rotate degree.', // added 7.3.2013
|
|
|
+ 'errResizeRotate' : 'Image dose not rotated.', // added 7.3.2013
|
|
|
+ 'errResizeSize' : 'Invalid image size.', // added 7.3.2013
|
|
|
+ 'errResizeNoChange' : 'Image size not changed.', // added 7.3.2013
|
|
|
+ 'errUsupportType' : 'Unsupported file type.',
|
|
|
+ 'errNotUTF8Content' : 'File "$1" is not in UTF-8 and cannot be edited.', // added 9.11.2011
|
|
|
+ 'errNetMount' : 'Unable to mount "$1".', // added 17.04.2012
|
|
|
+ 'errNetMountNoDriver' : 'Unsupported protocol.', // added 17.04.2012
|
|
|
+ 'errNetMountFailed' : 'Mount failed.', // added 17.04.2012
|
|
|
+ 'errNetMountHostReq' : 'Host required.', // added 18.04.2012
|
|
|
+ 'errSessionExpires' : 'Your session has expired due to inactivity.',
|
|
|
+ 'errCreatingTempDir' : 'Unable to create temporary directory: "$1"',
|
|
|
+ 'errFtpDownloadFile' : 'Unable to download file from FTP: "$1"',
|
|
|
+ 'errFtpUploadFile' : 'Unable to upload file to FTP: "$1"',
|
|
|
+ 'errFtpMkdir' : 'Unable to create remote directory on FTP: "$1"',
|
|
|
+ 'errArchiveExec' : 'Error while archiving files: "$1"',
|
|
|
+ 'errExtractExec' : 'Error while extracting files: "$1"',
|
|
|
+
|
|
|
+ /******************************* commands names ********************************/
|
|
|
+ 'cmdarchive' : 'Create archive',
|
|
|
+ 'cmdback' : 'Back',
|
|
|
+ 'cmdcopy' : 'Copy',
|
|
|
+ 'cmdcut' : 'Cut',
|
|
|
+ 'cmddownload' : 'Download',
|
|
|
+ 'cmdduplicate' : 'Duplicate',
|
|
|
+ 'cmdedit' : 'Edit file',
|
|
|
+ 'cmdextract' : 'Extract files from archive',
|
|
|
+ 'cmdforward' : 'Forward',
|
|
|
+ 'cmdgetfile' : 'Select files',
|
|
|
+ 'cmdhelp' : 'About this software',
|
|
|
+ 'cmdhome' : 'Home',
|
|
|
+ 'cmdinfo' : 'Get info',
|
|
|
+ 'cmdmkdir' : 'New folder',
|
|
|
+ 'cmdmkfile' : 'New text file',
|
|
|
+ 'cmdopen' : 'Open',
|
|
|
+ 'cmdpaste' : 'Paste',
|
|
|
+ 'cmdquicklook' : 'Preview',
|
|
|
+ 'cmdreload' : 'Reload',
|
|
|
+ 'cmdrename' : 'Rename',
|
|
|
+ 'cmdrm' : 'Delete',
|
|
|
+ 'cmdsearch' : 'Find files',
|
|
|
+ 'cmdup' : 'Go to parent directory',
|
|
|
+ 'cmdupload' : 'Upload files',
|
|
|
+ 'cmdview' : 'View',
|
|
|
+ 'cmdresize' : 'Resize & Rotate',
|
|
|
+ 'cmdsort' : 'Sort',
|
|
|
+ 'cmdnetmount' : 'Mount network volume', // added 18.04.2012
|
|
|
+
|
|
|
+ /*********************************** buttons ***********************************/
|
|
|
+ 'btnClose' : 'Close',
|
|
|
+ 'btnSave' : 'Save',
|
|
|
+ 'btnRm' : 'Remove',
|
|
|
+ 'btnApply' : 'Apply',
|
|
|
+ 'btnCancel' : 'Cancel',
|
|
|
+ 'btnNo' : 'No',
|
|
|
+ 'btnYes' : 'Yes',
|
|
|
+ 'btnMount' : 'Mount', // added 18.04.2012
|
|
|
+ /******************************** notifications ********************************/
|
|
|
+ 'ntfopen' : 'Open folder',
|
|
|
+ 'ntffile' : 'Open file',
|
|
|
+ 'ntfreload' : 'Reload folder content',
|
|
|
+ 'ntfmkdir' : 'Creating directory',
|
|
|
+ 'ntfmkfile' : 'Creating files',
|
|
|
+ 'ntfrm' : 'Delete files',
|
|
|
+ 'ntfcopy' : 'Copy files',
|
|
|
+ 'ntfmove' : 'Move files',
|
|
|
+ 'ntfprepare' : 'Prepare to copy files',
|
|
|
+ 'ntfrename' : 'Rename files',
|
|
|
+ 'ntfupload' : 'Uploading files',
|
|
|
+ 'ntfdownload' : 'Downloading files',
|
|
|
+ 'ntfsave' : 'Save files',
|
|
|
+ 'ntfarchive' : 'Creating archive',
|
|
|
+ 'ntfextract' : 'Extracting files from archive',
|
|
|
+ 'ntfsearch' : 'Searching files',
|
|
|
+ 'ntfresize' : 'Resizing images',
|
|
|
+ 'ntfsmth' : 'Doing something',
|
|
|
+ 'ntfloadimg' : 'Loading image',
|
|
|
+ 'ntfnetmount' : 'Mounting network volume', // added 18.04.2012
|
|
|
+ 'ntfdim' : 'Acquiring image dimension', // added 20.05.2013
|
|
|
+ 'ntfreaddir' : 'Reading folder infomation', // added 01.07.2013
|
|
|
+
|
|
|
+ /************************************ dates **********************************/
|
|
|
+ 'dateUnknown' : 'unknown',
|
|
|
+ 'Today' : 'Today',
|
|
|
+ 'Yesterday' : 'Yesterday',
|
|
|
+ 'Jan' : 'Jan',
|
|
|
+ 'Feb' : 'Feb',
|
|
|
+ 'Mar' : 'Mar',
|
|
|
+ 'Apr' : 'Apr',
|
|
|
+ 'May' : 'May',
|
|
|
+ 'Jun' : 'Jun',
|
|
|
+ 'Jul' : 'Jul',
|
|
|
+ 'Aug' : 'Aug',
|
|
|
+ 'Sep' : 'Sep',
|
|
|
+ 'Oct' : 'Oct',
|
|
|
+ 'Nov' : 'Nov',
|
|
|
+ 'Dec' : 'Dec',
|
|
|
+
|
|
|
+ /******************************** sort variants ********************************/
|
|
|
+ 'sortname' : 'by name',
|
|
|
+ 'sortkind' : 'by kind',
|
|
|
+ 'sortsize' : 'by size',
|
|
|
+ 'sortdate' : 'by date',
|
|
|
+ 'sortFoldersFirst' : 'Folders first',
|
|
|
+
|
|
|
+ /********************************** messages **********************************/
|
|
|
+ 'confirmReq' : 'Confirmation required',
|
|
|
+ 'confirmRm' : 'Are you sure you want to remove files?<br/>This cannot be undone!',
|
|
|
+ 'confirmRepl' : 'Replace old file with new one?',
|
|
|
+ 'apllyAll' : 'Apply to all',
|
|
|
+ 'name' : 'Name',
|
|
|
+ 'size' : 'Size',
|
|
|
+ 'perms' : 'Permissions',
|
|
|
+ 'modify' : 'Modified',
|
|
|
+ 'kind' : 'Kind',
|
|
|
+ 'read' : 'read',
|
|
|
+ 'write' : 'write',
|
|
|
+ 'noaccess' : 'no access',
|
|
|
+ 'and' : 'and',
|
|
|
+ 'unknown' : 'unknown',
|
|
|
+ 'selectall' : 'Select all files',
|
|
|
+ 'selectfiles' : 'Select file(s)',
|
|
|
+ 'selectffile' : 'Select first file',
|
|
|
+ 'selectlfile' : 'Select last file',
|
|
|
+ 'viewlist' : 'List view',
|
|
|
+ 'viewicons' : 'Icons view',
|
|
|
+ 'places' : 'Places',
|
|
|
+ 'calc' : 'Calculate',
|
|
|
+ 'path' : 'Path',
|
|
|
+ 'aliasfor' : 'Alias for',
|
|
|
+ 'locked' : 'Locked',
|
|
|
+ 'dim' : 'Dimensions',
|
|
|
+ 'files' : 'Files',
|
|
|
+ 'folders' : 'Folders',
|
|
|
+ 'items' : 'Items',
|
|
|
+ 'yes' : 'yes',
|
|
|
+ 'no' : 'no',
|
|
|
+ 'link' : 'Link',
|
|
|
+ 'searcresult' : 'Search results',
|
|
|
+ 'selected' : 'selected items',
|
|
|
+ 'about' : 'About',
|
|
|
+ 'shortcuts' : 'Shortcuts',
|
|
|
+ 'help' : 'Help',
|
|
|
+ 'webfm' : 'Web file manager',
|
|
|
+ 'ver' : 'Version',
|
|
|
+ 'protocolver' : 'protocol version',
|
|
|
+ 'homepage' : 'Project home',
|
|
|
+ 'docs' : 'Documentation',
|
|
|
+ 'github' : 'Fork us on Github',
|
|
|
+ 'twitter' : 'Follow us on twitter',
|
|
|
+ 'facebook' : 'Join us on facebook',
|
|
|
+ 'team' : 'Team',
|
|
|
+ 'chiefdev' : 'chief developer',
|
|
|
+ 'developer' : 'developer',
|
|
|
+ 'contributor' : 'contributor',
|
|
|
+ 'maintainer' : 'maintainer',
|
|
|
+ 'translator' : 'translator',
|
|
|
+ 'icons' : 'Icons',
|
|
|
+ 'dontforget' : 'and don\'t forget to take your towel',
|
|
|
+ 'shortcutsof' : 'Shortcuts disabled',
|
|
|
+ 'dropFiles' : 'Drop files here',
|
|
|
+ 'dropFilesBrowser': 'Drop or paste files from browser', // added 30.05.2012
|
|
|
+ 'or' : 'or',
|
|
|
+ 'selectForUpload' : 'Select files to upload',
|
|
|
+ 'moveFiles' : 'Move files',
|
|
|
+ 'copyFiles' : 'Copy files',
|
|
|
+ 'rmFromPlaces' : 'Remove from places',
|
|
|
+ 'aspectRatio' : 'Aspect ratio',
|
|
|
+ 'scale' : 'Scale',
|
|
|
+ 'width' : 'Width',
|
|
|
+ 'height' : 'Height',
|
|
|
+ 'resize' : 'Resize',
|
|
|
+ 'crop' : 'Crop',
|
|
|
+ 'rotate' : 'Rotate',
|
|
|
+ 'rotate-cw' : 'Rotate 90 degrees CW',
|
|
|
+ 'rotate-ccw' : 'Rotate 90 degrees CCW',
|
|
|
+ 'degree' : '°',
|
|
|
+ 'netMountDialogTitle' : 'Mount network volume', // added 18.04.2012
|
|
|
+ 'protocol' : 'Protocol', // added 18.04.2012
|
|
|
+ 'host' : 'Host', // added 18.04.2012
|
|
|
+ 'port' : 'Port', // added 18.04.2012
|
|
|
+ 'user' : 'User', // added 18.04.2012
|
|
|
+ 'pass' : 'Password', // added 18.04.2012
|
|
|
+
|
|
|
+ /********************************** mimetypes **********************************/
|
|
|
+ 'kindUnknown' : 'Unknown',
|
|
|
+ 'kindFolder' : 'Folder',
|
|
|
+ 'kindAlias' : 'Alias',
|
|
|
+ 'kindAliasBroken' : 'Broken alias',
|
|
|
+ // applications
|
|
|
+ 'kindApp' : 'Application',
|
|
|
+ 'kindPostscript' : 'Postscript document',
|
|
|
+ 'kindMsOffice' : 'Microsoft Office document',
|
|
|
+ 'kindMsWord' : 'Microsoft Word document',
|
|
|
+ 'kindMsExcel' : 'Microsoft Excel document',
|
|
|
+ 'kindMsPP' : 'Microsoft Powerpoint presentation',
|
|
|
+ 'kindOO' : 'Open Office document',
|
|
|
+ 'kindAppFlash' : 'Flash application',
|
|
|
+ 'kindPDF' : 'Portable Document Format (PDF)',
|
|
|
+ 'kindTorrent' : 'Bittorrent file',
|
|
|
+ 'kind7z' : '7z archive',
|
|
|
+ 'kindTAR' : 'TAR archive',
|
|
|
+ 'kindGZIP' : 'GZIP archive',
|
|
|
+ 'kindBZIP' : 'BZIP archive',
|
|
|
+ 'kindZIP' : 'ZIP archive',
|
|
|
+ 'kindRAR' : 'RAR archive',
|
|
|
+ 'kindJAR' : 'Java JAR file',
|
|
|
+ 'kindTTF' : 'True Type font',
|
|
|
+ 'kindOTF' : 'Open Type font',
|
|
|
+ 'kindRPM' : 'RPM package',
|
|
|
+ // texts
|
|
|
+ 'kindText' : 'Text document',
|
|
|
+ 'kindTextPlain' : 'Plain text',
|
|
|
+ 'kindPHP' : 'PHP source',
|
|
|
+ 'kindCSS' : 'Cascading style sheet',
|
|
|
+ 'kindHTML' : 'HTML document',
|
|
|
+ 'kindJS' : 'Javascript source',
|
|
|
+ 'kindRTF' : 'Rich Text Format',
|
|
|
+ 'kindC' : 'C source',
|
|
|
+ 'kindCHeader' : 'C header source',
|
|
|
+ 'kindCPP' : 'C++ source',
|
|
|
+ 'kindCPPHeader' : 'C++ header source',
|
|
|
+ 'kindShell' : 'Unix shell script',
|
|
|
+ 'kindPython' : 'Python source',
|
|
|
+ 'kindJava' : 'Java source',
|
|
|
+ 'kindRuby' : 'Ruby source',
|
|
|
+ 'kindPerl' : 'Perl script',
|
|
|
+ 'kindSQL' : 'SQL source',
|
|
|
+ 'kindXML' : 'XML document',
|
|
|
+ 'kindAWK' : 'AWK source',
|
|
|
+ 'kindCSV' : 'Comma separated values',
|
|
|
+ 'kindDOCBOOK' : 'Docbook XML document',
|
|
|
+ // images
|
|
|
+ 'kindImage' : 'Image',
|
|
|
+ 'kindBMP' : 'BMP image',
|
|
|
+ 'kindJPEG' : 'JPEG image',
|
|
|
+ 'kindGIF' : 'GIF Image',
|
|
|
+ 'kindPNG' : 'PNG Image',
|
|
|
+ 'kindTIFF' : 'TIFF image',
|
|
|
+ 'kindTGA' : 'TGA image',
|
|
|
+ 'kindPSD' : 'Adobe Photoshop image',
|
|
|
+ 'kindXBITMAP' : 'X bitmap image',
|
|
|
+ 'kindPXM' : 'Pixelmator image',
|
|
|
+ // media
|
|
|
+ 'kindAudio' : 'Audio media',
|
|
|
+ 'kindAudioMPEG' : 'MPEG audio',
|
|
|
+ 'kindAudioMPEG4' : 'MPEG-4 audio',
|
|
|
+ 'kindAudioMIDI' : 'MIDI audio',
|
|
|
+ 'kindAudioOGG' : 'Ogg Vorbis audio',
|
|
|
+ 'kindAudioWAV' : 'WAV audio',
|
|
|
+ 'AudioPlaylist' : 'MP3 playlist',
|
|
|
+ 'kindVideo' : 'Video media',
|
|
|
+ 'kindVideoDV' : 'DV movie',
|
|
|
+ 'kindVideoMPEG' : 'MPEG movie',
|
|
|
+ 'kindVideoMPEG4' : 'MPEG-4 movie',
|
|
|
+ 'kindVideoAVI' : 'AVI movie',
|
|
|
+ 'kindVideoMOV' : 'Quick Time movie',
|
|
|
+ 'kindVideoWM' : 'Windows Media movie',
|
|
|
+ 'kindVideoFlash' : 'Flash movie',
|
|
|
+ 'kindVideoMKV' : 'Matroska movie',
|
|
|
+ 'kindVideoOGG' : 'Ogg movie'
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/button.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder toolbar button widget.
|
|
|
+ * If command has variants - create menu
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.elfinderbutton = function(cmd) {
|
|
|
+ return this.each(function() {
|
|
|
+
|
|
|
+ var c = 'class',
|
|
|
+ fm = cmd.fm,
|
|
|
+ disabled = fm.res(c, 'disabled'),
|
|
|
+ active = fm.res(c, 'active'),
|
|
|
+ hover = fm.res(c, 'hover'),
|
|
|
+ item = 'elfinder-button-menu-item',
|
|
|
+ selected = 'elfinder-button-menu-item-selected',
|
|
|
+ menu,
|
|
|
+ button = $(this).addClass('ui-state-default elfinder-button')
|
|
|
+ .attr('title', cmd.title)
|
|
|
+ .append('<span class="elfinder-button-icon elfinder-button-icon-'+cmd.name+'"/>')
|
|
|
+ .hover(function(e) { !button.is('.'+disabled) && button[e.type == 'mouseleave' ? 'removeClass' : 'addClass'](hover) /**button.toggleClass(hover);*/ })
|
|
|
+ .click(function(e) {
|
|
|
+ if (!button.is('.'+disabled)) {
|
|
|
+ if (menu && cmd.variants.length > 1) {
|
|
|
+ // close other menus
|
|
|
+ menu.is(':hidden') && cmd.fm.getUI().click();
|
|
|
+ e.stopPropagation();
|
|
|
+ menu.slideToggle(100);
|
|
|
+ } else {
|
|
|
+ cmd.exec();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }),
|
|
|
+ hideMenu = function() {
|
|
|
+ menu.hide();
|
|
|
+ };
|
|
|
+
|
|
|
+ // if command has variants create menu
|
|
|
+ if ($.isArray(cmd.variants)) {
|
|
|
+ button.addClass('elfinder-menubutton');
|
|
|
+
|
|
|
+ menu = $('<div class="ui-widget ui-widget-content elfinder-button-menu ui-corner-all"/>')
|
|
|
+ .hide()
|
|
|
+ .appendTo(button)
|
|
|
+ .zIndex(12+button.zIndex())
|
|
|
+ .delegate('.'+item, 'hover', function() { $(this).toggleClass(hover) })
|
|
|
+ .delegate('.'+item, 'click', function(e) {
|
|
|
+ e.preventDefault();
|
|
|
+ e.stopPropagation();
|
|
|
+ button.removeClass(hover);
|
|
|
+ cmd.exec(cmd.fm.selected(), $(this).data('value'));
|
|
|
+ });
|
|
|
+
|
|
|
+ cmd.fm.bind('disable select', hideMenu).getUI().click(hideMenu);
|
|
|
+
|
|
|
+ cmd.change(function() {
|
|
|
+ menu.html('');
|
|
|
+ $.each(cmd.variants, function(i, variant) {
|
|
|
+ menu.append($('<div class="'+item+'">'+variant[1]+'</div>').data('value', variant[0]).addClass(variant[0] == cmd.value ? selected : ''));
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ cmd.change(function() {
|
|
|
+ if (cmd.disabled()) {
|
|
|
+ button.removeClass(active+' '+hover).addClass(disabled);
|
|
|
+ } else {
|
|
|
+ button.removeClass(disabled);
|
|
|
+ button[cmd.active() ? 'addClass' : 'removeClass'](active);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .change();
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/contextmenu.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder contextmenu
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.elfindercontextmenu = function(fm) {
|
|
|
+
|
|
|
+ return this.each(function() {
|
|
|
+ var menu = $(this).addClass('ui-helper-reset ui-widget ui-state-default ui-corner-all elfinder-contextmenu elfinder-contextmenu-'+fm.direction)
|
|
|
+ .hide()
|
|
|
+ .appendTo('body')
|
|
|
+ .delegate('.elfinder-contextmenu-item', 'mouseenter mouseleave', function() {
|
|
|
+ $(this).toggleClass('ui-state-hover')
|
|
|
+ }),
|
|
|
+ subpos = fm.direction == 'ltr' ? 'left' : 'right',
|
|
|
+ types = $.extend({}, fm.options.contextmenu),
|
|
|
+ tpl = '<div class="elfinder-contextmenu-item"><span class="elfinder-button-icon {icon} elfinder-contextmenu-icon"/><span>{label}</span></div>',
|
|
|
+ item = function(label, icon, callback) {
|
|
|
+ return $(tpl.replace('{icon}', icon ? 'elfinder-button-icon-'+icon : '').replace('{label}', label))
|
|
|
+ .click(function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+ e.stopPropagation();
|
|
|
+ callback();
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ open = function(x, y) {
|
|
|
+ var win = $(window),
|
|
|
+ width = menu.outerWidth(),
|
|
|
+ height = menu.outerHeight(),
|
|
|
+ wwidth = win.width(),
|
|
|
+ wheight = win.height(),
|
|
|
+ scrolltop = win.scrollTop(),
|
|
|
+ scrollleft = win.scrollLeft(),
|
|
|
+ css = {
|
|
|
+ top : (y + height < wheight ? y : y - height > 0 ? y - height : y) + scrolltop,
|
|
|
+ left : (x + width < wwidth ? x : x - width) + scrollleft,
|
|
|
+ 'z-index' : 100 + fm.getUI('workzone').zIndex()
|
|
|
+ };
|
|
|
+
|
|
|
+ menu.css(css)
|
|
|
+ .show();
|
|
|
+
|
|
|
+ css = {'z-index' : css['z-index']+10};
|
|
|
+ css[subpos] = parseInt(menu.width());
|
|
|
+ menu.find('.elfinder-contextmenu-sub').css(css);
|
|
|
+ },
|
|
|
+
|
|
|
+ close = function() {
|
|
|
+ menu.hide().empty();
|
|
|
+ },
|
|
|
+
|
|
|
+ create = function(type, targets) {
|
|
|
+ var sep = false;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ $.each(types[type]||[], function(i, name) {
|
|
|
+ var cmd, node, submenu;
|
|
|
+
|
|
|
+ if (name == '|' && sep) {
|
|
|
+ menu.append('<div class="elfinder-contextmenu-separator"/>');
|
|
|
+ sep = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ cmd = fm.command(name);
|
|
|
+
|
|
|
+ if (cmd && cmd.getstate(targets) != -1) {
|
|
|
+ if (cmd.variants) {
|
|
|
+ if (!cmd.variants.length) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ node = item(cmd.title, cmd.name, function() {});
|
|
|
+
|
|
|
+ submenu = $('<div class="ui-corner-all elfinder-contextmenu-sub"/>')
|
|
|
+ .appendTo(node.append('<span class="elfinder-contextmenu-arrow"/>'));
|
|
|
+
|
|
|
+ node.addClass('elfinder-contextmenu-group')
|
|
|
+ .hover(function() {
|
|
|
+ submenu.toggle()
|
|
|
+ })
|
|
|
+
|
|
|
+ $.each(cmd.variants, function(i, variant) {
|
|
|
+ submenu.append(
|
|
|
+ $('<div class="elfinder-contextmenu-item"><span>'+variant[1]+'</span></div>')
|
|
|
+ .click(function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+ close();
|
|
|
+ cmd.exec(targets, variant[0]);
|
|
|
+ })
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
+ } else {
|
|
|
+ node = item(cmd.title, cmd.name, function() {
|
|
|
+ close();
|
|
|
+ cmd.exec(targets);
|
|
|
+ })
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ menu.append(node)
|
|
|
+ sep = true;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ createFromRaw = function(raw) {
|
|
|
+ $.each(raw, function(i, data) {
|
|
|
+ var node;
|
|
|
+
|
|
|
+ if (data.label && typeof data.callback == 'function') {
|
|
|
+ node = item(data.label, data.icon, function() {
|
|
|
+ close();
|
|
|
+ data.callback();
|
|
|
+ });
|
|
|
+ menu.append(node);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ };
|
|
|
+
|
|
|
+ fm.one('load', function() {
|
|
|
+ fm.bind('contextmenu', function(e) {
|
|
|
+ var data = e.data;
|
|
|
+
|
|
|
+ close();
|
|
|
+
|
|
|
+ if (data.type && data.targets) {
|
|
|
+ create(data.type, data.targets);
|
|
|
+ } else if (data.raw) {
|
|
|
+ createFromRaw(data.raw);
|
|
|
+ }
|
|
|
+
|
|
|
+ menu.children().length && open(data.x, data.y);
|
|
|
+ })
|
|
|
+ .one('destroy', function() { menu.remove(); })
|
|
|
+ .bind('disable select', close)
|
|
|
+ .getUI().click(close);
|
|
|
+ });
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/cwd.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * elFinder current working directory ui.
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.elfindercwd = function(fm, options) {
|
|
|
+
|
|
|
+ this.not('.elfinder-cwd').each(function() {
|
|
|
+ // fm.time('cwdLoad');
|
|
|
+
|
|
|
+ var
|
|
|
+ list = fm.viewType == 'list',
|
|
|
+
|
|
|
+ undef = 'undefined',
|
|
|
+ /**
|
|
|
+ * Select event full name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ evtSelect = 'select.'+fm.namespace,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Unselect event full name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ evtUnselect = 'unselect.'+fm.namespace,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Disable event full name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ evtDisable = 'disable.'+fm.namespace,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Disable event full name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ evtEnable = 'enable.'+fm.namespace,
|
|
|
+
|
|
|
+ c = 'class',
|
|
|
+ /**
|
|
|
+ * File css class
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ clFile = fm.res(c, 'cwdfile'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Selected css class
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ fileSelector = '.'+clFile,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Selected css class
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ clSelected = 'ui-selected',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Disabled css class
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ clDisabled = fm.res(c, 'disabled'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Draggable css class
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ clDraggable = fm.res(c, 'draggable'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Droppable css class
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ clDroppable = fm.res(c, 'droppable'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Hover css class
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ clHover = fm.res(c, 'hover'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Hover css class
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ clDropActive = fm.res(c, 'adroppable'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Css class for temporary nodes (for mkdir/mkfile) commands
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ clTmp = clFile+'-tmp',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Number of thumbnails to load in one request (new api only)
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ **/
|
|
|
+ tmbNum = fm.options.loadTmbs > 0 ? fm.options.loadTmbs : 5,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Current search query.
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ query = '',
|
|
|
+
|
|
|
+ lastSearch = [],
|
|
|
+
|
|
|
+ /**
|
|
|
+ * File templates
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ templates = {
|
|
|
+ icon : '<div id="{hash}" class="'+clFile+' {permsclass} {dirclass} ui-corner-all" title="{tooltip}"><div class="elfinder-cwd-file-wrapper ui-corner-all"><div class="elfinder-cwd-icon {mime} ui-corner-all" unselectable="on" {style}/>{marker}</div><div class="elfinder-cwd-filename" title="{name}">{name}</div></div>',
|
|
|
+ row : '<tr id="{hash}" class="'+clFile+' {permsclass} {dirclass}" title="{tooltip}"><td><div class="elfinder-cwd-file-wrapper"><span class="elfinder-cwd-icon {mime}"/>{marker}<span class="elfinder-cwd-filename">{name}</span></div></td><td>{perms}</td><td>{date}</td><td>{size}</td><td>{kind}</td></tr>'
|
|
|
+ },
|
|
|
+
|
|
|
+ permsTpl = fm.res('tpl', 'perms'),
|
|
|
+
|
|
|
+ symlinkTpl = fm.res('tpl', 'symlink'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Template placeholders replacement rules
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ replacement = {
|
|
|
+ permsclass : function(f) {
|
|
|
+ return fm.perms2class(f);
|
|
|
+ },
|
|
|
+ perms : function(f) {
|
|
|
+ return fm.formatPermissions(f);
|
|
|
+ },
|
|
|
+ dirclass : function(f) {
|
|
|
+ return f.mime == 'directory' ? 'directory' : '';
|
|
|
+ },
|
|
|
+ mime : function(f) {
|
|
|
+ return fm.mime2class(f.mime);
|
|
|
+ },
|
|
|
+ size : function(f) {
|
|
|
+ return fm.formatSize(f.size);
|
|
|
+ },
|
|
|
+ date : function(f) {
|
|
|
+ return fm.formatDate(f);
|
|
|
+ },
|
|
|
+ kind : function(f) {
|
|
|
+ return fm.mime2kind(f);
|
|
|
+ },
|
|
|
+ marker : function(f) {
|
|
|
+ return (f.alias || f.mime == 'symlink-broken' ? symlinkTpl : '')+(!f.read || !f.write ? permsTpl : '');
|
|
|
+ },
|
|
|
+ tooltip : function(f) {
|
|
|
+ var title = fm.formatDate(f) + (f.size > 0 ? ' ('+fm.formatSize(f.size)+')' : '');
|
|
|
+ return f.tooltip? fm.escape(f.tooltip).replace(/"/g, '"').replace(/\r/g, ' ') + ' ' + title : title;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return file html
|
|
|
+ *
|
|
|
+ * @param Object file info
|
|
|
+ * @return String
|
|
|
+ **/
|
|
|
+ itemhtml = function(f) {
|
|
|
+ f.name = fm.escape(f.name);
|
|
|
+ return templates[list ? 'row' : 'icon']
|
|
|
+ .replace(/\{([a-z]+)\}/g, function(s, e) {
|
|
|
+ return replacement[e] ? replacement[e](f) : (f[e] ? f[e] : '');
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Flag. Required for msie to avoid unselect files on dragstart
|
|
|
+ *
|
|
|
+ * @type Boolean
|
|
|
+ **/
|
|
|
+ selectLock = false,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Move selection to prev/next file
|
|
|
+ *
|
|
|
+ * @param String move direction
|
|
|
+ * @param Boolean append to current selection
|
|
|
+ * @return void
|
|
|
+ * @rise select
|
|
|
+ */
|
|
|
+ select = function(keyCode, append) {
|
|
|
+ var code = $.ui.keyCode,
|
|
|
+ prev = keyCode == code.LEFT || keyCode == code.UP,
|
|
|
+ sel = cwd.find('[id].'+clSelected),
|
|
|
+ selector = prev ? 'first:' : 'last',
|
|
|
+ s, n, sib, top, left;
|
|
|
+
|
|
|
+ function sibling(n, direction) {
|
|
|
+ return n[direction+'All']('[id]:not(.'+clDisabled+'):not(.elfinder-cwd-parent):first');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sel.length) {
|
|
|
+ s = sel.filter(prev ? ':first' : ':last');
|
|
|
+ sib = sibling(s, prev ? 'prev' : 'next');
|
|
|
+
|
|
|
+ if (!sib.length) {
|
|
|
+ // there is no sibling on required side - do not move selection
|
|
|
+ n = s;
|
|
|
+ } else if (list || keyCode == code.LEFT || keyCode == code.RIGHT) {
|
|
|
+ // find real prevoius file
|
|
|
+ n = sib;
|
|
|
+ } else {
|
|
|
+ // find up/down side file in icons view
|
|
|
+ top = s.position().top;
|
|
|
+ left = s.position().left;
|
|
|
+
|
|
|
+ n = s;
|
|
|
+ if (prev) {
|
|
|
+ do {
|
|
|
+ n = n.prev('[id]');
|
|
|
+ } while (n.length && !(n.position().top < top && n.position().left <= left));
|
|
|
+
|
|
|
+ if (n.is('.'+clDisabled)) {
|
|
|
+ n = sibling(n, 'next');
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ do {
|
|
|
+ n = n.next('[id]');
|
|
|
+ } while (n.length && !(n.position().top > top && n.position().left >= left));
|
|
|
+
|
|
|
+ if (n.is('.'+clDisabled)) {
|
|
|
+ n = sibling(n, 'prev');
|
|
|
+ }
|
|
|
+ // there is row before last one - select last file
|
|
|
+ if (!n.length) {
|
|
|
+ sib = cwd.find('[id]:not(.'+clDisabled+'):last');
|
|
|
+ if (sib.position().top > top) {
|
|
|
+ n = sib;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // !append && unselectAll();
|
|
|
+ } else {
|
|
|
+ // there are no selected file - select first/last one
|
|
|
+ n = cwd.find('[id]:not(.'+clDisabled+'):not(.elfinder-cwd-parent):'+(prev ? 'last' : 'first'));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (n && n.length && !n.is('.elfinder-cwd-parent')) {
|
|
|
+ if (append) {
|
|
|
+ // append new files to selected
|
|
|
+ n = s.add(s[prev ? 'prevUntil' : 'nextUntil']('#'+n.attr('id'))).add(n);
|
|
|
+ } else {
|
|
|
+ // unselect selected files
|
|
|
+ sel.trigger(evtUnselect);
|
|
|
+ }
|
|
|
+ // select file(s)
|
|
|
+ n.trigger(evtSelect);
|
|
|
+ // set its visible
|
|
|
+ scrollToView(n.filter(prev ? ':first' : ':last'));
|
|
|
+ // update cache/view
|
|
|
+ trigger();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ selectedFiles = [],
|
|
|
+
|
|
|
+ selectFile = function(hash) {
|
|
|
+ cwd.find('#'+hash).trigger(evtSelect);
|
|
|
+ },
|
|
|
+
|
|
|
+ selectAll = function() {
|
|
|
+ var phash = fm.cwd().hash;
|
|
|
+
|
|
|
+ cwd.find('[id]:not(.'+clSelected+'):not(.elfinder-cwd-parent)').trigger(evtSelect);
|
|
|
+ selectedFiles = $.map(fm.files(), function(f) { return f.phash == phash ? f.hash : null ;});
|
|
|
+ trigger();
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Unselect all files
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ unselectAll = function() {
|
|
|
+ selectedFiles = [];
|
|
|
+ cwd.find('[id].'+clSelected).trigger(evtUnselect);
|
|
|
+ trigger();
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return selected files hashes list
|
|
|
+ *
|
|
|
+ * @return Array
|
|
|
+ */
|
|
|
+ selected = function() {
|
|
|
+ return selectedFiles;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Fire elfinder "select" event and pass selected files to it
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ trigger = function() {
|
|
|
+ fm.trigger('select', {selected : selectedFiles});
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Scroll file to set it visible
|
|
|
+ *
|
|
|
+ * @param DOMElement file/dir node
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ scrollToView = function(o) {
|
|
|
+ var ftop = o.position().top,
|
|
|
+ fheight = o.outerHeight(true),
|
|
|
+ wtop = wrapper.scrollTop(),
|
|
|
+ wheight = wrapper.innerHeight();
|
|
|
+
|
|
|
+ if (ftop + fheight > wtop + wheight) {
|
|
|
+ wrapper.scrollTop(parseInt(ftop + fheight - wheight));
|
|
|
+ } else if (ftop < wtop) {
|
|
|
+ wrapper.scrollTop(ftop);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Files we get from server but not show yet
|
|
|
+ *
|
|
|
+ * @type Array
|
|
|
+ **/
|
|
|
+ buffer = [],
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return index of elements with required hash in buffer
|
|
|
+ *
|
|
|
+ * @param String file hash
|
|
|
+ * @return Number
|
|
|
+ */
|
|
|
+ index = function(hash) {
|
|
|
+ var l = buffer.length;
|
|
|
+
|
|
|
+ while (l--) {
|
|
|
+ if (buffer[l].hash == hash) {
|
|
|
+ return l;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Scroll event name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ **/
|
|
|
+ scrollEvent = 'scroll.'+fm.namespace,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Cwd scroll event handler.
|
|
|
+ * Lazy load - append to cwd not shown files
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ render = function() {
|
|
|
+ var html = [],
|
|
|
+ dirs = false,
|
|
|
+ ltmb = [],
|
|
|
+ atmb = {},
|
|
|
+ last = cwd.find('[id]:last'),
|
|
|
+ top = !last.length,
|
|
|
+ place = list ? cwd.children('table').children('tbody') : cwd,
|
|
|
+ files;
|
|
|
+
|
|
|
+ if (!buffer.length) {
|
|
|
+ return wrapper.unbind(scrollEvent);
|
|
|
+ }
|
|
|
+
|
|
|
+ while ((!last.length || last.position().top <= wrapper.height() + wrapper.scrollTop() + fm.options.showThreshold)
|
|
|
+ && (files = buffer.splice(0, fm.options.showFiles)).length) {
|
|
|
+
|
|
|
+ html = $.map(files, function(f) {
|
|
|
+ if (f.hash && f.name) {
|
|
|
+ if (f.mime == 'directory') {
|
|
|
+ dirs = true;
|
|
|
+ }
|
|
|
+ if (f.tmb) {
|
|
|
+ f.tmb === 1 ? ltmb.push(f.hash) : (atmb[f.hash] = f.tmb);
|
|
|
+ }
|
|
|
+ return itemhtml(f);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ });
|
|
|
+
|
|
|
+ place.append(html.join(''));
|
|
|
+ last = cwd.find('[id]:last');
|
|
|
+ // scroll top on dir load to avoid scroll after page reload
|
|
|
+ top && cwd.scrollTop(0);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // load/attach thumbnails
|
|
|
+ attachThumbnails(atmb);
|
|
|
+ ltmb.length && loadThumbnails(ltmb);
|
|
|
+
|
|
|
+ // make directory droppable
|
|
|
+ dirs && makeDroppable();
|
|
|
+
|
|
|
+ if (selectedFiles.length) {
|
|
|
+ place.find('[id]:not(.'+clSelected+'):not(.elfinder-cwd-parent)').each(function() {
|
|
|
+ var id = this.id;
|
|
|
+
|
|
|
+ $.inArray(id, selectedFiles) !== -1 && $(this).trigger(evtSelect);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Droppable options for cwd.
|
|
|
+ * Do not add class on childs file over
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ */
|
|
|
+ droppable = $.extend({}, fm.droppable, {
|
|
|
+ over : function(e, ui) {
|
|
|
+ var hash = fm.cwd().hash;
|
|
|
+ $.each(ui.helper.data('files'), function(i, h) {
|
|
|
+ if (fm.file(h).phash == hash) {
|
|
|
+ cwd.removeClass(clDropActive);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Make directory droppable
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ makeDroppable = function() {
|
|
|
+ setTimeout(function() {
|
|
|
+ cwd.find('.directory:not(.'+clDroppable+',.elfinder-na,.elfinder-ro)').droppable(fm.droppable);
|
|
|
+ }, 20);
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Preload required thumbnails and on load add css to files.
|
|
|
+ * Return false if required file is not visible yet (in buffer) -
|
|
|
+ * required for old api to stop loading thumbnails.
|
|
|
+ *
|
|
|
+ * @param Object file hash -> thumbnail map
|
|
|
+ * @return Boolean
|
|
|
+ */
|
|
|
+ attachThumbnails = function(images) {
|
|
|
+ var url = fm.option('tmbUrl'),
|
|
|
+ ret = true,
|
|
|
+ ndx;
|
|
|
+
|
|
|
+ $.each(images, function(hash, tmb) {
|
|
|
+ var node = cwd.find('#'+hash);
|
|
|
+
|
|
|
+ if (node.length) {
|
|
|
+
|
|
|
+ (function(node, tmb) {
|
|
|
+ $('<img/>')
|
|
|
+ .load(function() { node.find('.elfinder-cwd-icon').css('background', "url('"+tmb+"') center center no-repeat"); })
|
|
|
+ .attr('src', tmb);
|
|
|
+ })(node, url+tmb);
|
|
|
+ } else {
|
|
|
+ ret = false;
|
|
|
+ if ((ndx = index(hash)) != -1) {
|
|
|
+ buffer[ndx].tmb = tmb;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return ret;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Load thumbnails from backend.
|
|
|
+ *
|
|
|
+ * @param Array|Boolean files hashes list for new api | true for old api
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ loadThumbnails = function(files) {
|
|
|
+ var tmbs = [];
|
|
|
+
|
|
|
+ if (fm.oldAPI) {
|
|
|
+ fm.request({
|
|
|
+ data : {cmd : 'tmb', current : fm.cwd().hash},
|
|
|
+ preventFail : true
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ if (attachThumbnails(data.images||[]) && data.tmb) {
|
|
|
+ loadThumbnails();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ tmbs = tmbs = files.splice(0, tmbNum);
|
|
|
+ if (tmbs.length) {
|
|
|
+ fm.request({
|
|
|
+ data : {cmd : 'tmb', targets : tmbs},
|
|
|
+ preventFail : true
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ if (attachThumbnails(data.images||[])) {
|
|
|
+ loadThumbnails(files);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Add new files to cwd/buffer
|
|
|
+ *
|
|
|
+ * @param Array new files
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ add = function(files) {
|
|
|
+ var place = list ? cwd.find('tbody') : cwd,
|
|
|
+ l = files.length,
|
|
|
+ ltmb = [],
|
|
|
+ atmb = {},
|
|
|
+ dirs = false,
|
|
|
+ findNode = function(file) {
|
|
|
+ var pointer = cwd.find('[id]:first'), file2;
|
|
|
+
|
|
|
+ while (pointer.length) {
|
|
|
+ file2 = fm.file(pointer.attr('id'));
|
|
|
+ if (!pointer.is('.elfinder-cwd-parent') && file2 && fm.compare(file, file2) < 0) {
|
|
|
+ return pointer;
|
|
|
+ }
|
|
|
+ pointer = pointer.next('[id]');
|
|
|
+ }
|
|
|
+ },
|
|
|
+ findIndex = function(file) {
|
|
|
+ var l = buffer.length, i;
|
|
|
+
|
|
|
+ for (i =0; i < l; i++) {
|
|
|
+ if (fm.compare(file, buffer[i]) < 0) {
|
|
|
+ return i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return l || -1;
|
|
|
+ },
|
|
|
+ file, hash, node, ndx;
|
|
|
+
|
|
|
+
|
|
|
+ while (l--) {
|
|
|
+ file = files[l];
|
|
|
+ hash = file.hash;
|
|
|
+
|
|
|
+ if (cwd.find('#'+hash).length) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((node = findNode(file)) && node.length) {
|
|
|
+ node.before(itemhtml(file));
|
|
|
+ } else if ((ndx = findIndex(file)) >= 0) {
|
|
|
+ buffer.splice(ndx, 0, file);
|
|
|
+ } else {
|
|
|
+ place.append(itemhtml(file));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cwd.find('#'+hash).length) {
|
|
|
+ if (file.mime == 'directory') {
|
|
|
+ dirs = true;
|
|
|
+ } else if (file.tmb) {
|
|
|
+ file.tmb === 1 ? ltmb.push(hash) : (atmb[hash] = file.tmb);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ attachThumbnails(atmb);
|
|
|
+ ltmb.length && loadThumbnails(ltmb);
|
|
|
+ dirs && makeDroppable();
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Remove files from cwd/buffer
|
|
|
+ *
|
|
|
+ * @param Array files hashes
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ remove = function(files) {
|
|
|
+ var l = files.length, hash, n, ndx;
|
|
|
+
|
|
|
+ while (l--) {
|
|
|
+ hash = files[l];
|
|
|
+ if ((n = cwd.find('#'+hash)).length) {
|
|
|
+ try {
|
|
|
+ n.detach();
|
|
|
+ } catch(e) {
|
|
|
+ fm.debug('error', e);
|
|
|
+ }
|
|
|
+ } else if ((ndx = index(hash)) != -1) {
|
|
|
+ buffer.splice(ndx, 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ msg = {
|
|
|
+ name : fm.i18n('name'),
|
|
|
+ perm : fm.i18n('perms'),
|
|
|
+ mod : fm.i18n('modify'),
|
|
|
+ size : fm.i18n('size'),
|
|
|
+ kind : fm.i18n('kind')
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Update directory content
|
|
|
+ *
|
|
|
+ * @param Array files
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ content = function(files, any) {
|
|
|
+ var phash = fm.cwd().hash;
|
|
|
+ // console.log(files)
|
|
|
+
|
|
|
+ unselectAll();
|
|
|
+
|
|
|
+ try {
|
|
|
+ // to avoid problem with draggable
|
|
|
+ cwd.children('table,'+fileSelector).remove();
|
|
|
+ } catch (e) {
|
|
|
+ cwd.html('');
|
|
|
+ }
|
|
|
+
|
|
|
+ cwd.removeClass('elfinder-cwd-view-icons elfinder-cwd-view-list')
|
|
|
+ .addClass('elfinder-cwd-view-'+(list ? 'list' :'icons'));
|
|
|
+
|
|
|
+ wrapper[list ? 'addClass' : 'removeClass']('elfinder-cwd-wrapper-list');
|
|
|
+
|
|
|
+ list && cwd.html('<table><thead><tr class="ui-state-default"><td >'+msg.name+'</td><td>'+msg.perm+'</td><td>'+msg.mod+'</td><td>'+msg.size+'</td><td>'+msg.kind+'</td></tr></thead><tbody/></table>');
|
|
|
+
|
|
|
+ buffer = $.map(files, function(f) { return any || f.phash == phash ? f : null; });
|
|
|
+
|
|
|
+ buffer = fm.sortFiles(buffer);
|
|
|
+
|
|
|
+ wrapper.bind(scrollEvent, render).trigger(scrollEvent);
|
|
|
+
|
|
|
+ phash = fm.cwd().phash;
|
|
|
+
|
|
|
+ if (options.oldSchool && phash && !query) {
|
|
|
+ var parent = $.extend(true, {}, fm.file(phash), {name : '..', mime : 'directory'});
|
|
|
+ parent = $(itemhtml(parent))
|
|
|
+ .addClass('elfinder-cwd-parent')
|
|
|
+ .bind('mousedown click mouseup touchstart touchmove touchend dblclick mouseenter', function(e) {
|
|
|
+ //.bind('mousedown click mouseup dblclick mouseenter', function(e) {
|
|
|
+ e.preventDefault();
|
|
|
+ e.stopPropagation();
|
|
|
+ })
|
|
|
+ .dblclick(function() {
|
|
|
+ fm.exec('open', this.id);
|
|
|
+ });
|
|
|
+
|
|
|
+ (list ? cwd.find('tbody') : cwd).prepend(parent);
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * CWD node itself
|
|
|
+ *
|
|
|
+ * @type JQuery
|
|
|
+ **/
|
|
|
+ cwd = $(this)
|
|
|
+ .addClass('ui-helper-clearfix elfinder-cwd')
|
|
|
+ .attr('unselectable', 'on')
|
|
|
+ // fix ui.selectable bugs and add shift+click support
|
|
|
+ .delegate(fileSelector, 'click.'+fm.namespace, function(e) {
|
|
|
+ var p = this.id ? $(this) : $(this).parents('[id]:first'),
|
|
|
+ prev = p.prevAll('.'+clSelected+':first'),
|
|
|
+ next = p.nextAll('.'+clSelected+':first'),
|
|
|
+ pl = prev.length,
|
|
|
+ nl = next.length,
|
|
|
+ sib;
|
|
|
+
|
|
|
+ e.stopImmediatePropagation();
|
|
|
+
|
|
|
+ if (e.shiftKey && (pl || nl)) {
|
|
|
+ sib = pl ? p.prevUntil('#'+prev.attr('id')) : p.nextUntil('#'+next.attr('id'));
|
|
|
+ sib.add(p).trigger(evtSelect);
|
|
|
+ } else if (e.ctrlKey || e.metaKey) {
|
|
|
+ p.trigger(p.is('.'+clSelected) ? evtUnselect : evtSelect);
|
|
|
+ } else {
|
|
|
+ if ($(this).data('touching') && p.is('.'+clSelected)) {
|
|
|
+ $(this).data('touching', null);
|
|
|
+ fm.dblclick({file : this.id});
|
|
|
+ unselectAll();
|
|
|
+ } else {
|
|
|
+ unselectAll();
|
|
|
+ p.trigger(evtSelect);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ trigger();
|
|
|
+ })
|
|
|
+ // call fm.open()
|
|
|
+ .delegate(fileSelector, 'dblclick.'+fm.namespace, function(e) {
|
|
|
+ fm.dblclick({file : this.id});
|
|
|
+ })
|
|
|
+ // for touch device
|
|
|
+ .delegate(fileSelector, 'touchstart.'+fm.namespace, function(e) {
|
|
|
+ $(this).data('touching', true);
|
|
|
+ var p = this.id ? $(this) : $(this).parents('[id]:first'),
|
|
|
+ sel = p.prevAll('.'+clSelected+':first').length +
|
|
|
+ p.nextAll('.'+clSelected+':first').length;
|
|
|
+ $(this).data('longtap', setTimeout(function(){
|
|
|
+ // long tap
|
|
|
+ p.trigger(p.is('.'+clSelected) ? evtUnselect : evtSelect);
|
|
|
+ trigger();
|
|
|
+ if (sel == 0 && p.is('.'+clSelected)) {
|
|
|
+ p.trigger('click');
|
|
|
+ trigger();
|
|
|
+ }
|
|
|
+ }, 500));
|
|
|
+ })
|
|
|
+ .delegate(fileSelector, 'touchmove.'+fm.namespace+' touchend.'+fm.namespace, function(e) {
|
|
|
+ clearTimeout($(this).data('longtap'));
|
|
|
+ })
|
|
|
+ // attach draggable
|
|
|
+ .delegate(fileSelector, 'mouseenter.'+fm.namespace, function(e) {
|
|
|
+ var $this = $(this),
|
|
|
+ target = list ? $this : $this.children();
|
|
|
+
|
|
|
+ if (!$this.is('.'+clTmp) && !target.is('.'+clDraggable+',.'+clDisabled)) {
|
|
|
+ target.draggable(fm.draggable);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // add hover class to selected file
|
|
|
+ .delegate(fileSelector, evtSelect, function(e) {
|
|
|
+ var $this = $(this),
|
|
|
+ id = $this.attr('id');
|
|
|
+
|
|
|
+ if (!selectLock && !$this.is('.'+clDisabled)) {
|
|
|
+ $this.addClass(clSelected).children().addClass(clHover);
|
|
|
+ if ($.inArray(id, selectedFiles) === -1) {
|
|
|
+ selectedFiles.push(id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // remove hover class from unselected file
|
|
|
+ .delegate(fileSelector, evtUnselect, function(e) {
|
|
|
+ var $this = $(this),
|
|
|
+ id = $this.attr('id'),
|
|
|
+ ndx;
|
|
|
+
|
|
|
+ if (!selectLock) {
|
|
|
+ $(this).removeClass(clSelected).children().removeClass(clHover);
|
|
|
+ ndx = $.inArray(id, selectedFiles);
|
|
|
+ if (ndx !== -1) {
|
|
|
+ selectedFiles.splice(ndx, 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ })
|
|
|
+ // disable files wich removing or moving
|
|
|
+ .delegate(fileSelector, evtDisable, function() {
|
|
|
+ var $this = $(this).removeClass(clSelected).addClass(clDisabled),
|
|
|
+ target = (list ? $this : $this.children()).removeClass(clHover);
|
|
|
+
|
|
|
+ $this.is('.'+clDroppable) && $this.droppable('disable');
|
|
|
+ target.is('.'+clDraggable) && target.draggable('disable');
|
|
|
+ !list && target.removeClass(clDisabled);
|
|
|
+ })
|
|
|
+ // if any files was not removed/moved - unlock its
|
|
|
+ .delegate(fileSelector, evtEnable, function() {
|
|
|
+ var $this = $(this).removeClass(clDisabled),
|
|
|
+ target = list ? $this : $this.children();
|
|
|
+
|
|
|
+ $this.is('.'+clDroppable) && $this.droppable('enable');
|
|
|
+ target.is('.'+clDraggable) && target.draggable('enable');
|
|
|
+ })
|
|
|
+ .delegate(fileSelector, 'scrolltoview', function() {
|
|
|
+ scrollToView($(this));
|
|
|
+ })
|
|
|
+ .delegate(fileSelector, 'hover', function(e) {
|
|
|
+ fm.trigger('hover', {hash : $(this).attr('id'), type : e.type});
|
|
|
+ })
|
|
|
+ .bind('contextmenu.'+fm.namespace, function(e) {
|
|
|
+ var file = $(e.target).closest('.'+clFile);
|
|
|
+
|
|
|
+ if (file.length) {
|
|
|
+ e.stopPropagation();
|
|
|
+ e.preventDefault();
|
|
|
+ if (!file.is('.'+clDisabled)) {
|
|
|
+ if (!file.is('.'+clSelected)) {
|
|
|
+ // cwd.trigger('unselectall');
|
|
|
+ unselectAll();
|
|
|
+ file.trigger(evtSelect);
|
|
|
+ trigger();
|
|
|
+ }
|
|
|
+ fm.trigger('contextmenu', {
|
|
|
+ 'type' : 'files',
|
|
|
+ 'targets' : fm.selected(),
|
|
|
+ 'x' : e.clientX,
|
|
|
+ 'y' : e.clientY
|
|
|
+ });
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ // e.preventDefault();
|
|
|
+
|
|
|
+
|
|
|
+ })
|
|
|
+
|
|
|
+ // make files selectable
|
|
|
+ .selectable({
|
|
|
+ filter : fileSelector,
|
|
|
+ stop : trigger,
|
|
|
+ selected : function(e, ui) { $(ui.selected).trigger(evtSelect); },
|
|
|
+ unselected : function(e, ui) { $(ui.unselected).trigger(evtUnselect); }
|
|
|
+ })
|
|
|
+ // make cwd itself droppable for folders from nav panel
|
|
|
+ .droppable(droppable)
|
|
|
+ // prepend fake file/dir
|
|
|
+ .bind('create.'+fm.namespace, function(e, file) {
|
|
|
+ var parent = list ? cwd.find('tbody') : cwd,
|
|
|
+ p = parent.find('.elfinder-cwd-parent'),
|
|
|
+ file = $(itemhtml(file)).addClass(clTmp);
|
|
|
+
|
|
|
+ unselectAll();
|
|
|
+
|
|
|
+ if (p.length) {
|
|
|
+ p.after(file);
|
|
|
+ } else {
|
|
|
+ parent.prepend(file);
|
|
|
+ }
|
|
|
+
|
|
|
+ cwd.scrollTop(0);
|
|
|
+ })
|
|
|
+ // unselect all selected files
|
|
|
+ .bind('unselectall', unselectAll)
|
|
|
+ .bind('selectfile', function(e, id) {
|
|
|
+ cwd.find('#'+id).trigger(evtSelect);
|
|
|
+ trigger();
|
|
|
+ }),
|
|
|
+ wrapper = $('<div class="elfinder-cwd-wrapper"/>')
|
|
|
+ .bind('contextmenu', function(e) {
|
|
|
+ e.preventDefault();
|
|
|
+ fm.trigger('contextmenu', {
|
|
|
+ 'type' : 'cwd',
|
|
|
+ 'targets' : [fm.cwd().hash],
|
|
|
+ 'x' : e.clientX,
|
|
|
+ 'y' : e.clientY
|
|
|
+ });
|
|
|
+
|
|
|
+ }),
|
|
|
+
|
|
|
+ resize = function() {
|
|
|
+ var h = 0;
|
|
|
+
|
|
|
+ wrapper.siblings('.elfinder-panel:visible').each(function() {
|
|
|
+ h += $(this).outerHeight(true);
|
|
|
+ });
|
|
|
+
|
|
|
+ wrapper.height(wz.height() - h);
|
|
|
+ },
|
|
|
+
|
|
|
+ // elfinder node
|
|
|
+ parent = $(this).parent().resize(resize),
|
|
|
+ // workzone node
|
|
|
+ wz = parent.children('.elfinder-workzone').append(wrapper.append(this))
|
|
|
+ ;
|
|
|
+
|
|
|
+
|
|
|
+ if (fm.dragUpload) {
|
|
|
+ wrapper[0].addEventListener('dragenter', function(e) {
|
|
|
+ e.preventDefault();
|
|
|
+ e.stopPropagation();
|
|
|
+
|
|
|
+ wrapper.addClass(clDropActive);
|
|
|
+ }, false);
|
|
|
+
|
|
|
+ wrapper[0].addEventListener('dragleave', function(e) {
|
|
|
+ e.preventDefault();
|
|
|
+ e.stopPropagation();
|
|
|
+ e.target == cwd[0] && wrapper.removeClass(clDropActive);
|
|
|
+ }, false);
|
|
|
+
|
|
|
+ wrapper[0].addEventListener('dragover', function(e) {
|
|
|
+ e.preventDefault();
|
|
|
+ e.stopPropagation();
|
|
|
+ }, false);
|
|
|
+
|
|
|
+ wrapper[0].addEventListener('drop', function(e) {
|
|
|
+ e.preventDefault();
|
|
|
+ wrapper.removeClass(clDropActive);
|
|
|
+ var file = false;
|
|
|
+ var type = '';
|
|
|
+ if (e.dataTransfer.getData('text/html')) {
|
|
|
+ file = [ e.dataTransfer.getData('text/html') ];
|
|
|
+ type = 'html';
|
|
|
+ } else if (e.dataTransfer.getData('text')) {
|
|
|
+ file = [ e.dataTransfer.getData('text') ];
|
|
|
+ type = 'text';
|
|
|
+ } else if (e.dataTransfer && e.dataTransfer.items && e.dataTransfer.items.length) {
|
|
|
+ file = e.dataTransfer;
|
|
|
+ type = 'data';
|
|
|
+ } else if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length) {
|
|
|
+ file = e.dataTransfer.files;
|
|
|
+ type = 'files';
|
|
|
+ }
|
|
|
+ if (file) {
|
|
|
+ fm.exec('upload', {files : file, type : type});
|
|
|
+ }
|
|
|
+ }, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ fm
|
|
|
+ .bind('open', function(e) {
|
|
|
+ content(e.data.files);
|
|
|
+ })
|
|
|
+ .bind('search', function(e) {
|
|
|
+ lastSearch = e.data.files;
|
|
|
+ content(lastSearch, true);
|
|
|
+ })
|
|
|
+ .bind('searchend', function() {
|
|
|
+ lastSearch = [];
|
|
|
+ if (query) {
|
|
|
+ query = '';
|
|
|
+ content(fm.files());
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .bind('searchstart', function(e) {
|
|
|
+ query = e.data.query;
|
|
|
+ })
|
|
|
+ .bind('sortchange', function() {
|
|
|
+ content(query ? lastSearch : fm.files(), !!query);
|
|
|
+ })
|
|
|
+ .bind('viewchange', function() {
|
|
|
+ var sel = fm.selected(),
|
|
|
+ l = fm.storage('view') == 'list';
|
|
|
+
|
|
|
+ if (l != list) {
|
|
|
+ list = l;
|
|
|
+ content(fm.files());
|
|
|
+
|
|
|
+ $.each(sel, function(i, h) {
|
|
|
+ selectFile(h);
|
|
|
+ });
|
|
|
+ trigger();
|
|
|
+ }
|
|
|
+ resize();
|
|
|
+ })
|
|
|
+ .add(function(e) {
|
|
|
+ var phash = fm.cwd().hash,
|
|
|
+ files = query
|
|
|
+ ? $.map(e.data.added || [], function(f) { return f.name.indexOf(query) === -1 ? null : f ;})
|
|
|
+ : $.map(e.data.added || [], function(f) { return f.phash == phash ? f : null; })
|
|
|
+ ;
|
|
|
+ add(files);
|
|
|
+ })
|
|
|
+ .change(function(e) {
|
|
|
+ var phash = fm.cwd().hash,
|
|
|
+ sel = fm.selected(),
|
|
|
+ files;
|
|
|
+
|
|
|
+ if (query) {
|
|
|
+ $.each(e.data.changed || [], function(i, file) {
|
|
|
+ remove([file.hash]);
|
|
|
+ if (file.name.indexOf(query) !== -1) {
|
|
|
+ add([file]);
|
|
|
+ $.inArray(file.hash, sel) !== -1 && selectFile(file.hash);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ $.each($.map(e.data.changed || [], function(f) { return f.phash == phash ? f : null; }), function(i, file) {
|
|
|
+ remove([file.hash]);
|
|
|
+ add([file]);
|
|
|
+ $.inArray(file.hash, sel) !== -1 && selectFile(file.hash);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ trigger();
|
|
|
+ })
|
|
|
+ .remove(function(e) {
|
|
|
+ remove(e.data.removed || []);
|
|
|
+ trigger();
|
|
|
+ })
|
|
|
+ // fix cwd height if it less then wrapper
|
|
|
+ .bind('open add search searchend', function() {
|
|
|
+ cwd.css('height', 'auto');
|
|
|
+
|
|
|
+ if (cwd.outerHeight(true) < wrapper.height()) {
|
|
|
+ cwd.height(wrapper.height() - (cwd.outerHeight(true) - cwd.height()) - 2);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // select dragged file if no selected, disable selectable
|
|
|
+ .dragstart(function(e) {
|
|
|
+ var target = $(e.data.target),
|
|
|
+ oe = e.data.originalEvent;
|
|
|
+
|
|
|
+ if (target.is(fileSelector)) {
|
|
|
+
|
|
|
+ if (!target.is('.'+clSelected)) {
|
|
|
+ !(oe.ctrlKey || oe.metaKey || oe.shiftKey) && unselectAll();
|
|
|
+ target.trigger(evtSelect);
|
|
|
+ trigger();
|
|
|
+ }
|
|
|
+ cwd.droppable('disable');
|
|
|
+ }
|
|
|
+
|
|
|
+ cwd.selectable('disable').removeClass(clDisabled);
|
|
|
+ selectLock = true;
|
|
|
+ })
|
|
|
+ // enable selectable
|
|
|
+ .dragstop(function() {
|
|
|
+ cwd.selectable('enable').droppable('enable');
|
|
|
+ selectLock = false;
|
|
|
+ })
|
|
|
+ .bind('lockfiles unlockfiles', function(e) {
|
|
|
+ var event = e.type == 'lockfiles' ? evtDisable : evtEnable,
|
|
|
+ files = e.data.files || [],
|
|
|
+ l = files.length;
|
|
|
+
|
|
|
+ while (l--) {
|
|
|
+ cwd.find('#'+files[l]).trigger(event);
|
|
|
+ }
|
|
|
+ trigger();
|
|
|
+ })
|
|
|
+ // select new files after some actions
|
|
|
+ .bind('mkdir mkfile duplicate upload rename archive extract', function(e) {
|
|
|
+ var phash = fm.cwd().hash, files;
|
|
|
+
|
|
|
+ unselectAll();
|
|
|
+
|
|
|
+ $.each(e.data.added || [], function(i, file) {
|
|
|
+ file && file.phash == phash && selectFile(file.hash);
|
|
|
+ });
|
|
|
+ trigger();
|
|
|
+ })
|
|
|
+ .shortcut({
|
|
|
+ pattern :'ctrl+a',
|
|
|
+ description : 'selectall',
|
|
|
+ callback : selectAll
|
|
|
+ })
|
|
|
+ .shortcut({
|
|
|
+ pattern : 'left right up down shift+left shift+right shift+up shift+down',
|
|
|
+ description : 'selectfiles',
|
|
|
+ type : 'keydown' , //fm.UA.Firefox || fm.UA.Opera ? 'keypress' : 'keydown',
|
|
|
+ callback : function(e) { select(e.keyCode, e.shiftKey); }
|
|
|
+ })
|
|
|
+ .shortcut({
|
|
|
+ pattern : 'home',
|
|
|
+ description : 'selectffile',
|
|
|
+ callback : function(e) {
|
|
|
+ unselectAll();
|
|
|
+ scrollToView(cwd.find('[id]:first').trigger(evtSelect));
|
|
|
+ trigger();
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .shortcut({
|
|
|
+ pattern : 'end',
|
|
|
+ description : 'selectlfile',
|
|
|
+ callback : function(e) {
|
|
|
+ unselectAll();
|
|
|
+ scrollToView(cwd.find('[id]:last').trigger(evtSelect)) ;
|
|
|
+ trigger();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+ // fm.timeEnd('cwdLoad')
|
|
|
+
|
|
|
+ return this;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/dialog.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder dialog
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.elfinderdialog = function(opts) {
|
|
|
+ var dialog;
|
|
|
+
|
|
|
+ if (typeof(opts) == 'string' && (dialog = this.closest('.ui-dialog')).length) {
|
|
|
+ if (opts == 'open') {
|
|
|
+ dialog.css('display') == 'none' && dialog.fadeIn(120, function() {
|
|
|
+ dialog.trigger('open');
|
|
|
+ });
|
|
|
+ } else if (opts == 'close') {
|
|
|
+ dialog.css('display') != 'none' && dialog.hide().trigger('close');
|
|
|
+ } else if (opts == 'destroy') {
|
|
|
+ dialog.hide().remove();
|
|
|
+ } else if (opts == 'toTop') {
|
|
|
+ dialog.trigger('totop');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ opts = $.extend({}, $.fn.elfinderdialog.defaults, opts);
|
|
|
+
|
|
|
+ this.filter(':not(.ui-dialog-content)').each(function() {
|
|
|
+ var self = $(this).addClass('ui-dialog-content ui-widget-content'),
|
|
|
+ parent = self.parent(),
|
|
|
+ clactive = 'elfinder-dialog-active',
|
|
|
+ cldialog = 'elfinder-dialog',
|
|
|
+ clnotify = 'elfinder-dialog-notify',
|
|
|
+ clhover = 'ui-state-hover',
|
|
|
+ id = parseInt(Math.random()*1000000),
|
|
|
+ overlay = parent.children('.elfinder-overlay'),
|
|
|
+ buttonset = $('<div class="ui-dialog-buttonset"/>'),
|
|
|
+ buttonpane = $('<div class=" ui-helper-clearfix ui-dialog-buttonpane ui-widget-content"/>')
|
|
|
+ .append(buttonset),
|
|
|
+
|
|
|
+ dialog = $('<div class="ui-dialog ui-widget ui-widget-content ui-corner-all ui-draggable std42-dialog '+cldialog+' '+opts.cssClass+'"/>')
|
|
|
+ .hide()
|
|
|
+ .append(self)
|
|
|
+ .appendTo(parent)
|
|
|
+ .draggable({ handle : '.ui-dialog-titlebar',
|
|
|
+ containment : 'document' })
|
|
|
+ .css({
|
|
|
+ width : opts.width,
|
|
|
+ height : opts.height
|
|
|
+ })
|
|
|
+ .mousedown(function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+
|
|
|
+ $(document).mousedown();
|
|
|
+
|
|
|
+ if (!dialog.is('.'+clactive)) {
|
|
|
+ parent.find('.'+cldialog+':visible').removeClass(clactive);
|
|
|
+ dialog.addClass(clactive).zIndex(maxZIndex() + 1);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .bind('open', function() {
|
|
|
+ dialog.trigger('totop');
|
|
|
+ typeof(opts.open) == 'function' && $.proxy(opts.open, self[0])();
|
|
|
+
|
|
|
+ if (!dialog.is('.'+clnotify)) {
|
|
|
+
|
|
|
+ parent.find('.'+cldialog+':visible').not('.'+clnotify).each(function() {
|
|
|
+ var d = $(this),
|
|
|
+ top = parseInt(d.css('top')),
|
|
|
+ left = parseInt(d.css('left')),
|
|
|
+ _top = parseInt(dialog.css('top')),
|
|
|
+ _left = parseInt(dialog.css('left'))
|
|
|
+ ;
|
|
|
+
|
|
|
+ if (d[0] != dialog[0] && (top == _top || left == _left)) {
|
|
|
+ dialog.css({
|
|
|
+ top : (top+10)+'px',
|
|
|
+ left : (left+10)+'px'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .bind('close', function() {
|
|
|
+ var dialogs = parent.find('.elfinder-dialog:visible'),
|
|
|
+ z = maxZIndex();
|
|
|
+
|
|
|
+ $(this).data('modal') && overlay.elfinderoverlay('hide');
|
|
|
+
|
|
|
+ // get focus to next dialog
|
|
|
+ if (dialogs.length) {
|
|
|
+ dialogs.each(function() {
|
|
|
+ var d = $(this);
|
|
|
+ if (d.zIndex() >= z) {
|
|
|
+ d.trigger('totop');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // return focus to parent
|
|
|
+ setTimeout(function() {
|
|
|
+ parent.mousedown().click();
|
|
|
+ }, 10);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if (typeof(opts.close) == 'function') {
|
|
|
+ $.proxy(opts.close, self[0])();
|
|
|
+ } else if (opts.destroyOnClose) {
|
|
|
+ dialog.hide().remove();
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .bind('totop', function() {
|
|
|
+ $(this).mousedown().find('.ui-button:first').focus().end().find(':text:first').focus();
|
|
|
+ $(this).data('modal') && overlay.elfinderoverlay('show');
|
|
|
+ overlay.zIndex($(this).zIndex());
|
|
|
+ })
|
|
|
+ .data({modal: opts.modal}),
|
|
|
+ maxZIndex = function() {
|
|
|
+ var z = parent.zIndex() + 10;
|
|
|
+ parent.find('.'+cldialog+':visible').each(function() {
|
|
|
+ var _z;
|
|
|
+ if (this != dialog[0]) {
|
|
|
+ _z = $(this).zIndex();
|
|
|
+ if (_z > z) {
|
|
|
+ z = _z;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return z;
|
|
|
+ },
|
|
|
+ top
|
|
|
+ ;
|
|
|
+
|
|
|
+ if (!opts.position) {
|
|
|
+ top = parseInt((parent.height() - dialog.outerHeight())/2 - 42);
|
|
|
+ opts.position = {
|
|
|
+ top : (top > 0 ? top : 0)+'px',
|
|
|
+ left : parseInt((parent.width() - dialog.outerWidth())/2)+'px'
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ dialog.css(opts.position);
|
|
|
+
|
|
|
+ if (opts.closeOnEscape) {
|
|
|
+ $(document).bind('keyup.'+id, function(e) {
|
|
|
+ if (e.keyCode == $.ui.keyCode.ESCAPE && dialog.is('.'+clactive)) {
|
|
|
+ self.elfinderdialog('close');
|
|
|
+ $(document).unbind('keyup.'+id);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ dialog.prepend(
|
|
|
+ $('<div class="ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix">'+opts.title+'</div>')
|
|
|
+ .prepend($('<a href="#" class="ui-dialog-titlebar-close ui-corner-all"><span class="ui-icon ui-icon-closethick"/></a>')
|
|
|
+ .mousedown(function(e) {
|
|
|
+ e.preventDefault();
|
|
|
+ self.elfinderdialog('close');
|
|
|
+ }))
|
|
|
+
|
|
|
+ );
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ $.each(opts.buttons, function(name, cb) {
|
|
|
+ var button = $('<button type="button" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"><span class="ui-button-text">'+name+'</span></button>')
|
|
|
+ .click($.proxy(cb, self[0]))
|
|
|
+ .hover(function(e) { $(this)[e.type == 'mouseenter' ? 'focus' : 'blur']() })
|
|
|
+ .focus(function() { $(this).addClass(clhover) })
|
|
|
+ .blur(function() { $(this).removeClass(clhover) })
|
|
|
+ .keydown(function(e) {
|
|
|
+ var next;
|
|
|
+
|
|
|
+ if (e.keyCode == $.ui.keyCode.ENTER) {
|
|
|
+ $(this).click();
|
|
|
+ } else if (e.keyCode == $.ui.keyCode.TAB) {
|
|
|
+ next = $(this).next('.ui-button');
|
|
|
+ next.length ? next.focus() : $(this).parent().children('.ui-button:first').focus()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ buttonset.append(button);
|
|
|
+ })
|
|
|
+
|
|
|
+ buttonset.children().length && dialog.append(buttonpane);
|
|
|
+ if (opts.resizable && $.fn.resizable) {
|
|
|
+ dialog.resizable({
|
|
|
+ minWidth : opts.minWidth,
|
|
|
+ minHeight : opts.minHeight,
|
|
|
+ alsoResize : this
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ typeof(opts.create) == 'function' && $.proxy(opts.create, this)();
|
|
|
+
|
|
|
+ opts.autoOpen && self.elfinderdialog('open');
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+ return this;
|
|
|
+}
|
|
|
+
|
|
|
+$.fn.elfinderdialog.defaults = {
|
|
|
+ cssClass : '',
|
|
|
+ title : '',
|
|
|
+ modal : false,
|
|
|
+ resizable : true,
|
|
|
+ autoOpen : true,
|
|
|
+ closeOnEscape : true,
|
|
|
+ destroyOnClose : false,
|
|
|
+ buttons : {},
|
|
|
+ position : null,
|
|
|
+ width : 320,
|
|
|
+ height : 'auto',
|
|
|
+ minWidth : 200,
|
|
|
+ minHeight : 110
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/navbar.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elfindernav - elFinder container for diretories tree and places
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.elfindernavbar = function(fm, opts) {
|
|
|
+
|
|
|
+ this.not('.elfinder-navbar').each(function() {
|
|
|
+ var nav = $(this).addClass('ui-state-default elfinder-navbar'),
|
|
|
+ parent = nav.parent()
|
|
|
+ .resize(function() {
|
|
|
+ nav.height(wz.height() - delta);
|
|
|
+ }),
|
|
|
+ wz = parent.children('.elfinder-workzone').append(nav),
|
|
|
+ delta = nav.outerHeight() - nav.height(),
|
|
|
+ ltr = fm.direction == 'ltr',
|
|
|
+ handle;
|
|
|
+
|
|
|
+
|
|
|
+ if ($.fn.resizable) {
|
|
|
+ handle = nav.resizable({
|
|
|
+ handles : ltr ? 'e' : 'w',
|
|
|
+ minWidth : opts.minWidth || 150,
|
|
|
+ maxWidth : opts.maxWidth || 500
|
|
|
+ })
|
|
|
+ .bind('resize scroll', function() {
|
|
|
+ var offset = (fm.UA.Opera && nav.scrollLeft())? 20 : 2;
|
|
|
+ handle.css({
|
|
|
+ top : parseInt(nav.scrollTop())+'px',
|
|
|
+ left : ltr ? 'auto' : parseInt(nav.scrollLeft() + offset),
|
|
|
+ right: ltr ? parseInt(nav.scrollLeft() - offset) * -1 : 'auto'
|
|
|
+ });
|
|
|
+ })
|
|
|
+ .find('.ui-resizable-handle').zIndex(nav.zIndex() + 10);
|
|
|
+
|
|
|
+ if (!ltr) {
|
|
|
+ nav.resize(function() {
|
|
|
+ nav.css('left', null).css('right', 0);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ fm.one('open', function() {
|
|
|
+ setTimeout(function() {
|
|
|
+ nav.trigger('resize');
|
|
|
+ }, 150);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return this;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/overlay.js
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+$.fn.elfinderoverlay = function(opts) {
|
|
|
+
|
|
|
+ this.filter(':not(.elfinder-overlay)').each(function() {
|
|
|
+ opts = $.extend({}, opts);
|
|
|
+ $(this).addClass('ui-widget-overlay elfinder-overlay')
|
|
|
+ .hide()
|
|
|
+ .mousedown(function(e) {
|
|
|
+ e.preventDefault();
|
|
|
+ e.stopPropagation();
|
|
|
+ })
|
|
|
+ .data({
|
|
|
+ cnt : 0,
|
|
|
+ show : typeof(opts.show) == 'function' ? opts.show : function() { },
|
|
|
+ hide : typeof(opts.hide) == 'function' ? opts.hide : function() { }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ if (opts == 'show') {
|
|
|
+ var o = this.eq(0),
|
|
|
+ cnt = o.data('cnt') + 1,
|
|
|
+ show = o.data('show');
|
|
|
+
|
|
|
+ o.data('cnt', cnt);
|
|
|
+
|
|
|
+ if (o.is(':hidden')) {
|
|
|
+ o.zIndex(o.parent().zIndex()+1);
|
|
|
+ o.show();
|
|
|
+ show();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (opts == 'hide') {
|
|
|
+ var o = this.eq(0),
|
|
|
+ cnt = o.data('cnt') - 1,
|
|
|
+ hide = o.data('hide');
|
|
|
+
|
|
|
+ o.data('cnt', cnt);
|
|
|
+
|
|
|
+ if (cnt == 0 && o.is(':visible')) {
|
|
|
+ o.hide();
|
|
|
+ hide();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return this;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/panel.js
|
|
|
+ */
|
|
|
+
|
|
|
+$.fn.elfinderpanel = function(fm) {
|
|
|
+
|
|
|
+ return this.each(function() {
|
|
|
+ var panel = $(this).addClass('elfinder-panel ui-state-default ui-corner-all'),
|
|
|
+ margin = 'margin-'+(fm.direction == 'ltr' ? 'left' : 'right');
|
|
|
+
|
|
|
+ fm.one('load', function(e) {
|
|
|
+ var navbar = fm.getUI('navbar');
|
|
|
+
|
|
|
+ panel.css(margin, parseInt(navbar.outerWidth(true)));
|
|
|
+ navbar.bind('resize', function() {
|
|
|
+ panel.is(':visible') && panel.css(margin, parseInt(navbar.outerWidth(true)))
|
|
|
+ })
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/path.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder ui
|
|
|
+ * Display current folder path in statusbar.
|
|
|
+ * Click on folder name in path - open folder
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.elfinderpath = function(fm) {
|
|
|
+ return this.each(function() {
|
|
|
+ var path = $(this).addClass('elfinder-path').html(' ')
|
|
|
+ .delegate('a', 'click', function(e) {
|
|
|
+ var hash = $(this).attr('href').substr(1);
|
|
|
+
|
|
|
+ e.preventDefault();
|
|
|
+ hash != fm.cwd().hash && fm.exec('open', hash);
|
|
|
+ })
|
|
|
+ .prependTo(fm.getUI('statusbar').show())
|
|
|
+
|
|
|
+ fm.bind('open searchend', function() {
|
|
|
+ var dirs = [];
|
|
|
+
|
|
|
+ $.each(fm.parents(fm.cwd().hash), function(i, hash) {
|
|
|
+ dirs.push('<a href="#'+hash+'">'+fm.escape(fm.file(hash).name)+'</a>');
|
|
|
+ });
|
|
|
+
|
|
|
+ path.html(dirs.join(fm.option('separator')));
|
|
|
+ })
|
|
|
+ .bind('search', function() {
|
|
|
+ path.html(fm.i18n('searcresult'));
|
|
|
+ });
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/places.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder places/favorites ui
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.elfinderplaces = function(fm, opts) {
|
|
|
+ return this.each(function() {
|
|
|
+ var dirs = [],
|
|
|
+ c = 'class',
|
|
|
+ navdir = fm.res(c, 'navdir'),
|
|
|
+ collapsed = fm.res(c, 'navcollapse'),
|
|
|
+ expanded = fm.res(c, 'navexpand'),
|
|
|
+ hover = fm.res(c, 'hover'),
|
|
|
+ clroot = fm.res(c, 'treeroot'),
|
|
|
+ tpl = fm.res('tpl', 'navdir'),
|
|
|
+ ptpl = fm.res('tpl', 'perms'),
|
|
|
+ spinner = $(fm.res('tpl', 'navspinner')),
|
|
|
+ /**
|
|
|
+ * Convert places dir node into dir hash
|
|
|
+ *
|
|
|
+ * @param String directory id
|
|
|
+ * @return String
|
|
|
+ **/
|
|
|
+ id2hash = function(id) { return id.substr(6); },
|
|
|
+ /**
|
|
|
+ * Convert places dir node into dir hash
|
|
|
+ *
|
|
|
+ * @param String directory id
|
|
|
+ * @return String
|
|
|
+ **/
|
|
|
+ hash2id = function(hash) { return 'place-'+hash; },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Save current places state
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ save = function() { fm.storage('places', dirs.join(',')); },
|
|
|
+ /**
|
|
|
+ * Return node for given dir object
|
|
|
+ *
|
|
|
+ * @param Object directory object
|
|
|
+ * @return jQuery
|
|
|
+ **/
|
|
|
+ create = function(dir) {
|
|
|
+ return $(tpl.replace(/\{id\}/, hash2id(dir.hash))
|
|
|
+ .replace(/\{name\}/, fm.escape(dir.name))
|
|
|
+ .replace(/\{cssclass\}/, fm.perms2class(dir))
|
|
|
+ .replace(/\{permissions\}/, !dir.read || !dir.write ? ptpl : '')
|
|
|
+ .replace(/\{symlink\}/, ''));
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * Add new node into places
|
|
|
+ *
|
|
|
+ * @param Object directory object
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ add = function(dir) {
|
|
|
+ var node = create(dir);
|
|
|
+
|
|
|
+ if (subtree.children().length) {
|
|
|
+ $.each(subtree.children(), function() {
|
|
|
+ var current = $(this);
|
|
|
+
|
|
|
+ if (dir.name.localeCompare(current.children('.'+navdir).text()) < 0) {
|
|
|
+ return !node.insertBefore(current);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ dirs.push(dir.hash);
|
|
|
+ !node.parent().length && subtree.append(node);
|
|
|
+ root.addClass(collapsed);
|
|
|
+ node.draggable({
|
|
|
+ appendTo : 'body',
|
|
|
+ revert : false,
|
|
|
+ helper : function() {
|
|
|
+ var dir = $(this);
|
|
|
+
|
|
|
+ dir.children().removeClass('ui-state-hover');
|
|
|
+
|
|
|
+ return $('<div class="elfinder-place-drag elfinder-'+fm.direction+'"/>')
|
|
|
+ .append(dir.clone())
|
|
|
+ .data('hash', id2hash(dir.children(':first').attr('id')));
|
|
|
+
|
|
|
+ },
|
|
|
+ start : function() { $(this).hide(); },
|
|
|
+ stop : function(e, ui) {
|
|
|
+ var top = places.offset().top,
|
|
|
+ left = places.offset().left,
|
|
|
+ width = places.width(),
|
|
|
+ height = places.height(),
|
|
|
+ x = e.clientX,
|
|
|
+ y = e.clientY;
|
|
|
+
|
|
|
+ if (x > left && x < left+width && y > top && y < y+height) {
|
|
|
+ $(this).show();
|
|
|
+ } else {
|
|
|
+ remove(ui.helper.data('hash'));
|
|
|
+ save();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * Remove dir from places
|
|
|
+ *
|
|
|
+ * @param String directory id
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ remove = function(hash) {
|
|
|
+ var ndx = $.inArray(hash, dirs);
|
|
|
+
|
|
|
+ if (ndx !== -1) {
|
|
|
+ dirs.splice(ndx, 1);
|
|
|
+ subtree.find('#'+hash2id(hash)).parent().remove();
|
|
|
+ !subtree.children().length && root.removeClass(collapsed+' '+expanded);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * Remove all dir from places
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ clear = function() {
|
|
|
+ subtree.empty();
|
|
|
+ root.removeClass(collapsed+' '+expanded);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * Node - wrapper for places root
|
|
|
+ *
|
|
|
+ * @type jQuery
|
|
|
+ **/
|
|
|
+ wrapper = create({
|
|
|
+ hash : 'root-'+fm.namespace,
|
|
|
+ name : fm.i18n(opts.name, 'places'),
|
|
|
+ read : true,
|
|
|
+ write : true
|
|
|
+ }),
|
|
|
+ /**
|
|
|
+ * Places root node
|
|
|
+ *
|
|
|
+ * @type jQuery
|
|
|
+ **/
|
|
|
+ root = wrapper.children('.'+navdir)
|
|
|
+ .addClass(clroot)
|
|
|
+ .click(function() {
|
|
|
+ if (root.is('.'+collapsed)) {
|
|
|
+ places.toggleClass(expanded);
|
|
|
+ subtree.slideToggle();
|
|
|
+ fm.storage('placesState', places.is('.'+expanded)? 1 : 0);
|
|
|
+ }
|
|
|
+ }),
|
|
|
+ /**
|
|
|
+ * Container for dirs
|
|
|
+ *
|
|
|
+ * @type jQuery
|
|
|
+ **/
|
|
|
+ subtree = wrapper.children('.'+fm.res(c, 'navsubtree')),
|
|
|
+ /**
|
|
|
+ * Main places container
|
|
|
+ *
|
|
|
+ * @type jQuery
|
|
|
+ **/
|
|
|
+ places = $(this).addClass(fm.res(c, 'tree')+' elfinder-places ui-corner-all')
|
|
|
+ .hide()
|
|
|
+ .append(wrapper)
|
|
|
+ .appendTo(fm.getUI('navbar'))
|
|
|
+ .delegate('.'+navdir, 'hover', function() {
|
|
|
+ $(this).toggleClass('ui-state-hover');
|
|
|
+ })
|
|
|
+ .delegate('.'+navdir, 'click', function(e) {
|
|
|
+ fm.exec('open', $(this).attr('id').substr(6));
|
|
|
+ })
|
|
|
+ .delegate('.'+navdir+':not(.'+clroot+')', 'contextmenu', function(e) {
|
|
|
+ var hash = $(this).attr('id').substr(6);
|
|
|
+
|
|
|
+ e.preventDefault();
|
|
|
+
|
|
|
+ fm.trigger('contextmenu', {
|
|
|
+ raw : [{
|
|
|
+ label : fm.i18n('rmFromPlaces'),
|
|
|
+ icon : 'rm',
|
|
|
+ callback : function() { remove(hash); save(); }
|
|
|
+ }],
|
|
|
+ 'x' : e.clientX,
|
|
|
+ 'y' : e.clientY
|
|
|
+ })
|
|
|
+
|
|
|
+ })
|
|
|
+ .droppable({
|
|
|
+ tolerance : 'pointer',
|
|
|
+ accept : '.elfinder-cwd-file-wrapper,.elfinder-tree-dir,.elfinder-cwd-file',
|
|
|
+ hoverClass : fm.res('class', 'adroppable'),
|
|
|
+ drop : function(e, ui) {
|
|
|
+ var resolve = true;
|
|
|
+
|
|
|
+ $.each(ui.helper.data('files'), function(i, hash) {
|
|
|
+ var dir = fm.file(hash);
|
|
|
+
|
|
|
+ if (dir && dir.mime == 'directory' && $.inArray(dir.hash, dirs) === -1) {
|
|
|
+ add(dir);
|
|
|
+ } else {
|
|
|
+ resolve = false;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ save();
|
|
|
+ resolve && ui.helper.hide();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ // on fm load - show places and load files from backend
|
|
|
+ fm.one('load', function() {
|
|
|
+ if (fm.oldAPI) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ places.show().parent().show();
|
|
|
+
|
|
|
+ dirs = $.map(fm.storage('places').split(','), function(hash) { return hash || null});
|
|
|
+
|
|
|
+ if (dirs.length) {
|
|
|
+ root.prepend(spinner);
|
|
|
+
|
|
|
+ fm.request({
|
|
|
+ data : {cmd : 'info', targets : dirs},
|
|
|
+ preventDefault : true
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ dirs = [];
|
|
|
+ $.each(data.files, function(i, file) {
|
|
|
+ file.mime == 'directory' && add(file);
|
|
|
+ });
|
|
|
+ save();
|
|
|
+ if (fm.storage('placesState') > 0) {
|
|
|
+ root.click();
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .always(function() {
|
|
|
+ spinner.remove();
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ fm.remove(function(e) {
|
|
|
+ $.each(e.data.removed, function(i, hash) {
|
|
|
+ remove(hash);
|
|
|
+ });
|
|
|
+ save();
|
|
|
+ })
|
|
|
+ .change(function(e) {
|
|
|
+ $.each(e.data.changed, function(i, file) {
|
|
|
+ if ($.inArray(file.hash, dirs) !== -1) {
|
|
|
+ remove(file.hash);
|
|
|
+ file.mime == 'directory' && add(file);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ save();
|
|
|
+ })
|
|
|
+ .bind('sync', function() {
|
|
|
+ if (dirs.length) {
|
|
|
+ root.prepend(spinner);
|
|
|
+
|
|
|
+ fm.request({
|
|
|
+ data : {cmd : 'info', targets : dirs},
|
|
|
+ preventDefault : true
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ $.each(data.files || [], function(i, file) {
|
|
|
+ if ($.inArray(file.hash, dirs) === -1) {
|
|
|
+ remove(file.hash);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ save();
|
|
|
+ })
|
|
|
+ .always(function() {
|
|
|
+ spinner.remove();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ })
|
|
|
+
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/searchbutton.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder toolbar search button widget.
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.elfindersearchbutton = function(cmd) {
|
|
|
+ return this.each(function() {
|
|
|
+ var result = false,
|
|
|
+ button = $(this).hide().addClass('ui-widget-content elfinder-button '+cmd.fm.res('class', 'searchbtn')+''),
|
|
|
+ search = function() {
|
|
|
+ var val = $.trim(input.val());
|
|
|
+ if (val) {
|
|
|
+ cmd.exec(val).done(function() {
|
|
|
+ result = true;
|
|
|
+ input.focus();
|
|
|
+ });
|
|
|
+
|
|
|
+ } else {
|
|
|
+ cmd.fm.trigger('searchend')
|
|
|
+ }
|
|
|
+ },
|
|
|
+ abort = function() {
|
|
|
+ input.val('');
|
|
|
+ if (result) {
|
|
|
+ result = false;
|
|
|
+ cmd.fm.trigger('searchend');
|
|
|
+ }
|
|
|
+ },
|
|
|
+ input = $('<input type="text" size="42"/>')
|
|
|
+ .appendTo(button)
|
|
|
+ // to avoid fm shortcuts on arrows
|
|
|
+ .keypress(function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+ })
|
|
|
+ .keydown(function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+
|
|
|
+ e.keyCode == 13 && search();
|
|
|
+
|
|
|
+ if (e.keyCode== 27) {
|
|
|
+ e.preventDefault();
|
|
|
+ abort();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ $('<span class="ui-icon ui-icon-search" title="'+cmd.title+'"/>')
|
|
|
+ .appendTo(button)
|
|
|
+ .click(search);
|
|
|
+
|
|
|
+ $('<span class="ui-icon ui-icon-close"/>')
|
|
|
+ .appendTo(button)
|
|
|
+ .click(abort)
|
|
|
+
|
|
|
+ // wait when button will be added to DOM
|
|
|
+ setTimeout(function() {
|
|
|
+ button.parent().detach();
|
|
|
+ cmd.fm.getUI('toolbar').prepend(button.show());
|
|
|
+ // position icons for ie7
|
|
|
+ if (cmd.fm.UA.ltIE7) {
|
|
|
+ var icon = button.children(cmd.fm.direction == 'ltr' ? '.ui-icon-close' : '.ui-icon-search');
|
|
|
+ icon.css({
|
|
|
+ right : '',
|
|
|
+ left : parseInt(button.width())-icon.outerWidth(true)
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }, 200);
|
|
|
+
|
|
|
+ cmd.fm
|
|
|
+ .error(function() {
|
|
|
+ input.unbind('keydown');
|
|
|
+ })
|
|
|
+ .select(function() {
|
|
|
+ input.blur();
|
|
|
+ })
|
|
|
+ .bind('searchend', function() {
|
|
|
+ input.val('');
|
|
|
+ })
|
|
|
+ .viewchange(abort)
|
|
|
+ .shortcut({
|
|
|
+ pattern : 'ctrl+f f3',
|
|
|
+ description : cmd.title,
|
|
|
+ callback : function() { input.select().focus(); }
|
|
|
+ });
|
|
|
+
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/sortbutton.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder toolbar button menu with sort variants.
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.elfindersortbutton = function(cmd) {
|
|
|
+
|
|
|
+ return this.each(function() {
|
|
|
+ var fm = cmd.fm,
|
|
|
+ name = cmd.name,
|
|
|
+ c = 'class',
|
|
|
+ disabled = fm.res(c, 'disabled'),
|
|
|
+ hover = fm.res(c, 'hover'),
|
|
|
+ item = 'elfinder-button-menu-item',
|
|
|
+ selected = item+'-selected',
|
|
|
+ asc = selected+'-asc',
|
|
|
+ desc = selected+'-desc',
|
|
|
+ button = $(this).addClass('ui-state-default elfinder-button elfinder-menubutton elfiner-button-'+name)
|
|
|
+ .attr('title', cmd.title)
|
|
|
+ .append('<span class="elfinder-button-icon elfinder-button-icon-'+name+'"/>')
|
|
|
+ .hover(function(e) { !button.is('.'+disabled) && button.toggleClass(hover); })
|
|
|
+ .click(function(e) {
|
|
|
+ if (!button.is('.'+disabled)) {
|
|
|
+ e.stopPropagation();
|
|
|
+ menu.is(':hidden') && cmd.fm.getUI().click();
|
|
|
+ menu.slideToggle(100);
|
|
|
+ }
|
|
|
+ }),
|
|
|
+ menu = $('<div class="ui-widget ui-widget-content elfinder-button-menu ui-corner-all"/>')
|
|
|
+ .hide()
|
|
|
+ .appendTo(button)
|
|
|
+ .zIndex(12+button.zIndex())
|
|
|
+ .delegate('.'+item, 'hover', function() { $(this).toggleClass(hover) })
|
|
|
+ .delegate('.'+item, 'click', function(e) {
|
|
|
+ e.preventDefault();
|
|
|
+ e.stopPropagation();
|
|
|
+ hide();
|
|
|
+ }),
|
|
|
+ update = function() {
|
|
|
+ menu.children(':not(:last)').removeClass(selected+' '+asc+' '+desc)
|
|
|
+ .filter('[rel="'+fm.sortType+'"]')
|
|
|
+ .addClass(selected+' '+(fm.sortOrder == 'asc' ? asc : desc));
|
|
|
+
|
|
|
+ menu.children(':last').toggleClass(selected, fm.sortStickFolders);
|
|
|
+ },
|
|
|
+ hide = function() { menu.hide(); };
|
|
|
+
|
|
|
+
|
|
|
+ $.each(fm.sortRules, function(name, value) {
|
|
|
+ menu.append($('<div class="'+item+'" rel="'+name+'"><span class="ui-icon ui-icon-arrowthick-1-n"/><span class="ui-icon ui-icon-arrowthick-1-s"/>'+fm.i18n('sort'+name)+'</div>').data('type', name));
|
|
|
+ });
|
|
|
+
|
|
|
+ menu.children().click(function(e) {
|
|
|
+ var type = $(this).attr('rel');
|
|
|
+
|
|
|
+ cmd.exec([], {
|
|
|
+ type : type,
|
|
|
+ order : type == fm.sortType ? fm.sortOrder == 'asc' ? 'desc' : 'asc' : fm.sortOrder,
|
|
|
+ stick : fm.sortStickFolders
|
|
|
+ });
|
|
|
+ })
|
|
|
+
|
|
|
+ $('<div class="'+item+' '+item+'-separated"><span class="ui-icon ui-icon-check"/>'+fm.i18n('sortFoldersFirst')+'</div>')
|
|
|
+ .appendTo(menu)
|
|
|
+ .click(function() {
|
|
|
+ cmd.exec([], {type : fm.sortType, order : fm.sortOrder, stick : !fm.sortStickFolders});
|
|
|
+ });
|
|
|
+
|
|
|
+ fm.bind('disable select', hide).getUI().click(hide);
|
|
|
+
|
|
|
+ fm.bind('sortchange', update)
|
|
|
+
|
|
|
+ if (menu.children().length > 1) {
|
|
|
+ cmd.change(function() {
|
|
|
+ button.toggleClass(disabled, cmd.disabled());
|
|
|
+ update();
|
|
|
+ })
|
|
|
+ .change();
|
|
|
+
|
|
|
+ } else {
|
|
|
+ button.addClass(disabled);
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/stat.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder ui
|
|
|
+ * Display number of files/selected files and its size in statusbar
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.elfinderstat = function(fm) {
|
|
|
+ return this.each(function() {
|
|
|
+ var size = $(this).addClass('elfinder-stat-size'),
|
|
|
+ sel = $('<div class="elfinder-stat-selected"/>'),
|
|
|
+ titlesize = fm.i18n('size').toLowerCase(),
|
|
|
+ titleitems = fm.i18n('items').toLowerCase(),
|
|
|
+ titlesel = fm.i18n('selected'),
|
|
|
+ setstat = function(files, cwd) {
|
|
|
+ var c = 0,
|
|
|
+ s = 0;
|
|
|
+
|
|
|
+ $.each(files, function(i, file) {
|
|
|
+ if (!cwd || file.phash == cwd) {
|
|
|
+ c++;
|
|
|
+ s += parseInt(file.size)||0;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ size.html(titleitems+': '+c+', '+titlesize+': '+fm.formatSize(s));
|
|
|
+ };
|
|
|
+
|
|
|
+ fm.getUI('statusbar').prepend(size).append(sel).show();
|
|
|
+
|
|
|
+ fm
|
|
|
+ .bind('open reload add remove change searchend', function() {
|
|
|
+ setstat(fm.files(), fm.cwd().hash)
|
|
|
+ })
|
|
|
+ .search(function(e) {
|
|
|
+ setstat(e.data.files);
|
|
|
+ })
|
|
|
+ .select(function() {
|
|
|
+ var s = 0,
|
|
|
+ c = 0,
|
|
|
+ files = fm.selectedFiles();
|
|
|
+
|
|
|
+ if (files.length == 1) {
|
|
|
+ s = files[0].size;
|
|
|
+ sel.html(fm.escape(files[0].name)+(s > 0 ? ', '+fm.formatSize(s) : ''));
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ $.each(files, function(i, file) {
|
|
|
+ c++;
|
|
|
+ s += parseInt(file.size)||0;
|
|
|
+ });
|
|
|
+
|
|
|
+ sel.html(c ? titlesel+': '+c+', '+titlesize+': '+fm.formatSize(s) : ' ');
|
|
|
+ })
|
|
|
+
|
|
|
+ ;
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/toolbar.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder toolbar
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.elfindertoolbar = function(fm, opts) {
|
|
|
+ this.not('.elfinder-toolbar').each(function() {
|
|
|
+ var commands = fm._commands,
|
|
|
+ self = $(this).addClass('ui-helper-clearfix ui-widget-header ui-corner-top elfinder-toolbar'),
|
|
|
+ panels = opts || [],
|
|
|
+ l = panels.length,
|
|
|
+ i, cmd, panel, button;
|
|
|
+
|
|
|
+ self.prev().length && self.parent().prepend(this);
|
|
|
+
|
|
|
+ while (l--) {
|
|
|
+ if (panels[l]) {
|
|
|
+ panel = $('<div class="ui-widget-content ui-corner-all elfinder-buttonset"/>');
|
|
|
+ i = panels[l].length;
|
|
|
+ while (i--) {
|
|
|
+ if ((cmd = commands[panels[l][i]])) {
|
|
|
+ button = 'elfinder'+cmd.options.ui;
|
|
|
+ $.fn[button] && panel.prepend($('<div/>')[button](cmd));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ panel.children().length && self.prepend(panel);
|
|
|
+ panel.children(':gt(0)').before('<span class="ui-widget-content elfinder-toolbar-button-separator"/>');
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ self.children().length && self.show();
|
|
|
+ });
|
|
|
+
|
|
|
+ return this;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/tree.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder folders tree
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.elfindertree = function(fm, opts) {
|
|
|
+ var treeclass = fm.res('class', 'tree');
|
|
|
+
|
|
|
+ this.not('.'+treeclass).each(function() {
|
|
|
+
|
|
|
+ var c = 'class',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Root directory class name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ root = fm.res(c, 'treeroot'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Open root dir if not opened yet
|
|
|
+ *
|
|
|
+ * @type Boolean
|
|
|
+ */
|
|
|
+ openRoot = opts.openRootOnLoad,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Subtree class name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ subtree = fm.res(c, 'navsubtree'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Directory class name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ navdir = fm.res(c, 'treedir'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Collapsed arrow class name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ collapsed = fm.res(c, 'navcollapse'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Expanded arrow class name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ expanded = fm.res(c, 'navexpand'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Class name to mark arrow for directory with already loaded children
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ loaded = 'elfinder-subtree-loaded',
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Arraw class name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ arrow = fm.res(c, 'navarrow'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Current directory class name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ active = fm.res(c, 'active'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Droppable dirs dropover class
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ dropover = fm.res(c, 'adroppable'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Hover class name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ hover = fm.res(c, 'hover'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Disabled dir class name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ disabled = fm.res(c, 'disabled'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Draggable dir class name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ draggable = fm.res(c, 'draggable'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Droppable dir class name
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ droppable = fm.res(c, 'droppable'),
|
|
|
+
|
|
|
+ insideNavbar = function(x) {
|
|
|
+ var left = navbar.offset().left;
|
|
|
+
|
|
|
+ return left <= x && x <= left + navbar.width();
|
|
|
+ },
|
|
|
+
|
|
|
+ drop = fm.droppable.drop,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Droppable options
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ */
|
|
|
+ droppableopts = $.extend(true, {}, fm.droppable, {
|
|
|
+ // show subfolders on dropover
|
|
|
+ over : function(e) {
|
|
|
+ var link = $(this),
|
|
|
+ cl = hover+' '+dropover;
|
|
|
+
|
|
|
+ if (insideNavbar(e.clientX)) {
|
|
|
+ link.addClass(cl)
|
|
|
+ if (link.is('.'+collapsed+':not(.'+expanded+')')) {
|
|
|
+ setTimeout(function() {
|
|
|
+ link.is('.'+dropover) && link.children('.'+arrow).click();
|
|
|
+ }, 500);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ link.removeClass(cl);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ out : function() { $(this).removeClass(hover+' '+dropover); },
|
|
|
+ drop : function(e, ui) { insideNavbar(e.clientX) && drop.call(this, e, ui); }
|
|
|
+ }),
|
|
|
+
|
|
|
+ spinner = $(fm.res('tpl', 'navspinner')),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Directory html template
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ tpl = fm.res('tpl', 'navdir'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Permissions marker html template
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ ptpl = fm.res('tpl', 'perms'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Symlink marker html template
|
|
|
+ *
|
|
|
+ * @type String
|
|
|
+ */
|
|
|
+ stpl = fm.res('tpl', 'symlink'),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Html template replacement methods
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ */
|
|
|
+ replace = {
|
|
|
+ id : function(dir) { return fm.navHash2Id(dir.hash) },
|
|
|
+ cssclass : function(dir) { return (dir.phash ? '' : root)+' '+navdir+' '+fm.perms2class(dir)+' '+(dir.dirs && !dir.link ? collapsed : ''); },
|
|
|
+ permissions : function(dir) { return !dir.read || !dir.write ? ptpl : ''; },
|
|
|
+ symlink : function(dir) { return dir.alias ? stpl : ''; }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return html for given dir
|
|
|
+ *
|
|
|
+ * @param Object directory
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ itemhtml = function(dir) {
|
|
|
+ dir.name = fm.escape(dir.i18 || dir.name);
|
|
|
+
|
|
|
+ return tpl.replace(/(?:\{([a-z]+)\})/ig, function(m, key) {
|
|
|
+ return dir[key] || (replace[key] ? replace[key](dir) : '');
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return only dirs from files list
|
|
|
+ *
|
|
|
+ * @param Array files list
|
|
|
+ * @return Array
|
|
|
+ */
|
|
|
+ filter = function(files) {
|
|
|
+ return $.map(files||[], function(f) { return f.mime == 'directory' ? f : null });
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Find parent subtree for required directory
|
|
|
+ *
|
|
|
+ * @param String dir hash
|
|
|
+ * @return jQuery
|
|
|
+ */
|
|
|
+ findSubtree = function(hash) {
|
|
|
+ return hash ? tree.find('#'+fm.navHash2Id(hash)).next('.'+subtree) : tree;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Find directory (wrapper) in required node
|
|
|
+ * before which we can insert new directory
|
|
|
+ *
|
|
|
+ * @param jQuery parent directory
|
|
|
+ * @param Object new directory
|
|
|
+ * @return jQuery
|
|
|
+ */
|
|
|
+ findSibling = function(subtree, dir) {
|
|
|
+ var node = subtree.children(':first'),
|
|
|
+ info;
|
|
|
+
|
|
|
+ while (node.length) {
|
|
|
+ info = fm.file(fm.navId2Hash(node.children('[id]').attr('id')));
|
|
|
+
|
|
|
+ if ((info = fm.file(fm.navId2Hash(node.children('[id]').attr('id'))))
|
|
|
+ && dir.name.toLowerCase().localeCompare(info.name.toLowerCase()) < 0) {
|
|
|
+ return node;
|
|
|
+ }
|
|
|
+ node = node.next();
|
|
|
+ }
|
|
|
+ return $('');
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Add new dirs in tree
|
|
|
+ *
|
|
|
+ * @param Array dirs list
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ updateTree = function(dirs) {
|
|
|
+ var length = dirs.length,
|
|
|
+ orphans = [],
|
|
|
+ i = dirs.length,
|
|
|
+ dir, html, parent, sibling;
|
|
|
+
|
|
|
+ var firstVol = true; // check for netmount volume
|
|
|
+ while (i--) {
|
|
|
+ dir = dirs[i];
|
|
|
+
|
|
|
+ if (tree.find('#'+fm.navHash2Id(dir.hash)).length) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((parent = findSubtree(dir.phash)).length) {
|
|
|
+ html = itemhtml(dir);
|
|
|
+ if (dir.phash && (sibling = findSibling(parent, dir)).length) {
|
|
|
+ sibling.before(html);
|
|
|
+ } else {
|
|
|
+ parent[firstVol || dir.phash ? 'append' : 'prepend'](html);
|
|
|
+ firstVol = false;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ orphans.push(dir);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (orphans.length && orphans.length < length) {
|
|
|
+ return updateTree(orphans);
|
|
|
+ }
|
|
|
+
|
|
|
+ setTimeout(function() {
|
|
|
+ updateDroppable();
|
|
|
+ }, 10);
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Mark current directory as active
|
|
|
+ * If current directory is not in tree - load it and its parents
|
|
|
+ *
|
|
|
+ * @param {Boolean} do not recursive call
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ sync = function(stopRec) {
|
|
|
+ var cwd = fm.cwd().hash,
|
|
|
+ current = tree.find('#'+fm.navHash2Id(cwd)),
|
|
|
+ rootNode, dir;
|
|
|
+
|
|
|
+ if (openRoot) {
|
|
|
+ rootNode = tree.find('#'+fm.navHash2Id(fm.root()));
|
|
|
+ rootNode.is('.'+loaded) && rootNode.addClass(expanded).next('.'+subtree).show();
|
|
|
+ openRoot = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!current.is('.'+active)) {
|
|
|
+ tree.find('.'+navdir+'.'+active).removeClass(active);
|
|
|
+ current.addClass(active);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (opts.syncTree) {
|
|
|
+ if (current.length) {
|
|
|
+ return current.parentsUntil('.'+root).filter('.'+subtree).show().prev('.'+navdir).addClass(expanded);
|
|
|
+ }
|
|
|
+ if (fm.newAPI) {
|
|
|
+ dir = fm.file(cwd);
|
|
|
+ if (dir && dir.phash && tree.find('#'+fm.navHash2Id(dir.phash)).length) {
|
|
|
+ updateTree([dir]);
|
|
|
+ return sync();
|
|
|
+ }
|
|
|
+ fm.request({
|
|
|
+ data : {cmd : 'parents', target : cwd},
|
|
|
+ preventFail : true
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ var dirs = filter(data.tree);
|
|
|
+ updateTree(dirs);
|
|
|
+ updateArrows(dirs, loaded);
|
|
|
+ cwd == fm.cwd().hash && sync(true);
|
|
|
+ })
|
|
|
+ ;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Make writable and not root dirs droppable
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ updateDroppable = function() {
|
|
|
+ tree.find('.'+navdir+':not(.'+droppable+',.elfinder-ro,.elfinder-na)').droppable(droppableopts);
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Check required folders for subfolders and update arrow classes
|
|
|
+ *
|
|
|
+ * @param Array folders to check
|
|
|
+ * @param String css class
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ updateArrows = function(dirs, cls) {
|
|
|
+ var sel = cls == loaded
|
|
|
+ ? '.'+collapsed+':not(.'+loaded+')'
|
|
|
+ : ':not(.'+collapsed+')';
|
|
|
+
|
|
|
+
|
|
|
+ //tree.find('.'+subtree+':has(*)').prev(':not(.'+collapsed+')').addClass(collapsed)
|
|
|
+
|
|
|
+ $.each(dirs, function(i, dir) {
|
|
|
+ tree.find('#'+fm.navHash2Id(dir.phash)+sel)
|
|
|
+ .filter(function() { return $(this).next('.'+subtree).children().length > 0 })
|
|
|
+ .addClass(cls);
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Navigation tree
|
|
|
+ *
|
|
|
+ * @type JQuery
|
|
|
+ */
|
|
|
+ tree = $(this).addClass(treeclass)
|
|
|
+ // make dirs draggable and toggle hover class
|
|
|
+ .delegate('.'+navdir, 'hover', function(e) {
|
|
|
+ var link = $(this),
|
|
|
+ enter = e.type == 'mouseenter';
|
|
|
+
|
|
|
+ if (!link.is('.'+dropover+' ,.'+disabled)) {
|
|
|
+ enter && !link.is('.'+root+',.'+draggable+',.elfinder-na,.elfinder-wo') && link.draggable(fm.draggable);
|
|
|
+ link.toggleClass(hover, enter);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // add/remove dropover css class
|
|
|
+ .delegate('.'+navdir, 'dropover dropout drop', function(e) {
|
|
|
+ $(this)[e.type == 'dropover' ? 'addClass' : 'removeClass'](dropover+' '+hover);
|
|
|
+ })
|
|
|
+ // open dir or open subfolders in tree
|
|
|
+ .delegate('.'+navdir, 'click', function(e) {
|
|
|
+ var link = $(this),
|
|
|
+ hash = fm.navId2Hash(link.attr('id')),
|
|
|
+ file = fm.file(hash);
|
|
|
+
|
|
|
+ fm.trigger('searchend');
|
|
|
+
|
|
|
+ if (hash != fm.cwd().hash && !link.is('.'+disabled)) {
|
|
|
+ fm.exec('open', file.thash || hash);
|
|
|
+ } else if (link.is('.'+collapsed)) {
|
|
|
+ link.children('.'+arrow).click();
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // toggle subfolders in tree
|
|
|
+ .delegate('.'+navdir+'.'+collapsed+' .'+arrow, 'click', function(e) {
|
|
|
+ var arrow = $(this),
|
|
|
+ link = arrow.parent('.'+navdir),
|
|
|
+ stree = link.next('.'+subtree);
|
|
|
+
|
|
|
+ e.stopPropagation();
|
|
|
+
|
|
|
+ if (link.is('.'+loaded)) {
|
|
|
+ link.toggleClass(expanded);
|
|
|
+ stree.slideToggle()
|
|
|
+ } else {
|
|
|
+ spinner.insertBefore(arrow);
|
|
|
+ link.removeClass(collapsed);
|
|
|
+
|
|
|
+ fm.request({cmd : 'tree', target : fm.navId2Hash(link.attr('id'))})
|
|
|
+ .done(function(data) {
|
|
|
+ updateTree(filter(data.tree));
|
|
|
+
|
|
|
+ if (stree.children().length) {
|
|
|
+ link.addClass(collapsed+' '+expanded);
|
|
|
+ stree.slideDown();
|
|
|
+ }
|
|
|
+ sync();
|
|
|
+ })
|
|
|
+ .always(function(data) {
|
|
|
+ spinner.remove();
|
|
|
+ link.addClass(loaded);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .delegate('.'+navdir, 'contextmenu', function(e) {
|
|
|
+ e.preventDefault();
|
|
|
+
|
|
|
+ fm.trigger('contextmenu', {
|
|
|
+ 'type' : 'navbar',
|
|
|
+ 'targets' : [fm.navId2Hash($(this).attr('id'))],
|
|
|
+ 'x' : e.clientX,
|
|
|
+ 'y' : e.clientY
|
|
|
+ });
|
|
|
+ }),
|
|
|
+ // move tree into navbar
|
|
|
+ navbar = fm.getUI('navbar').append(tree).show()
|
|
|
+
|
|
|
+ ;
|
|
|
+
|
|
|
+ fm.open(function(e) {
|
|
|
+ var data = e.data,
|
|
|
+ dirs = filter(data.files);
|
|
|
+
|
|
|
+ data.init && tree.empty();
|
|
|
+
|
|
|
+ if (dirs.length) {
|
|
|
+ updateTree(dirs);
|
|
|
+ updateArrows(dirs, loaded);
|
|
|
+ }
|
|
|
+ sync();
|
|
|
+ })
|
|
|
+ // add new dirs
|
|
|
+ .add(function(e) {
|
|
|
+ var dirs = filter(e.data.added);
|
|
|
+
|
|
|
+ if (dirs.length) {
|
|
|
+ updateTree(dirs);
|
|
|
+ updateArrows(dirs, collapsed);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // update changed dirs
|
|
|
+ .change(function(e) {
|
|
|
+ var dirs = filter(e.data.changed),
|
|
|
+ l = dirs.length,
|
|
|
+ dir, node, tmp, realParent, reqParent, realSibling, reqSibling, isExpanded, isLoaded;
|
|
|
+
|
|
|
+ while (l--) {
|
|
|
+ dir = dirs[l];
|
|
|
+ if ((node = tree.find('#'+fm.navHash2Id(dir.hash))).length) {
|
|
|
+ if (dir.phash) {
|
|
|
+ realParent = node.closest('.'+subtree);
|
|
|
+ reqParent = findSubtree(dir.phash);
|
|
|
+ realSibling = node.parent().next();
|
|
|
+ reqSibling = findSibling(reqParent, dir);
|
|
|
+
|
|
|
+ if (!reqParent.length) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (reqParent[0] !== realParent[0] || realSibling.get(0) !== reqSibling.get(0)) {
|
|
|
+ reqSibling.length ? reqSibling.before(node) : reqParent.append(node);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ isExpanded = node.is('.'+expanded);
|
|
|
+ isLoaded = node.is('.'+loaded);
|
|
|
+ tmp = $(itemhtml(dir));
|
|
|
+ node.replaceWith(tmp.children('.'+navdir));
|
|
|
+
|
|
|
+ if (dir.dirs
|
|
|
+ && (isExpanded || isLoaded)
|
|
|
+ && (node = tree.find('#'+fm.navHash2Id(dir.hash)))
|
|
|
+ && node.next('.'+subtree).children().length) {
|
|
|
+ isExpanded && node.addClass(expanded);
|
|
|
+ isLoaded && node.addClass(loaded);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ sync();
|
|
|
+ updateDroppable();
|
|
|
+ })
|
|
|
+ // remove dirs
|
|
|
+ .remove(function(e) {
|
|
|
+ var dirs = e.data.removed,
|
|
|
+ l = dirs.length,
|
|
|
+ node, stree;
|
|
|
+
|
|
|
+ while (l--) {
|
|
|
+ if ((node = tree.find('#'+fm.navHash2Id(dirs[l]))).length) {
|
|
|
+ stree = node.closest('.'+subtree);
|
|
|
+ node.parent().detach();
|
|
|
+ if (!stree.children().length) {
|
|
|
+ stree.hide().prev('.'+navdir).removeClass(collapsed+' '+expanded+' '+loaded);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // add/remove active class for current dir
|
|
|
+ .bind('search searchend', function(e) {
|
|
|
+ tree.find('#'+fm.navHash2Id(fm.cwd().hash))[e.type == 'search' ? 'removeClass' : 'addClass'](active);
|
|
|
+ })
|
|
|
+ // lock/unlock dirs while moving
|
|
|
+ .bind('lockfiles unlockfiles', function(e) {
|
|
|
+ var lock = e.type == 'lockfiles',
|
|
|
+ act = lock ? 'disable' : 'enable',
|
|
|
+ dirs = $.map(e.data.files||[], function(h) {
|
|
|
+ var dir = fm.file(h);
|
|
|
+ return dir && dir.mime == 'directory' ? h : null;
|
|
|
+ })
|
|
|
+
|
|
|
+ $.each(dirs, function(i, hash) {
|
|
|
+ var dir = tree.find('#'+fm.navHash2Id(hash));
|
|
|
+
|
|
|
+ if (dir.length) {
|
|
|
+ dir.is('.'+draggable) && dir.draggable(act);
|
|
|
+ dir.is('.'+droppable) && dir.droppable(active);
|
|
|
+ dir[lock ? 'addClass' : 'removeClass'](disabled);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ })
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+ return this;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/uploadButton.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder toolbar's button tor upload file
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.elfinderuploadbutton = function(cmd) {
|
|
|
+ return this.each(function() {
|
|
|
+ var button = $(this).elfinderbutton(cmd)
|
|
|
+ .unbind('click'),
|
|
|
+ form = $('<form/>').appendTo(button),
|
|
|
+ input = $('<input type="file" multiple="true"/>')
|
|
|
+ .change(function() {
|
|
|
+ var _input = $(this);
|
|
|
+ if (_input.val()) {
|
|
|
+ cmd.exec({input : _input.remove()[0]});
|
|
|
+ input.clone(true).appendTo(form);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ form.append(input.clone(true));
|
|
|
+
|
|
|
+ cmd.change(function() {
|
|
|
+ form[cmd.disabled() ? 'hide' : 'show']();
|
|
|
+ })
|
|
|
+ .change();
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/viewbutton.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder toolbar button to switch current directory view.
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.elfinderviewbutton = function(cmd) {
|
|
|
+ return this.each(function() {
|
|
|
+ var button = $(this).elfinderbutton(cmd),
|
|
|
+ icon = button.children('.elfinder-button-icon');
|
|
|
+
|
|
|
+ cmd.change(function() {
|
|
|
+ var icons = cmd.value == 'icons';
|
|
|
+
|
|
|
+ icon.toggleClass('elfinder-button-icon-view-list', icons);
|
|
|
+ button.attr('title', cmd.fm.i18n(icons ? 'viewlist' : 'viewicons'));
|
|
|
+ });
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/ui/workzone.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elfinderworkzone - elFinder container for nav and current directory
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+$.fn.elfinderworkzone = function(fm) {
|
|
|
+ var cl = 'elfinder-workzone';
|
|
|
+
|
|
|
+ this.not('.'+cl).each(function() {
|
|
|
+ var wz = $(this).addClass(cl),
|
|
|
+ wdelta = wz.outerHeight(true) - wz.height(),
|
|
|
+ parent = wz.parent();
|
|
|
+
|
|
|
+ parent.add(window).bind('resize', function() {
|
|
|
+ var height = parent.height();
|
|
|
+
|
|
|
+ parent.children(':visible:not(.'+cl+')').each(function() {
|
|
|
+ var ch = $(this);
|
|
|
+
|
|
|
+ if (ch.css('position') != 'absolute') {
|
|
|
+ height -= ch.outerHeight(true);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ wz.height(height - wdelta);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ return this;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/archive.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "archive"
|
|
|
+ * Archive selected files
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.archive = function() {
|
|
|
+ var self = this,
|
|
|
+ fm = self.fm,
|
|
|
+ mimes = [];
|
|
|
+
|
|
|
+ this.variants = [];
|
|
|
+
|
|
|
+ this.disableOnSearch = true;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Update mimes on open/reload
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ fm.bind('open reload', function() {
|
|
|
+ self.variants = [];
|
|
|
+ $.each((mimes = fm.option('archivers')['create'] || []), function(i, mime) {
|
|
|
+ self.variants.push([mime, fm.mime2kind(mime)])
|
|
|
+ });
|
|
|
+ self.change();
|
|
|
+ });
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ return !this._disabled && mimes.length && fm.selected().length && fm.cwd().write ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function(hashes, type) {
|
|
|
+ var files = this.files(hashes),
|
|
|
+ cnt = files.length,
|
|
|
+ mime = type || mimes[0],
|
|
|
+ cwd = fm.cwd(),
|
|
|
+ error = ['errArchive', 'errPerm', 'errCreatingTempDir', 'errFtpDownloadFile', 'errFtpUploadFile', 'errFtpMkdir', 'errArchiveExec', 'errExtractExec', 'errRm'],
|
|
|
+ dfrd = $.Deferred().fail(function(error) {
|
|
|
+ error && fm.error(error);
|
|
|
+ }),
|
|
|
+ i;
|
|
|
+
|
|
|
+ if (!(this.enabled() && cnt && mimes.length && $.inArray(mime, mimes) !== -1)) {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!cwd.write) {
|
|
|
+ return dfrd.reject(error);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < cnt; i++) {
|
|
|
+ if (!files[i].read) {
|
|
|
+ return dfrd.reject(error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return fm.request({
|
|
|
+ data : {cmd : 'archive', targets : this.hashes(hashes), type : mime},
|
|
|
+ notify : {type : 'archive', cnt : 1},
|
|
|
+ syncOnFail : true
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/back.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "back"
|
|
|
+ * Open last visited folder
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.back = function() {
|
|
|
+ this.alwaysEnabled = true;
|
|
|
+ this.updateOnSelect = false;
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'ctrl+left backspace'
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ return this.fm.history.canBack() ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function() {
|
|
|
+ return this.fm.history.back();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/copy.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "copy".
|
|
|
+ * Put files in filemanager clipboard.
|
|
|
+ *
|
|
|
+ * @type elFinder.command
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ */
|
|
|
+elFinder.prototype.commands.copy = function() {
|
|
|
+
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'ctrl+c ctrl+insert'
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.getstate = function(sel) {
|
|
|
+ var sel = this.files(sel),
|
|
|
+ cnt = sel.length;
|
|
|
+
|
|
|
+ return cnt && $.map(sel, function(f) { return f.phash && f.read ? f : null }).length == cnt ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function(hashes) {
|
|
|
+ var fm = this.fm,
|
|
|
+ dfrd = $.Deferred()
|
|
|
+ .fail(function(error) {
|
|
|
+ fm.error(error);
|
|
|
+ });
|
|
|
+
|
|
|
+ $.each(this.files(hashes), function(i, file) {
|
|
|
+ if (!(file.read && file.phash)) {
|
|
|
+ return !dfrd.reject(['errCopy', file.name, 'errPerm']);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return dfrd.state() == 'rejected' ? dfrd : dfrd.resolve(fm.clipboard(this.hashes(hashes)));
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/cut.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "copy".
|
|
|
+ * Put files in filemanager clipboard.
|
|
|
+ *
|
|
|
+ * @type elFinder.command
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ */
|
|
|
+elFinder.prototype.commands.cut = function() {
|
|
|
+
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'ctrl+x shift+insert'
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.getstate = function(sel) {
|
|
|
+ var sel = this.files(sel),
|
|
|
+ cnt = sel.length;
|
|
|
+
|
|
|
+ return cnt && $.map(sel, function(f) { return f.phash && f.read && !f.locked ? f : null }).length == cnt ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function(hashes) {
|
|
|
+ var fm = this.fm,
|
|
|
+ dfrd = $.Deferred()
|
|
|
+ .fail(function(error) {
|
|
|
+ fm.error(error);
|
|
|
+ });
|
|
|
+
|
|
|
+ $.each(this.files(hashes), function(i, file) {
|
|
|
+ if (!(file.read && file.phash) ) {
|
|
|
+ return !dfrd.reject(['errCopy', file.name, 'errPerm']);
|
|
|
+ }
|
|
|
+ if (file.locked) {
|
|
|
+ return !dfrd.reject(['errLocked', file.name]);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return dfrd.state() == 'rejected' ? dfrd : dfrd.resolve(fm.clipboard(this.hashes(hashes), true));
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/download.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "download".
|
|
|
+ * Download selected files.
|
|
|
+ * Only for new api
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov, dio@std42.ru
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.download = function() {
|
|
|
+ var self = this,
|
|
|
+ fm = this.fm,
|
|
|
+ filter = function(hashes) {
|
|
|
+ return $.map(self.files(hashes), function(f) { return f.mime == 'directory' ? null : f });
|
|
|
+ };
|
|
|
+
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'shift+enter'
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ var sel = this.fm.selected(),
|
|
|
+ cnt = sel.length;
|
|
|
+
|
|
|
+ return !this._disabled && cnt && (!fm.UA.IE || cnt == 1) && cnt == filter(sel).length ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function(hashes) {
|
|
|
+ var fm = this.fm,
|
|
|
+ base = fm.options.url,
|
|
|
+ files = filter(hashes),
|
|
|
+ dfrd = $.Deferred(),
|
|
|
+ iframes = '',
|
|
|
+ cdata = '',
|
|
|
+ i, url;
|
|
|
+
|
|
|
+ if (this.disabled()) {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (fm.oldAPI) {
|
|
|
+ fm.error('errCmdNoSupport');
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ cdata = $.param(fm.options.customData || {});
|
|
|
+ if (cdata) {
|
|
|
+ cdata = '&' + cdata;
|
|
|
+ }
|
|
|
+
|
|
|
+ base += base.indexOf('?') === -1 ? '?' : '&';
|
|
|
+
|
|
|
+ for (i = 0; i < files.length; i++) {
|
|
|
+ iframes += '<iframe class="downloader" id="downloader-' + files[i].hash+'" style="display:none" src="'+base + 'cmd=file&target=' + files[i].hash+'&download=1'+cdata+'"/>';
|
|
|
+ }
|
|
|
+ $(iframes)
|
|
|
+ .appendTo('body')
|
|
|
+ .ready(function() {
|
|
|
+ setTimeout(function() {
|
|
|
+ $(iframes).each(function() {
|
|
|
+ $('#' + $(this).attr('id')).remove();
|
|
|
+ });
|
|
|
+ }, fm.UA.Firefox? (20000 + (10000 * i)) : 1000); // give mozilla 20 sec + 10 sec for each file to be saved
|
|
|
+ });
|
|
|
+ fm.trigger('download', {files : files});
|
|
|
+ return dfrd.resolve(hashes);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/duplicate.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "duplicate"
|
|
|
+ * Create file/folder copy with suffix "copy Number"
|
|
|
+ *
|
|
|
+ * @type elFinder.command
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ */
|
|
|
+elFinder.prototype.commands.duplicate = function() {
|
|
|
+ var fm = this.fm;
|
|
|
+
|
|
|
+ this.getstate = function(sel) {
|
|
|
+ var sel = this.files(sel),
|
|
|
+ cnt = sel.length;
|
|
|
+
|
|
|
+ return !this._disabled && cnt && fm.cwd().write && $.map(sel, function(f) { return f.phash && f.read ? f : null }).length == cnt ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function(hashes) {
|
|
|
+ var fm = this.fm,
|
|
|
+ files = this.files(hashes),
|
|
|
+ cnt = files.length,
|
|
|
+ dfrd = $.Deferred()
|
|
|
+ .fail(function(error) {
|
|
|
+ error && fm.error(error);
|
|
|
+ }),
|
|
|
+ args = [];
|
|
|
+
|
|
|
+ if (!cnt || this._disabled) {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ $.each(files, function(i, file) {
|
|
|
+ if (!file.read || !fm.file(file.phash).write) {
|
|
|
+ return !dfrd.reject(['errCopy', file.name, 'errPerm']);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (dfrd.state() == 'rejected') {
|
|
|
+ return dfrd;
|
|
|
+ }
|
|
|
+
|
|
|
+ return fm.request({
|
|
|
+ data : {cmd : 'duplicate', targets : this.hashes(hashes)},
|
|
|
+ notify : {type : 'copy', cnt : cnt}
|
|
|
+ });
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/edit.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "edit".
|
|
|
+ * Edit text file in dialog window
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov, dio@std42.ru
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.edit = function() {
|
|
|
+ var self = this,
|
|
|
+ fm = this.fm,
|
|
|
+ mimes = fm.res('mimes', 'text') || [],
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return files acceptable to edit
|
|
|
+ *
|
|
|
+ * @param Array files hashes
|
|
|
+ * @return Array
|
|
|
+ **/
|
|
|
+ filter = function(files) {
|
|
|
+ return $.map(files, function(file) {
|
|
|
+ return (file.mime.indexOf('text/') === 0 || $.inArray(file.mime, mimes) !== -1)
|
|
|
+ && file.mime.indexOf('text/rtf')
|
|
|
+ && (!self.onlyMimes.length || $.inArray(file.mime, self.onlyMimes) !== -1)
|
|
|
+ && file.read && file.write ? file : null;
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Open dialog with textarea to edit file
|
|
|
+ *
|
|
|
+ * @param String id dialog id
|
|
|
+ * @param Object file file object
|
|
|
+ * @param String content file content
|
|
|
+ * @return $.Deferred
|
|
|
+ **/
|
|
|
+ dialog = function(id, file, content) {
|
|
|
+
|
|
|
+ var dfrd = $.Deferred(),
|
|
|
+ ta = $('<textarea class="elfinder-file-edit" rows="20" id="'+id+'-ta">'+fm.escape(content)+'</textarea>'),
|
|
|
+ save = function() {
|
|
|
+ ta.editor && ta.editor.save(ta[0], ta.editor.instance);
|
|
|
+ dfrd.resolve(ta.getContent());
|
|
|
+ ta.elfinderdialog('close');
|
|
|
+ },
|
|
|
+ cancel = function() {
|
|
|
+ dfrd.reject();
|
|
|
+ ta.elfinderdialog('close');
|
|
|
+ },
|
|
|
+ opts = {
|
|
|
+ title : file.name,
|
|
|
+ width : self.options.dialogWidth || 450,
|
|
|
+ buttons : {},
|
|
|
+ close : function() {
|
|
|
+ ta.editor && ta.editor.close(ta[0], ta.editor.instance);
|
|
|
+ $(this).elfinderdialog('destroy');
|
|
|
+ },
|
|
|
+ open : function() {
|
|
|
+ fm.disable();
|
|
|
+ ta.focus();
|
|
|
+ ta[0].setSelectionRange && ta[0].setSelectionRange(0, 0);
|
|
|
+ ta.editor && ta.editor.load(ta[0]);
|
|
|
+ }
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ ta.getContent = function() {
|
|
|
+ return ta.val()
|
|
|
+ }
|
|
|
+
|
|
|
+ $.each(self.options.editors || [], function(i, editor) {
|
|
|
+ if ($.inArray(file.mime, editor.mimes || []) !== -1
|
|
|
+ && typeof editor.load == 'function'
|
|
|
+ && typeof editor.save == 'function') {
|
|
|
+ ta.editor = {
|
|
|
+ load : editor.load,
|
|
|
+ save : editor.save,
|
|
|
+ close : typeof editor.close == 'function' ? editor.close : function() {},
|
|
|
+ instance : null
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!ta.editor) {
|
|
|
+ ta.keydown(function(e) {
|
|
|
+ var code = e.keyCode,
|
|
|
+ value, start;
|
|
|
+
|
|
|
+ e.stopPropagation();
|
|
|
+ if (code == 9) {
|
|
|
+ e.preventDefault();
|
|
|
+ // insert tab on tab press
|
|
|
+ if (this.setSelectionRange) {
|
|
|
+ value = this.value;
|
|
|
+ start = this.selectionStart;
|
|
|
+ this.value = value.substr(0, start) + "\t" + value.substr(this.selectionEnd);
|
|
|
+ start += 1;
|
|
|
+ this.setSelectionRange(start, start);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (e.ctrlKey || e.metaKey) {
|
|
|
+ // close on ctrl+w/q
|
|
|
+ if (code == 81 || code == 87) {
|
|
|
+ e.preventDefault();
|
|
|
+ cancel();
|
|
|
+ }
|
|
|
+ if (code == 83) {
|
|
|
+ e.preventDefault();
|
|
|
+ save();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ opts.buttons[fm.i18n('Save')] = save;
|
|
|
+ opts.buttons[fm.i18n('Cancel')] = cancel
|
|
|
+
|
|
|
+ fm.dialog(ta, opts).attr('id', id);
|
|
|
+ return dfrd.promise();
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get file content and
|
|
|
+ * open dialog with textarea to edit file content
|
|
|
+ *
|
|
|
+ * @param String file hash
|
|
|
+ * @return jQuery.Deferred
|
|
|
+ **/
|
|
|
+ edit = function(file) {
|
|
|
+ var hash = file.hash,
|
|
|
+ opts = fm.options,
|
|
|
+ dfrd = $.Deferred(),
|
|
|
+ data = {cmd : 'file', target : hash},
|
|
|
+ url = fm.url(hash) || fm.options.url,
|
|
|
+ id = 'edit-'+fm.namespace+'-'+file.hash,
|
|
|
+ d = fm.getUI().find('#'+id),
|
|
|
+ error;
|
|
|
+
|
|
|
+
|
|
|
+ if (d.length) {
|
|
|
+ d.elfinderdialog('toTop');
|
|
|
+ return dfrd.resolve();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!file.read || !file.write) {
|
|
|
+ error = ['errOpen', file.name, 'errPerm']
|
|
|
+ fm.error(error)
|
|
|
+ return dfrd.reject(error);
|
|
|
+ }
|
|
|
+
|
|
|
+ fm.request({
|
|
|
+ data : {cmd : 'get', target : hash},
|
|
|
+ notify : {type : 'openfile', cnt : 1},
|
|
|
+ syncOnFail : true
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ dialog(id, file, data.content)
|
|
|
+ .done(function(content) {
|
|
|
+ fm.request({
|
|
|
+ options : {type : 'post'},
|
|
|
+ data : {
|
|
|
+ cmd : 'put',
|
|
|
+ target : hash,
|
|
|
+ content : content
|
|
|
+ },
|
|
|
+ notify : {type : 'save', cnt : 1},
|
|
|
+ syncOnFail : true
|
|
|
+ })
|
|
|
+ .fail(function(error) {
|
|
|
+ dfrd.reject(error);
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ data.changed && data.changed.length && fm.change(data);
|
|
|
+ dfrd.resolve(data);
|
|
|
+ });
|
|
|
+ })
|
|
|
+ })
|
|
|
+ .fail(function(error) {
|
|
|
+ dfrd.reject(error);
|
|
|
+ })
|
|
|
+
|
|
|
+ return dfrd.promise();
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'ctrl+e'
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.init = function() {
|
|
|
+ this.onlyMimes = this.options.mimes || []
|
|
|
+ }
|
|
|
+
|
|
|
+ this.getstate = function(sel) {
|
|
|
+ var sel = this.files(sel),
|
|
|
+ cnt = sel.length;
|
|
|
+
|
|
|
+ return !this._disabled && cnt && filter(sel).length == cnt ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function(hashes) {
|
|
|
+ var files = filter(this.files(hashes)),
|
|
|
+ list = [],
|
|
|
+ file;
|
|
|
+
|
|
|
+ if (this.disabled()) {
|
|
|
+ return $.Deferred().reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ while ((file = files.shift())) {
|
|
|
+ list.push(edit(file));
|
|
|
+ }
|
|
|
+
|
|
|
+ return list.length
|
|
|
+ ? $.when.apply(null, list)
|
|
|
+ : $.Deferred().reject();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/extract.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "extract"
|
|
|
+ * Extract files from archive
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.extract = function() {
|
|
|
+ var self = this,
|
|
|
+ fm = self.fm,
|
|
|
+ mimes = [],
|
|
|
+ filter = function(files) {
|
|
|
+ return $.map(files, function(file) {
|
|
|
+ return file.read && $.inArray(file.mime, mimes) !== -1 ? file : null
|
|
|
+
|
|
|
+ })
|
|
|
+ };
|
|
|
+
|
|
|
+ this.disableOnSearch = true;
|
|
|
+
|
|
|
+ // Update mimes list on open/reload
|
|
|
+ fm.bind('open reload', function() {
|
|
|
+ mimes = fm.option('archivers')['extract'] || [];
|
|
|
+ self.change();
|
|
|
+ });
|
|
|
+
|
|
|
+ this.getstate = function(sel) {
|
|
|
+ var sel = this.files(sel),
|
|
|
+ cnt = sel.length;
|
|
|
+
|
|
|
+ return !this._disabled && cnt && this.fm.cwd().write && filter(sel).length == cnt ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function(hashes) {
|
|
|
+ var files = this.files(hashes),
|
|
|
+ dfrd = $.Deferred(),
|
|
|
+ cnt = files.length,
|
|
|
+ i, error,
|
|
|
+ decision;
|
|
|
+
|
|
|
+ var overwriteAll = false;
|
|
|
+ var omitAll = false;
|
|
|
+
|
|
|
+ var names = $.map(fm.files(hashes), function(file) { return file.name; });
|
|
|
+ var map = {};
|
|
|
+ $.map(fm.files(hashes), function(file) { map[file.name] = file; });
|
|
|
+
|
|
|
+ var decide = function(decision) {
|
|
|
+ switch (decision) {
|
|
|
+ case 'overwrite_all' :
|
|
|
+ overwriteAll = true;
|
|
|
+ break;
|
|
|
+ case 'omit_all':
|
|
|
+ omitAll = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ var unpack = function(file) {
|
|
|
+ if (!(file.read && fm.file(file.phash).write)) {
|
|
|
+ error = ['errExtract', file.name, 'errPerm'];
|
|
|
+ fm.error(error);
|
|
|
+ dfrd.reject(error);
|
|
|
+ } else if ($.inArray(file.mime, mimes) === -1) {
|
|
|
+ error = ['errExtract', file.name, 'errNoArchive'];
|
|
|
+ fm.error(error);
|
|
|
+ dfrd.reject(error);
|
|
|
+ } else {
|
|
|
+ fm.request({
|
|
|
+ data:{cmd:'extract', target:file.hash},
|
|
|
+ notify:{type:'extract', cnt:1},
|
|
|
+ syncOnFail:true
|
|
|
+ })
|
|
|
+ .fail(function (error) {
|
|
|
+ if (dfrd.state() != 'rejected') {
|
|
|
+ dfrd.reject(error);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .done(function () {
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ var confirm = function(files, index) {
|
|
|
+ var file = files[index];
|
|
|
+ var name = file.name.replace(/\.((tar\.(gz|bz|bz2|z|lzo))|cpio\.gz|ps\.gz|xcf\.(gz|bz2)|[a-z0-9]{1,4})$/ig, '');
|
|
|
+ var existed = ($.inArray(name, names) >= 0);
|
|
|
+ if(existed && map[name].mime != 'directory') {
|
|
|
+ fm.confirm(
|
|
|
+ {
|
|
|
+ title : fm.i18n('ntfextract'),
|
|
|
+ text : fm.i18n(['errExists', name, 'confirmRepl']),
|
|
|
+ accept:{
|
|
|
+ label : 'btnYes',
|
|
|
+ callback:function (all) {
|
|
|
+ decision = all ? 'overwrite_all' : 'overwrite';
|
|
|
+ decide(decision);
|
|
|
+ if(!overwriteAll && !omitAll) {
|
|
|
+ if('overwrite' == decision) {
|
|
|
+ unpack(file);
|
|
|
+ }
|
|
|
+ if((index+1) < cnt) {
|
|
|
+ confirm(files, index+1);
|
|
|
+ } else {
|
|
|
+ dfrd.resolve();
|
|
|
+ }
|
|
|
+ } else if(overwriteAll) {
|
|
|
+ for (i = 0; i < cnt; i++) {
|
|
|
+ unpack(files[i]);
|
|
|
+ }
|
|
|
+ dfrd.resolve();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ reject : {
|
|
|
+ label : 'btnNo',
|
|
|
+ callback:function (all) {
|
|
|
+ decision = all ? 'omit_all' : 'omit';
|
|
|
+ decide(decision);
|
|
|
+ if(!overwriteAll && !omitAll && (index+1) < cnt) {
|
|
|
+ confirm(files, index+1);
|
|
|
+ } else if (omitAll) {
|
|
|
+ dfrd.resolve();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ cancel : {
|
|
|
+ label : 'btnCancel',
|
|
|
+ callback:function () {
|
|
|
+ dfrd.resolve();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ all : (cnt > 1)
|
|
|
+ }
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ unpack(file);
|
|
|
+ if((index+1) < cnt) {
|
|
|
+ confirm(files, index+1);
|
|
|
+ } else {
|
|
|
+ dfrd.resolve();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ if (!(this.enabled() && cnt && mimes.length)) {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ if(cnt > 0) {
|
|
|
+ confirm(files, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ return dfrd;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/forward.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "forward"
|
|
|
+ * Open next visited folder
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.forward = function() {
|
|
|
+ this.alwaysEnabled = true;
|
|
|
+ this.updateOnSelect = true;
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'ctrl+right'
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ return this.fm.history.canForward() ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function() {
|
|
|
+ return this.fm.history.forward();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/getfile.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "getfile".
|
|
|
+ * Return selected files info into outer callback.
|
|
|
+ * For use elFinder with wysiwyg editors etc.
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov, dio@std42.ru
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.getfile = function() {
|
|
|
+ var self = this,
|
|
|
+ fm = this.fm,
|
|
|
+ filter = function(files) {
|
|
|
+ var o = self.options;
|
|
|
+
|
|
|
+ files = $.map(files, function(file) {
|
|
|
+ return file.mime != 'directory' || o.folders ? file : null;
|
|
|
+ });
|
|
|
+
|
|
|
+ return o.multiple || files.length == 1 ? files : [];
|
|
|
+ };
|
|
|
+
|
|
|
+ this.alwaysEnabled = true;
|
|
|
+ this.callback = fm.options.getFileCallback;
|
|
|
+ this._disabled = typeof(this.callback) == 'function';
|
|
|
+
|
|
|
+ this.getstate = function(sel) {
|
|
|
+ var sel = this.files(sel),
|
|
|
+ cnt = sel.length;
|
|
|
+
|
|
|
+ return this.callback && cnt && filter(sel).length == cnt ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function(hashes) {
|
|
|
+ var fm = this.fm,
|
|
|
+ opts = this.options,
|
|
|
+ files = this.files(hashes),
|
|
|
+ cnt = files.length,
|
|
|
+ url = fm.option('url'),
|
|
|
+ tmb = fm.option('tmbUrl'),
|
|
|
+ dfrd = $.Deferred()
|
|
|
+ .done(function(data) {
|
|
|
+ fm.trigger('getfile', {files : data});
|
|
|
+ self.callback(data, fm);
|
|
|
+
|
|
|
+ if (opts.oncomplete == 'close') {
|
|
|
+ fm.hide();
|
|
|
+ } else if (opts.oncomplete == 'destroy') {
|
|
|
+ fm.destroy();
|
|
|
+ }
|
|
|
+ }),
|
|
|
+ result = function(file) {
|
|
|
+ return opts.onlyURL
|
|
|
+ ? opts.multiple ? $.map(files, function(f) { return f.url; }) : files[0].url
|
|
|
+ : opts.multiple ? files : files[0];
|
|
|
+ },
|
|
|
+ req = [],
|
|
|
+ i, file, dim;
|
|
|
+
|
|
|
+ if (this.getstate() == -1) {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < cnt; i++) {
|
|
|
+ file = files[i];
|
|
|
+ if (file.mime == 'directory' && !opts.folders) {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+ file.baseUrl = url;
|
|
|
+ file.url = fm.url(file.hash);
|
|
|
+ file.path = fm.path(file.hash);
|
|
|
+ if (file.tmb && file.tmb != 1) {
|
|
|
+ file.tmb = tmb + file.tmb;
|
|
|
+ }
|
|
|
+ if (!file.width && !file.height) {
|
|
|
+ if (file.dim) {
|
|
|
+ dim = file.dim.split('x');
|
|
|
+ file.width = dim[0];
|
|
|
+ file.height = dim[1];
|
|
|
+ } else if (file.mime.indexOf('image') !== -1) {
|
|
|
+ req.push(fm.request({
|
|
|
+ data : {cmd : 'dim', target : file.hash},
|
|
|
+ notify : {type : 'dim', cnt : 1, hideCnt : true},
|
|
|
+ preventDefault : true
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ if (data.dim) {
|
|
|
+ var dim = data.dim.split('x');
|
|
|
+ var rfile = fm.file(this.hash);
|
|
|
+ rfile.width = this.width = dim[0];
|
|
|
+ rfile.height = this.height = dim[1];
|
|
|
+ }
|
|
|
+ }.bind(file)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (req.length) {
|
|
|
+ $.when.apply(null, req).always(function() {
|
|
|
+ dfrd.resolve(result(files));
|
|
|
+ })
|
|
|
+ return dfrd;
|
|
|
+ }
|
|
|
+
|
|
|
+ return dfrd.resolve(result(files));
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/help.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "help"
|
|
|
+ * "About" dialog
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.help = function() {
|
|
|
+ var fm = this.fm,
|
|
|
+ self = this,
|
|
|
+ linktpl = '<div class="elfinder-help-link"> <a href="{url}">{link}</a></div>',
|
|
|
+ linktpltgt = '<div class="elfinder-help-link"> <a href="{url}" target="_blank">{link}</a></div>',
|
|
|
+ atpl = '<div class="elfinder-help-team"><div>{author}</div>{work}</div>',
|
|
|
+ url = /\{url\}/,
|
|
|
+ link = /\{link\}/,
|
|
|
+ author = /\{author\}/,
|
|
|
+ work = /\{work\}/,
|
|
|
+ r = 'replace',
|
|
|
+ prim = 'ui-priority-primary',
|
|
|
+ sec = 'ui-priority-secondary',
|
|
|
+ lic = 'elfinder-help-license',
|
|
|
+ tab = '<li class="ui-state-default ui-corner-top"><a href="#{id}">{title}</a></li>',
|
|
|
+ html = ['<div class="ui-tabs ui-widget ui-widget-content ui-corner-all elfinder-help">',
|
|
|
+ '<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">'],
|
|
|
+ stpl = '<div class="elfinder-help-shortcut"><div class="elfinder-help-shortcut-pattern">{pattern}</div> {descrip}</div>',
|
|
|
+ sep = '<div class="elfinder-help-separator"/>',
|
|
|
+
|
|
|
+
|
|
|
+ about = function() {
|
|
|
+ html.push('<div id="about" class="ui-tabs-panel ui-widget-content ui-corner-bottom"><div class="elfinder-help-logo"/>')
|
|
|
+ html.push('<h3>elFinder</h3>');
|
|
|
+ html.push('<div class="'+prim+'">'+fm.i18n('webfm')+'</div>');
|
|
|
+ html.push('<div class="'+sec+'">'+fm.i18n('ver')+': '+fm.version+', '+fm.i18n('protocolver')+': <span id="apiver"></span></div>');
|
|
|
+ html.push('<div class="'+sec+'">jQuery/jQuery UI: '+$().jquery+'/'+$.ui.version+'</div>');
|
|
|
+
|
|
|
+ html.push(sep);
|
|
|
+
|
|
|
+ html.push(linktpltgt[r](url, 'http://elfinder.org/')[r](link, fm.i18n('homepage')));
|
|
|
+ html.push(linktpltgt[r](url, 'https://github.com/Studio-42/elFinder/wiki')[r](link, fm.i18n('docs')));
|
|
|
+ html.push(linktpltgt[r](url, 'https://github.com/Studio-42/elFinder')[r](link, fm.i18n('github')));
|
|
|
+ html.push(linktpltgt[r](url, 'http://twitter.com/elrte_elfinder')[r](link, fm.i18n('twitter')));
|
|
|
+
|
|
|
+ html.push(sep);
|
|
|
+
|
|
|
+ html.push('<div class="'+prim+'">'+fm.i18n('team')+'</div>');
|
|
|
+
|
|
|
+ html.push(atpl[r](author, 'Dmitry "dio" Levashov <dio@std42.ru>')[r](work, fm.i18n('chiefdev')));
|
|
|
+ html.push(atpl[r](author, 'Troex Nevelin <troex@fury.scancode.ru>')[r](work, fm.i18n('maintainer')));
|
|
|
+ html.push(atpl[r](author, 'Alexey Sukhotin <strogg@yandex.ru>')[r](work, fm.i18n('contributor')));
|
|
|
+ html.push(atpl[r](author, 'Naoki Sawada <hypweb@gmail.com>')[r](work, fm.i18n('contributor')));
|
|
|
+
|
|
|
+ fm.i18[fm.lang].translator && html.push(atpl[r](author, fm.i18[fm.lang].translator)[r](work, fm.i18n('translator')+' ('+fm.i18[fm.lang].language+')'));
|
|
|
+
|
|
|
+ html.push(sep);
|
|
|
+ html.push('<div class="'+lic+'">'+fm.i18n('icons')+': Pixelmixer, <a href="http://p.yusukekamiyamane.com" target="_blank">Fugue</a></div>');
|
|
|
+
|
|
|
+ html.push(sep);
|
|
|
+ html.push('<div class="'+lic+'">Licence: BSD Licence</div>');
|
|
|
+ html.push('<div class="'+lic+'">Copyright © 2009-2011, Studio 42</div>');
|
|
|
+ html.push('<div class="'+lic+'">„ …'+fm.i18n('dontforget')+' ”</div>');
|
|
|
+ html.push('</div>');
|
|
|
+ },
|
|
|
+ shortcuts = function() {
|
|
|
+ var sh = fm.shortcuts();
|
|
|
+ // shortcuts tab
|
|
|
+ html.push('<div id="shortcuts" class="ui-tabs-panel ui-widget-content ui-corner-bottom">');
|
|
|
+
|
|
|
+ if (sh.length) {
|
|
|
+ html.push('<div class="ui-widget-content elfinder-help-shortcuts">');
|
|
|
+ $.each(sh, function(i, s) {
|
|
|
+ html.push(stpl.replace(/\{pattern\}/, s[0]).replace(/\{descrip\}/, s[1]));
|
|
|
+ });
|
|
|
+
|
|
|
+ html.push('</div>');
|
|
|
+ } else {
|
|
|
+ html.push('<div class="elfinder-help-disabled">'+fm.i18n('shortcutsof')+'</div>')
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ html.push('</div>')
|
|
|
+
|
|
|
+ },
|
|
|
+ help = function() {
|
|
|
+ // help tab
|
|
|
+ html.push('<div id="help" class="ui-tabs-panel ui-widget-content ui-corner-bottom">');
|
|
|
+ html.push('<a href="http://elfinder.org/forum/" target="_blank" class="elfinder-dont-panic"><span>DON\'T PANIC</span></a>');
|
|
|
+ html.push('</div>');
|
|
|
+ // end help
|
|
|
+ },
|
|
|
+ content;
|
|
|
+
|
|
|
+ this.alwaysEnabled = true;
|
|
|
+ this.updateOnSelect = false;
|
|
|
+ this.state = 0;
|
|
|
+
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'f1',
|
|
|
+ description : this.title
|
|
|
+ }];
|
|
|
+
|
|
|
+ setTimeout(function() {
|
|
|
+ var parts = self.options.view || ['about', 'shortcuts', 'help'];
|
|
|
+
|
|
|
+ $.each(parts, function(i, title) {
|
|
|
+ html.push(tab[r](/\{id\}/, title)[r](/\{title\}/, fm.i18n(title)));
|
|
|
+ });
|
|
|
+
|
|
|
+ html.push('</ul>');
|
|
|
+
|
|
|
+ $.inArray('about', parts) !== -1 && about();
|
|
|
+ $.inArray('shortcuts', parts) !== -1 && shortcuts();
|
|
|
+ $.inArray('help', parts) !== -1 && help();
|
|
|
+
|
|
|
+ html.push('</div>');
|
|
|
+ content = $(html.join(''));
|
|
|
+
|
|
|
+ fm.one('load', function setapi() { content.find('#apiver').text(fm.api); });
|
|
|
+
|
|
|
+ content.find('.ui-tabs-nav li')
|
|
|
+ .hover(function() {
|
|
|
+ $(this).toggleClass('ui-state-hover')
|
|
|
+ })
|
|
|
+ .children()
|
|
|
+ .click(function(e) {
|
|
|
+ var link = $(this);
|
|
|
+
|
|
|
+ e.preventDefault();
|
|
|
+ e.stopPropagation();
|
|
|
+
|
|
|
+ if (!link.is('.ui-tabs-selected')) {
|
|
|
+ link.parent().addClass('ui-tabs-selected ui-state-active').siblings().removeClass('ui-tabs-selected').removeClass('ui-state-active');
|
|
|
+ content.find('.ui-tabs-panel').hide().filter(link.attr('href')).show();
|
|
|
+ }
|
|
|
+
|
|
|
+ })
|
|
|
+ .filter(':first').click();
|
|
|
+
|
|
|
+ }, 200)
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function() {
|
|
|
+ if (!this.dialog) {
|
|
|
+ this.dialog = this.fm.dialog(content, {title : this.title, width : 530, autoOpen : false, destroyOnClose : false});
|
|
|
+ }
|
|
|
+
|
|
|
+ this.dialog.elfinderdialog('open').find('.ui-tabs-nav li a:first').click();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/home.js
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+elFinder.prototype.commands.home = function() {
|
|
|
+ this.title = 'Home';
|
|
|
+ this.alwaysEnabled = true;
|
|
|
+ this.updateOnSelect = false;
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'ctrl+home ctrl+shift+up',
|
|
|
+ description : 'Home'
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ var root = this.fm.root(),
|
|
|
+ cwd = this.fm.cwd().hash;
|
|
|
+
|
|
|
+ return root && cwd && root != cwd ? 0: -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function() {
|
|
|
+ return this.fm.exec('open', this.fm.root());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/info.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "info".
|
|
|
+ * Display dialog with file properties.
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov, dio@std42.ru
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.info = function() {
|
|
|
+ var m = 'msg',
|
|
|
+ fm = this.fm,
|
|
|
+ spclass = 'elfinder-info-spinner',
|
|
|
+ msg = {
|
|
|
+ calc : fm.i18n('calc'),
|
|
|
+ size : fm.i18n('size'),
|
|
|
+ unknown : fm.i18n('unknown'),
|
|
|
+ path : fm.i18n('path'),
|
|
|
+ aliasfor : fm.i18n('aliasfor'),
|
|
|
+ modify : fm.i18n('modify'),
|
|
|
+ perms : fm.i18n('perms'),
|
|
|
+ locked : fm.i18n('locked'),
|
|
|
+ dim : fm.i18n('dim'),
|
|
|
+ kind : fm.i18n('kind'),
|
|
|
+ files : fm.i18n('files'),
|
|
|
+ folders : fm.i18n('folders'),
|
|
|
+ items : fm.i18n('items'),
|
|
|
+ yes : fm.i18n('yes'),
|
|
|
+ no : fm.i18n('no'),
|
|
|
+ link : fm.i18n('link')
|
|
|
+ };
|
|
|
+
|
|
|
+ this.tpl = {
|
|
|
+ main : '<div class="ui-helper-clearfix elfinder-info-title"><span class="elfinder-cwd-icon {class} ui-corner-all"/>{title}</div><table class="elfinder-info-tb">{content}</table>',
|
|
|
+ itemTitle : '<strong>{name}</strong><span class="elfinder-info-kind">{kind}</span>',
|
|
|
+ groupTitle : '<strong>{items}: {num}</strong>',
|
|
|
+ row : '<tr><td>{label} : </td><td>{value}</td></tr>',
|
|
|
+ spinner : '<span>{text}</span> <span class="'+spclass+'"/>'
|
|
|
+ }
|
|
|
+
|
|
|
+ this.alwaysEnabled = true;
|
|
|
+ this.updateOnSelect = false;
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'ctrl+i'
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.init = function() {
|
|
|
+ $.each(msg, function(k, v) {
|
|
|
+ msg[k] = fm.i18n(v);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function(hashes) {
|
|
|
+ var files = this.files(hashes);
|
|
|
+ if (! files.length) {
|
|
|
+ files = this.files([ this.fm.cwd().hash ]);
|
|
|
+ }
|
|
|
+ var self = this,
|
|
|
+ fm = this.fm,
|
|
|
+ tpl = this.tpl,
|
|
|
+ row = tpl.row,
|
|
|
+ cnt = files.length,
|
|
|
+ content = [],
|
|
|
+ view = tpl.main,
|
|
|
+ l = '{label}',
|
|
|
+ v = '{value}',
|
|
|
+ opts = {
|
|
|
+ title : this.title,
|
|
|
+ width : 'auto',
|
|
|
+ close : function() { $(this).elfinderdialog('destroy'); }
|
|
|
+ },
|
|
|
+ count = [],
|
|
|
+ replSpinner = function(msg) { dialog.find('.'+spclass).parent().text(msg); },
|
|
|
+ id = fm.namespace+'-info-'+$.map(files, function(f) { return f.hash }).join('-'),
|
|
|
+ dialog = fm.getUI().find('#'+id),
|
|
|
+ size, tmb, file, title, dcnt;
|
|
|
+
|
|
|
+ if (!cnt) {
|
|
|
+ return $.Deferred().reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dialog.length) {
|
|
|
+ dialog.elfinderdialog('toTop');
|
|
|
+ return $.Deferred().resolve();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (cnt == 1) {
|
|
|
+ file = files[0];
|
|
|
+
|
|
|
+ view = view.replace('{class}', fm.mime2class(file.mime));
|
|
|
+ title = tpl.itemTitle.replace('{name}', fm.escape(file.i18 || file.name)).replace('{kind}', fm.mime2kind(file));
|
|
|
+
|
|
|
+ if (file.tmb) {
|
|
|
+ tmb = fm.option('tmbUrl')+file.tmb;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!file.read) {
|
|
|
+ size = msg.unknown;
|
|
|
+ } else if (file.mime != 'directory' || file.alias) {
|
|
|
+ size = fm.formatSize(file.size);
|
|
|
+ } else {
|
|
|
+ size = tpl.spinner.replace('{text}', msg.calc);
|
|
|
+ count.push(file.hash);
|
|
|
+ }
|
|
|
+
|
|
|
+ content.push(row.replace(l, msg.size).replace(v, size));
|
|
|
+ file.alias && content.push(row.replace(l, msg.aliasfor).replace(v, file.alias));
|
|
|
+ content.push(row.replace(l, msg.path).replace(v, fm.escape(fm.path(file.hash, true))));
|
|
|
+ file.read && content.push(row.replace(l, msg.link).replace(v, '<a href="'+fm.url(file.hash)+'" target="_blank">'+file.name+'</a>'));
|
|
|
+
|
|
|
+ if (file.dim) { // old api
|
|
|
+ content.push(row.replace(l, msg.dim).replace(v, file.dim));
|
|
|
+ } else if (file.mime.indexOf('image') !== -1) {
|
|
|
+ if (file.width && file.height) {
|
|
|
+ content.push(row.replace(l, msg.dim).replace(v, file.width+'x'+file.height));
|
|
|
+ } else {
|
|
|
+ content.push(row.replace(l, msg.dim).replace(v, tpl.spinner.replace('{text}', msg.calc)));
|
|
|
+ fm.request({
|
|
|
+ data : {cmd : 'dim', target : file.hash},
|
|
|
+ preventDefault : true
|
|
|
+ })
|
|
|
+ .fail(function() {
|
|
|
+ replSpinner(msg.unknown);
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ replSpinner(data.dim || msg.unknown);
|
|
|
+ if (data.dim) {
|
|
|
+ var dim = data.dim.split('x');
|
|
|
+ var rfile = fm.file(file.hash);
|
|
|
+ rfile.width = dim[0];
|
|
|
+ rfile.height = dim[1];
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ content.push(row.replace(l, msg.modify).replace(v, fm.formatDate(file)));
|
|
|
+ content.push(row.replace(l, msg.perms).replace(v, fm.formatPermissions(file)));
|
|
|
+ content.push(row.replace(l, msg.locked).replace(v, file.locked ? msg.yes : msg.no));
|
|
|
+ } else {
|
|
|
+ view = view.replace('{class}', 'elfinder-cwd-icon-group');
|
|
|
+ title = tpl.groupTitle.replace('{items}', msg.items).replace('{num}', cnt);
|
|
|
+ dcnt = $.map(files, function(f) { return f.mime == 'directory' ? 1 : null }).length;
|
|
|
+ if (!dcnt) {
|
|
|
+ size = 0;
|
|
|
+ $.each(files, function(h, f) {
|
|
|
+ var s = parseInt(f.size);
|
|
|
+
|
|
|
+ if (s >= 0 && size >= 0) {
|
|
|
+ size += s;
|
|
|
+ } else {
|
|
|
+ size = 'unknown';
|
|
|
+ }
|
|
|
+ });
|
|
|
+ content.push(row.replace(l, msg.kind).replace(v, msg.files));
|
|
|
+ content.push(row.replace(l, msg.size).replace(v, fm.formatSize(size)));
|
|
|
+ } else {
|
|
|
+ content.push(row.replace(l, msg.kind).replace(v, dcnt == cnt ? msg.folders : msg.folders+' '+dcnt+', '+msg.files+' '+(cnt-dcnt)))
|
|
|
+ content.push(row.replace(l, msg.size).replace(v, tpl.spinner.replace('{text}', msg.calc)));
|
|
|
+ count = $.map(files, function(f) { return f.hash });
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ view = view.replace('{title}', title).replace('{content}', content.join(''));
|
|
|
+
|
|
|
+ dialog = fm.dialog(view, opts);
|
|
|
+ dialog.attr('id', id)
|
|
|
+
|
|
|
+ // load thumbnail
|
|
|
+ if (tmb) {
|
|
|
+ $('<img/>')
|
|
|
+ .load(function() { dialog.find('.elfinder-cwd-icon').css('background', 'url("'+tmb+'") center center no-repeat'); })
|
|
|
+ .attr('src', tmb);
|
|
|
+ }
|
|
|
+
|
|
|
+ // send request to count total size
|
|
|
+ if (count.length) {
|
|
|
+ fm.request({
|
|
|
+ data : {cmd : 'size', targets : count},
|
|
|
+ preventDefault : true
|
|
|
+ })
|
|
|
+ .fail(function() {
|
|
|
+ replSpinner(msg.unknown);
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ var size = parseInt(data.size);
|
|
|
+ replSpinner(size >= 0 ? fm.formatSize(size) : msg.unknown);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/mkdir.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "mkdir"
|
|
|
+ * Create new folder
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.mkdir = function() {
|
|
|
+ this.disableOnSearch = true;
|
|
|
+ this.updateOnSelect = false;
|
|
|
+ this.mime = 'directory';
|
|
|
+ this.prefix = 'untitled folder';
|
|
|
+ this.exec = $.proxy(this.fm.res('mixin', 'make'), this);
|
|
|
+
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'ctrl+shift+n'
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ return !this._disabled && this.fm.cwd().write ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/mkfile.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "mkfile"
|
|
|
+ * Create new empty file
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.mkfile = function() {
|
|
|
+ this.disableOnSearch = true;
|
|
|
+ this.updateOnSelect = false;
|
|
|
+ this.mime = 'text/plain';
|
|
|
+ this.prefix = 'untitled file.txt';
|
|
|
+ this.exec = $.proxy(this.fm.res('mixin', 'make'), this);
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ return !this._disabled && this.fm.cwd().write ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/netmount.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "netmount"
|
|
|
+ * Mount network volume with user credentials.
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.netmount = function() {
|
|
|
+ var self = this;
|
|
|
+
|
|
|
+ this.alwaysEnabled = true;
|
|
|
+ this.updateOnSelect = false;
|
|
|
+
|
|
|
+ this.drivers = [];
|
|
|
+
|
|
|
+ this.handlers = {
|
|
|
+ load : function() {
|
|
|
+ this.drivers = this.fm.netDrivers;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ return this.drivers.length ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function() {
|
|
|
+ var fm = self.fm,
|
|
|
+ dfrd = $.Deferred(),
|
|
|
+ create = function() {
|
|
|
+ var inputs = {
|
|
|
+ protocol : $('<select/>'),
|
|
|
+ host : $('<input type="text"/>'),
|
|
|
+ port : $('<input type="text"/>'),
|
|
|
+ path : $('<input type="text" value="/"/>'),
|
|
|
+ user : $('<input type="text"/>'),
|
|
|
+ pass : $('<input type="password"/>')
|
|
|
+ },
|
|
|
+ opts = {
|
|
|
+ title : fm.i18n('netMountDialogTitle'),
|
|
|
+ resizable : false,
|
|
|
+ modal : true,
|
|
|
+ destroyOnClose : true,
|
|
|
+ close : function() {
|
|
|
+ delete self.dialog;
|
|
|
+ dfrd.state() == 'pending' && dfrd.reject();
|
|
|
+ },
|
|
|
+ buttons : {}
|
|
|
+ },
|
|
|
+ content = $('<table class="elfinder-info-tb elfinder-netmount-tb"/>');
|
|
|
+
|
|
|
+ $.each(self.drivers, function(i, protocol) {
|
|
|
+ inputs.protocol.append('<option value="'+protocol+'">'+fm.i18n(protocol)+'</option>');
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ $.each(inputs, function(name, input) {
|
|
|
+ name != 'protocol' && input.addClass('ui-corner-all');
|
|
|
+ content.append($('<tr/>').append($('<td>'+fm.i18n(name)+'</td>')).append($('<td/>').append(input)));
|
|
|
+ });
|
|
|
+
|
|
|
+ opts.buttons[fm.i18n('btnMount')] = function() {
|
|
|
+ var data = {cmd : 'netmount'};
|
|
|
+
|
|
|
+ $.each(inputs, function(name, input) {
|
|
|
+ var val = $.trim(input.val());
|
|
|
+
|
|
|
+ if (val) {
|
|
|
+ data[name] = val;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!data.host) {
|
|
|
+ return self.fm.trigger('error', {error : 'errNetMountHostReq'});
|
|
|
+ }
|
|
|
+
|
|
|
+ self.fm.request({data : data, notify : {type : 'netmount', cnt : 1}})
|
|
|
+ .done(function() { dfrd.resolve(); })
|
|
|
+ .fail(function(error) { dfrd.reject(error); });
|
|
|
+
|
|
|
+ self.dialog.elfinderdialog('close');
|
|
|
+ }
|
|
|
+
|
|
|
+ opts.buttons[fm.i18n('btnCancel')] = function() {
|
|
|
+ self.dialog.elfinderdialog('close');
|
|
|
+ }
|
|
|
+
|
|
|
+ return fm.dialog(content, opts);
|
|
|
+ }
|
|
|
+ ;
|
|
|
+
|
|
|
+ if (!self.dialog) {
|
|
|
+ self.dialog = create()
|
|
|
+ }
|
|
|
+
|
|
|
+ return dfrd.promise();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/open.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "open"
|
|
|
+ * Enter folder or open files in new windows
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.open = function() {
|
|
|
+ this.alwaysEnabled = true;
|
|
|
+
|
|
|
+ this._handlers = {
|
|
|
+ dblclick : function(e) { e.preventDefault(); this.exec() },
|
|
|
+ 'select enable disable reload' : function(e) { this.update(e.type == 'disable' ? -1 : void(0)); }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'ctrl+down numpad_enter'+(this.fm.OS != 'mac' && ' enter')
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.getstate = function(sel) {
|
|
|
+ var sel = this.files(sel),
|
|
|
+ cnt = sel.length;
|
|
|
+
|
|
|
+ return cnt == 1
|
|
|
+ ? 0
|
|
|
+ : cnt ? ($.map(sel, function(file) { return file.mime == 'directory' ? null : file}).length == cnt ? 0 : -1) : -1
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function(hashes) {
|
|
|
+ var fm = this.fm,
|
|
|
+ dfrd = $.Deferred().fail(function(error) { error && fm.error(error); }),
|
|
|
+ files = this.files(hashes),
|
|
|
+ cnt = files.length,
|
|
|
+ file, url, s, w;
|
|
|
+
|
|
|
+ if (!cnt) {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ // open folder
|
|
|
+ if (cnt == 1 && (file = files[0]) && file.mime == 'directory') {
|
|
|
+ return file && !file.read
|
|
|
+ ? dfrd.reject(['errOpen', file.name, 'errPerm'])
|
|
|
+ : fm.request({
|
|
|
+ data : {cmd : 'open', target : file.thash || file.hash},
|
|
|
+ notify : {type : 'open', cnt : 1, hideCnt : true},
|
|
|
+ syncOnFail : true
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ files = $.map(files, function(file) { return file.mime != 'directory' ? file : null });
|
|
|
+
|
|
|
+ // nothing to open or files and folders selected - do nothing
|
|
|
+ if (cnt != files.length) {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ // open files
|
|
|
+ cnt = files.length;
|
|
|
+ while (cnt--) {
|
|
|
+ file = files[cnt];
|
|
|
+
|
|
|
+ if (!file.read) {
|
|
|
+ return dfrd.reject(['errOpen', file.name, 'errPerm']);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!(url = fm.url(/*file.thash || */file.hash))) {
|
|
|
+ url = fm.options.url;
|
|
|
+ url = url + (url.indexOf('?') === -1 ? '?' : '&')
|
|
|
+ + (fm.oldAPI ? 'cmd=open¤t='+file.phash : 'cmd=file')
|
|
|
+ + '&target=' + file.hash;
|
|
|
+ }
|
|
|
+
|
|
|
+ // set window size for image if set
|
|
|
+ if (file.dim) {
|
|
|
+ s = file.dim.split('x');
|
|
|
+ w = 'width='+(parseInt(s[0])+20) + ',height='+(parseInt(s[1])+20);
|
|
|
+ } else {
|
|
|
+ w = 'width='+parseInt(2*$(window).width()/3)+',height='+parseInt(2*$(window).height()/3);
|
|
|
+ }
|
|
|
+
|
|
|
+ var wnd = window.open('', 'new_window', w + ',top=50,left=50,scrollbars=yes,resizable=yes');
|
|
|
+ if (!wnd) {
|
|
|
+ return dfrd.reject('errPopup');
|
|
|
+ }
|
|
|
+
|
|
|
+ var form = document.createElement("form");
|
|
|
+ form.action = fm.options.url;
|
|
|
+ form.method = 'POST';
|
|
|
+ form.target = 'new_window';
|
|
|
+ form.style.display = 'none';
|
|
|
+ var params = $.extend({}, fm.options.customData, {
|
|
|
+ cmd: 'file',
|
|
|
+ target: file.hash
|
|
|
+ });
|
|
|
+ $.each(params, function(key, val)
|
|
|
+ {
|
|
|
+ var input = document.createElement("input");
|
|
|
+ input.name = key;
|
|
|
+ input.value = val;
|
|
|
+ form.appendChild(input);
|
|
|
+ });
|
|
|
+
|
|
|
+ document.body.appendChild(form);
|
|
|
+ form.submit();
|
|
|
+ }
|
|
|
+ return dfrd.resolve(hashes);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/paste.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "paste"
|
|
|
+ * Paste filesfrom clipboard into directory.
|
|
|
+ * If files pasted in its parent directory - files duplicates will created
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.paste = function() {
|
|
|
+
|
|
|
+ this.updateOnSelect = false;
|
|
|
+
|
|
|
+ this.handlers = {
|
|
|
+ changeclipboard : function() { this.update(); }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'ctrl+v shift+insert'
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.getstate = function(dst) {
|
|
|
+ if (this._disabled) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if (dst) {
|
|
|
+ if ($.isArray(dst)) {
|
|
|
+ if (dst.length != 1) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ dst = this.fm.file(dst[0]);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ dst = this.fm.cwd();
|
|
|
+ }
|
|
|
+
|
|
|
+ return this.fm.clipboard().length && dst.mime == 'directory' && dst.write ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function(dst) {
|
|
|
+ var self = this,
|
|
|
+ fm = self.fm,
|
|
|
+ dst = dst ? this.files(dst)[0] : fm.cwd(),
|
|
|
+ files = fm.clipboard(),
|
|
|
+ cnt = files.length,
|
|
|
+ cut = cnt ? files[0].cut : false,
|
|
|
+ error = cut ? 'errMove' : 'errCopy',
|
|
|
+ fpaste = [],
|
|
|
+ fcopy = [],
|
|
|
+ dfrd = $.Deferred()
|
|
|
+ .fail(function(error) {
|
|
|
+ error && fm.error(error);
|
|
|
+ }),
|
|
|
+ copy = function(files) {
|
|
|
+ return files.length && fm._commands.duplicate
|
|
|
+ ? fm.exec('duplicate', files)
|
|
|
+ : $.Deferred().resolve();
|
|
|
+ },
|
|
|
+ paste = function(files) {
|
|
|
+ var dfrd = $.Deferred(),
|
|
|
+ existed = [],
|
|
|
+ intersect = function(files, names) {
|
|
|
+ var ret = [],
|
|
|
+ i = files.length;
|
|
|
+
|
|
|
+ while (i--) {
|
|
|
+ $.inArray(files[i].name, names) !== -1 && ret.unshift(i);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+ },
|
|
|
+ confirm = function(ndx) {
|
|
|
+ var i = existed[ndx],
|
|
|
+ file = files[i],
|
|
|
+ last = ndx == existed.length-1;
|
|
|
+
|
|
|
+ if (!file) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ fm.confirm({
|
|
|
+ title : fm.i18n(cut ? 'moveFiles' : 'copyFiles'),
|
|
|
+ text : fm.i18n(['errExists', file.name, 'confirmRepl']),
|
|
|
+ all : !last,
|
|
|
+ accept : {
|
|
|
+ label : 'btnYes',
|
|
|
+ callback : function(all) {
|
|
|
+ !last && !all
|
|
|
+ ? confirm(++ndx)
|
|
|
+ : paste(files);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ reject : {
|
|
|
+ label : 'btnNo',
|
|
|
+ callback : function(all) {
|
|
|
+ var i;
|
|
|
+
|
|
|
+ if (all) {
|
|
|
+ i = existed.length;
|
|
|
+ while (ndx < i--) {
|
|
|
+ files[existed[i]].remove = true
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ files[existed[ndx]].remove = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ !last && !all
|
|
|
+ ? confirm(++ndx)
|
|
|
+ : paste(files);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ cancel : {
|
|
|
+ label : 'btnCancel',
|
|
|
+ callback : function() {
|
|
|
+ dfrd.resolve();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ valid = function(names) {
|
|
|
+ existed = intersect(files, names);
|
|
|
+ existed.length ? confirm(0) : paste(files);
|
|
|
+ },
|
|
|
+ paste = function(files) {
|
|
|
+ var files = $.map(files, function(file) { return !file.remove ? file : null } ),
|
|
|
+ cnt = files.length,
|
|
|
+ groups = {},
|
|
|
+ args = [],
|
|
|
+ src;
|
|
|
+
|
|
|
+ if (!cnt) {
|
|
|
+ return dfrd.resolve();
|
|
|
+ }
|
|
|
+
|
|
|
+ src = files[0].phash;
|
|
|
+ files = $.map(files, function(f) { return f.hash});
|
|
|
+
|
|
|
+ fm.request({
|
|
|
+ data : {cmd : 'paste', dst : dst.hash, targets : files, cut : cut ? 1 : 0, src : src},
|
|
|
+ notify : {type : cut ? 'move' : 'copy', cnt : cnt}
|
|
|
+ })
|
|
|
+ .always(function() {
|
|
|
+ dfrd.resolve();
|
|
|
+ fm.unlockfiles({files : files});
|
|
|
+ });
|
|
|
+ }
|
|
|
+ ;
|
|
|
+
|
|
|
+ if (self._disabled || !files.length) {
|
|
|
+ return dfrd.resolve();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (fm.oldAPI) {
|
|
|
+ paste(files);
|
|
|
+ } else {
|
|
|
+
|
|
|
+ if (!fm.option('copyOverwrite')) {
|
|
|
+ paste(files);
|
|
|
+ } else {
|
|
|
+
|
|
|
+ dst.hash == fm.cwd().hash
|
|
|
+ ? valid($.map(fm.files(), function(file) { return file.phash == dst.hash ? file.name : null }))
|
|
|
+ : fm.request({
|
|
|
+ data : {cmd : 'ls', target : dst.hash},
|
|
|
+ notify : {type : 'prepare', cnt : 1, hideCnt : true},
|
|
|
+ preventFail : true
|
|
|
+ })
|
|
|
+ .always(function(data) {
|
|
|
+ valid(data.list || [])
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return dfrd;
|
|
|
+ },
|
|
|
+ parents, fparents;
|
|
|
+
|
|
|
+
|
|
|
+ if (!cnt || !dst || dst.mime != 'directory') {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!dst.write) {
|
|
|
+ return dfrd.reject([error, files[0].name, 'errPerm']);
|
|
|
+ }
|
|
|
+
|
|
|
+ parents = fm.parents(dst.hash);
|
|
|
+
|
|
|
+ $.each(files, function(i, file) {
|
|
|
+ if (!file.read) {
|
|
|
+ return !dfrd.reject([error, files[0].name, 'errPerm']);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cut && file.locked) {
|
|
|
+ return !dfrd.reject(['errLocked', file.name]);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($.inArray(file.hash, parents) !== -1) {
|
|
|
+ return !dfrd.reject(['errCopyInItself', file.name]);
|
|
|
+ }
|
|
|
+
|
|
|
+ fparents = fm.parents(file.hash);
|
|
|
+ if ($.inArray(dst.hash, fparents) !== -1) {
|
|
|
+
|
|
|
+ if ($.map(fparents, function(h) { var d = fm.file(h); return d.phash == dst.hash && d.name == file.name ? d : null }).length) {
|
|
|
+ return !dfrd.reject(['errReplByChild', file.name]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (file.phash == dst.hash) {
|
|
|
+ fcopy.push(file.hash);
|
|
|
+ } else {
|
|
|
+ fpaste.push({
|
|
|
+ hash : file.hash,
|
|
|
+ phash : file.phash,
|
|
|
+ name : file.name
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (dfrd.state() == 'rejected') {
|
|
|
+ return dfrd;
|
|
|
+ }
|
|
|
+
|
|
|
+ return $.when(
|
|
|
+ copy(fcopy),
|
|
|
+ paste(fpaste)
|
|
|
+ ).always(function() {
|
|
|
+ cut && fm.clipboard([]);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/quicklook.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "quicklook"
|
|
|
+ * Fast preview for some files types
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.quicklook = function() {
|
|
|
+ var self = this,
|
|
|
+ fm = self.fm,
|
|
|
+ /**
|
|
|
+ * window closed state
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ **/
|
|
|
+ closed = 0,
|
|
|
+ /**
|
|
|
+ * window animated state
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ **/
|
|
|
+ animated = 1,
|
|
|
+ /**
|
|
|
+ * window opened state
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ **/
|
|
|
+ opened = 2,
|
|
|
+ /**
|
|
|
+ * window state
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ **/
|
|
|
+ state = closed,
|
|
|
+ /**
|
|
|
+ * next/prev event name (requied to cwd catch it)
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ **/
|
|
|
+ // keydown = fm.UA.Firefox || fm.UA.Opera ? 'keypress' : 'keydown',
|
|
|
+ /**
|
|
|
+ * navbar icon class
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ **/
|
|
|
+ navicon = 'elfinder-quicklook-navbar-icon',
|
|
|
+ /**
|
|
|
+ * navbar "fullscreen" icon class
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ **/
|
|
|
+ fullscreen = 'elfinder-quicklook-fullscreen',
|
|
|
+ /**
|
|
|
+ * Triger keydown/keypress event with left/right arrow key code
|
|
|
+ *
|
|
|
+ * @param Number left/right arrow key code
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ navtrigger = function(code) {
|
|
|
+ $(document).trigger($.Event('keydown', { keyCode: code, ctrlKey : false, shiftKey : false, altKey : false, metaKey : false }));
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * Return css for closed window
|
|
|
+ *
|
|
|
+ * @param jQuery file node in cwd
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ closedCss = function(node) {
|
|
|
+ return {
|
|
|
+ opacity : 0,
|
|
|
+ width : 20,//node.width(),
|
|
|
+ height : fm.view == 'list' ? 1 : 20,
|
|
|
+ top : node.offset().top+'px',
|
|
|
+ left : node.offset().left+'px'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * Return css for opened window
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ openedCss = function() {
|
|
|
+ var win = $(window);
|
|
|
+ return {
|
|
|
+ opacity : 1,
|
|
|
+ width : width,
|
|
|
+ height : height,
|
|
|
+ top : parseInt((win.height() - height)/2 + win.scrollTop()),
|
|
|
+ left : parseInt((win.width() - width)/2 + win.scrollLeft())
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ support = function(codec) {
|
|
|
+ var media = document.createElement(codec.substr(0, codec.indexOf('/'))),
|
|
|
+ value = false;
|
|
|
+
|
|
|
+ try {
|
|
|
+ value = media.canPlayType && media.canPlayType(codec);
|
|
|
+ } catch (e) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return value && value !== '' && value != 'no';
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Opened window width (from config)
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ **/
|
|
|
+ width,
|
|
|
+ /**
|
|
|
+ * Opened window height (from config)
|
|
|
+ *
|
|
|
+ * @type Number
|
|
|
+ **/
|
|
|
+ height,
|
|
|
+ /**
|
|
|
+ * elFinder node
|
|
|
+ *
|
|
|
+ * @type jQuery
|
|
|
+ **/
|
|
|
+ parent,
|
|
|
+ /**
|
|
|
+ * elFinder current directory node
|
|
|
+ *
|
|
|
+ * @type jQuery
|
|
|
+ **/
|
|
|
+ cwd,
|
|
|
+ title = $('<div class="elfinder-quicklook-title"/>'),
|
|
|
+ icon = $('<div/>'),
|
|
|
+ info = $('<div class="elfinder-quicklook-info"/>'),//.hide(),
|
|
|
+ fsicon = $('<div class="'+navicon+' '+navicon+'-fullscreen"/>')
|
|
|
+ .mousedown(function(e) {
|
|
|
+ var win = self.window,
|
|
|
+ full = win.is('.'+fullscreen),
|
|
|
+ scroll = 'scroll.'+fm.namespace,
|
|
|
+ $window = $(window);
|
|
|
+
|
|
|
+ e.stopPropagation();
|
|
|
+
|
|
|
+ if (full) {
|
|
|
+ win.css(win.data('position')).unbind('mousemove');
|
|
|
+ $window.unbind(scroll).trigger(self.resize).unbind(self.resize);
|
|
|
+ navbar.unbind('mouseenter').unbind('mousemove');
|
|
|
+ } else {
|
|
|
+ win.data('position', {
|
|
|
+ left : win.css('left'),
|
|
|
+ top : win.css('top'),
|
|
|
+ width : win.width(),
|
|
|
+ height : win.height()
|
|
|
+ })
|
|
|
+ .css({
|
|
|
+ width : '100%',
|
|
|
+ height : '100%'
|
|
|
+ });
|
|
|
+
|
|
|
+ $(window).bind(scroll, function() {
|
|
|
+ win.css({
|
|
|
+ left : parseInt($(window).scrollLeft())+'px',
|
|
|
+ top : parseInt($(window).scrollTop()) +'px'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ .bind(self.resize, function(e) {
|
|
|
+ self.preview.trigger('changesize');
|
|
|
+ })
|
|
|
+ .trigger(scroll)
|
|
|
+ .trigger(self.resize);
|
|
|
+
|
|
|
+ win.bind('mousemove', function(e) {
|
|
|
+ navbar.stop(true, true).show().delay(3000).fadeOut('slow');
|
|
|
+ })
|
|
|
+ .mousemove();
|
|
|
+
|
|
|
+ navbar.mouseenter(function() {
|
|
|
+ navbar.stop(true, true).show();
|
|
|
+ })
|
|
|
+ .mousemove(function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ navbar.attr('style', '').draggable(full ? 'destroy' : {});
|
|
|
+ win.toggleClass(fullscreen);
|
|
|
+ $(this).toggleClass(navicon+'-fullscreen-off');
|
|
|
+ $.fn.resizable && parent.add(win).resizable(full ? 'enable' : 'disable').removeClass('ui-state-disabled');
|
|
|
+ }),
|
|
|
+
|
|
|
+ navbar = $('<div class="elfinder-quicklook-navbar"/>')
|
|
|
+ .append($('<div class="'+navicon+' '+navicon+'-prev"/>').mousedown(function() { navtrigger(37); }))
|
|
|
+ .append(fsicon)
|
|
|
+ .append($('<div class="'+navicon+' '+navicon+'-next"/>').mousedown(function() { navtrigger(39); }))
|
|
|
+ .append('<div class="elfinder-quicklook-navbar-separator"/>')
|
|
|
+ .append($('<div class="'+navicon+' '+navicon+'-close"/>').mousedown(function() { self.window.trigger('close'); }))
|
|
|
+ ;
|
|
|
+
|
|
|
+ this.resize = 'resize.'+fm.namespace;
|
|
|
+ this.info = $('<div class="elfinder-quicklook-info-wrapper"/>')
|
|
|
+ .append(icon)
|
|
|
+ .append(info);
|
|
|
+
|
|
|
+ this.preview = $('<div class="elfinder-quicklook-preview ui-helper-clearfix"/>')
|
|
|
+ // clean info/icon
|
|
|
+ .bind('change', function(e) {
|
|
|
+ self.info.attr('style', '').hide();
|
|
|
+ icon.removeAttr('class').attr('style', '');
|
|
|
+ info.html('');
|
|
|
+
|
|
|
+ })
|
|
|
+ // update info/icon
|
|
|
+ .bind('update', function(e) {
|
|
|
+ var fm = self.fm,
|
|
|
+ preview = self.preview,
|
|
|
+ file = e.file,
|
|
|
+ tpl = '<div class="elfinder-quicklook-info-data">{value}</div>',
|
|
|
+ tmb;
|
|
|
+
|
|
|
+ if (file) {
|
|
|
+ !file.read && e.stopImmediatePropagation();
|
|
|
+ self.window.data('hash', file.hash);
|
|
|
+ self.preview.unbind('changesize').trigger('change').children().remove();
|
|
|
+ title.html(fm.escape(file.name));
|
|
|
+
|
|
|
+ info.html(
|
|
|
+ tpl.replace(/\{value\}/, file.name)
|
|
|
+ + tpl.replace(/\{value\}/, fm.mime2kind(file))
|
|
|
+ + (file.mime == 'directory' ? '' : tpl.replace(/\{value\}/, fm.formatSize(file.size)))
|
|
|
+ + tpl.replace(/\{value\}/, fm.i18n('modify')+': '+ fm.formatDate(file))
|
|
|
+ )
|
|
|
+ icon.addClass('elfinder-cwd-icon ui-corner-all '+fm.mime2class(file.mime));
|
|
|
+
|
|
|
+ if (file.tmb) {
|
|
|
+ $('<img/>')
|
|
|
+ .hide()
|
|
|
+ .appendTo(self.preview)
|
|
|
+ .load(function() {
|
|
|
+ icon.css('background', 'url("'+tmb+'") center center no-repeat');
|
|
|
+ $(this).remove();
|
|
|
+ })
|
|
|
+ .attr('src', (tmb = fm.tmb(file.hash)));
|
|
|
+ }
|
|
|
+ self.info.delay(100).fadeIn(10);
|
|
|
+ } else {
|
|
|
+ e.stopImmediatePropagation();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ this.window = $('<div class="ui-helper-reset ui-widget elfinder-quicklook" style="position:absolute"/>')
|
|
|
+ .click(function(e) { e.stopPropagation(); })
|
|
|
+ .append(
|
|
|
+ $('<div class="elfinder-quicklook-titlebar"/>')
|
|
|
+ .append(title)
|
|
|
+ .append($('<span class="ui-icon ui-icon-circle-close"/>').mousedown(function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+ self.window.trigger('close');
|
|
|
+ }))
|
|
|
+ )
|
|
|
+ .append(this.preview.add(navbar))
|
|
|
+ .append(self.info.hide())
|
|
|
+ .draggable({handle : 'div.elfinder-quicklook-titlebar'})
|
|
|
+ .bind('open', function(e) {
|
|
|
+ var win = self.window,
|
|
|
+ file = self.value,
|
|
|
+ node;
|
|
|
+
|
|
|
+ if (self.closed() && file && (node = cwd.find('#'+file.hash)).length) {
|
|
|
+ navbar.attr('style', '');
|
|
|
+ state = animated;
|
|
|
+ node.trigger('scrolltoview');
|
|
|
+ win.css(closedCss(node))
|
|
|
+ .show()
|
|
|
+ .animate(openedCss(), 550, function() {
|
|
|
+ state = opened;
|
|
|
+ self.update(1, self.value);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .bind('close', function(e) {
|
|
|
+ var win = self.window,
|
|
|
+ preview = self.preview.trigger('change'),
|
|
|
+ file = self.value,
|
|
|
+ node = cwd.find('#'+win.data('hash')),
|
|
|
+ close = function() {
|
|
|
+ state = closed;
|
|
|
+ win.hide();
|
|
|
+ preview.children().remove();
|
|
|
+ self.update(0, self.value);
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ if (self.opened()) {
|
|
|
+ state = animated;
|
|
|
+ win.is('.'+fullscreen) && fsicon.mousedown()
|
|
|
+ node.length
|
|
|
+ ? win.animate(closedCss(node), 500, close)
|
|
|
+ : close();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This command cannot be disable by backend
|
|
|
+ *
|
|
|
+ * @type Boolean
|
|
|
+ **/
|
|
|
+ this.alwaysEnabled = true;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Selected file
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ **/
|
|
|
+ this.value = null;
|
|
|
+
|
|
|
+ this.handlers = {
|
|
|
+ // save selected file
|
|
|
+ select : function() { this.update(void(0), this.fm.selectedFiles()[0]); },
|
|
|
+ error : function() { self.window.is(':visible') && self.window.data('hash', '').trigger('close'); },
|
|
|
+ 'searchshow searchhide' : function() { this.opened() && this.window.trigger('close'); }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'space'
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.support = {
|
|
|
+ audio : {
|
|
|
+ ogg : support('audio/ogg; codecs="vorbis"'),
|
|
|
+ mp3 : support('audio/mpeg;'),
|
|
|
+ wav : support('audio/wav; codecs="1"'),
|
|
|
+ m4a : support('audio/x-m4a;') || support('audio/aac;')
|
|
|
+ },
|
|
|
+ video : {
|
|
|
+ ogg : support('video/ogg; codecs="theora"'),
|
|
|
+ webm : support('video/webm; codecs="vp8, vorbis"'),
|
|
|
+ mp4 : support('video/mp4; codecs="avc1.42E01E"') || support('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return true if quickLoock window is visible and not animated
|
|
|
+ *
|
|
|
+ * @return Boolean
|
|
|
+ **/
|
|
|
+ this.closed = function() {
|
|
|
+ return state == closed;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return true if quickLoock window is hidden
|
|
|
+ *
|
|
|
+ * @return Boolean
|
|
|
+ **/
|
|
|
+ this.opened = function() {
|
|
|
+ return state == opened;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Init command.
|
|
|
+ * Add default plugins and init other plugins
|
|
|
+ *
|
|
|
+ * @return Object
|
|
|
+ **/
|
|
|
+ this.init = function() {
|
|
|
+ var o = this.options,
|
|
|
+ win = this.window,
|
|
|
+ preview = this.preview,
|
|
|
+ i, p;
|
|
|
+
|
|
|
+ width = o.width > 0 ? parseInt(o.width) : 450;
|
|
|
+ height = o.height > 0 ? parseInt(o.height) : 300;
|
|
|
+
|
|
|
+ fm.one('load', function() {
|
|
|
+ parent = fm.getUI();
|
|
|
+ cwd = fm.getUI('cwd');
|
|
|
+
|
|
|
+ win.appendTo('body').zIndex(100 + parent.zIndex());
|
|
|
+
|
|
|
+ // close window on escape
|
|
|
+ $(document).keydown(function(e) {
|
|
|
+ e.keyCode == 27 && self.opened() && win.trigger('close')
|
|
|
+ })
|
|
|
+
|
|
|
+ if ($.fn.resizable) {
|
|
|
+ win.resizable({
|
|
|
+ handles : 'se',
|
|
|
+ minWidth : 350,
|
|
|
+ minHeight : 120,
|
|
|
+ resize : function() {
|
|
|
+ // use another event to avoid recursion in fullscreen mode
|
|
|
+ // may be there is clever solution, but i cant find it :(
|
|
|
+ preview.trigger('changesize');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ self.change(function() {
|
|
|
+ if (self.opened()) {
|
|
|
+ self.value ? preview.trigger($.Event('update', {file : self.value})) : win.trigger('close');
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ $.each(fm.commands.quicklook.plugins || [], function(i, plugin) {
|
|
|
+ if (typeof(plugin) == 'function') {
|
|
|
+ new plugin(self)
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ preview.bind('update', function() {
|
|
|
+ self.info.show();
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ return this.fm.selected().length == 1 ? state == opened ? 1 : 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function() {
|
|
|
+ this.enabled() && this.window.trigger(this.opened() ? 'close' : 'open');
|
|
|
+ }
|
|
|
+
|
|
|
+ this.hideinfo = function() {
|
|
|
+ this.info.stop(true).hide();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/quicklook.plugins.js
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+elFinder.prototype.commands.quicklook.plugins = [
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Images preview plugin
|
|
|
+ *
|
|
|
+ * @param elFinder.commands.quicklook
|
|
|
+ **/
|
|
|
+ function(ql) {
|
|
|
+ var mimes = ['image/jpeg', 'image/png', 'image/gif'],
|
|
|
+ preview = ql.preview;
|
|
|
+
|
|
|
+ // what kind of images we can display
|
|
|
+ $.each(navigator.mimeTypes, function(i, o) {
|
|
|
+ var mime = o.type;
|
|
|
+
|
|
|
+ if (mime.indexOf('image/') === 0 && $.inArray(mime, mimes)) {
|
|
|
+ mimes.push(mime);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ preview.bind('update', function(e) {
|
|
|
+ var file = e.file,
|
|
|
+ img;
|
|
|
+
|
|
|
+ if ($.inArray(file.mime, mimes) !== -1) {
|
|
|
+ // this is our file - stop event propagation
|
|
|
+ e.stopImmediatePropagation();
|
|
|
+
|
|
|
+ img = $('<img/>')
|
|
|
+ .hide()
|
|
|
+ .appendTo(preview)
|
|
|
+ .load(function() {
|
|
|
+ // timeout - because of strange safari bug -
|
|
|
+ // sometimes cant get image height 0_o
|
|
|
+ setTimeout(function() {
|
|
|
+ var prop = (img.width()/img.height()).toFixed(2);
|
|
|
+ preview.bind('changesize', function() {
|
|
|
+ var pw = parseInt(preview.width()),
|
|
|
+ ph = parseInt(preview.height()),
|
|
|
+ w, h;
|
|
|
+
|
|
|
+ if (prop < (pw/ph).toFixed(2)) {
|
|
|
+ h = ph;
|
|
|
+ w = Math.floor(h * prop);
|
|
|
+ } else {
|
|
|
+ w = pw;
|
|
|
+ h = Math.floor(w/prop);
|
|
|
+ }
|
|
|
+ img.width(w).height(h).css('margin-top', h < ph ? Math.floor((ph - h)/2) : 0);
|
|
|
+
|
|
|
+ })
|
|
|
+ .trigger('changesize');
|
|
|
+
|
|
|
+ // hide info/icon
|
|
|
+ ql.hideinfo();
|
|
|
+ //show image
|
|
|
+ img.fadeIn(100);
|
|
|
+ }, 1)
|
|
|
+ })
|
|
|
+ .attr('src', ql.fm.url(file.hash));
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * HTML preview plugin
|
|
|
+ *
|
|
|
+ * @param elFinder.commands.quicklook
|
|
|
+ **/
|
|
|
+ function(ql) {
|
|
|
+ var mimes = ['text/html', 'application/xhtml+xml'],
|
|
|
+ preview = ql.preview,
|
|
|
+ fm = ql.fm;
|
|
|
+
|
|
|
+ preview.bind('update', function(e) {
|
|
|
+ var file = e.file, jqxhr;
|
|
|
+
|
|
|
+ if ($.inArray(file.mime, mimes) !== -1) {
|
|
|
+ e.stopImmediatePropagation();
|
|
|
+
|
|
|
+ // stop loading on change file if not loaded yet
|
|
|
+ preview.one('change', function() {
|
|
|
+ jqxhr.state() == 'pending' && jqxhr.reject();
|
|
|
+ });
|
|
|
+
|
|
|
+ jqxhr = fm.request({
|
|
|
+ data : {cmd : 'get', target : file.hash, current : file.phash},
|
|
|
+ preventDefault : true
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ ql.hideinfo();
|
|
|
+ doc = $('<iframe class="elfinder-quicklook-preview-html"/>').appendTo(preview)[0].contentWindow.document;
|
|
|
+ doc.open();
|
|
|
+ doc.write(data.content);
|
|
|
+ doc.close();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Texts preview plugin
|
|
|
+ *
|
|
|
+ * @param elFinder.commands.quicklook
|
|
|
+ **/
|
|
|
+ function(ql) {
|
|
|
+ var fm = ql.fm,
|
|
|
+ mimes = fm.res('mimes', 'text'),
|
|
|
+ preview = ql.preview;
|
|
|
+
|
|
|
+
|
|
|
+ preview.bind('update', function(e) {
|
|
|
+ var file = e.file,
|
|
|
+ mime = file.mime,
|
|
|
+ jqxhr;
|
|
|
+
|
|
|
+ if (mime.indexOf('text/') === 0 || $.inArray(mime, mimes) !== -1) {
|
|
|
+ e.stopImmediatePropagation();
|
|
|
+
|
|
|
+ // stop loading on change file if not loadin yet
|
|
|
+ preview.one('change', function() {
|
|
|
+ jqxhr.state() == 'pending' && jqxhr.reject();
|
|
|
+ });
|
|
|
+
|
|
|
+ jqxhr = fm.request({
|
|
|
+ data : {cmd : 'get', target : file.hash },
|
|
|
+ preventDefault : true
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ ql.hideinfo();
|
|
|
+ $('<div class="elfinder-quicklook-preview-text-wrapper"><pre class="elfinder-quicklook-preview-text">'+fm.escape(data.content)+'</pre></div>').appendTo(preview);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * PDF preview plugin
|
|
|
+ *
|
|
|
+ * @param elFinder.commands.quicklook
|
|
|
+ **/
|
|
|
+ function(ql) {
|
|
|
+ var fm = ql.fm,
|
|
|
+ mime = 'application/pdf',
|
|
|
+ preview = ql.preview,
|
|
|
+ active = false;
|
|
|
+
|
|
|
+ if ((fm.UA.Safari && fm.OS == 'mac') || fm.UA.IE) {
|
|
|
+ active = true;
|
|
|
+ } else {
|
|
|
+ $.each(navigator.plugins, function(i, plugins) {
|
|
|
+ $.each(plugins, function(i, plugin) {
|
|
|
+ if (plugin.type == mime) {
|
|
|
+ return !(active = true);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ active && preview.bind('update', function(e) {
|
|
|
+ var file = e.file, node;
|
|
|
+
|
|
|
+ if (file.mime == mime) {
|
|
|
+ e.stopImmediatePropagation();
|
|
|
+ preview.one('change', function() {
|
|
|
+ node.unbind('load').remove();
|
|
|
+ });
|
|
|
+
|
|
|
+ node = $('<iframe class="elfinder-quicklook-preview-pdf"/>')
|
|
|
+ .hide()
|
|
|
+ .appendTo(preview)
|
|
|
+ .load(function() {
|
|
|
+ ql.hideinfo();
|
|
|
+ node.show();
|
|
|
+ })
|
|
|
+ .attr('src', fm.url(file.hash));
|
|
|
+ }
|
|
|
+
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Flash preview plugin
|
|
|
+ *
|
|
|
+ * @param elFinder.commands.quicklook
|
|
|
+ **/
|
|
|
+ function(ql) {
|
|
|
+ var fm = ql.fm,
|
|
|
+ mime = 'application/x-shockwave-flash',
|
|
|
+ preview = ql.preview,
|
|
|
+ active = false;
|
|
|
+
|
|
|
+ $.each(navigator.plugins, function(i, plugins) {
|
|
|
+ $.each(plugins, function(i, plugin) {
|
|
|
+ if (plugin.type == mime) {
|
|
|
+ return !(active = true);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ active && preview.bind('update', function(e) {
|
|
|
+ var file = e.file,
|
|
|
+ node;
|
|
|
+
|
|
|
+ if (file.mime == mime) {
|
|
|
+ e.stopImmediatePropagation();
|
|
|
+ ql.hideinfo();
|
|
|
+ preview.append((node = $('<embed class="elfinder-quicklook-preview-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" src="'+fm.url(file.hash)+'" quality="high" type="application/x-shockwave-flash" />')));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * HTML5 audio preview plugin
|
|
|
+ *
|
|
|
+ * @param elFinder.commands.quicklook
|
|
|
+ **/
|
|
|
+ function(ql) {
|
|
|
+ var preview = ql.preview,
|
|
|
+ autoplay = !!ql.options['autoplay'],
|
|
|
+ mimes = {
|
|
|
+ 'audio/mpeg' : 'mp3',
|
|
|
+ 'audio/mpeg3' : 'mp3',
|
|
|
+ 'audio/mp3' : 'mp3',
|
|
|
+ 'audio/x-mpeg3' : 'mp3',
|
|
|
+ 'audio/x-mp3' : 'mp3',
|
|
|
+ 'audio/x-wav' : 'wav',
|
|
|
+ 'audio/wav' : 'wav',
|
|
|
+ 'audio/x-m4a' : 'm4a',
|
|
|
+ 'audio/aac' : 'm4a',
|
|
|
+ 'audio/mp4' : 'm4a',
|
|
|
+ 'audio/x-mp4' : 'm4a',
|
|
|
+ 'audio/ogg' : 'ogg'
|
|
|
+ },
|
|
|
+ node;
|
|
|
+
|
|
|
+ preview.bind('update', function(e) {
|
|
|
+ var file = e.file,
|
|
|
+ type = mimes[file.mime];
|
|
|
+
|
|
|
+ if (ql.support.audio[type]) {
|
|
|
+ e.stopImmediatePropagation();
|
|
|
+
|
|
|
+ node = $('<audio class="elfinder-quicklook-preview-audio" controls preload="auto" autobuffer><source src="'+ql.fm.url(file.hash)+'" /></audio>')
|
|
|
+ .appendTo(preview);
|
|
|
+ autoplay && node[0].play();
|
|
|
+ }
|
|
|
+ }).bind('change', function() {
|
|
|
+ if (node && node.parent().length) {
|
|
|
+ node[0].pause();
|
|
|
+ node.remove();
|
|
|
+ node= null;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * HTML5 video preview plugin
|
|
|
+ *
|
|
|
+ * @param elFinder.commands.quicklook
|
|
|
+ **/
|
|
|
+ function(ql) {
|
|
|
+ var preview = ql.preview,
|
|
|
+ autoplay = !!ql.options['autoplay'],
|
|
|
+ mimes = {
|
|
|
+ 'video/mp4' : 'mp4',
|
|
|
+ 'video/x-m4v' : 'mp4',
|
|
|
+ 'video/ogg' : 'ogg',
|
|
|
+ 'application/ogg' : 'ogg',
|
|
|
+ 'video/webm' : 'webm'
|
|
|
+ },
|
|
|
+ node;
|
|
|
+
|
|
|
+ preview.bind('update', function(e) {
|
|
|
+ var file = e.file,
|
|
|
+ type = mimes[file.mime];
|
|
|
+
|
|
|
+ if (ql.support.video[type]) {
|
|
|
+ e.stopImmediatePropagation();
|
|
|
+
|
|
|
+ ql.hideinfo();
|
|
|
+ node = $('<video class="elfinder-quicklook-preview-video" controls preload="auto" autobuffer><source src="'+ql.fm.url(file.hash)+'" /></video>').appendTo(preview);
|
|
|
+ autoplay && node[0].play();
|
|
|
+
|
|
|
+ }
|
|
|
+ }).bind('change', function() {
|
|
|
+ if (node && node.parent().length) {
|
|
|
+ node[0].pause();
|
|
|
+ node.remove();
|
|
|
+ node= null;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Audio/video preview plugin using browser plugins
|
|
|
+ *
|
|
|
+ * @param elFinder.commands.quicklook
|
|
|
+ **/
|
|
|
+ function(ql) {
|
|
|
+ var preview = ql.preview,
|
|
|
+ mimes = [],
|
|
|
+ node;
|
|
|
+
|
|
|
+ $.each(navigator.plugins, function(i, plugins) {
|
|
|
+ $.each(plugins, function(i, plugin) {
|
|
|
+ (plugin.type.indexOf('audio/') === 0 || plugin.type.indexOf('video/') === 0) && mimes.push(plugin.type);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ preview.bind('update', function(e) {
|
|
|
+ var file = e.file,
|
|
|
+ mime = file.mime,
|
|
|
+ video;
|
|
|
+
|
|
|
+ if ($.inArray(file.mime, mimes) !== -1) {
|
|
|
+ e.stopImmediatePropagation();
|
|
|
+ (video = mime.indexOf('video/') === 0) && ql.hideinfo();
|
|
|
+ node = $('<embed src="'+ql.fm.url(file.hash)+'" type="'+mime+'" class="elfinder-quicklook-preview-'+(video ? 'video' : 'audio')+'"/>')
|
|
|
+ .appendTo(preview);
|
|
|
+ }
|
|
|
+ }).bind('change', function() {
|
|
|
+ if (node && node.parent().length) {
|
|
|
+ node.remove();
|
|
|
+ node= null;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+]
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/reload.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "reload"
|
|
|
+ * Sync files and folders
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.reload = function() {
|
|
|
+
|
|
|
+ this.alwaysEnabled = true;
|
|
|
+ this.updateOnSelect = true;
|
|
|
+
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'ctrl+shift+r f5'
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function() {
|
|
|
+ var fm = this.fm,
|
|
|
+ dfrd = fm.sync(),
|
|
|
+ timeout = setTimeout(function() {
|
|
|
+ fm.notify({type : 'reload', cnt : 1, hideCnt : true});
|
|
|
+ dfrd.always(function() { fm.notify({type : 'reload', cnt : -1}); });
|
|
|
+ }, fm.notifyDelay);
|
|
|
+
|
|
|
+ return dfrd.always(function() {
|
|
|
+ clearTimeout(timeout);
|
|
|
+ fm.trigger('reload');
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/rename.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "rename".
|
|
|
+ * Rename selected file.
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov, dio@std42.ru
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.rename = function() {
|
|
|
+
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'f2'+(this.fm.OS == 'mac' ? ' enter' : '')
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ var sel = this.fm.selectedFiles();
|
|
|
+
|
|
|
+ return !this._disabled && sel.length == 1 && sel[0].phash && !sel[0].locked ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function() {
|
|
|
+ var fm = this.fm,
|
|
|
+ cwd = fm.getUI('cwd'),
|
|
|
+ sel = fm.selected(),
|
|
|
+ cnt = sel.length,
|
|
|
+ file = fm.file(sel.shift()),
|
|
|
+ filename = '.elfinder-cwd-filename',
|
|
|
+ dfrd = $.Deferred()
|
|
|
+ .fail(function(error) {
|
|
|
+ var parent = input.parent(),
|
|
|
+ name = fm.escape(file.name);
|
|
|
+
|
|
|
+
|
|
|
+ if (parent.length) {
|
|
|
+ input.remove();
|
|
|
+ parent.html(name);
|
|
|
+ } else {
|
|
|
+ cwd.find('#'+file.hash).find(filename).html(name);
|
|
|
+ setTimeout(function() {
|
|
|
+ cwd.find('#'+file.hash).click();
|
|
|
+ }, 50);
|
|
|
+ }
|
|
|
+
|
|
|
+ error && fm.error(error);
|
|
|
+ })
|
|
|
+ .always(function() {
|
|
|
+ fm.enable();
|
|
|
+ }),
|
|
|
+ input = $('<input type="text"/>')
|
|
|
+ .keydown(function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+ e.stopImmediatePropagation();
|
|
|
+ if (e.keyCode == $.ui.keyCode.ESCAPE) {
|
|
|
+ dfrd.reject();
|
|
|
+ } else if (e.keyCode == $.ui.keyCode.ENTER) {
|
|
|
+ input.blur();
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .mousedown(function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+ })
|
|
|
+ .dblclick(function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+ e.preventDefault();
|
|
|
+ })
|
|
|
+ .blur(function() {
|
|
|
+ var name = $.trim(input.val()),
|
|
|
+ parent = input.parent();
|
|
|
+
|
|
|
+ if (parent.length) {
|
|
|
+ if (input[0].setSelectionRange) {
|
|
|
+ input[0].setSelectionRange(0, 0)
|
|
|
+ }
|
|
|
+ if (name == file.name) {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+ if (!name) {
|
|
|
+ return dfrd.reject('errInvName');
|
|
|
+ }
|
|
|
+ if (fm.fileByName(name, file.phash)) {
|
|
|
+ return dfrd.reject(['errExists', name]);
|
|
|
+ }
|
|
|
+
|
|
|
+ parent.html(fm.escape(name));
|
|
|
+ fm.lockfiles({files : [file.hash]});
|
|
|
+ fm.request({
|
|
|
+ data : {cmd : 'rename', target : file.hash, name : name},
|
|
|
+ notify : {type : 'rename', cnt : 1}
|
|
|
+ })
|
|
|
+ .fail(function(error) {
|
|
|
+ dfrd.reject();
|
|
|
+ fm.sync();
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ dfrd.resolve(data);
|
|
|
+ })
|
|
|
+ .always(function() {
|
|
|
+ fm.unlockfiles({files : [file.hash]})
|
|
|
+ });
|
|
|
+
|
|
|
+ }
|
|
|
+ }),
|
|
|
+ node = cwd.find('#'+file.hash).find(filename).empty().append(input.val(file.name)),
|
|
|
+ name = input.val().replace(/\.((tar\.(gz|bz|bz2|z|lzo))|cpio\.gz|ps\.gz|xcf\.(gz|bz2)|[a-z0-9]{1,4})$/ig, '')
|
|
|
+ ;
|
|
|
+
|
|
|
+ if (this.disabled()) {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!file || cnt > 1 || !node.length) {
|
|
|
+ return dfrd.reject('errCmdParams', this.title);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (file.locked) {
|
|
|
+ return dfrd.reject(['errLocked', file.name]);
|
|
|
+ }
|
|
|
+
|
|
|
+ fm.one('select', function() {
|
|
|
+ input.parent().length && file && $.inArray(file.hash, fm.selected()) === -1 && input.blur();
|
|
|
+ })
|
|
|
+
|
|
|
+ input.select().focus();
|
|
|
+
|
|
|
+ input[0].setSelectionRange && input[0].setSelectionRange(0, name.length);
|
|
|
+
|
|
|
+ return dfrd;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/resize.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "resize"
|
|
|
+ * Open dialog to resize image
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ * @author Alexey Sukhotin
|
|
|
+ * @author Naoki Sawada
|
|
|
+ * @author Sergio Jovani
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.resize = function() {
|
|
|
+
|
|
|
+ this.updateOnSelect = false;
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ var sel = this.fm.selectedFiles();
|
|
|
+ return !this._disabled && sel.length == 1 && sel[0].read && sel[0].write && sel[0].mime.indexOf('image/') !== -1 ? 0 : -1;
|
|
|
+ };
|
|
|
+
|
|
|
+ this.exec = function(hashes) {
|
|
|
+ var fm = this.fm,
|
|
|
+ files = this.files(hashes),
|
|
|
+ dfrd = $.Deferred(),
|
|
|
+
|
|
|
+ open = function(file, id) {
|
|
|
+ var dialog = $('<div class="elfinder-dialog-resize"/>'),
|
|
|
+ input = '<input type="text" size="5"/>',
|
|
|
+ row = '<div class="elfinder-resize-row"/>',
|
|
|
+ label = '<div class="elfinder-resize-label"/>',
|
|
|
+ control = $('<div class="elfinder-resize-control"/>'),
|
|
|
+ preview = $('<div class="elfinder-resize-preview"/>'),
|
|
|
+ spinner = $('<div class="elfinder-resize-spinner">'+fm.i18n('ntfloadimg')+'</div>'),
|
|
|
+ rhandle = $('<div class="elfinder-resize-handle"/>'),
|
|
|
+ rhandlec = $('<div class="elfinder-resize-handle"/>'),
|
|
|
+ uiresize = $('<div class="elfinder-resize-uiresize"/>'),
|
|
|
+ uicrop = $('<div class="elfinder-resize-uicrop"/>'),
|
|
|
+ uibuttonset = '<div class="ui-widget-content ui-corner-all elfinder-buttonset"/>',
|
|
|
+ uibutton = '<div class="ui-state-default elfinder-button"/>',
|
|
|
+ uiseparator = '<span class="ui-widget-content elfinder-toolbar-button-separator"/>',
|
|
|
+ uirotate = $('<div class="elfinder-resize-rotate"/>'),
|
|
|
+ uideg270 = $(uibutton).attr('title',fm.i18n('rotate-cw')).append($('<span class="elfinder-button-icon elfinder-button-icon-rotate-l"/>')
|
|
|
+ .click(function(){
|
|
|
+ rdegree = rdegree - 90;
|
|
|
+ rotate.update(rdegree);
|
|
|
+ })),
|
|
|
+ uideg90 = $(uibutton).attr('title',fm.i18n('rotate-ccw')).append($('<span class="elfinder-button-icon elfinder-button-icon-rotate-r"/>')
|
|
|
+ .click(function(){
|
|
|
+ rdegree = rdegree + 90;
|
|
|
+ rotate.update(rdegree);
|
|
|
+ })),
|
|
|
+ uiprop = $('<span />'),
|
|
|
+ reset = $('<div class="ui-state-default ui-corner-all elfinder-resize-reset"><span class="ui-icon ui-icon-arrowreturnthick-1-w"/></div>'),
|
|
|
+ uitype = $('<div class="elfinder-resize-type"/>')
|
|
|
+ .append('<input type="radio" name="type" id="'+id+'-resize" value="resize" checked="checked" /><label for="'+id+'-resize">'+fm.i18n('resize')+'</label>')
|
|
|
+ .append('<input type="radio" name="type" id="'+id+'-crop" value="crop" /><label for="'+id+'-crop">'+fm.i18n('crop')+'</label>')
|
|
|
+ .append('<input type="radio" name="type" id="'+id+'-rotate" value="rotate" /><label for="'+id+'-rotate">'+fm.i18n('rotate')+'</label>'),
|
|
|
+ type = $('input', uitype).attr('disabled', 'disabled')
|
|
|
+ .change(function() {
|
|
|
+ var val = $('input:checked', uitype).val();
|
|
|
+
|
|
|
+ resetView();
|
|
|
+ resizable(true);
|
|
|
+ croppable(true);
|
|
|
+ rotateable(true);
|
|
|
+
|
|
|
+ if (val == 'resize') {
|
|
|
+ uiresize.show();
|
|
|
+ uirotate.hide();
|
|
|
+ uicrop.hide();
|
|
|
+ resizable();
|
|
|
+ }
|
|
|
+ else if (val == 'crop') {
|
|
|
+ uirotate.hide();
|
|
|
+ uiresize.hide();
|
|
|
+ uicrop.show();
|
|
|
+ croppable();
|
|
|
+ } else if (val == 'rotate') {
|
|
|
+ uiresize.hide();
|
|
|
+ uicrop.hide();
|
|
|
+ uirotate.show();
|
|
|
+ rotateable();
|
|
|
+ }
|
|
|
+ }),
|
|
|
+ constr = $('<input type="checkbox" checked="checked"/>')
|
|
|
+ .change(function() {
|
|
|
+ cratio = !!constr.prop('checked');
|
|
|
+ resize.fixHeight();
|
|
|
+ resizable(true);
|
|
|
+ resizable();
|
|
|
+ }),
|
|
|
+ width = $(input)
|
|
|
+ .change(function() {
|
|
|
+ var w = parseInt(width.val()),
|
|
|
+ h = parseInt(cratio ? Math.round(w/ratio) : height.val());
|
|
|
+
|
|
|
+ if (w > 0 && h > 0) {
|
|
|
+ resize.updateView(w, h);
|
|
|
+ height.val(h);
|
|
|
+ }
|
|
|
+ }),
|
|
|
+ height = $(input)
|
|
|
+ .change(function() {
|
|
|
+ var h = parseInt(height.val()),
|
|
|
+ w = parseInt(cratio ? Math.round(h*ratio) : width.val());
|
|
|
+
|
|
|
+ if (w > 0 && h > 0) {
|
|
|
+ resize.updateView(w, h);
|
|
|
+ width.val(w);
|
|
|
+ }
|
|
|
+ }),
|
|
|
+ pointX = $(input).change(function(){crop.updateView();}),
|
|
|
+ pointY = $(input).change(function(){crop.updateView();}),
|
|
|
+ offsetX = $(input).change(function(){crop.updateView();}),
|
|
|
+ offsetY = $(input).change(function(){crop.updateView();}),
|
|
|
+ degree = $('<input type="text" size="3" maxlength="3" value="0" />')
|
|
|
+ .change(function() {
|
|
|
+ rotate.update();
|
|
|
+ }),
|
|
|
+ uidegslider = $('<div class="elfinder-resize-rotate-slider"/>')
|
|
|
+ .slider({
|
|
|
+ min: 0,
|
|
|
+ max: 359,
|
|
|
+ value: degree.val(),
|
|
|
+ animate: true,
|
|
|
+ change: function(event, ui) {
|
|
|
+ if (ui.value != uidegslider.slider('value')) {
|
|
|
+ rotate.update(ui.value);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ slide: function(event, ui) {
|
|
|
+ rotate.update(ui.value, false);
|
|
|
+ }
|
|
|
+ }),
|
|
|
+ ratio = 1,
|
|
|
+ prop = 1,
|
|
|
+ owidth = 0,
|
|
|
+ oheight = 0,
|
|
|
+ cratio = true,
|
|
|
+ pwidth = 0,
|
|
|
+ pheight = 0,
|
|
|
+ rwidth = 0,
|
|
|
+ rheight = 0,
|
|
|
+ rdegree = 0,
|
|
|
+ img = $('<img/>')
|
|
|
+ .load(function() {
|
|
|
+ spinner.remove();
|
|
|
+
|
|
|
+ owidth = img.width();
|
|
|
+ oheight = img.height();
|
|
|
+ ratio = owidth/oheight;
|
|
|
+ resize.updateView(owidth, oheight);
|
|
|
+
|
|
|
+ rhandle.append(img.show()).show();
|
|
|
+ width.val(owidth);
|
|
|
+ height.val(oheight);
|
|
|
+
|
|
|
+ var r_scale = Math.min(pwidth, pheight) / Math.sqrt(Math.pow(owidth, 2) + Math.pow(oheight, 2));
|
|
|
+ rwidth = owidth * r_scale;
|
|
|
+ rheight = oheight * r_scale;
|
|
|
+
|
|
|
+ type.button('enable');
|
|
|
+ control.find('input,select').removeAttr('disabled')
|
|
|
+ .filter(':text').keydown(function(e) {
|
|
|
+ var c = e.keyCode, i;
|
|
|
+
|
|
|
+ e.stopPropagation();
|
|
|
+
|
|
|
+ if ((c >= 37 && c <= 40)
|
|
|
+ || c == $.ui.keyCode.BACKSPACE
|
|
|
+ || c == $.ui.keyCode.DELETE
|
|
|
+ || (c == 65 && (e.ctrlKey||e.metaKey))
|
|
|
+ || c == 27) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (c == 9) {
|
|
|
+ i = $(this).parent()[e.shiftKey ? 'prev' : 'next']('.elfinder-resize-row').children(':text');
|
|
|
+
|
|
|
+ if (i.length) {
|
|
|
+ i.focus();
|
|
|
+ } else {
|
|
|
+ $(this).parent().parent().find(':text:' + (e.shiftKey ? 'last' : 'first')).focus();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (c == 13) {
|
|
|
+ fm.confirm({
|
|
|
+ title : $('input:checked', uitype).val(),
|
|
|
+ text : 'confirmReq',
|
|
|
+ accept : {
|
|
|
+ label : 'btnApply',
|
|
|
+ callback : function() {
|
|
|
+ save();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ cancel : {
|
|
|
+ label : 'btnCancel',
|
|
|
+ callback : function(){}
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!((c >= 48 && c <= 57) || (c >= 96 && c <= 105))) {
|
|
|
+ e.preventDefault();
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .filter(':first').focus();
|
|
|
+
|
|
|
+ resizable();
|
|
|
+
|
|
|
+ reset.hover(function() { reset.toggleClass('ui-state-hover'); }).click(resetView);
|
|
|
+
|
|
|
+ })
|
|
|
+ .error(function() {
|
|
|
+ spinner.text('Unable to load image').css('background', 'transparent');
|
|
|
+ }),
|
|
|
+ basec = $('<div/>'),
|
|
|
+ imgc = $('<img/>'),
|
|
|
+ coverc = $('<div/>'),
|
|
|
+ imgr = $('<img/>'),
|
|
|
+ resetView = function() {
|
|
|
+ width.val(owidth);
|
|
|
+ height.val(oheight);
|
|
|
+ resize.updateView(owidth, oheight);
|
|
|
+ },
|
|
|
+ resize = {
|
|
|
+ update : function() {
|
|
|
+ width.val(Math.round(img.width()/prop));
|
|
|
+ height.val(Math.round(img.height()/prop));
|
|
|
+ },
|
|
|
+
|
|
|
+ updateView : function(w, h) {
|
|
|
+ if (w > pwidth || h > pheight) {
|
|
|
+ if (w / pwidth > h / pheight) {
|
|
|
+ prop = pwidth / w;
|
|
|
+ img.width(pwidth).height(Math.ceil(h*prop));
|
|
|
+ } else {
|
|
|
+ prop = pheight / h;
|
|
|
+ img.height(pheight).width(Math.ceil(w*prop));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ img.width(w).height(h);
|
|
|
+ }
|
|
|
+
|
|
|
+ prop = img.width()/w;
|
|
|
+ uiprop.text('1 : '+(1/prop).toFixed(2));
|
|
|
+ resize.updateHandle();
|
|
|
+ },
|
|
|
+
|
|
|
+ updateHandle : function() {
|
|
|
+ rhandle.width(img.width()).height(img.height());
|
|
|
+ },
|
|
|
+ fixWidth : function() {
|
|
|
+ var w, h;
|
|
|
+ if (cratio) {
|
|
|
+ h = height.val();
|
|
|
+ h = Math.round(h*ratio);
|
|
|
+ resize.updateView(w, h);
|
|
|
+ width.val(w);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ fixHeight : function() {
|
|
|
+ var w, h;
|
|
|
+ if (cratio) {
|
|
|
+ w = width.val();
|
|
|
+ h = Math.round(w/ratio);
|
|
|
+ resize.updateView(w, h);
|
|
|
+ height.val(h);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ crop = {
|
|
|
+ update : function() {
|
|
|
+ offsetX.val(Math.round((rhandlec.data('w')||rhandlec.width())/prop));
|
|
|
+ offsetY.val(Math.round((rhandlec.data('h')||rhandlec.height())/prop));
|
|
|
+ pointX.val(Math.round(((rhandlec.data('x')||rhandlec.offset().left)-imgc.offset().left)/prop));
|
|
|
+ pointY.val(Math.round(((rhandlec.data('y')||rhandlec.offset().top)-imgc.offset().top)/prop));
|
|
|
+ },
|
|
|
+ updateView : function() {
|
|
|
+ var x = parseInt(pointX.val()) * prop + imgc.offset().left;
|
|
|
+ var y = parseInt(pointY.val()) * prop + imgc.offset().top;
|
|
|
+ var w = offsetX.val() * prop;
|
|
|
+ var h = offsetY.val() * prop;
|
|
|
+ rhandlec.data({x: x, y: y, w: w, h: h});
|
|
|
+ rhandlec.width(Math.round(w));
|
|
|
+ rhandlec.height(Math.round(h));
|
|
|
+ coverc.width(rhandlec.width());
|
|
|
+ coverc.height(rhandlec.height());
|
|
|
+ rhandlec.offset({left: Math.round(x), top: Math.round(y)});
|
|
|
+ },
|
|
|
+ resize_update : function() {
|
|
|
+ rhandlec.data({w: null, h: null});
|
|
|
+ crop.update();
|
|
|
+ coverc.width(rhandlec.width());
|
|
|
+ coverc.height(rhandlec.height());
|
|
|
+ },
|
|
|
+ drag_update : function() {
|
|
|
+ rhandlec.data({x: null, y: null});
|
|
|
+ crop.update();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ rotate = {
|
|
|
+ mouseStartAngle : 0,
|
|
|
+ imageStartAngle : 0,
|
|
|
+ imageBeingRotated : false,
|
|
|
+
|
|
|
+ update : function(value, animate) {
|
|
|
+ if (typeof value == 'undefined') {
|
|
|
+ rdegree = value = parseInt(degree.val());
|
|
|
+ }
|
|
|
+ if (typeof animate == 'undefined') {
|
|
|
+ animate = true;
|
|
|
+ }
|
|
|
+ if (! animate || fm.UA.Opera || fm.UA.ltIE8) {
|
|
|
+ imgr.rotate(value);
|
|
|
+ } else {
|
|
|
+ imgr.animate({rotate: value + 'deg'});
|
|
|
+ }
|
|
|
+ value = value % 360;
|
|
|
+ if (value < 0) {
|
|
|
+ value += 360;
|
|
|
+ }
|
|
|
+ degree.val(parseInt(value));
|
|
|
+
|
|
|
+ uidegslider.slider('value', degree.val());
|
|
|
+ },
|
|
|
+
|
|
|
+ execute : function ( e ) {
|
|
|
+
|
|
|
+ if ( !rotate.imageBeingRotated ) return;
|
|
|
+
|
|
|
+ var imageCentre = rotate.getCenter( imgr );
|
|
|
+ var mouseXFromCentre = e.pageX - imageCentre[0];
|
|
|
+ var mouseYFromCentre = e.pageY - imageCentre[1];
|
|
|
+ var mouseAngle = Math.atan2( mouseYFromCentre, mouseXFromCentre );
|
|
|
+
|
|
|
+ var rotateAngle = mouseAngle - rotate.mouseStartAngle + rotate.imageStartAngle;
|
|
|
+ rotateAngle = Math.round(parseFloat(rotateAngle) * 180 / Math.PI);
|
|
|
+
|
|
|
+ if ( e.shiftKey ) {
|
|
|
+ rotateAngle = Math.round((rotateAngle + 6)/15) * 15;
|
|
|
+ }
|
|
|
+
|
|
|
+ imgr.rotate(rotateAngle);
|
|
|
+
|
|
|
+ rotateAngle = rotateAngle % 360;
|
|
|
+ if (rotateAngle < 0) {
|
|
|
+ rotateAngle += 360;
|
|
|
+ }
|
|
|
+ degree.val(rotateAngle);
|
|
|
+
|
|
|
+ uidegslider.slider('value', degree.val());
|
|
|
+
|
|
|
+ return false;
|
|
|
+ },
|
|
|
+
|
|
|
+ start : function ( e ) {
|
|
|
+
|
|
|
+ rotate.imageBeingRotated = true;
|
|
|
+
|
|
|
+ var imageCentre = rotate.getCenter( imgr );
|
|
|
+ var mouseStartXFromCentre = e.pageX - imageCentre[0];
|
|
|
+ var mouseStartYFromCentre = e.pageY - imageCentre[1];
|
|
|
+ rotate.mouseStartAngle = Math.atan2( mouseStartYFromCentre, mouseStartXFromCentre );
|
|
|
+
|
|
|
+ rotate.imageStartAngle = parseFloat(imgr.rotate()) * Math.PI / 180.0;
|
|
|
+
|
|
|
+ $(document).mousemove( rotate.execute );
|
|
|
+
|
|
|
+ return false;
|
|
|
+ },
|
|
|
+
|
|
|
+ stop : function ( e ) {
|
|
|
+
|
|
|
+ if ( !rotate.imageBeingRotated ) return;
|
|
|
+
|
|
|
+ $(document).unbind( 'mousemove' , rotate.execute);
|
|
|
+
|
|
|
+ setTimeout( function() { rotate.imageBeingRotated = false; }, 10 );
|
|
|
+ return false;
|
|
|
+ },
|
|
|
+
|
|
|
+ getCenter : function ( image ) {
|
|
|
+
|
|
|
+ var currentRotation = imgr.rotate();
|
|
|
+ imgr.rotate(0);
|
|
|
+
|
|
|
+ var imageOffset = imgr.offset();
|
|
|
+ var imageCentreX = imageOffset.left + imgr.width() / 2;
|
|
|
+ var imageCentreY = imageOffset.top + imgr.height() / 2;
|
|
|
+
|
|
|
+ imgr.rotate(currentRotation);
|
|
|
+
|
|
|
+ return Array( imageCentreX, imageCentreY );
|
|
|
+ }
|
|
|
+ },
|
|
|
+ resizable = function(destroy) {
|
|
|
+ if ($.fn.resizable) {
|
|
|
+ if (destroy) {
|
|
|
+ rhandle.filter(':ui-resizable').resizable('destroy');
|
|
|
+ rhandle.hide();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ rhandle.show();
|
|
|
+ rhandle.resizable({
|
|
|
+ alsoResize : img,
|
|
|
+ aspectRatio : cratio,
|
|
|
+ resize : resize.update,
|
|
|
+ stop : resize.fixHeight
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ croppable = function(destroy) {
|
|
|
+ if ($.fn.draggable && $.fn.resizable) {
|
|
|
+ if (destroy) {
|
|
|
+ rhandlec.filter(':ui-resizable').resizable('destroy');
|
|
|
+ rhandlec.filter(':ui-draggable').draggable('destroy');
|
|
|
+ basec.hide();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ imgc
|
|
|
+ .width(img.width())
|
|
|
+ .height(img.height());
|
|
|
+
|
|
|
+ coverc
|
|
|
+ .width(img.width())
|
|
|
+ .height(img.height());
|
|
|
+
|
|
|
+ rhandlec
|
|
|
+ .width(imgc.width())
|
|
|
+ .height(imgc.height())
|
|
|
+ .offset(imgc.offset())
|
|
|
+ .resizable({
|
|
|
+ containment : basec,
|
|
|
+ resize : crop.resize_update,
|
|
|
+ handles : 'all'
|
|
|
+ })
|
|
|
+ .draggable({
|
|
|
+ handle : coverc,
|
|
|
+ containment : imgc,
|
|
|
+ drag : crop.drag_update
|
|
|
+ });
|
|
|
+
|
|
|
+ basec.show()
|
|
|
+ .width(img.width())
|
|
|
+ .height(img.height());
|
|
|
+
|
|
|
+ crop.update();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ rotateable = function(destroy) {
|
|
|
+ if ($.fn.draggable && $.fn.resizable) {
|
|
|
+ if (destroy) {
|
|
|
+ imgr.hide();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ imgr.show()
|
|
|
+ .width(rwidth)
|
|
|
+ .height(rheight)
|
|
|
+ .css('margin-top', (pheight-rheight)/2 + 'px')
|
|
|
+ .css('margin-left', (pwidth-rwidth)/2 + 'px');
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ save = function() {
|
|
|
+ var w, h, x, y, d;
|
|
|
+ var mode = $('input:checked', uitype).val();
|
|
|
+
|
|
|
+ //width.add(height).change(); // may be unnecessary
|
|
|
+
|
|
|
+ if (mode == 'resize') {
|
|
|
+ w = parseInt(width.val()) || 0;
|
|
|
+ h = parseInt(height.val()) || 0;
|
|
|
+ } else if (mode == 'crop') {
|
|
|
+ w = parseInt(offsetX.val()) || 0;
|
|
|
+ h = parseInt(offsetY.val()) || 0;
|
|
|
+ x = parseInt(pointX.val()) || 0;
|
|
|
+ y = parseInt(pointY.val()) || 0;
|
|
|
+ } else if (mode == 'rotate') {
|
|
|
+ w = owidth;
|
|
|
+ h = oheight;
|
|
|
+ d = parseInt(degree.val()) || 0;
|
|
|
+ if (d < 0 || d > 360) {
|
|
|
+ return fm.error('Invalid rotate degree');
|
|
|
+ }
|
|
|
+ if (d == 0 || d == 360) {
|
|
|
+ return fm.error('Image dose not rotated');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mode != 'rotate') {
|
|
|
+
|
|
|
+ if (w <= 0 || h <= 0) {
|
|
|
+ return fm.error('Invalid image size');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (w == owidth && h == oheight) {
|
|
|
+ return fm.error('Image size not changed');
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ dialog.elfinderdialog('close');
|
|
|
+
|
|
|
+ fm.request({
|
|
|
+ data : {
|
|
|
+ cmd : 'resize',
|
|
|
+ target : file.hash,
|
|
|
+ width : w,
|
|
|
+ height : h,
|
|
|
+ x : x,
|
|
|
+ y : y,
|
|
|
+ degree : d,
|
|
|
+ mode : mode
|
|
|
+ },
|
|
|
+ notify : {type : 'resize', cnt : 1}
|
|
|
+ })
|
|
|
+ .fail(function(error) {
|
|
|
+ dfrd.reject(error);
|
|
|
+ })
|
|
|
+ .done(function() {
|
|
|
+ dfrd.resolve();
|
|
|
+ });
|
|
|
+
|
|
|
+ },
|
|
|
+ buttons = {},
|
|
|
+ hline = 'elfinder-resize-handle-hline',
|
|
|
+ vline = 'elfinder-resize-handle-vline',
|
|
|
+ rpoint = 'elfinder-resize-handle-point',
|
|
|
+ src = fm.url(file.hash)
|
|
|
+ ;
|
|
|
+
|
|
|
+ imgr.mousedown( rotate.start );
|
|
|
+ $(document).mouseup( rotate.stop );
|
|
|
+
|
|
|
+ uiresize.append($(row).append($(label).text(fm.i18n('width'))).append(width).append(reset))
|
|
|
+ .append($(row).append($(label).text(fm.i18n('height'))).append(height))
|
|
|
+ .append($(row).append($('<label/>').text(fm.i18n('aspectRatio')).prepend(constr)))
|
|
|
+ .append($(row).append(fm.i18n('scale')+' ').append(uiprop));
|
|
|
+
|
|
|
+ uicrop.append($(row).append($(label).text('X')).append(pointX))
|
|
|
+ .append($(row).append($(label).text('Y')).append(pointY))
|
|
|
+ .append($(row).append($(label).text(fm.i18n('width'))).append(offsetX))
|
|
|
+ .append($(row).append($(label).text(fm.i18n('height'))).append(offsetY));
|
|
|
+
|
|
|
+ uirotate.append($(row)
|
|
|
+ .append($(label).text(fm.i18n('rotate')))
|
|
|
+ .append($('<div style="float:left; width: 130px;">')
|
|
|
+ .append($('<div style="float:left;">')
|
|
|
+ .append(degree)
|
|
|
+ .append($('<span/>').text(fm.i18n('degree')))
|
|
|
+ )
|
|
|
+ .append($(uibuttonset).append(uideg270).append($(uiseparator)).append(uideg90))
|
|
|
+ )
|
|
|
+ .append(uidegslider)
|
|
|
+ );
|
|
|
+
|
|
|
+
|
|
|
+ dialog.append(uitype);
|
|
|
+
|
|
|
+ control.append($(row))
|
|
|
+ .append(uiresize)
|
|
|
+ .append(uicrop.hide())
|
|
|
+ .append(uirotate.hide())
|
|
|
+ .find('input,select').attr('disabled', 'disabled');
|
|
|
+
|
|
|
+ rhandle.append('<div class="'+hline+' '+hline+'-top"/>')
|
|
|
+ .append('<div class="'+hline+' '+hline+'-bottom"/>')
|
|
|
+ .append('<div class="'+vline+' '+vline+'-left"/>')
|
|
|
+ .append('<div class="'+vline+' '+vline+'-right"/>')
|
|
|
+ .append('<div class="'+rpoint+' '+rpoint+'-e"/>')
|
|
|
+ .append('<div class="'+rpoint+' '+rpoint+'-se"/>')
|
|
|
+ .append('<div class="'+rpoint+' '+rpoint+'-s"/>');
|
|
|
+
|
|
|
+ preview.append(spinner).append(rhandle.hide()).append(img.hide());
|
|
|
+
|
|
|
+ rhandlec.css('position', 'absolute')
|
|
|
+ .append('<div class="'+hline+' '+hline+'-top"/>')
|
|
|
+ .append('<div class="'+hline+' '+hline+'-bottom"/>')
|
|
|
+ .append('<div class="'+vline+' '+vline+'-left"/>')
|
|
|
+ .append('<div class="'+vline+' '+vline+'-right"/>')
|
|
|
+ .append('<div class="'+rpoint+' '+rpoint+'-n"/>')
|
|
|
+ .append('<div class="'+rpoint+' '+rpoint+'-e"/>')
|
|
|
+ .append('<div class="'+rpoint+' '+rpoint+'-s"/>')
|
|
|
+ .append('<div class="'+rpoint+' '+rpoint+'-w"/>')
|
|
|
+ .append('<div class="'+rpoint+' '+rpoint+'-ne"/>')
|
|
|
+ .append('<div class="'+rpoint+' '+rpoint+'-se"/>')
|
|
|
+ .append('<div class="'+rpoint+' '+rpoint+'-sw"/>')
|
|
|
+ .append('<div class="'+rpoint+' '+rpoint+'-nw"/>');
|
|
|
+
|
|
|
+ preview.append(basec.css('position', 'absolute').hide().append(imgc).append(rhandlec.append(coverc)));
|
|
|
+
|
|
|
+ preview.append(imgr.hide());
|
|
|
+
|
|
|
+ preview.css('overflow', 'hidden');
|
|
|
+
|
|
|
+ dialog.append(preview).append(control);
|
|
|
+
|
|
|
+ buttons[fm.i18n('btnApply')] = save;
|
|
|
+ buttons[fm.i18n('btnCancel')] = function() { dialog.elfinderdialog('close'); };
|
|
|
+
|
|
|
+ fm.dialog(dialog, {
|
|
|
+ title : file.name,
|
|
|
+ width : 650,
|
|
|
+ resizable : false,
|
|
|
+ destroyOnClose : true,
|
|
|
+ buttons : buttons,
|
|
|
+ open : function() { preview.zIndex(1+$(this).parent().zIndex()); }
|
|
|
+ }).attr('id', id);
|
|
|
+
|
|
|
+ // for IE < 9 dialog mising at open second+ time.
|
|
|
+ if (fm.UA.ltIE8) {
|
|
|
+ $('.elfinder-dialog').css('filter', '');
|
|
|
+ }
|
|
|
+
|
|
|
+ reset.css('left', width.position().left + width.width() + 12);
|
|
|
+
|
|
|
+ coverc.css({ 'opacity': 0.2, 'background-color': '#fff', 'position': 'absolute'}),
|
|
|
+ rhandlec.css('cursor', 'move');
|
|
|
+ rhandlec.find('.elfinder-resize-handle-point').css({
|
|
|
+ 'background-color' : '#fff',
|
|
|
+ 'opacity': 0.5,
|
|
|
+ 'border-color':'#000'
|
|
|
+ });
|
|
|
+
|
|
|
+ imgr.css('cursor', 'pointer');
|
|
|
+
|
|
|
+ uitype.buttonset();
|
|
|
+
|
|
|
+ pwidth = preview.width() - (rhandle.outerWidth() - rhandle.width());
|
|
|
+ pheight = preview.height() - (rhandle.outerHeight() - rhandle.height());
|
|
|
+
|
|
|
+ img.attr('src', src + (src.indexOf('?') === -1 ? '?' : '&')+'_='+Math.random());
|
|
|
+ imgc.attr('src', img.attr('src'));
|
|
|
+ imgr.attr('src', img.attr('src'));
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ id, dialog
|
|
|
+ ;
|
|
|
+
|
|
|
+
|
|
|
+ if (!files.length || files[0].mime.indexOf('image/') === -1) {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ id = 'resize-'+fm.namespace+'-'+files[0].hash;
|
|
|
+ dialog = fm.getUI().find('#'+id);
|
|
|
+
|
|
|
+ if (dialog.length) {
|
|
|
+ dialog.elfinderdialog('toTop');
|
|
|
+ return dfrd.resolve();
|
|
|
+ }
|
|
|
+
|
|
|
+ open(files[0], id);
|
|
|
+
|
|
|
+ return dfrd;
|
|
|
+ };
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+(function ($) {
|
|
|
+
|
|
|
+ var findProperty = function (styleObject, styleArgs) {
|
|
|
+ var i = 0 ;
|
|
|
+ for( i in styleArgs) {
|
|
|
+ if (typeof styleObject[styleArgs[i]] != 'undefined')
|
|
|
+ return styleArgs[i];
|
|
|
+ }
|
|
|
+ styleObject[styleArgs[i]] = '';
|
|
|
+ return styleArgs[i];
|
|
|
+ };
|
|
|
+
|
|
|
+ $.cssHooks.rotate = {
|
|
|
+ get: function(elem, computed, extra) {
|
|
|
+ return $(elem).rotate();
|
|
|
+ },
|
|
|
+ set: function(elem, value) {
|
|
|
+ $(elem).rotate(value);
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ $.cssHooks.transform = {
|
|
|
+ get: function(elem, computed, extra) {
|
|
|
+ var name = findProperty( elem.style ,
|
|
|
+ ['WebkitTransform', 'MozTransform', 'OTransform' , 'msTransform' , 'transform'] );
|
|
|
+ return elem.style[name];
|
|
|
+ },
|
|
|
+ set: function(elem, value) {
|
|
|
+ var name = findProperty( elem.style ,
|
|
|
+ ['WebkitTransform', 'MozTransform', 'OTransform' , 'msTransform' , 'transform'] );
|
|
|
+ elem.style[name] = value;
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ $.fn.rotate = function(val) {
|
|
|
+ if (typeof val == 'undefined') {
|
|
|
+ if (!!window.opera) {
|
|
|
+ var r = this.css('transform').match(/rotate\((.*?)\)/);
|
|
|
+ return ( r && r[1])?
|
|
|
+ Math.round(parseFloat(r[1]) * 180 / Math.PI) : 0;
|
|
|
+ } else {
|
|
|
+ var r = this.css('transform').match(/rotate\((.*?)\)/);
|
|
|
+ return ( r && r[1])? parseInt(r[1]) : 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.css('transform',
|
|
|
+ this.css('transform').replace(/none|rotate\(.*?\)/, '') + 'rotate(' + parseInt(val) + 'deg)');
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+
|
|
|
+ $.fx.step.rotate = function(fx) {
|
|
|
+ if ( fx.state == 0 ) {
|
|
|
+ fx.start = $(fx.elem).rotate();
|
|
|
+ fx.now = fx.start;
|
|
|
+ }
|
|
|
+ $(fx.elem).rotate(fx.now);
|
|
|
+ };
|
|
|
+
|
|
|
+ if (typeof window.addEventListener == "undefined" && typeof document.getElementsByClassName == "undefined") { // IE & IE<9
|
|
|
+ var GetAbsoluteXY = function(element) {
|
|
|
+ var pnode = element;
|
|
|
+ var x = pnode.offsetLeft;
|
|
|
+ var y = pnode.offsetTop;
|
|
|
+
|
|
|
+ while ( pnode.offsetParent ) {
|
|
|
+ pnode = pnode.offsetParent;
|
|
|
+ if (pnode != document.body && pnode.currentStyle['position'] != 'static') {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (pnode != document.body && pnode != document.documentElement) {
|
|
|
+ x -= pnode.scrollLeft;
|
|
|
+ y -= pnode.scrollTop;
|
|
|
+ }
|
|
|
+ x += pnode.offsetLeft;
|
|
|
+ y += pnode.offsetTop;
|
|
|
+ }
|
|
|
+
|
|
|
+ return { x: x, y: y };
|
|
|
+ };
|
|
|
+
|
|
|
+ var StaticToAbsolute = function (element) {
|
|
|
+ if ( element.currentStyle['position'] != 'static') {
|
|
|
+ return ;
|
|
|
+ }
|
|
|
+
|
|
|
+ var xy = GetAbsoluteXY(element);
|
|
|
+ element.style.position = 'absolute' ;
|
|
|
+ element.style.left = xy.x + 'px';
|
|
|
+ element.style.top = xy.y + 'px';
|
|
|
+ };
|
|
|
+
|
|
|
+ var IETransform = function(element,transform){
|
|
|
+
|
|
|
+ var r;
|
|
|
+ var m11 = 1;
|
|
|
+ var m12 = 1;
|
|
|
+ var m21 = 1;
|
|
|
+ var m22 = 1;
|
|
|
+
|
|
|
+ if (typeof element.style['msTransform'] != 'undefined'){
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ StaticToAbsolute(element);
|
|
|
+
|
|
|
+ r = transform.match(/rotate\((.*?)\)/);
|
|
|
+ var rotate = ( r && r[1]) ? parseInt(r[1]) : 0;
|
|
|
+
|
|
|
+ rotate = rotate % 360;
|
|
|
+ if (rotate < 0) rotate = 360 + rotate;
|
|
|
+
|
|
|
+ var radian= rotate * Math.PI / 180;
|
|
|
+ var cosX =Math.cos(radian);
|
|
|
+ var sinY =Math.sin(radian);
|
|
|
+
|
|
|
+ m11 *= cosX;
|
|
|
+ m12 *= -sinY;
|
|
|
+ m21 *= sinY;
|
|
|
+ m22 *= cosX;
|
|
|
+
|
|
|
+ element.style.filter = (element.style.filter || '').replace(/progid:DXImageTransform\.Microsoft\.Matrix\([^)]*\)/, "" ) +
|
|
|
+ ("progid:DXImageTransform.Microsoft.Matrix(" +
|
|
|
+ "M11=" + m11 +
|
|
|
+ ",M12=" + m12 +
|
|
|
+ ",M21=" + m21 +
|
|
|
+ ",M22=" + m22 +
|
|
|
+ ",FilterType='bilinear',sizingMethod='auto expand')")
|
|
|
+ ;
|
|
|
+
|
|
|
+ var ow = parseInt(element.style.width || element.width || 0 );
|
|
|
+ var oh = parseInt(element.style.height || element.height || 0 );
|
|
|
+
|
|
|
+ var radian = rotate * Math.PI / 180;
|
|
|
+ var absCosX =Math.abs(Math.cos(radian));
|
|
|
+ var absSinY =Math.abs(Math.sin(radian));
|
|
|
+
|
|
|
+ var dx = (ow - (ow * absCosX + oh * absSinY)) / 2;
|
|
|
+ var dy = (oh - (ow * absSinY + oh * absCosX)) / 2;
|
|
|
+
|
|
|
+ element.style.marginLeft = Math.floor(dx) + "px";
|
|
|
+ element.style.marginTop = Math.floor(dy) + "px";
|
|
|
+
|
|
|
+ return(true);
|
|
|
+ };
|
|
|
+
|
|
|
+ var transform_set = $.cssHooks.transform.set;
|
|
|
+ $.cssHooks.transform.set = function(elem, value) {
|
|
|
+ transform_set.apply(this, [elem, value] );
|
|
|
+ IETransform(elem,value);
|
|
|
+ return value;
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+})(jQuery);
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/rm.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "rm"
|
|
|
+ * Delete files
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.rm = function() {
|
|
|
+
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'delete ctrl+backspace'
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.getstate = function(sel) {
|
|
|
+ var fm = this.fm;
|
|
|
+ sel = sel || fm.selected();
|
|
|
+ return !this._disabled && sel.length && $.map(sel, function(h) { var f = fm.file(h); return f && f.phash && !f.locked ? h : null }).length == sel.length
|
|
|
+ ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function(hashes) {
|
|
|
+ var self = this,
|
|
|
+ fm = this.fm,
|
|
|
+ dfrd = $.Deferred()
|
|
|
+ .fail(function(error) {
|
|
|
+ error && fm.error(error);
|
|
|
+ }),
|
|
|
+ files = this.files(hashes),
|
|
|
+ cnt = files.length,
|
|
|
+ cwd = fm.cwd().hash,
|
|
|
+ goroot = false;
|
|
|
+
|
|
|
+ if (!cnt || this._disabled) {
|
|
|
+ return dfrd.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ $.each(files, function(i, file) {
|
|
|
+ if (!file.phash) {
|
|
|
+ return !dfrd.reject(['errRm', file.name, 'errPerm']);
|
|
|
+ }
|
|
|
+ if (file.locked) {
|
|
|
+ return !dfrd.reject(['errLocked', file.name]);
|
|
|
+ }
|
|
|
+ if (file.hash == cwd) {
|
|
|
+ goroot = fm.root(file.hash);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (dfrd.state() == 'pending') {
|
|
|
+ files = this.hashes(hashes);
|
|
|
+
|
|
|
+ fm.confirm({
|
|
|
+ title : self.title,
|
|
|
+ text : 'confirmRm',
|
|
|
+ accept : {
|
|
|
+ label : 'btnRm',
|
|
|
+ callback : function() {
|
|
|
+ fm.lockfiles({files : files});
|
|
|
+ fm.request({
|
|
|
+ data : {cmd : 'rm', targets : files},
|
|
|
+ notify : {type : 'rm', cnt : cnt},
|
|
|
+ preventFail : true
|
|
|
+ })
|
|
|
+ .fail(function(error) {
|
|
|
+ dfrd.reject(error);
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ dfrd.done(data);
|
|
|
+ goroot && fm.exec('open', goroot)
|
|
|
+ }
|
|
|
+ ).always(function() {
|
|
|
+ fm.unlockfiles({files : files});
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ cancel : {
|
|
|
+ label : 'btnCancel',
|
|
|
+ callback : function() { dfrd.reject(); }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ return dfrd;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/search.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "search"
|
|
|
+ * Find files
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.search = function() {
|
|
|
+ this.title = 'Find files';
|
|
|
+ this.options = {ui : 'searchbutton'}
|
|
|
+ this.alwaysEnabled = true;
|
|
|
+ this.updateOnSelect = false;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return command status.
|
|
|
+ * Search does not support old api.
|
|
|
+ *
|
|
|
+ * @return Number
|
|
|
+ **/
|
|
|
+ this.getstate = function() {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Send search request to backend.
|
|
|
+ *
|
|
|
+ * @param String search string
|
|
|
+ * @return $.Deferred
|
|
|
+ **/
|
|
|
+ this.exec = function(q) {
|
|
|
+ var fm = this.fm;
|
|
|
+
|
|
|
+ if (typeof(q) == 'string' && q) {
|
|
|
+ fm.trigger('searchstart', {query : q});
|
|
|
+
|
|
|
+ return fm.request({
|
|
|
+ data : {cmd : 'search', q : q},
|
|
|
+ notify : {type : 'search', cnt : 1, hideCnt : true}
|
|
|
+ });
|
|
|
+ }
|
|
|
+ fm.getUI('toolbar').find('.'+fm.res('class', 'searchbtn')+' :text').focus();
|
|
|
+ return $.Deferred().reject();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/sort.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "sort"
|
|
|
+ * Change sort files rule
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.sort = function() {
|
|
|
+ /**
|
|
|
+ * Command options
|
|
|
+ *
|
|
|
+ * @type Object
|
|
|
+ */
|
|
|
+ this.options = {ui : 'sortbutton'};
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function(hashes, sort) {
|
|
|
+ var fm = this.fm,
|
|
|
+ sort = $.extend({
|
|
|
+ type : fm.sortType,
|
|
|
+ order : fm.sortOrder,
|
|
|
+ stick : fm.sortStickFolders
|
|
|
+ }, sort);
|
|
|
+
|
|
|
+ this.fm.setSort(sort.type, sort.order, sort.stick);
|
|
|
+ return $.Deferred().resolve();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/up.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "up"
|
|
|
+ * Go into parent directory
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.up = function() {
|
|
|
+ this.alwaysEnabled = true;
|
|
|
+ this.updateOnSelect = false;
|
|
|
+
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'ctrl+up'
|
|
|
+ }];
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ return this.fm.cwd().phash ? 0 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function() {
|
|
|
+ return this.fm.cwd().phash ? this.fm.exec('open', this.fm.cwd().phash) : $.Deferred().reject();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/upload.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "upload"
|
|
|
+ * Upload files using iframe or XMLHttpRequest & FormData.
|
|
|
+ * Dialog allow to send files using drag and drop
|
|
|
+ *
|
|
|
+ * @type elFinder.command
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ */
|
|
|
+elFinder.prototype.commands.upload = function() {
|
|
|
+ var hover = this.fm.res('class', 'hover');
|
|
|
+
|
|
|
+ this.disableOnSearch = true;
|
|
|
+ this.updateOnSelect = false;
|
|
|
+
|
|
|
+ // Shortcut opens dialog
|
|
|
+ this.shortcuts = [{
|
|
|
+ pattern : 'ctrl+u'
|
|
|
+ }];
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return command state
|
|
|
+ *
|
|
|
+ * @return Number
|
|
|
+ **/
|
|
|
+ this.getstate = function() {
|
|
|
+ return !this._disabled && this.fm.cwd().write ? 0 : -1;
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ this.exec = function(data) {
|
|
|
+ var fm = this.fm,
|
|
|
+ upload = function(data) {
|
|
|
+ dialog.elfinderdialog('close');
|
|
|
+ fm.upload(data)
|
|
|
+ .fail(function(error) {
|
|
|
+ dfrd.reject(error);
|
|
|
+ })
|
|
|
+ .done(function(data) {
|
|
|
+ dfrd.resolve(data);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ dfrd, dialog, input, button, dropbox, pastebox;
|
|
|
+
|
|
|
+ if (this.disabled()) {
|
|
|
+ return $.Deferred().reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data && (data.input || data.files)) {
|
|
|
+ return fm.upload(data);
|
|
|
+ }
|
|
|
+
|
|
|
+ dfrd = $.Deferred();
|
|
|
+
|
|
|
+
|
|
|
+ input = $('<input type="file" multiple="true"/>')
|
|
|
+ .change(function() {
|
|
|
+ upload({input : input[0]});
|
|
|
+ });
|
|
|
+
|
|
|
+ button = $('<div class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"><span class="ui-button-text">'+fm.i18n('selectForUpload')+'</span></div>')
|
|
|
+ .append($('<form/>').append(input))
|
|
|
+ .hover(function() {
|
|
|
+ button.toggleClass(hover)
|
|
|
+ });
|
|
|
+
|
|
|
+ dialog = $('<div class="elfinder-upload-dialog-wrapper"/>')
|
|
|
+ .append(button);
|
|
|
+
|
|
|
+ pastebox = $('<div class="ui-corner-all elfinder-upload-dropbox" contenteditable=true></div>')
|
|
|
+ .on('paste drop', function (evt) {
|
|
|
+ var e = evt.originalEvent || evt;
|
|
|
+ var files = [];
|
|
|
+ var file;
|
|
|
+ if (e.clipboardData && e.clipboardData.items && e.clipboardData.items.length){
|
|
|
+ for (var i=0; i < e.clipboardData.items.length; i++) {
|
|
|
+ if (e.clipboardData.items[i].kind == 'file') {
|
|
|
+ file = e.clipboardData.items[i].getAsFile();
|
|
|
+ files.push(file);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (files.length) {
|
|
|
+ upload({files : files, type : 'files'});
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ var my = e.target;
|
|
|
+ setTimeout(function () {
|
|
|
+ if (my.innerHTML) {
|
|
|
+ var src = my.innerHTML.replace(/<br[^>]*>/gi, ' ');
|
|
|
+ var type = src.match(/<[^>]+>/)? 'html' : 'text';
|
|
|
+ my.innerHTML = '';
|
|
|
+ upload({files : [ src ], type : type});
|
|
|
+ }
|
|
|
+ }, 1);
|
|
|
+ })
|
|
|
+ .on('dragenter mouseover', function(){
|
|
|
+ pastebox.addClass(hover);
|
|
|
+ })
|
|
|
+ .on('dragleave mouseout', function(){
|
|
|
+ pastebox.removeClass(hover);
|
|
|
+ });
|
|
|
+
|
|
|
+ if (fm.dragUpload) {
|
|
|
+ dropbox = $('<div class="ui-corner-all elfinder-upload-dropbox">'+fm.i18n('dropFiles')+'</div>')
|
|
|
+ .prependTo(dialog)
|
|
|
+ .after('<div class="elfinder-upload-dialog-or">'+fm.i18n('or')+'</div>')
|
|
|
+ .after(pastebox)
|
|
|
+ .after('<div>'+fm.i18n('dropFilesBrowser')+'</div>')
|
|
|
+ .after('<div class="elfinder-upload-dialog-or">'+fm.i18n('or')+'</div>')[0];
|
|
|
+
|
|
|
+ dropbox.addEventListener('dragenter', function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+ e.preventDefault();
|
|
|
+ $(dropbox).addClass(hover);
|
|
|
+ }, false);
|
|
|
+
|
|
|
+ dropbox.addEventListener('dragleave', function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+ e.preventDefault();
|
|
|
+ $(dropbox).removeClass(hover);
|
|
|
+ }, false);
|
|
|
+
|
|
|
+ dropbox.addEventListener('dragover', function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+ e.preventDefault();
|
|
|
+ $(dropbox).addClass(hover);
|
|
|
+ }, false);
|
|
|
+
|
|
|
+ dropbox.addEventListener('drop', function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+ e.preventDefault();
|
|
|
+ var file = false;
|
|
|
+ var type = '';
|
|
|
+ if (e.dataTransfer && e.dataTransfer.items && e.dataTransfer.items.length) {
|
|
|
+ file = e.dataTransfer.items;
|
|
|
+ type = 'data';
|
|
|
+ } else if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length) {
|
|
|
+ file = e.dataTransfer.files;
|
|
|
+ type = 'files';
|
|
|
+ } else if (e.dataTransfer.getData('text/html')) {
|
|
|
+ file = [ e.dataTransfer.getData('text/html') ];
|
|
|
+ type = 'html';
|
|
|
+ } else if (e.dataTransfer.getData('text')) {
|
|
|
+ file = [ e.dataTransfer.getData('text') ];
|
|
|
+ type = 'text';
|
|
|
+ }
|
|
|
+ if (file) {
|
|
|
+ upload({files : file, type : type});
|
|
|
+ }
|
|
|
+ }, false);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ $('<div>'+fm.i18n('dropFilesBrowser')+'</div>')
|
|
|
+ .append(pastebox)
|
|
|
+ .prependTo(dialog)
|
|
|
+ .after('<div class="elfinder-upload-dialog-or">'+fm.i18n('or')+'</div>')[0];
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ fm.dialog(dialog, {
|
|
|
+ title : this.title,
|
|
|
+ modal : true,
|
|
|
+ resizable : false,
|
|
|
+ destroyOnClose : true
|
|
|
+ });
|
|
|
+
|
|
|
+ return dfrd;
|
|
|
+ };
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+/*
|
|
|
+ * File: /home/osc/elFinder-build/elFinder/js/commands/view.js
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @class elFinder command "view"
|
|
|
+ * Change current directory view (icons/list)
|
|
|
+ *
|
|
|
+ * @author Dmitry (dio) Levashov
|
|
|
+ **/
|
|
|
+elFinder.prototype.commands.view = function() {
|
|
|
+ this.value = this.fm.viewType;
|
|
|
+ this.alwaysEnabled = true;
|
|
|
+ this.updateOnSelect = false;
|
|
|
+
|
|
|
+ this.options = { ui : 'viewbutton'};
|
|
|
+
|
|
|
+ this.getstate = function() {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.exec = function() {
|
|
|
+ var value = this.fm.storage('view', this.value == 'list' ? 'icons' : 'list');
|
|
|
+ this.fm.viewchange();
|
|
|
+ this.update(void(0), value);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+})(jQuery);
|