105 |
106 | * elFinder (1.0.1):
107 | - In directory tree panel added arrows to open/close directories
108 | without entering in.
109 | - Added shortcut support for copy/cut/paste/delete files and
110 | folders. For Mac users added Command+Backspace support.
111 | - Added context menu to current directory.
112 | - Added help.
113 | - [bugfix] invalid determing files/folders permissions using
114 | "perms" options in php connector
115 |
116 |
--------------------------------------------------------------------------------
/js/Finder.resources.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Finder resources registry.
4 | * Store shared data
5 | *
6 | * @type Object
7 | * @author Dmitry (dio) Levashov
8 | **/
9 | Finder.prototype.resources = {
10 | 'class' : {
11 | hover : 'ui-state-hover',
12 | active : 'ui-state-active',
13 | disabled : 'ui-state-disabled',
14 | draggable : 'ui-draggable',
15 | droppable : 'ui-droppable',
16 | adroppable : 'finder-droppable-active',
17 | cwdfile : 'finder-cwd-file',
18 | cwd : 'finder-cwd',
19 | tree : 'finder-tree',
20 | treeroot : 'finder-navbar-root',
21 | navdir : 'finder-navbar-dir',
22 | navdirwrap : 'finder-navbar-dir-wrapper',
23 | navarrow : 'finder-navbar-arrow',
24 | navsubtree : 'finder-navbar-subtree',
25 | navcollapse : 'finder-navbar-collapsed',
26 | navexpand : 'finder-navbar-expanded',
27 | treedir : 'finder-tree-dir',
28 | placedir : 'finder-place-dir',
29 | searchbtn : 'finder-button-search'
30 | },
31 | tpl : {
32 | perms : ' ',
33 | symlink : ' ',
34 | navicon : ' ',
35 | navspinner : ' ',
36 | navdir : ' {symlink}{permissions}{name}
'
37 |
38 | },
39 |
40 | mimes : {
41 | text : [
42 | 'application/x-empty',
43 | 'application/javascript',
44 | 'application/xhtml+xml',
45 | 'audio/x-mp3-playlist',
46 | 'application/x-web-config',
47 | 'application/docbook+xml',
48 | 'application/x-php',
49 | 'application/x-perl',
50 | 'application/x-awk',
51 | 'application/x-config',
52 | 'application/x-csh',
53 | 'application/xml'
54 | ]
55 | },
56 |
57 | mixin : {
58 | make : function() {
59 | var fm = this.fm,
60 | cmd = this.name,
61 | cwd = fm.getUI('cwd'),
62 | dfrd = $.Deferred()
63 | .fail(function(error) {
64 | cwd.trigger('unselectall');
65 | error && fm.error(error);
66 | })
67 | .always(function() {
68 | input.remove();
69 | node.remove();
70 | fm.enable();
71 | }),
72 | id = 'tmp_'+parseInt(Math.random()*100000),
73 | phash = fm.cwd().hash,
74 | date = new Date(),
75 | file = {
76 | hash : id,
77 | name : fm.uniqueName(this.prefix),
78 | mime : this.mime,
79 | read : true,
80 | write : true,
81 | date : 'Today '+date.getHours()+':'+date.getMinutes()
82 | },
83 | node = cwd.trigger('create.'+fm.namespace, file).find('#'+id),
84 | input = $(' ')
85 | .keydown(function(e) {
86 | e.stopImmediatePropagation();
87 |
88 | if (e.keyCode == $.ui.keyCode.ESCAPE) {
89 | dfrd.reject();
90 | } else if (e.keyCode == $.ui.keyCode.ENTER) {
91 | input.blur();
92 | }
93 | })
94 | .mousedown(function(e) {
95 | e.stopPropagation();
96 | })
97 | .blur(function() {
98 | var name = $.trim(input.val()),
99 | parent = input.parent();
100 |
101 | if (parent.length) {
102 |
103 | if (!name) {
104 | return dfrd.reject('errInvName');
105 | }
106 | if (fm.fileByName(name, phash)) {
107 | return dfrd.reject(['errExists', name]);
108 | }
109 |
110 | parent.html(fm.escape(name));
111 |
112 | fm.lockfiles({files : [id]});
113 |
114 | fm.request({
115 | data : {cmd : cmd, name : name, target : phash},
116 | notify : {type : cmd, cnt : 1},
117 | preventFail : true,
118 | syncOnFail : true
119 | })
120 | .fail(function(error) {
121 | dfrd.reject(error);
122 | })
123 | .done(function(data) {
124 | dfrd.resolve(data);
125 | });
126 | }
127 | });
128 |
129 |
130 | if (this.disabled() || !node.length) {
131 | return dfrd.reject();
132 | }
133 |
134 | fm.disable();
135 | node.find('.finder-cwd-filename').empty('').append(input.val(file.name));
136 | input.select().focus();
137 |
138 | return dfrd;
139 |
140 |
141 |
142 | }
143 |
144 | }
145 | }
146 |
147 |
--------------------------------------------------------------------------------
/js/ui/contextmenu.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /**
3 | * @class Finder contextmenu
4 | *
5 | * @author Dmitry (dio) Levashov
6 | **/
7 | $.fn.findercontextmenu = function(fm) {
8 |
9 | return this.each(function() {
10 | var menu = $(this).addClass('ui-helper-reset ui-widget ui-state-default ui-corner-all finder-contextmenu finder-contextmenu-'+fm.direction)
11 | .hide()
12 | .appendTo('body')
13 | .delegate('.finder-contextmenu-item', 'mouseenter mouseleave', function() {
14 | $(this).toggleClass('ui-state-hover')
15 | }),
16 | subpos = fm.direction == 'ltr' ? 'left' : 'right',
17 | types = $.extend({}, fm.options.contextmenu),
18 | tpl = '',
19 | item = function(label, icon, callback) {
20 | return $(tpl.replace('{icon}', icon ? 'finder-button-icon-'+icon : '').replace('{label}', label))
21 | .click(function(e) {
22 | e.stopPropagation();
23 | e.stopPropagation();
24 | callback();
25 | });
26 | },
27 |
28 | open = function(x, y) {
29 | var win = $(window),
30 | width = menu.outerWidth(),
31 | height = menu.outerHeight(),
32 | wwidth = win.width(),
33 | wheight = win.height(),
34 | scrolltop = win.scrollTop(),
35 | scrollleft = win.scrollLeft(),
36 | css = {
37 | top : (y + height < wheight ? y : y - height > 0 ? y - height : y) + scrolltop,
38 | left : (x + width < wwidth ? x : x - width) + scrollleft,
39 | 'z-index' : 100 + fm.getUI('workzone').zIndex()
40 | };
41 |
42 | menu.css(css)
43 | .show();
44 |
45 | css = {'z-index' : css['z-index']+10};
46 | css[subpos] = parseInt(menu.width());
47 | menu.find('.finder-contextmenu-sub').css(css);
48 | },
49 |
50 | close = function() {
51 | menu.hide().empty();
52 | },
53 |
54 | create = function(type, targets) {
55 | var sep = false;
56 |
57 |
58 |
59 | $.each(types[type]||[], function(i, name) {
60 | var cmd, node, submenu;
61 |
62 | if (name == '|' && sep) {
63 | menu.append('');
64 | sep = false;
65 | return;
66 | }
67 |
68 | cmd = fm.command(name);
69 |
70 | if (cmd && cmd.getstate(targets) != -1) {
71 | if (cmd.variants) {
72 | if (!cmd.variants.length) {
73 | return;
74 | }
75 | node = item(cmd.title, cmd.name, function() {});
76 |
77 | submenu = $('')
78 | .appendTo(node.append(''));
79 |
80 | node.addClass('finder-contextmenu-group')
81 | .hover(function() {
82 | submenu.toggle()
83 | })
84 |
85 | $.each(cmd.variants, function(i, variant) {
86 | submenu.append(
87 | $('')
88 | .click(function(e) {
89 | e.stopPropagation();
90 | close();
91 | cmd.exec(targets, variant[0]);
92 | })
93 | );
94 | });
95 |
96 | } else {
97 | node = item(cmd.title, cmd.name, function() {
98 | close();
99 | cmd.exec(targets);
100 | })
101 |
102 | }
103 |
104 | menu.append(node)
105 | sep = true;
106 | }
107 | })
108 | },
109 |
110 | createFromRaw = function(raw) {
111 | $.each(raw, function(i, data) {
112 | var node;
113 |
114 | if (data.label && typeof data.callback == 'function') {
115 | node = item(data.label, data.icon, function() {
116 | close();
117 | data.callback();
118 | });
119 | menu.append(node);
120 | }
121 | })
122 | };
123 |
124 | fm.one('load', function() {
125 | fm.bind('contextmenu', function(e) {
126 | var data = e.data;
127 |
128 | close();
129 |
130 | if (data.type && data.targets) {
131 | create(data.type, data.targets);
132 | } else if (data.raw) {
133 | createFromRaw(data.raw);
134 | }
135 |
136 | menu.children().length && open(data.x, data.y);
137 | })
138 | .one('destroy', function() { menu.remove(); })
139 | .bind('disable select', close)
140 | .getUI().click(close);
141 | });
142 |
143 | });
144 |
145 | }
146 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | gpFinder
2 | ========
3 |
4 |
5 | ______ _ _
6 | | ____(_) | |
7 | __ _ _ __ | |__ _ _ __ __| | ___ _ __
8 | / _` | '_ \| __| | | '_ \ / _` |/ _ \ '__|
9 | | (_| | |_) | | | | | | | (_| | __/ |
10 | \__, | .__/|_| |_|_| |_|\__,_|\___|_|
11 | __/ | |
12 | |___/|_|
13 |
14 | an adaptation of
15 | _ ______ _ _
16 | | | ____(_) | |
17 | ___| | |__ _ _ __ __| | ___ _ __
18 | / _ \ | __| | | '_ \ / _` |/ _ \ '__|
19 | | __/ | | | | | | | (_| | __/ |
20 | \___|_|_| |_|_| |_|\__,_|\___|_|
21 |
22 |
23 |
24 | gpFinder is an open-source file manager based on the elFinder project (http://elfinder.org)
25 | gpFinder is written in JavaScript using jQuery UI and can be easily integrated with all of the
26 | most popular web editors (elRTE, CKEditor, TinyMCE)
27 |
28 |
29 | Features
30 | --------
31 |
32 | * All operations with files and folders on a remote server (copy, move,
33 | upload, create folder/file, rename, etc.)
34 | * High performance server beckend and light client UI
35 | * Multi-root support
36 | * Local file system, MySQL, FTP volume storage drivers
37 | * Background file upload with Drag & Drop HTML5 support
38 | * List and Icons view
39 | * Keyboard shortcuts
40 | * Standard methods of file/group selection using mouse or keyboard
41 | * Move/Copy files with Drag & Drop
42 | * Archives create/extract (zip, rar, 7z, tar, gzip, bzip2)
43 | * Rich context menu and toolbar
44 | * Quicklook, preview for common file types
45 | * Edit text files and images
46 | * "Places" for your favorites
47 | * Calculate directory sizes
48 | * Thumbnails for image files
49 | * Easy to integrate with web editors (elRTE, CKEditor, TinyMCE)
50 | * Flexible configuration of access rights, upload file types, user interface
51 | and other
52 | * Extensibility
53 | * Simple client-server API based on JSON
54 |
55 |
56 | Requirements
57 | ------------
58 |
59 | ### Client
60 | * Modern browser. gpFinder was tested in Firefox 12, Internet Explorer 8+,
61 | Safari 6, Opera 12 and Chrome 19
62 |
63 | ### Server
64 | * Any web server
65 | * PHP 5.2+ (for thumbnails - mogrify utility or GD/Imagick module)
66 |
67 |
68 | 3rd party connectors
69 | --------------------
70 | * [Python](https://github.com/Studio-42/elfinder-python)
71 | * [Django](https://github.com/mikery/django-elfinder)
72 | * [Ruby/Rails](https://github.com/phallstrom/el_finder)
73 | * [Java Servlet](https://github.com/Studio-42/elfinder-servlet)
74 |
75 |
76 | Support
77 | -------
78 | * [Wiki](https://github.com/oyejorge/gpFinder/wiki)
79 | * [Issues](https://github.com/oyejorge/gpFinder/issues)
80 |
81 |
82 | License
83 | -------
84 |
85 | gpFinder is issued under a 3-clauses BSD license.
86 |
87 |
88 | Copyright (c) 2012, gpFinder
89 | All rights reserved.
90 |
91 | Redistribution and use in source and binary forms, with or without
92 | modification, are permitted provided that the following conditions are met:
93 | * Redistributions of source code must retain the above copyright
94 | notice, this list of conditions and the following disclaimer.
95 | * Redistributions in binary form must reproduce the above copyright
96 | notice, this list of conditions and the following disclaimer in the
97 | documentation and/or other materials provided with the distribution.
98 | * Neither the name of gpFinder nor the
99 | names of its contributors may be used to endorse or promote products
100 | derived from this software without specific prior written permission.
101 |
102 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
103 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
104 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
105 | DISCLAIMED. IN NO EVENT SHALL "gpFinder" BE LIABLE FOR ANY DIRECT, INDIRECT,
106 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
107 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
108 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
109 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
110 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
111 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
112 |
113 |
--------------------------------------------------------------------------------
/php/Archive.php:
--------------------------------------------------------------------------------
1 | path = $path;
22 | $this->extension = $this->Extension($path);
23 | $this->exists = file_exists($path);
24 |
25 | switch( strtolower($this->extension) ){
26 | case 'zip':
27 | $this->InitZip();
28 | break;
29 | default:
30 | $this->InitTar();
31 | break;
32 | }
33 |
34 | }
35 |
36 |
37 | /**
38 | * Initialize tar
39 | *
40 | */
41 | protected function InitTar(){
42 |
43 | if( $this->exists ){
44 | $this->php_object = new \PharData($this->path);
45 | return;
46 | }
47 |
48 | switch( strtolower($this->extension) ){
49 | case 'tbz':
50 | case 'tgz':
51 | $this->path = preg_replace('#\.(tgz|tbz)$#','.tar',$this->path);
52 | break;
53 | }
54 |
55 |
56 | $this->php_object = new \PharData($this->path);
57 | }
58 |
59 |
60 | /**
61 | * Initialize a zip archive
62 | *
63 | */
64 | protected function InitZip(){
65 |
66 | $this->php_class = 'ZipArchive';
67 | $this->php_object = new \ZipArchive();
68 |
69 | if( $this->exists ){
70 | $this->php_object->open($this->path);
71 | }else{
72 | $this->php_object->open($this->path, \ZipArchive::CREATE);
73 | }
74 | }
75 |
76 |
77 | /**
78 | * Get the extension of the file
79 | *
80 | */
81 | protected function Extension($path){
82 |
83 | $parts = explode('.',$path);
84 | return array_pop($parts);
85 | }
86 |
87 |
88 | /**
89 | * Call method on the archive object
90 | *
91 | */
92 | public function __call( $name , $arguments ){
93 | return call_user_func_array( array($this->php_object,$name), $arguments);
94 | }
95 |
96 |
97 | /**
98 | * Get the contents of a file within the archive
99 | *
100 | */
101 | public function getFromName($name){
102 |
103 | if( $this->php_class === 'ZipArchive' ){
104 | return $this->php_object->getFromName($name);
105 | }
106 |
107 | $full_path = 'phar://'.$this->path.'/'.ltrim($name,'/');
108 | return file_get_contents($full_path);
109 | }
110 |
111 |
112 | /**
113 | * Add the final compression to the archive
114 | *
115 | */
116 | public function Compress(){
117 |
118 | switch($this->extension){
119 | case 'tbz':
120 | $this->php_object->compress(\Phar::BZ2,'tbz');
121 | unlink($this->path);
122 | break;
123 | case 'tgz':
124 | $this->php_object->compress(\Phar::GZ,'tgz');
125 | unlink($this->path);
126 | break;
127 | }
128 |
129 | }
130 |
131 | /**
132 | * Count the number of files
133 | *
134 | */
135 | public function Count(){
136 |
137 | if( method_exists($this->php_object,'Count') ){
138 | return $this->php_object->Count();
139 | }
140 |
141 | return $this->php_object->numFiles;
142 | }
143 |
144 | /**
145 | * List the files in the archive
146 | * ToDo: ListFiles() for pharData
147 | *
148 | */
149 | public function ListFiles(){
150 |
151 | $list = array();
152 | $count = $this->Count();
153 | for( $i = 0; $i < $count; $i++ ){
154 | $list[] = $this->php_object->statIndex( $i );
155 | }
156 | return $list;
157 | }
158 |
159 |
160 | /**
161 | * Recursively add files to the archive
162 | *
163 | */
164 | public function Add( $path, $localname = null){
165 |
166 | if( !file_exists($path) ){
167 | return false;
168 | }
169 |
170 | if( is_null($localname) ){
171 | $localname = $path;
172 | }
173 |
174 | if( is_link($path) ){
175 | return true;
176 | }
177 |
178 |
179 | if( !is_dir($path) ){
180 | $localname = ltrim($localname,'\\/'); //so windows can open zip archives
181 | return $this->php_object->AddFile($path, $localname);
182 | }
183 |
184 |
185 | $files = scandir($path);
186 | foreach($files as $file){
187 | if( $file === '.' || $file === '..' ){
188 | continue;
189 | }
190 | $full_path = $path.'/'.$file;
191 | $_localname = $localname.'/'.$file;
192 |
193 | $this->Add( $full_path, $_localname);
194 | }
195 | }
196 |
197 |
198 | }
199 |
--------------------------------------------------------------------------------
/js/commands/upload.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /**
3 | * @class Finder command "upload"
4 | * Upload files using iframe or XMLHttpRequest & FormData.
5 | * Dialog allow to send files using drag and drop
6 | *
7 | * @type Finder.command
8 | * @author Dmitry (dio) Levashov
9 | */
10 | Finder.prototype.commands.upload = function() {
11 | var hover = this.fm.res('class', 'hover');
12 |
13 | this.disableOnSearch = true;
14 | this.updateOnSelect = false;
15 |
16 | // Shortcut opens dialog
17 | this.shortcuts = [{
18 | pattern : 'ctrl+u'
19 | }];
20 |
21 | /**
22 | * Return command state
23 | *
24 | * @return Number
25 | **/
26 | this.getstate = function() {
27 | return !this._disabled && this.fm.cwd().write ? 0 : -1;
28 | };
29 |
30 |
31 | this.exec = function(data) {
32 | var fm = this.fm,
33 | upload = function(data) {
34 | dialog.finderdialog('close');
35 | fm.upload(data)
36 | .fail(function(error) {
37 | dfrd.reject(error);
38 | })
39 | .done(function(data) {
40 | dfrd.resolve(data);
41 | });
42 | },
43 | dfrd, dialog, input, button, dropbox, pastebox;
44 |
45 | if (this.disabled()) {
46 | return $.Deferred().reject();
47 | }
48 |
49 | if (data && (data.input || data.files)) {
50 | return fm.upload(data);
51 | }
52 |
53 | dfrd = $.Deferred();
54 |
55 |
56 | input = $(' ')
57 | .change(function() {
58 | upload({input : input[0]});
59 | });
60 |
61 | button = $(''+fm.i18n('selectForUpload')+'
')
62 | .append($('').append(input))
63 | .hover(function() {
64 | button.toggleClass(hover)
65 | });
66 |
67 | dialog = $('
')
68 | .append(button);
69 |
70 | pastebox = $('
')
71 | .focus(function() {
72 | if (this.innerHTML) {
73 | var type = this.innerHTML.match(/<[^>]+>/)? 'html' : 'text';
74 | var src = this.innerHTML;
75 | this.innerHTML = '';
76 | upload({files : [ src ], type : type});
77 | }
78 | })
79 | .bind('dragenter mouseover', function(){
80 | this.focus();
81 | $(pastebox).addClass(hover);
82 | })
83 | .bind('dragleave mouseout', function(){
84 | this.blur();
85 | $(pastebox).removeClass(hover);
86 | })
87 | .bind('mouseup keyup', function() {
88 | setTimeout(function(){
89 | $(pastebox).focus();
90 | }, 100);
91 | });
92 |
93 | if (fm.dragUpload) {
94 | dropbox = $(''+fm.i18n('dropFiles')+'
')
95 | .prependTo(dialog)
96 | .after(''+fm.i18n('or')+'
')
97 | .after(pastebox)
98 | .after(''+fm.i18n('dropFilesBrowser')+'
')
99 | .after(''+fm.i18n('or')+'
')[0];
100 |
101 | dropbox.addEventListener('dragenter', function(e) {
102 | e.stopPropagation();
103 | e.preventDefault();
104 | $(dropbox).addClass(hover);
105 | }, false);
106 |
107 | dropbox.addEventListener('dragleave', function(e) {
108 | e.stopPropagation();
109 | e.preventDefault();
110 | $(dropbox).removeClass(hover);
111 | }, false);
112 |
113 | dropbox.addEventListener('dragover', function(e) {
114 | e.stopPropagation();
115 | e.preventDefault();
116 | $(dropbox).addClass(hover);
117 | }, false);
118 |
119 | dropbox.addEventListener('drop', function(e) {
120 | e.stopPropagation();
121 | e.preventDefault();
122 | var file = false;
123 | var type = '';
124 | if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length) {
125 | file = e.dataTransfer.files;
126 | type = 'files';
127 | } else if (e.dataTransfer.getData('text/html')) {
128 | file = [ e.dataTransfer.getData('text/html') ];
129 | type = 'html';
130 | } else if (e.dataTransfer.getData('text')) {
131 | file = [ e.dataTransfer.getData('text') ];
132 | type = 'text';
133 | }
134 | if (file) {
135 | upload({files : file, type : type});
136 | }
137 | }, false);
138 |
139 | } else {
140 | $(''+fm.i18n('dropFilesBrowser')+'
')
141 | .append(pastebox)
142 | .prependTo(dialog)
143 | .after(''+fm.i18n('or')+'
')[0];
144 |
145 | }
146 |
147 | fm.dialog(dialog, {
148 | title : this.title,
149 | modal : true,
150 | resizable : false,
151 | destroyOnClose : true
152 | });
153 |
154 | return dfrd;
155 | };
156 |
157 | };
--------------------------------------------------------------------------------
/css/navbar.css:
--------------------------------------------------------------------------------
1 | /*********************************************/
2 | /* NAVIGATION PANEL */
3 | /*********************************************/
4 |
5 | /* container */
6 | .finder .finder-navbar {
7 | height:100%;
8 | width:230px;
9 | padding:3px 5px;
10 | background-image:none;
11 | border-top:0 solid;
12 | border-bottom:0 solid;
13 | overflow:auto;
14 | display:none;
15 | position:relative;
16 | -moz-user-select: none;
17 | -khtml-user-select: none;
18 | -webkit-user-select: none;
19 | user-select: none;
20 | /* border:1px solid #111;*/
21 | }
22 |
23 |
24 | /* ltr/rtl enviroment */
25 | .finder-ltr .finder-navbar {
26 | float:left;
27 | border-left:0 solid;
28 | padding-right:13px;
29 | }
30 | .finder-rtl .finder-navbar {
31 | float:right;
32 | border-right:0 solid;
33 | padding-left:13px;
34 | }
35 |
36 | /* folders tree container */
37 | .finder-tree {
38 | display:table;
39 | width:100%;
40 | margin: 0 0 .5em 0;
41 | }
42 |
43 | /* one folder wrapper */
44 | .finder-navbar-wrapper, .finder-place-wrapper { }
45 |
46 | /* folder */
47 | .finder-navbar-dir {
48 | position:relative;
49 | display:block;
50 | white-space:nowrap;
51 | padding:3px 12px;
52 | margin: 0;
53 | outline:0px solid;
54 | border:1px solid transparent;
55 | cursor:default;
56 |
57 | }
58 |
59 | /* ltr/rtl enviroment */
60 | .finder-ltr .finder-navbar-dir { padding-left:35px; }
61 | .finder-rtl .finder-navbar-dir { padding-right:35px; }
62 |
63 | /* arrow before icon */
64 | .finder-navbar-arrow {
65 | width:12px;
66 | height:14px;
67 | position:absolute;
68 | display:none;
69 | top:50%;
70 | margin-top:-8px;
71 | background-image:url("../img/arrows-normal.png");
72 | background-repeat:no-repeat;
73 | /* border:1px solid #111;*/
74 | }
75 |
76 | .ui-state-active .finder-navbar-arrow { background-image:url("../img/arrows-active.png"); }
77 |
78 | /* collapsed/expanded arrow view */
79 | .finder-navbar-collapsed .finder-navbar-arrow { display:block; }
80 |
81 | /* arrow ltr/rtl enviroment */
82 | .finder-ltr .finder-navbar-collapsed .finder-navbar-arrow { background-position: 0 4px; left:0; }
83 | .finder-rtl .finder-navbar-collapsed .finder-navbar-arrow { background-position: 0 -10px; right:0; }
84 | .finder-ltr .finder-navbar-expanded .finder-navbar-arrow,
85 | .finder-rtl .finder-navbar-expanded .finder-navbar-arrow { background-position:0 -21px; }
86 |
87 |
88 | /* folder icon */
89 | .finder-navbar-icon {
90 | width:16px;
91 | height:16px;
92 | position:absolute;
93 | top:50%;
94 | margin-top:-8px;
95 | background-image:url("../img/toolbar.png");
96 | background-repeat:no-repeat;
97 | background-position:0 -16px;
98 | }
99 |
100 | /* ltr/rtl enviroment */
101 | .finder-ltr .finder-navbar-icon { left:14px; }
102 | .finder-rtl .finder-navbar-icon { right:14px; }
103 |
104 | /* root folder */
105 | .finder-tree .finder-navbar-root .finder-navbar-icon { background-position:0 0; }
106 | .finder-places .finder-navbar-root .finder-navbar-icon { background-position:0 -48px; }
107 |
108 | /* netmount */
109 | .finder-tree .finder-navbar-net .finder-navbar-icon { background-position: 0 -656px; }
110 |
111 |
112 |
113 | /* icon in active/hove/dropactive state */
114 | .ui-state-active .finder-navbar-icon,
115 | .finder-droppable-active .finder-navbar-icon,
116 | .ui-state-hover .finder-navbar-icon { background-position:0 -32px; }
117 |
118 | /* subdirs tree */
119 | .finder-navbar-subtree { display:none; }
120 |
121 | /* ltr/rtl enviroment */
122 | .finder-ltr .finder-navbar-subtree { margin-left:12px; }
123 | .finder-rtl .finder-navbar-subtree { margin-right:12px; }
124 |
125 |
126 | /* spinner */
127 | .finder-navbar-spinner {
128 | width:14px;
129 | height:14px;
130 | position:absolute;
131 | display:block;
132 | top:50%;
133 | margin-top:-7px;
134 | background: url("../img/spinner-mini.gif") center center no-repeat;
135 | }
136 | /* spinner ltr/rtl enviroment */
137 | .finder-ltr .finder-navbar-spinner { left:0; margin-left:-2px; }
138 | .finder-rtl .finder-navbar-spinner { right:0; margin-right:-2px; }
139 |
140 | /* permissions marker */
141 | .finder-navbar .finder-perms { top:50%; margin-top:-8px; }
142 |
143 | /* permissions/symlink markers ltr/rtl enviroment */
144 | .finder-ltr .finder-navbar .finder-perms { left: 18px; }
145 | .finder-rtl .finder-navbar .finder-perms { right: 18px; }
146 | .finder-ltr .finder-navbar .finder-symlink { left: 8px; }
147 | .finder-rtl .finder-navbar .finder-symlink { right: 8px; }
148 |
149 | /* resizable */
150 | .finder-navbar .ui-resizable-handle {
151 | width:12px;
152 | background:transparent url('../img/resize.png') center center no-repeat;
153 | right:1px;
154 | }
155 | .finder-rtl .finder-navbar .ui-resizable-handle {
156 | left:1px;
157 | }
158 |
159 |
160 | .finder-nav-handle-icon {
161 | position:absolute;
162 | top:50%;
163 | margin:-8px 2px 0 2px;
164 | opacity: .5; filter:Alpha(Opacity=50);
165 | }
166 |
167 | .finder-places { border:1px solid transparent;}
168 | .finder-places.finder-droppable-active {
169 | border:1px solid #8cafed;
170 | }
171 |
172 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/css/quicklook.css:
--------------------------------------------------------------------------------
1 | /* quicklook window */
2 | .finder-quicklook {
3 | position:absolute;
4 | background:url("../img/quicklook-bg.png");
5 | display:none;
6 | overflow:hidden;
7 | border-radius:7px;
8 | padding:20px 0 40px 0;
9 | }
10 |
11 | .finder-quicklook .ui-resizable-se {
12 | width:14px;
13 | height:14px;
14 | right:5px;
15 | bottom:3px;
16 | background:url("../img/toolbar.png") 0 -496px no-repeat;}
17 |
18 | /* quicklook fullscreen window */
19 | .finder-quicklook-fullscreen {
20 | border-radius:0;
21 | -webkit-background-clip: padding-box;
22 | /* background-clip:padding-box;*/
23 | padding:0;
24 | background:#000;
25 | z-index:90000;
26 | display:block;
27 | }
28 | /* hide titlebar in fullscreen mode */
29 | .finder-quicklook-fullscreen .finder-quicklook-titlebar { display:none; }
30 |
31 | /* hide preview border in fullscreen mode */
32 | .finder-quicklook-fullscreen .finder-quicklook-preview { border:0 solid ;}
33 |
34 | /* quicklook titlebar */
35 | .finder-quicklook-titlebar {
36 | text-align:center;
37 | background:#777;
38 | position:absolute;
39 | left:0;
40 | top:0;
41 | width:100%;
42 | height:20px;
43 | border-top-left-radius: 7px;
44 | border-top-right-radius: 7px;
45 | cursor:move;
46 | }
47 |
48 | /* window title */
49 | .finder-quicklook-title {
50 | color:#fff;
51 | white-space:nowrap;
52 | overflow:hidden;
53 | padding:2px 0;
54 | }
55 |
56 | /* icon "close" in titlebar */
57 | .finder-quicklook-titlebar .ui-icon {
58 | position:absolute;
59 | left : 4px;
60 | top:50%;
61 | margin-top:-8px;
62 | width:16px;
63 | height:16px;
64 | cursor:default;
65 | }
66 |
67 | /* main part of quicklook window */
68 | .finder-quicklook-preview {
69 | overflow:hidden;
70 | position:relative;
71 | border:0 solid;
72 | border-left:1px solid transparent;
73 | border-right:1px solid transparent;
74 | height:100%;
75 | }
76 |
77 | /* wrapper for file info/icon */
78 | .finder-quicklook-info-wrapper {
79 | position:absolute;
80 | width:100%;
81 | left:0;
82 | top:50%;
83 | margin-top:-50px;
84 | }
85 |
86 | /* file info */
87 | .finder-quicklook-info {
88 | padding: 0 12px 0 112px;
89 | }
90 |
91 | /* file name in info */
92 | .finder-quicklook-info .finder-quicklook-info-data:first-child {
93 | color:#fff;
94 | font-weight:bold;
95 | padding-bottom:.5em;
96 | }
97 |
98 | /* other data in info */
99 | .finder-quicklook-info-data {
100 | padding-bottom:.2em;
101 | color:#fff;
102 | }
103 |
104 |
105 | /* file icon */
106 | .finder-quicklook .finder-cwd-icon {
107 | position:absolute;
108 | left:32px;
109 | top:50%;
110 | margin-top:-20px;
111 | }
112 |
113 | /* image in preview */
114 | .finder-quicklook-preview img {
115 | display:block;
116 | margin:0 auto;
117 | }
118 |
119 | /* navigation bar on quicklook window bottom */
120 | .finder-quicklook-navbar {
121 | position:absolute;
122 | left:50%;
123 | bottom:4px;
124 | width:140px;
125 | height:32px;
126 | padding:0px;
127 | margin-left:-70px;
128 | border:1px solid transparent;
129 | border-radius:19px;
130 | }
131 |
132 | /* navigation bar in fullscreen mode */
133 | .finder-quicklook-fullscreen .finder-quicklook-navbar {
134 | width:188px;
135 | margin-left:-94px;
136 | padding:5px;
137 | border:1px solid #eee;
138 | background:#000;
139 | }
140 |
141 | /* show close icon in fullscreen mode */
142 | .finder-quicklook-fullscreen .finder-quicklook-navbar-icon-close,
143 | .finder-quicklook-fullscreen .finder-quicklook-navbar-separator {
144 | display:inline;
145 | }
146 |
147 | /* icons in navbar */
148 | .finder-quicklook-navbar-icon {
149 | width:32px;
150 | height:32px;
151 | margin:0 7px;
152 | float:left;
153 | background:url("../img/quicklook-icons.png") 0 0 no-repeat;
154 |
155 | }
156 |
157 | /* fullscreen icon */
158 | .finder-quicklook-navbar-icon-fullscreen {
159 | background-position:0 -64px;
160 | }
161 |
162 | /* exit fullscreen icon */
163 | .finder-quicklook-navbar-icon-fullscreen-off {
164 | background-position:0 -96px;
165 | }
166 |
167 | /* prev file icon */
168 | .finder-quicklook-navbar-icon-prev {
169 | background-position:0 0;
170 | }
171 |
172 | /* next file icon */
173 | .finder-quicklook-navbar-icon-next {
174 | background-position:0 -32px;
175 | }
176 |
177 | /* close icon */
178 | .finder-quicklook-navbar-icon-close {
179 | background-position:0 -128px;
180 | display:none;
181 | }
182 |
183 | /* icons separator */
184 | .finder-quicklook-navbar-separator {
185 | width:1px;
186 | height:32px;
187 | float:left;
188 | border-left:1px solid #fff;
189 | display:none;
190 | }
191 |
192 | /* text files preview wrapper */
193 | .finder-quicklook-preview-text-wrapper {
194 | width: 100%;
195 | height:100%;
196 | background:#fff;
197 | color:#222;
198 | overflow:auto;
199 | }
200 |
201 | /* text preview */
202 | pre.finder-quicklook-preview-text {
203 | margin:0;
204 | padding:3px 9px;
205 | }
206 |
207 | /* html/pdf preview */
208 | .finder-quicklook-preview-html,
209 | .finder-quicklook-preview-pdf {
210 | width:100%;
211 | height:100%;
212 | background:#fff;
213 | border:0 solid;
214 | margin:0;
215 | }
216 |
217 | /* swf preview container */
218 | .finder-quicklook-preview-flash {
219 | width:100%;
220 | height:100%;
221 | }
222 |
223 | /* audio preview container */
224 | .finder-quicklook-preview-audio {
225 | width:100%;
226 | position:absolute;
227 | bottom:0;
228 | left:0;
229 | }
230 |
231 | /* audio preview using embed */
232 | embed.finder-quicklook-preview-audio {
233 | height:30px;
234 | background:transparent;
235 | }
236 |
237 | /* video preview container */
238 | .finder-quicklook-preview-video {
239 | width:100%;
240 | height:100%;
241 | }
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
--------------------------------------------------------------------------------
/js/commands/help.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /**
3 | * @class Finder command "help"
4 | * "About" dialog
5 | *
6 | * @author Dmitry (dio) Levashov
7 | **/
8 | Finder.prototype.commands.help = function() {
9 | var fm = this.fm,
10 | self = this,
11 | linktpl = '',
12 | atpl = '',
13 | url = /\{url\}/,
14 | link = /\{link\}/,
15 | author = /\{author\}/,
16 | work = /\{work\}/,
17 | r = 'replace',
18 | prim = 'ui-priority-primary',
19 | sec = 'ui-priority-secondary',
20 | lic = 'finder-help-license',
21 | tab = '{title} ',
22 | html = ['',
23 | '');
111 |
112 | $.inArray('about', parts) !== -1 && about();
113 | $.inArray('shortcuts', parts) !== -1 && shortcuts();
114 | $.inArray('help', parts) !== -1 && help();
115 |
116 | html.push('
');
117 | content = $(html.join(''));
118 |
119 | fm.one('load', function setapi() { content.find('#apiver').text(fm.api); });
120 |
121 | content.find('.ui-tabs-nav li')
122 | .hover(function() {
123 | $(this).toggleClass('ui-state-hover')
124 | })
125 | .children()
126 | .click(function(e) {
127 | var link = $(this);
128 |
129 | e.preventDefault();
130 | e.stopPropagation();
131 |
132 | if (!link.is('.ui-tabs-selected')) {
133 | link.parent().addClass('ui-tabs-selected ui-state-active').siblings().removeClass('ui-tabs-selected').removeClass('ui-state-active');
134 | content.find('.ui-tabs-panel').hide().filter(link.attr('href')).show();
135 | }
136 |
137 | })
138 | .filter(':first').click();
139 |
140 | }, 200)
141 |
142 | this.getstate = function() {
143 | return 0;
144 | }
145 |
146 | this.exec = function() {
147 | if (!this.dialog) {
148 | this.dialog = this.fm.dialog(content, {title : this.title, width : 530, autoOpen : false, destroyOnClose : false});
149 | }
150 |
151 | this.dialog.finderdialog('open').find('.ui-tabs-nav li a:first').click();
152 | }
153 |
154 | }
155 |
--------------------------------------------------------------------------------
/js/commands/edit.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | /**
3 | * @class Finder command "edit".
4 | * Edit text file in dialog window
5 | *
6 | * @author Dmitry (dio) Levashov, dio@std42.ru
7 | **/
8 | Finder.prototype.commands.edit = function() {
9 | var self = this,
10 | fm = this.fm,
11 | mimes = fm.res('mimes', 'text') || [],
12 |
13 | /**
14 | * Return files acceptable to edit
15 | *
16 | * @param Array files hashes
17 | * @return Array
18 | **/
19 | filter = function(files) {
20 | return $.map(files, function(file) {
21 | return (file.mime.indexOf('text/') === 0 || $.inArray(file.mime, mimes) !== -1)
22 | && file.mime.indexOf('text/rtf')
23 | && (!self.onlyMimes.length || $.inArray(file.mime, self.onlyMimes) !== -1)
24 | && file.read && file.write ? file : null;
25 | });
26 | },
27 |
28 | /**
29 | * Open dialog with textarea to edit file
30 | *
31 | * @param String id dialog id
32 | * @param Object file file object
33 | * @param String content file content
34 | * @return $.Deferred
35 | **/
36 | dialog = function(id, file, content) {
37 |
38 | var dfrd = $.Deferred(),
39 | ta = $(''),
40 | save = function() {
41 | ta.editor && ta.editor.save(ta[0], ta.editor.instance);
42 | dfrd.resolve(ta.getContent());
43 | ta.finderdialog('close');
44 | },
45 | cancel = function() {
46 | dfrd.reject();
47 | ta.finderdialog('close');
48 | },
49 | opts = {
50 | title : file.name,
51 | width : self.options.dialogWidth || 450,
52 | buttons : {},
53 | close : function() {
54 | ta.editor && ta.editor.close(ta[0], ta.editor.instance);
55 | $(this).finderdialog('destroy');
56 | },
57 | open : function() {
58 | fm.disable();
59 | ta.focus();
60 | ta[0].setSelectionRange && ta[0].setSelectionRange(0, 0);
61 | ta.editor && ta.editor.load(ta[0]);
62 | }
63 |
64 | };
65 |
66 | ta.getContent = function() {
67 | return ta.val()
68 | }
69 |
70 | $.each(self.options.editors || [], function(i, editor) {
71 | if ($.inArray(file.mime, editor.mimes || []) !== -1
72 | && typeof editor.load == 'function'
73 | && typeof editor.save == 'function') {
74 | ta.editor = {
75 | load : editor.load,
76 | save : editor.save,
77 | close : typeof editor.close == 'function' ? editor.close : function() {},
78 | instance : null
79 | }
80 |
81 | return false;
82 | }
83 | });
84 |
85 | if (!ta.editor) {
86 | ta.keydown(function(e) {
87 | var code = e.keyCode,
88 | value, start;
89 |
90 | e.stopPropagation();
91 | if (code == 9) {
92 | e.preventDefault();
93 | // insert tab on tab press
94 | if (this.setSelectionRange) {
95 | value = this.value;
96 | start = this.selectionStart;
97 | this.value = value.substr(0, start) + "\t" + value.substr(this.selectionEnd);
98 | start += 1;
99 | this.setSelectionRange(start, start);
100 | }
101 | }
102 |
103 | if (e.ctrlKey || e.metaKey) {
104 | // close on ctrl+w/q
105 | if (code == 81 || code == 87) {
106 | e.preventDefault();
107 | cancel();
108 | }
109 | if (code == 83) {
110 | e.preventDefault();
111 | save();
112 | }
113 | }
114 |
115 | })
116 | }
117 |
118 | opts.buttons[fm.i18n('Save')] = save;
119 | opts.buttons[fm.i18n('Cancel')] = cancel
120 |
121 | fm.dialog(ta, opts).attr('id', id);
122 | return dfrd.promise();
123 | },
124 |
125 | /**
126 | * Get file content and
127 | * open dialog with textarea to edit file content
128 | *
129 | * @param String file hash
130 | * @return jQuery.Deferred
131 | **/
132 | edit = function(file) {
133 | var hash = file.hash,
134 | opts = fm.options,
135 | dfrd = $.Deferred(),
136 | data = {cmd : 'file', target : hash},
137 | url = fm.url(hash) || fm.options.url,
138 | id = 'edit-'+fm.namespace+'-'+file.hash,
139 | d = fm.getUI().find('#'+id),
140 | error;
141 |
142 |
143 | if (d.length) {
144 | d.finderdialog('toTop');
145 | return dfrd.resolve();
146 | }
147 |
148 | if (!file.read || !file.write) {
149 | error = ['errOpen', file.name, 'errPerm']
150 | fm.error(error)
151 | return dfrd.reject(error);
152 | }
153 |
154 | fm.request({
155 | data : {cmd : 'get', target : hash},
156 | notify : {type : 'openfile', cnt : 1},
157 | syncOnFail : true
158 | })
159 | .done(function(data) {
160 | dialog(id, file, data.content)
161 | .done(function(content) {
162 | fm.request({
163 | options : {type : 'post'},
164 | data : {
165 | cmd : 'put',
166 | target : hash,
167 | content : content
168 | },
169 | notify : {type : 'save', cnt : 1},
170 | syncOnFail : true
171 | })
172 | .fail(function(error) {
173 | dfrd.reject(error);
174 | })
175 | .done(function(data) {
176 | data.changed && data.changed.length && fm.change(data);
177 | dfrd.resolve(data);
178 | });
179 | })
180 | })
181 | .fail(function(error) {
182 | dfrd.reject(error);
183 | })
184 |
185 | return dfrd.promise();
186 | };
187 |
188 |
189 |
190 | this.shortcuts = [{
191 | pattern : 'ctrl+e'
192 | }];
193 |
194 | this.init = function() {
195 | this.onlyMimes = this.options.mimes || []
196 | }
197 |
198 | this.getstate = function(sel) {
199 | var sel = this.files(sel),
200 | cnt = sel.length;
201 |
202 | return !this._disabled && cnt && filter(sel).length == cnt ? 0 : -1;
203 | }
204 |
205 | this.exec = function(hashes) {
206 | var files = filter(this.files(hashes)),
207 | list = [],
208 | file;
209 |
210 | if (this.disabled()) {
211 | return $.Deferred().reject();
212 | }
213 |
214 | while ((file = files.shift())) {
215 | list.push(edit(file));
216 | }
217 |
218 | return list.length
219 | ? $.when.apply(null, list)
220 | : $.Deferred().reject();
221 | }
222 |
223 | }
--------------------------------------------------------------------------------
/js/commands/paste.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /**
3 | * @class Finder command "paste"
4 | * Paste filesfrom clipboard into directory.
5 | * If files pasted in its parent directory - files duplicates will created
6 | *
7 | * @author Dmitry (dio) Levashov
8 | **/
9 | Finder.prototype.commands.paste = function() {
10 |
11 | this.updateOnSelect = false;
12 |
13 | this.handlers = {
14 | changeclipboard : function() { this.update(); }
15 | }
16 |
17 | this.shortcuts = [{
18 | pattern : 'ctrl+v shift+insert'
19 | }];
20 |
21 | this.getstate = function(dst) {
22 | if (this._disabled) {
23 | return -1;
24 | }
25 | if (dst) {
26 | if ($.isArray(dst)) {
27 | if (dst.length != 1) {
28 | return -1;
29 | }
30 | dst = this.fm.file(dst[0]);
31 | }
32 | } else {
33 | dst = this.fm.cwd();
34 | }
35 |
36 | //return this.fm.clipboard().length && dst.mime == 'directory' && dst.write ? 0 : -1;
37 | return dst.mime == 'directory' && dst.write ? 0 : -1;
38 | }
39 |
40 | this.exec = function(dst) {
41 | var self = this,
42 | fm = self.fm,
43 | dst = dst ? this.files(dst)[0] : fm.cwd(),
44 | files = fm.clipboard(),
45 | cnt = files.length,
46 | cut = cnt ? files[0].cut : false,
47 | error = cut ? 'errMove' : 'errCopy',
48 | fpaste = [],
49 | fcopy = [],
50 | dfrd = $.Deferred()
51 | .fail(function(error) {
52 | error && fm.error(error);
53 | }),
54 | copy = function(files) {
55 | return files.length && fm._commands.duplicate
56 | ? fm.exec('duplicate', files)
57 | : $.Deferred().resolve();
58 | },
59 | paste = function(files) {
60 | var dfrd = $.Deferred(),
61 | existed = [],
62 | intersect = function(files, names) {
63 | var ret = [],
64 | i = files.length;
65 |
66 | while (i--) {
67 | $.inArray(files[i].name, names) !== -1 && ret.unshift(i);
68 | }
69 | return ret;
70 | },
71 | confirm = function(ndx) {
72 | var i = existed[ndx],
73 | file = files[i],
74 | last = ndx == existed.length-1;
75 |
76 | if (!file) {
77 | return;
78 | }
79 |
80 | fm.confirm({
81 | title : fm.i18n(cut ? 'moveFiles' : 'copyFiles'),
82 | text : fm.i18n(['errExists', file.name, 'confirmRepl']),
83 | all : !last,
84 | accept : {
85 | label : 'btnYes',
86 | callback : function(all) {
87 | !last && !all
88 | ? confirm(++ndx)
89 | : paste(files);
90 | }
91 | },
92 | reject : {
93 | label : 'btnNo',
94 | callback : function(all) {
95 | var i;
96 |
97 | if (all) {
98 | i = existed.length;
99 | while (ndx < i--) {
100 | files[existed[i]].remove = true
101 | }
102 | } else {
103 | files[existed[ndx]].remove = true;
104 | }
105 |
106 | !last && !all
107 | ? confirm(++ndx)
108 | : paste(files);
109 | }
110 | },
111 | cancel : {
112 | label : 'btnCancel',
113 | callback : function() {
114 | dfrd.resolve();
115 | }
116 | }
117 | })
118 | },
119 | valid = function(names) {
120 | existed = intersect(files, names);
121 | existed.length ? confirm(0) : paste(files);
122 | },
123 | paste = function(files) {
124 | var files = $.map(files, function(file) { return !file.remove ? file : null } ),
125 | cnt = files.length,
126 | groups = {},
127 | args = [],
128 | src;
129 |
130 | if (!cnt) {
131 | return dfrd.resolve();
132 | }
133 |
134 | src = files[0].phash;
135 | files = $.map(files, function(f) { return f.hash});
136 |
137 | fm.request({
138 | data : {cmd : 'paste', dst : dst.hash, targets : files, cut : cut ? 1 : 0, src : src},
139 | notify : {type : cut ? 'move' : 'copy', cnt : cnt}
140 | })
141 | .always(function() {
142 | dfrd.resolve();
143 | fm.unlockfiles({files : files});
144 | });
145 | }
146 | ;
147 |
148 | if (self._disabled || !files.length) {
149 | return dfrd.resolve();
150 | }
151 |
152 |
153 | if (!fm.option('copyOverwrite')) {
154 | paste(files);
155 | } else {
156 |
157 | dst.hash == fm.cwd().hash
158 | ? valid($.map(fm.files(), function(file) { return file.phash == dst.hash ? file.name : null }))
159 | : fm.request({
160 | data : {cmd : 'ls', target : dst.hash},
161 | notify : {type : 'prepare', cnt : 1, hideCnt : true},
162 | preventFail : true
163 | })
164 | .always(function(data) {
165 | valid(data.list || [])
166 | });
167 | }
168 |
169 | return dfrd;
170 | },
171 | parents, fparents;
172 |
173 |
174 | if (!cnt || !dst || dst.mime != 'directory') {
175 | return dfrd.reject();
176 | }
177 |
178 | if (!dst.write) {
179 | return dfrd.reject([error, files[0].name, 'errPerm']);
180 | }
181 |
182 | parents = fm.parents(dst.hash);
183 |
184 | $.each(files, function(i, file) {
185 | if (!file.read) {
186 | return !dfrd.reject([error, files[0].name, 'errPerm']);
187 | }
188 |
189 | if (cut && file.locked) {
190 | return !dfrd.reject(['errLocked', file.name]);
191 | }
192 |
193 | if ($.inArray(file.hash, parents) !== -1) {
194 | return !dfrd.reject(['errCopyInItself', file.name]);
195 | }
196 |
197 | fparents = fm.parents(file.hash);
198 | if ($.inArray(dst.hash, fparents) !== -1) {
199 |
200 | if ($.map(fparents, function(h) { var d = fm.file(h); return d.phash == dst.hash && d.name == file.name ? d : null }).length) {
201 | return !dfrd.reject(['errReplByChild', file.name]);
202 | }
203 | }
204 |
205 | if (file.phash == dst.hash) {
206 | fcopy.push(file.hash);
207 | } else {
208 | fpaste.push({
209 | hash : file.hash,
210 | phash : file.phash,
211 | name : file.name
212 | });
213 | }
214 | });
215 |
216 | if( dfrd.state() == 'rejected' ){
217 | return dfrd;
218 | }
219 |
220 | return $.when(
221 | copy(fcopy),
222 | paste(fpaste)
223 | ).always(function() {
224 | cut && fm.clipboard([]);
225 | });
226 | }
227 |
228 | }
--------------------------------------------------------------------------------
/css/commands.css:
--------------------------------------------------------------------------------
1 | /******************************************************************/
2 | /* COMMANDS STYLES */
3 | /******************************************************************/
4 |
5 | /********************** COMMAND "RESIZE" ****************************/
6 | .finder-dialog-resize { margin-top:.3em; }
7 | .finder-resize-type { float:left; margin-bottom: .4em; }
8 | .finder-resize-control { padding-top:3em; }
9 | .finder-resize-control input[type=text] { border:1px solid #aaa; text-align: right; }
10 | .finder-resize-preview {
11 | width:400px;
12 | height:400px;
13 | padding:10px;
14 | background:#fff;
15 | border:1px solid #aaa;
16 | float:right;
17 | position:relative;
18 | overflow:auto;
19 | /* z-index:100;*/
20 | }
21 |
22 | .finder-resize-handle { position:relative;}
23 |
24 | .finder-resize-handle-hline,
25 | .finder-resize-handle-vline {
26 | position:absolute;
27 | background-image:url("../img/crop.gif");
28 | }
29 |
30 | .finder-resize-handle-hline {
31 | width:100%;
32 | height:1px !important;
33 | background-repeat:repeat-x;
34 | }
35 | .finder-resize-handle-vline {
36 | width:1px !important;
37 | height:100%;
38 | background-repeat:repeat-y;
39 | }
40 |
41 | .finder-resize-handle-hline-top { top:0; left:0; }
42 | .finder-resize-handle-hline-bottom { bottom:0; left:0; }
43 | .finder-resize-handle-vline-left { top:0; left:0; }
44 | .finder-resize-handle-vline-right { top:0; right:0; }
45 |
46 | .finder-resize-handle-point {
47 | position:absolute;
48 | width:8px;
49 | height:8px;
50 | border:1px solid #777;
51 | background:transparent;
52 | }
53 |
54 | .finder-resize-handle-point-n {
55 | top:0;
56 | left:50%;
57 | margin-top:-5px;
58 | margin-left:-5px;
59 | }
60 | .finder-resize-handle-point-ne {
61 | top:0;
62 | right:0;
63 | margin-top:-5px;
64 | margin-right:-5px;
65 | }
66 | .finder-resize-handle-point-e {
67 | top:50%;
68 | right:0;
69 | margin-top:-5px;
70 | margin-right:-5px;
71 | }
72 | .finder-resize-handle-point-se {
73 | bottom:0;
74 | right:0;
75 | margin-bottom:-5px;
76 | margin-right:-5px;
77 | }
78 | .finder-resize-handle-point-s {
79 | bottom:0;
80 | left:50%;
81 | margin-bottom:-5px;
82 | margin-left:-5px;
83 | }
84 | .finder-resize-handle-point-sw {
85 | bottom:0;
86 | left:0;
87 | margin-bottom:-5px;
88 | margin-left:-5px;
89 | }
90 | .finder-resize-handle-point-w {
91 | top:50%;
92 | left:0;
93 | margin-top:-5px;
94 | margin-left:-5px;
95 | }
96 | .finder-resize-handle-point-nw {
97 | top:0;
98 | left:0;
99 | margin-top:-5px;
100 | margin-left:-5px;
101 | }
102 |
103 | .finder-resize-spinner {
104 | position:absolute;
105 | width:200px;
106 | height:30px;
107 | top:50%;
108 | margin-top:-25px;
109 | left:50%;
110 | margin-left:-100px;
111 | text-align:center;
112 | background:url(../img/progress.gif) center bottom repeat-x;
113 | }
114 |
115 | .finder-resize-row { margin-bottom:7px; position:relative;}
116 |
117 | .finder-resize-label { float:left; width:80px; padding-top: 3px; }
118 |
119 | .finder-resize-reset {
120 | width:16px;
121 | height:16px;
122 | /* border:1px solid #111;*/
123 | position:absolute;
124 | margin-top:-8px;
125 | }
126 |
127 | .finder-dialog .finder-dialog-resize .ui-resizable-e { height:100%; width:10px; }
128 | .finder-dialog .finder-dialog-resize .ui-resizable-s { width:100%; height:10px; }
129 | .finder-dialog .finder-dialog-resize .ui-resizable-se {
130 | background:transparent;
131 | bottom:0;
132 | right:0;
133 | margin-right:-7px;
134 | margin-bottom:-7px;
135 | }
136 |
137 | .finder-dialog-resize .ui-icon-grip-solid-vertical {
138 | position:absolute;
139 | top:50%;
140 | right:0;
141 | margin-top:-8px;
142 | margin-right:-11px;
143 | }
144 | .finder-dialog-resize .ui-icon-grip-solid-horizontal {
145 | position:absolute;
146 | left:50%;
147 | bottom:0;
148 | margin-left:-8px;
149 | margin-bottom:-11px;;
150 | }
151 |
152 | .finder-resize-row .finder-buttonset { float:right; }
153 |
154 | .finder-resize-rotate-slider {
155 | float: left;
156 | width: 195px;
157 | margin: 7px 7px 0;
158 | }
159 |
160 | /********************** COMMAND "EDIT" ****************************/
161 | /* edit text file textarea */
162 | .finder-file-edit {
163 | width:99%;
164 | height:99%;
165 | margin:0;
166 | padding:2px;
167 | border:1px solid #ccc;
168 | }
169 |
170 |
171 | /********************** COMMAND "HELP" ****************************/
172 | /* help dialog */
173 | .finder-help { margin-bottom:.5em; }
174 |
175 | /* fix tabs */
176 | .finder-help .ui-tabs-panel { padding:.5em; }
177 | .finder-dialog .ui-tabs .ui-tabs-nav li a { padding:.2em 1em;}
178 |
179 | .finder-help-shortcuts {
180 | height:300px;
181 | padding:1em;
182 | margin:.5em 0;
183 | overflow:auto;
184 | }
185 | .finder-help-shortcut { white-space:nowrap; clear:both;}
186 |
187 | .finder-help-shortcut-pattern { float:left; width:160px;}
188 |
189 | .finder-help h3 { font-size:1.5em; margin:.2em 0 .3em 0; }
190 |
191 | .finder-help-separator { clear:both; padding:.5em; }
192 |
193 | .finder-help-link { padding:2px; }
194 |
195 | .finder-help .ui-priority-secondary { font-size:.9em;}
196 |
197 | .finder-help .ui-priority-primary { margin-bottom:7px;}
198 |
199 | .finder-help-team {
200 | clear: both;
201 | text-align:right;
202 | border-bottom:1px solid #ccc;
203 | margin:.5em 0;
204 | font-size:.9em;
205 | }
206 |
207 | .finder-help-team div { float:left; }
208 | .finder-help-license { font-size:.9em;}
209 |
210 | .finder-help-disabled {
211 | font-weight:bold;
212 | text-align:center;
213 | margin:90px 0;
214 | }
215 |
216 | .finder-help .finder-dont-panic {
217 | display:block;
218 | border:1px solid transparent;
219 | width:200px;
220 | height:200px;
221 | margin:30px auto;
222 | text-decoration:none;
223 | text-align:center;
224 | position:relative;
225 | background:#d90004;
226 | -moz-box-shadow: 5px 5px 9px #111;
227 | -webkit-box-shadow: 5px 5px 9px #111;
228 | box-shadow: 5px 5px 9px #111;
229 | background: -moz-radial-gradient(80px 80px, circle farthest-corner, #d90004 35%, #960004 100%);
230 | background: -webkit-gradient(radial, 80 80, 60, 80 80, 120, from(#d90004), to(#960004));
231 | border-radius: 100px;
232 | outline:none;
233 | }
234 |
235 | .finder-help .finder-dont-panic span {
236 | font-size:3em;
237 | font-weight:bold;
238 | text-align:center;
239 | color:#fff;
240 | position:absolute;
241 | left:0;
242 | top:45px;
243 | }
244 |
245 |
246 |
247 |
--------------------------------------------------------------------------------
/js/commands/info.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /**
3 | * @class Finder command "info".
4 | * Display dialog with file properties.
5 | *
6 | * @author Dmitry (dio) Levashov, dio@std42.ru
7 | **/
8 | Finder.prototype.commands.info = function() {
9 | var m = 'msg',
10 | fm = this.fm,
11 | spclass = 'finder-info-spinner',
12 | msg = {
13 | calc : fm.i18n('calc'),
14 | size : fm.i18n('size'),
15 | unknown : fm.i18n('unknown'),
16 | path : fm.i18n('path'),
17 | aliasfor : fm.i18n('aliasfor'),
18 | modify : fm.i18n('modify'),
19 | perms : fm.i18n('perms'),
20 | locked : fm.i18n('locked'),
21 | dim : fm.i18n('dim'),
22 | kind : fm.i18n('kind'),
23 | files : fm.i18n('files'),
24 | folders : fm.i18n('folders'),
25 | items : fm.i18n('items'),
26 | yes : fm.i18n('yes'),
27 | no : fm.i18n('no'),
28 | link : fm.i18n('link')
29 | };
30 |
31 | this.tpl = {
32 | main : ' {title}
',
33 | itemTitle : '{name} {kind} ',
34 | groupTitle : '{items}: {num} ',
35 | row : '{label} : {value} ',
36 | spinner : '{text} '
37 | }
38 |
39 | this.alwaysEnabled = true;
40 | this.updateOnSelect = false;
41 | this.shortcuts = [{
42 | pattern : 'ctrl+i'
43 | }];
44 |
45 | this.init = function() {
46 | $.each(msg, function(k, v) {
47 | msg[k] = fm.i18n(v);
48 | });
49 | }
50 |
51 | this.getstate = function(sel) {
52 | var sel = this.files(sel);
53 | return sel.length ? 0 : -1;
54 | }
55 |
56 | this.exec = function(hashes) {
57 | var self = this,
58 | fm = this.fm,
59 | tpl = this.tpl,
60 | row = tpl.row,
61 | files = this.files(hashes),
62 | cnt = files.length,
63 | content = [],
64 | view = tpl.main,
65 | l = '{label}',
66 | v = '{value}',
67 | opts = {
68 | title : this.title,
69 | width : 'auto',
70 | close : function() { $(this).finderdialog('destroy'); }
71 | },
72 | count = [],
73 | replSpinner = function(msg) { dialog.find('.'+spclass).parent().text(msg); },
74 | id = fm.namespace+'-info-'+$.map(files, function(f) { return f.hash }).join('-'),
75 | dialog = fm.getUI().find('#'+id),
76 | size, tmb, file, title, dcnt;
77 |
78 | if (!cnt) {
79 | return $.Deferred().reject();
80 | }
81 |
82 | if (dialog.length) {
83 | dialog.finderdialog('toTop');
84 | return $.Deferred().resolve();
85 | }
86 |
87 |
88 | if (cnt == 1) {
89 | file = files[0];
90 | view = view.replace('{class}', fm.mime2class(file.mime));
91 | title = tpl.itemTitle.replace('{name}', file.name).replace('{kind}', fm.mime2kind(file));
92 |
93 | if (file.tmb) {
94 | tmb = fm.option('tmbUrl')+file.tmb;
95 | }
96 |
97 | if (!file.read) {
98 | size = msg.unknown;
99 | } else if (file.mime != 'directory' || file.alias) {
100 | size = fm.formatSize(file.size);
101 | } else {
102 | size = tpl.spinner.replace('{text}', msg.calc);
103 | count.push(file.hash);
104 | }
105 |
106 | content.push(row.replace(l, msg.size).replace(v, size));
107 | file.alias && content.push(row.replace(l, msg.aliasfor).replace(v, file.alias));
108 | content.push(row.replace(l, msg.path).replace(v, fm.escape(fm.path(file.hash))));
109 | file.read && content.push(row.replace(l, msg.link).replace(v, ''+file.name+' '));
110 |
111 | if (file.dim) { // old api
112 | content.push(row.replace(l, msg.dim).replace(v, file.dim));
113 | } else if (file.mime.indexOf('image') !== -1) {
114 | if (file.width && file.height) {
115 | content.push(row.replace(l, msg.dim).replace(v, file.width+'x'+file.height));
116 | } else {
117 | content.push(row.replace(l, msg.dim).replace(v, tpl.spinner.replace('{text}', msg.calc)));
118 | fm.request({
119 | data : {cmd : 'dim', target : file.hash},
120 | preventDefault : true
121 | })
122 | .fail(function() {
123 | replSpinner(msg.unknown);
124 | })
125 | .done(function(data) {
126 | replSpinner(data.dim || msg.unknown);
127 | });
128 | }
129 | }
130 |
131 |
132 | content.push(row.replace(l, msg.modify).replace(v, fm.formatDate(file)));
133 | content.push(row.replace(l, msg.perms).replace(v, fm.formatPermissions(file)));
134 | content.push(row.replace(l, msg.locked).replace(v, file.locked ? msg.yes : msg.no));
135 | } else {
136 | view = view.replace('{class}', 'finder-cwd-icon-group');
137 | title = tpl.groupTitle.replace('{items}', msg.items).replace('{num}', cnt);
138 | dcnt = $.map(files, function(f) { return f.mime == 'directory' ? 1 : null }).length;
139 | if (!dcnt) {
140 | size = 0;
141 | $.each(files, function(h, f) {
142 | var s = parseInt(f.size);
143 |
144 | if (s >= 0 && size >= 0) {
145 | size += s;
146 | } else {
147 | size = 'unknown';
148 | }
149 | });
150 | content.push(row.replace(l, msg.kind).replace(v, msg.files));
151 | content.push(row.replace(l, msg.size).replace(v, fm.formatSize(size)));
152 | } else {
153 | content.push(row.replace(l, msg.kind).replace(v, dcnt == cnt ? msg.folders : msg.folders+' '+dcnt+', '+msg.files+' '+(cnt-dcnt)))
154 | content.push(row.replace(l, msg.size).replace(v, tpl.spinner.replace('{text}', msg.calc)));
155 | count = $.map(files, function(f) { return f.hash });
156 |
157 | }
158 | }
159 |
160 | view = view.replace('{title}', title).replace('{content}', content.join(''));
161 |
162 | dialog = fm.dialog(view, opts);
163 | dialog.attr('id', id)
164 |
165 | // load thumbnail
166 | if (tmb) {
167 | $(' ')
168 | .load(function() { dialog.find('.finder-cwd-icon').css('background', 'url("'+tmb+'") center center no-repeat'); })
169 | .attr('src', tmb);
170 | }
171 |
172 | // send request to count total size
173 | if (count.length) {
174 | fm.request({
175 | data : {cmd : 'size', targets : count},
176 | preventDefault : true
177 | })
178 | .fail(function() {
179 | replSpinner(msg.unknown);
180 | })
181 | .done(function(data) {
182 | var size = parseInt(data.size);
183 | replSpinner(size >= 0 ? fm.formatSize(size) : msg.unknown);
184 | });
185 | }
186 |
187 | }
188 |
189 | }
190 |
--------------------------------------------------------------------------------
/js/Finder.command.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Finder command prototype
3 | *
4 | * @type Finder.command
5 | * @author Dmitry (dio) Levashov
6 | */
7 | Finder.prototype.command = function(fm) {
8 |
9 | /**
10 | * Finder instance
11 | *
12 | * @type Finder
13 | */
14 | this.fm = fm;
15 |
16 | /**
17 | * Command name, same as class name
18 | *
19 | * @type String
20 | */
21 | this.name = '';
22 |
23 | /**
24 | * Short command description
25 | *
26 | * @type String
27 | */
28 | this.title = '';
29 |
30 | /**
31 | * Current command state
32 | *
33 | * @example
34 | * this.state = -1; // command disabled
35 | * this.state = 0; // command enabled
36 | * this.state = 1; // command active (for example "fullscreen" command while finder in fullscreen mode)
37 | * @default -1
38 | * @type Number
39 | */
40 | this.state = -1;
41 |
42 | /**
43 | * If true, command can not be disabled by connector.
44 | * @see this.update()
45 | *
46 | * @type Boolen
47 | */
48 | this.alwaysEnabled = false;
49 |
50 | /**
51 | * If true, this means command was disabled by connector.
52 | * @see this.update()
53 | *
54 | * @type Boolen
55 | */
56 | this._disabled = false;
57 |
58 | this.disableOnSearch = false;
59 |
60 | this.updateOnSelect = true;
61 |
62 | /**
63 | * Finder events defaults handlers.
64 | * Inside handlers "this" is current command object
65 | *
66 | * @type Object
67 | */
68 | this._handlers = {
69 | enable : function() { this.update(void(0), this.value); },
70 | disable : function() { this.update(-1, this.value); },
71 | 'open reload load' : function(e) {
72 | this._disabled = !(this.alwaysEnabled || this.fm.isCommandEnabled(this.name));
73 | this.update(void(0), this.value)
74 | this.change();
75 | }
76 | };
77 |
78 | /**
79 | * Finder events handlers.
80 | * Inside handlers "this" is current command object
81 | *
82 | * @type Object
83 | */
84 | this.handlers = {}
85 |
86 | /**
87 | * Shortcuts
88 | *
89 | * @type Array
90 | */
91 | this.shortcuts = [];
92 |
93 | /**
94 | * Command options
95 | *
96 | * @type Object
97 | */
98 | this.options = {ui : 'button'};
99 |
100 | /**
101 | * Prepare object -
102 | * bind events and shortcuts
103 | *
104 | * @return void
105 | */
106 | this.setup = function(name, opts) {
107 | var self = this,
108 | fm = this.fm, i, s;
109 |
110 | this.name = name;
111 | this.title = fm.messages['cmd'+name] ? fm.i18n('cmd'+name) : name,
112 | this.options = $.extend({}, this.options, opts);
113 | this.listeners = [];
114 |
115 | if (this.updateOnSelect) {
116 | this._handlers.select = function() { this.update(void(0), this.value); }
117 | }
118 |
119 | $.each($.extend({}, self._handlers, self.handlers), function(cmd, handler) {
120 | fm.bind(cmd, $.proxy(handler, self));
121 | });
122 |
123 | for (i = 0; i < this.shortcuts.length; i++) {
124 | s = this.shortcuts[i];
125 | s.callback = $.proxy(s.callback || function() { this.exec() }, this);
126 | !s.description && (s.description = this.title);
127 | fm.shortcut(s);
128 | }
129 |
130 | if (this.disableOnSearch) {
131 | fm.bind('search searchend', function(e) {
132 | self._disabled = e.type == 'search';
133 | self.update(void(0), self.value);
134 | });
135 | }
136 |
137 | this.init();
138 | }
139 |
140 | /**
141 | * Command specific init stuffs
142 | *
143 | * @return void
144 | */
145 | this.init = function() { }
146 |
147 | /**
148 | * Exec command
149 | *
150 | * @param Array target files hashes
151 | * @param Array|Object command value
152 | * @return $.Deferred
153 | */
154 | this.exec = function(files, opts) {
155 | return $.Deferred().reject();
156 | }
157 |
158 | /**
159 | * Return true if command disabled.
160 | *
161 | * @return Boolen
162 | */
163 | this.disabled = function() {
164 | return this.state < 0;
165 | }
166 |
167 | /**
168 | * Return true if command enabled.
169 | *
170 | * @return Boolen
171 | */
172 | this.enabled = function() {
173 | return this.state > -1;
174 | }
175 |
176 | /**
177 | * Return true if command active.
178 | *
179 | * @return Boolen
180 | */
181 | this.active = function() {
182 | return this.state > 0;
183 | }
184 |
185 | /**
186 | * Return current command state.
187 | * Must be overloaded in most commands
188 | *
189 | * @return Number
190 | */
191 | this.getstate = function() {
192 | return -1;
193 | }
194 |
195 | /**
196 | * Update command state/value
197 | * and rize 'change' event if smth changed
198 | *
199 | * @param Number new state or undefined to auto update state
200 | * @param mixed new value
201 | * @return void
202 | */
203 | this.update = function(s, v) {
204 | var state = this.state,
205 | value = this.value;
206 |
207 | if (this._disabled) {
208 | this.state = -1;
209 | } else {
210 | this.state = s !== void(0) ? s : this.getstate();
211 | }
212 |
213 | this.value = v;
214 |
215 | if (state != this.state || value != this.value) {
216 | this.change();
217 | }
218 | }
219 |
220 | /**
221 | * Bind handler / fire 'change' event.
222 | *
223 | * @param Function|undefined event callback
224 | * @return void
225 | */
226 | this.change = function(c) {
227 | var cmd, i;
228 |
229 | if (typeof(c) === 'function') {
230 | this.listeners.push(c);
231 | } else {
232 | for (i = 0; i < this.listeners.length; i++) {
233 | cmd = this.listeners[i];
234 | try {
235 | cmd(this.state, this.value);
236 | } catch (e) {
237 | this.fm.debug('error', e)
238 | }
239 | }
240 | }
241 | return this;
242 | }
243 |
244 |
245 | /**
246 | * With argument check given files hashes and return list of existed files hashes.
247 | * Without argument return selected files hashes.
248 | *
249 | * @param Array|String|void hashes
250 | * @return Array
251 | */
252 | this.hashes = function(hashes) {
253 | return hashes
254 | ? $.map($.isArray(hashes) ? hashes : [hashes], function(hash) { return fm.file(hash) ? hash : null; })
255 | : fm.selected();
256 | }
257 |
258 | /**
259 | * Return only existed files from given fils hashes | selected files
260 | *
261 | * @param Array|String|void hashes
262 | * @return Array
263 | */
264 | this.files = function(hashes) {
265 | var fm = this.fm;
266 |
267 | return hashes
268 | ? $.map($.isArray(hashes) ? hashes : [hashes], function(hash) { return fm.file(hash) || null })
269 | : fm.selectedFiles();
270 | }
271 | }
272 |
273 |
274 |
--------------------------------------------------------------------------------
/css/toolbar.css:
--------------------------------------------------------------------------------
1 | /*********************************************/
2 | /* TOOLBAR STYLES */
3 | /*********************************************/
4 | /* toolbar container */
5 | .finder-toolbar {
6 | padding:4px 0 3px 0;
7 | border-left:0 solid transparent;
8 | border-top:0 solid transparent;
9 | border-right:0 solid transparent;
10 | }
11 |
12 | /* container for button's group */
13 | .finder-buttonset {
14 | margin: 1px 4px;
15 | float:left;
16 | background:transparent;
17 | padding:0;
18 | border-radius: 4px;
19 | }
20 |
21 | /*.finder-buttonset:first-child { margin:0; }*/
22 |
23 | /* button */
24 | .finder .finder-button {
25 | width:16px;
26 | height:16px;
27 | margin:0;
28 | padding:4px;
29 | float:left;
30 | overflow:hidden;
31 | position:relative;
32 | border:0 solid;
33 | cursor:pointer;
34 | }
35 |
36 | .finder .ui-icon-search { cursor:pointer;}
37 |
38 | .finder-button:first-child {
39 | border-top-left-radius: 4px;
40 | border-bottom-left-radius: 4px;
41 | }
42 |
43 | .finder-button:last-child {
44 | border-top-right-radius: 4px;
45 | border-bottom-right-radius: 4px;
46 | }
47 |
48 | /* separator between buttons, required for berder between button with ui color */
49 | .finder-toolbar-button-separator {
50 | float:left;
51 | padding:0;
52 | height:24px;
53 | border-top:0 solid;
54 | border-right:0 solid;
55 | border-bottom:0 solid;
56 | width:0;
57 | }
58 |
59 | /* change icon opacity^ not button */
60 | .finder .finder-button.ui-state-disabled { opacity:1; filter:Alpha(Opacity=100);}
61 | .finder .finder-button.ui-state-disabled .finder-button-icon { opacity:.4; filter:Alpha(Opacity=40);}
62 |
63 | /* rtl enviroment */
64 | .finder-rtl .finder-buttonset { float:right; }
65 |
66 | /* icon inside button */
67 | .finder-button-icon {
68 | width:16px;
69 | height:16px;
70 | display:block;
71 | background:url('../img/toolbar.png') no-repeat;
72 | }
73 |
74 | /* buttons icons */
75 | .finder-button-icon-home { background-position: 0 0; }
76 | .finder-button-icon-back { background-position: 0 -112px; }
77 | .finder-button-icon-forward { background-position: 0 -128px; }
78 | .finder-button-icon-up { background-position: 0 -144px; }
79 | .finder-button-icon-reload { background-position: 0 -160px; }
80 | .finder-button-icon-open { background-position: 0 -176px; }
81 | .finder-button-icon-mkdir { background-position: 0 -192px; }
82 | .finder-button-icon-mkfile { background-position: 0 -208px; }
83 | .finder-button-icon-rm { background-position: 0 -224px; }
84 | .finder-button-icon-copy { background-position: 0 -240px; }
85 | .finder-button-icon-cut { background-position: 0 -256px; }
86 | .finder-button-icon-paste { background-position: 0 -272px; }
87 | .finder-button-icon-getfile { background-position: 0 -288px; }
88 | .finder-button-icon-duplicate { background-position: 0 -304px; }
89 | .finder-button-icon-rename { background-position: 0 -320px; }
90 | .finder-button-icon-edit { background-position: 0 -336px; }
91 | .finder-button-icon-quicklook { background-position: 0 -352px; }
92 | .finder-button-icon-upload { background-position: 0 -368px; }
93 | .finder-button-icon-download { background-position: 0 -384px; }
94 | .finder-button-icon-info { background-position: 0 -400px; }
95 | .finder-button-icon-extract { background-position: 0 -416px; }
96 | .finder-button-icon-archive { background-position: 0 -432px; }
97 | .finder-button-icon-view { background-position: 0 -448px; }
98 | .finder-button-icon-view-list { background-position: 0 -464px; }
99 | .finder-button-icon-help { background-position: 0 -480px; }
100 | .finder-button-icon-resize { background-position: 0 -512px; }
101 | .finder-button-icon-search { background-position: 0 -561px; }
102 | .finder-button-icon-sort { background-position: 0 -577px; }
103 | .finder-button-icon-rotate-r { background-position: 0 -625px; }
104 | .finder-button-icon-rotate-l { background-position: 0 -641px; }
105 | .finder-button-icon-netmount { background-position: 0 -656px; }
106 |
107 | /* button with dropdown menu*/
108 | .finder .finder-menubutton { overflow:visible; }
109 |
110 |
111 |
112 | /* menu */
113 | .finder-button-menu {
114 | position:absolute;
115 | left:0;
116 | top:25px;
117 | padding:3px 0;
118 | }
119 |
120 | /* menu item */
121 | .finder-button-menu-item {
122 | white-space:nowrap;
123 | cursor:default;
124 | padding:5px 19px;
125 | position:relative;
126 | }
127 |
128 | /* fix hover ui class */
129 | .finder-button-menu .ui-state-hover { border:0 solid; }
130 |
131 | .finder-button-menu-item-separated { border-top:1px solid #ccc; }
132 |
133 | .finder-button-menu-item .ui-icon {
134 | width:16px;
135 | height:16px;
136 | position:absolute;
137 | left:2px;
138 | top:50%;
139 | margin-top:-8px;
140 | display:none;
141 | }
142 |
143 | .finder-button-menu-item-selected .ui-icon { display:block; }
144 | .finder-button-menu-item-selected-asc .ui-icon-arrowthick-1-n { display:none; }
145 | .finder-button-menu-item-selected-desc .ui-icon-arrowthick-1-s { display:none; }
146 |
147 | /* hack for upload button */
148 | .finder-button form {
149 | position:absolute;
150 | top:0;
151 | right:0;
152 | opacity: 0; filter:Alpha(Opacity=0);
153 | cursor: pointer;
154 | }
155 |
156 | .finder .finder-button form input { background:transparent; cursor: default;}
157 |
158 | /* search "button" */
159 | .finder .finder-button-search {
160 | border:0 solid;
161 | background:transparent;
162 | padding:0;
163 | margin: 1px 4px;
164 | height: auto;
165 | min-height: 26px;
166 | float:right;
167 | width:202px;
168 | }
169 |
170 | /* ltr/rte enviroment */
171 | .finder-ltr .finder-button-search { float:right; margin-right:10px; }
172 | .finder-rtl .finder-button-search { float:left; margin-left:10px; }
173 |
174 | /* search text field */
175 | .finder-button-search input {
176 | width:160px;
177 | height:22px;
178 | padding:0 20px;
179 | line-height: 22px;
180 | border:0 solid;
181 | border:1px solid #aaa;
182 | border-radius: 12px;
183 | outline:0px solid;
184 | }
185 |
186 | .finder-rtl .finder-button-search input { direction:rtl; }
187 |
188 | /* icons */
189 | .finder-button-search .ui-icon {
190 | position:absolute;
191 | height:18px;
192 | top: 50%;
193 | margin:-9px 4px 0 4px;
194 | opacity: .6;
195 | filter:Alpha(Opacity=60);
196 | }
197 |
198 | /* search/close icons */
199 | .finder-ltr .finder-button-search .ui-icon-search { left:0;}
200 | .finder-rtl .finder-button-search .ui-icon-search { right:0;}
201 | .finder-ltr .finder-button-search .ui-icon-close { right:0;}
202 | .finder-rtl .finder-button-search .ui-icon-close { left:0;}
203 |
204 |
205 |
206 |
207 |
208 |
209 |
--------------------------------------------------------------------------------
/js/ui/dialog.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /**
3 | * @class Finder dialog
4 | *
5 | * @author Dmitry (dio) Levashov
6 | **/
7 | $.fn.finderdialog = function(opts) {
8 | var dialog;
9 |
10 | if (typeof(opts) == 'string' && (dialog = this.closest('.ui-dialog')).length) {
11 | if (opts == 'open') {
12 | dialog.css('display') == 'none' && dialog.fadeIn(120, function() {
13 | dialog.trigger('open');
14 | });
15 | } else if (opts == 'close') {
16 | dialog.css('display') != 'none' && dialog.hide().trigger('close');
17 | } else if (opts == 'destroy') {
18 | dialog.hide().remove();
19 | } else if (opts == 'toTop') {
20 | dialog.trigger('totop');
21 | }
22 | }
23 |
24 | opts = $.extend({}, $.fn.finderdialog.defaults, opts);
25 |
26 | this.filter(':not(.ui-dialog-content)').each(function() {
27 | var self = $(this).addClass('ui-dialog-content ui-widget-content'),
28 | parent = self.parent(),
29 | clactive = 'finder-dialog-active',
30 | cldialog = 'finder-dialog',
31 | clnotify = 'finder-dialog-notify',
32 | clhover = 'ui-state-hover',
33 | id = parseInt(Math.random()*1000000),
34 | overlay = parent.children('.finder-overlay'),
35 | buttonset = $('
'),
36 | buttonpane = $('
')
37 | .append(buttonset),
38 |
39 |
40 | dialog = $('
')
41 | .hide()
42 | .append(self)
43 | .appendTo(parent)
44 | .draggable({
45 | handle : '.ui-dialog-titlebar'
46 | })
47 | .css({
48 | width : opts.width,
49 | height : opts.height,
50 | position: 'absolute'
51 | })
52 | .mousedown(function(e) {
53 | e.stopPropagation();
54 |
55 | $(document).mousedown();
56 |
57 | if (!dialog.is('.'+clactive)) {
58 | parent.find('.'+cldialog+':visible').removeClass(clactive);
59 | dialog.addClass(clactive).zIndex(maxZIndex() + 1);
60 | }
61 | })
62 | .bind('open', function() {
63 | opts.modal && overlay.finderoverlay('show');
64 | dialog.trigger('totop');
65 | typeof(opts.open) == 'function' && $.proxy(opts.open, self[0])();
66 |
67 | if (!dialog.is('.'+clnotify)) {
68 |
69 | parent.find('.'+cldialog+':visible').not('.'+clnotify).each(function() {
70 | var d = $(this),
71 | top = parseInt(d.css('top')),
72 | left = parseInt(d.css('left')),
73 | _top = parseInt(dialog.css('top')),
74 | _left = parseInt(dialog.css('left'))
75 | ;
76 |
77 | if (d[0] != dialog[0] && (top == _top || left == _left)) {
78 | dialog.css({
79 | top : (top+10),
80 | left : (left+10)
81 | });
82 | }
83 | });
84 | }
85 | })
86 | .bind('close', function() {
87 | var dialogs = parent.find('.finder-dialog:visible'),
88 | z = maxZIndex();
89 |
90 | opts.modal && overlay.finderoverlay('hide');
91 |
92 | // get focus to next dialog
93 | if (dialogs.length) {
94 | dialogs.each(function() {
95 | var d = $(this);
96 | if (d.zIndex() >= z) {
97 | d.trigger('totop');
98 | return false;
99 | }
100 | })
101 | } else {
102 | // return focus to parent
103 | setTimeout(function() {
104 | parent.mousedown().click();
105 | }, 10);
106 |
107 | }
108 |
109 | if (typeof(opts.close) == 'function') {
110 | $.proxy(opts.close, self[0])();
111 | } else if (opts.destroyOnClose) {
112 | dialog.hide().remove();
113 | }
114 | })
115 | .bind('totop', function() {
116 | $(this).mousedown().find('.ui-button:first').focus().end().find(':text:first').focus()
117 | }),
118 | maxZIndex = function() {
119 | var z = parent.zIndex() + 10;
120 | parent.find('.'+cldialog+':visible').each(function() {
121 | var _z;
122 | if (this != dialog[0]) {
123 | _z = $(this).zIndex();
124 | if (_z > z) {
125 | z = _z;
126 | }
127 | }
128 | })
129 | return z;
130 | },
131 | top
132 | ;
133 |
134 | if (!opts.position) {
135 | top = parseInt((parent.height() - dialog.outerHeight())/2 - 42);
136 | opts.position = {
137 | top : (top > 0 ? top : 0),
138 | left : parseInt((parent.width() - dialog.outerWidth())/2)
139 | }
140 | }
141 |
142 | dialog.css(opts.position);
143 |
144 | if (opts.closeOnEscape) {
145 | $(document).bind('keyup.'+id, function(e) {
146 | if (e.keyCode == $.ui.keyCode.ESCAPE && dialog.is('.'+clactive)) {
147 | self.finderdialog('close');
148 | $(document).unbind('keyup.'+id);
149 | }
150 | })
151 | }
152 | dialog.prepend(
153 | $('')
154 | .prepend($(' ')
155 | .mousedown(function(e) {
156 | e.preventDefault();
157 | self.finderdialog('close');
158 | }))
159 |
160 | );
161 |
162 |
163 |
164 | $.each(opts.buttons, function(name, cb) {
165 | var button = $(''+name+' ')
166 | .click($.proxy(cb, self[0]))
167 | .hover(function(e) { $(this)[e.type == 'mouseenter' ? 'focus' : 'blur']() })
168 | .focus(function() { $(this).addClass(clhover) })
169 | .blur(function() { $(this).removeClass(clhover) })
170 | .keydown(function(e) {
171 | var next;
172 |
173 | if (e.keyCode == $.ui.keyCode.ENTER) {
174 | $(this).click();
175 | } else if (e.keyCode == $.ui.keyCode.TAB) {
176 | next = $(this).next('.ui-button');
177 | next.length ? next.focus() : $(this).siblings('.ui-button:first').focus()
178 | }
179 | })
180 | buttonset.append(button);
181 | })
182 |
183 | buttonset.children().length && dialog.append(buttonpane);
184 | if (opts.resizable && $.fn.resizable) {
185 | dialog.resizable({
186 | minWidth : opts.minWidth,
187 | minHeight : opts.minHeight,
188 | alsoResize : this
189 | });
190 | }
191 |
192 | typeof(opts.create) == 'function' && $.proxy(opts.create, this)();
193 |
194 | opts.autoOpen && self.finderdialog('open');
195 |
196 | });
197 |
198 | return this;
199 | }
200 |
201 | $.fn.finderdialog.defaults = {
202 | cssClass : '',
203 | title : '',
204 | modal : false,
205 | resizable : true,
206 | autoOpen : true,
207 | closeOnEscape : true,
208 | destroyOnClose : false,
209 | buttons : {},
210 | position : null,
211 | width : 320,
212 | height : 'auto',
213 | minWidth : 200,
214 | minHeight : 110
215 | }
--------------------------------------------------------------------------------
/css/dialog.css:
--------------------------------------------------------------------------------
1 | /*********************************************/
2 | /* DIALOGS STYLES */
3 | /*********************************************/
4 |
5 | /* common dialogs class */
6 | .std42-dialog {
7 | padding:0;
8 | position:absolute;
9 | left:auto;
10 | right:auto;
11 | }
12 |
13 | /* titlebar */
14 | .std42-dialog .ui-dialog-titlebar {
15 | border-left:0 solid transparent;
16 | border-top:0 solid transparent;
17 | border-right:0 solid transparent;
18 | border-bottom-left-radius: 0;
19 | border-bottom-right-radius: 0;
20 | font-weight:normal;
21 | padding:.2em 1em;
22 | }
23 |
24 | .std42-dialog .ui-dialog-titlebar-close,
25 | .std42-dialog .ui-dialog-titlebar-close:hover { padding:1px; }
26 |
27 | .finder-rtl .finder-dialog .ui-dialog-titlebar { text-align:right; }
28 | .finder-rtl .finder-dialog .ui-dialog-titlebar .ui-dialog-titlebar-close { right:auto; left:.3em; }
29 |
30 | /* content */
31 | .std42-dialog .ui-dialog-content {
32 | padding:.3em .5em;
33 | }
34 |
35 | /* buttons */
36 | .std42-dialog .ui-dialog-buttonpane {
37 | border:0 solid;
38 | margin:0;
39 | padding:.5em .7em;
40 | }
41 |
42 | .std42-dialog .ui-dialog-buttonpane button { margin:0 0 0 .4em; padding:0; outline:0px solid; }
43 | .std42-dialog .ui-dialog-buttonpane button span { padding:2px 9px; }
44 |
45 | .finder-dialog .ui-resizable-e,
46 | .finder-dialog .ui-resizable-s { width:0; height:0;}
47 |
48 | .std42-dialog .ui-button input { cursor: pointer;}
49 |
50 | /* error/notify/confirm dialogs icon */
51 | .finder-dialog-icon {
52 | position:absolute;
53 | width:32px;
54 | height:32px;
55 | left:12px;
56 | top:50%;
57 | margin-top:-15px;
58 | background:url("../img/dialogs.png") 0 0 no-repeat;
59 | }
60 |
61 | .finder-rtl .finder-dialog-icon { left:auto; right:12px;}
62 |
63 |
64 |
65 | /*********************** ERROR DIALOG **************************/
66 |
67 | .finder-dialog-error .ui-dialog-content,
68 | .finder-dialog-confirm .ui-dialog-content { padding-left: 56px; min-height:35px; }
69 |
70 | .finder-rtl .finder-dialog-error .ui-dialog-content,
71 | .finder-rtl .finder-dialog-confirm .ui-dialog-content { padding-left:0; padding-right: 56px; }
72 |
73 | /*********************** NOTIFY DIALOG **************************/
74 |
75 | .finder-dialog-notify .ui-dialog-titlebar-close { display:none; }
76 | .finder-dialog-notify .ui-dialog-content { padding:0; }
77 |
78 | /* one notification container */
79 | .finder-notify {
80 | border-bottom:1px solid #ccc;
81 | position:relative;
82 | padding:.5em;
83 |
84 | text-align:center;
85 | overflow:hidden;
86 | }
87 |
88 | .finder-ltr .finder-notify { padding-left:30px; }
89 | .finder-rtl .finder-notify { padding-right:30px; }
90 |
91 | .finder-notify:last-child { border:0 solid; }
92 |
93 | /* progressbar */
94 | .finder-notify-progressbar {
95 | width:180px;
96 | height:8px;
97 | border:1px solid #aaa;
98 | background:#f5f5f5;
99 | margin:5px auto;
100 | overflow:hidden;
101 | }
102 |
103 | .finder-notify-progress {
104 | width:100%;
105 | height:8px;
106 | background:url(../img/progress.gif) center center repeat-x;
107 | }
108 |
109 | .finder-notify-progressbar, .finder-notify-progress {
110 | border-radius: 2px;
111 | }
112 |
113 | /* icons */
114 | .finder-dialog-icon-open,
115 | .finder-dialog-icon-file { background-position: 0 -225px; }
116 | .finder-dialog-icon-reload { background-position: 0 -225px; }
117 | .finder-dialog-icon-mkdir { background-position: 0 -64px; }
118 | .finder-dialog-icon-mkfile { background-position: 0 -96px; }
119 | .finder-dialog-icon-copy,
120 | .finder-dialog-icon-prepare,
121 | .finder-dialog-icon-move { background-position: 0 -128px;}
122 | .finder-dialog-icon-upload { background-position: 0 -160px; }
123 | .finder-dialog-icon-rm { background-position: 0 -192px; }
124 | .finder-dialog-icon-download { background-position: 0 -260px; }
125 | .finder-dialog-icon-save { background-position: 0 -295px; }
126 | .finder-dialog-icon-rename { background-position: 0 -330px; }
127 | .finder-dialog-icon-archive,
128 | .finder-dialog-icon-extract { background-position: 0 -365px; }
129 | .finder-dialog-icon-search { background-position: 0 -402px; }
130 |
131 | /*********************** CONFIRM DIALOG **************************/
132 |
133 | .finder-dialog-confirm-applyall { padding-top:3px; }
134 |
135 | .finder-dialog-confirm .finder-dialog-icon { background-position:0 -32px; }
136 |
137 |
138 |
139 | /*********************** FILE INFO DIALOG **************************/
140 |
141 |
142 | .finder-info-title .finder-cwd-icon {
143 | float:left;
144 | width:48px;
145 | height:48px;
146 | margin-right:1em;
147 | }
148 |
149 | .finder-info-title strong { display:block; padding:.3em 0 .5em 0; }
150 |
151 | .finder-info-tb {
152 | min-width:200px;
153 | border:0 solid;
154 | margin:1em .2em 1em .2em;
155 | }
156 |
157 | .finder-info-tb td { white-space:nowrap; padding:2px; }
158 |
159 | .finder-info-tb tr td:first-child { text-align:right; }
160 |
161 | .finder-info-tb span { float:left;}
162 | .finder-info-tb a { outline: none; text-decoration:underline; }
163 | .finder-info-tb a:hover { text-decoration:none; }
164 | .finder-info-spinner {
165 | width:14px;
166 | height:14px;
167 | float:left;
168 | background: url("../img/spinner-mini.gif") center center no-repeat;
169 | margin:0 5px;
170 | }
171 |
172 | .finder-netmount-tb { margin:0 auto; }
173 | .finder-netmount-tb input { border:1px solid #ccc; }
174 | /*********************** UPLOAD DIALOG **************************/
175 |
176 | .finder-upload-dropbox {
177 | text-align:center;
178 | padding:2em 0;
179 | border:3px dashed #aaa;
180 | }
181 |
182 | .finder-upload-dropbox.ui-state-hover {
183 | background:#dfdfdf;
184 | border:3px dashed #555;
185 | }
186 |
187 | .finder-upload-dialog-or {
188 | margin:.3em 0;
189 | text-align:center;
190 | }
191 |
192 | .finder-upload-dialog-wrapper { text-align:center; }
193 |
194 | .finder-upload-dialog-wrapper .ui-button { position:relative; overflow:hidden; }
195 |
196 | .finder-upload-dialog-wrapper .ui-button form {
197 | position:absolute;
198 | right:0;
199 | top:0;
200 | opacity: 0; filter:Alpha(Opacity=0);
201 | }
202 |
203 | .finder-upload-dialog-wrapper .ui-button form input {
204 | padding:0 20px;
205 | font-size:3em;
206 |
207 | }
208 |
209 |
210 | /* dialog for Finder itself */
211 | .dialogfinder .dialogfinder-drag {
212 | border-left:0 solid;
213 | border-top:0 solid;
214 | border-right:0 solid;
215 | font-weight:normal;
216 | padding:2px 12px;
217 | cursor:move;
218 | position:relative;
219 | text-align:left;
220 | }
221 |
222 | .finder-rtl .dialogfinder-drag { text-align:right;}
223 |
224 | .dialogfinder-drag-close {
225 | position: absolute;
226 | top:50%;
227 | margin-top:-8px;
228 | }
229 |
230 | .finder-ltr .dialogfinder-drag-close { right:12px; }
231 | .finder-rtl .dialogfinder-drag-close { left:12px; }
232 |
233 |
234 |
--------------------------------------------------------------------------------
/js/Finder.mime.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * File mimetype to kind mapping
4 | *
5 | * @type Object
6 | */
7 | Finder.prototype.kinds = {
8 |
9 | 'unknown' : 'Unknown',
10 | 'directory' : 'Folder',
11 | 'symlink' : 'Alias',
12 | 'symlink-broken' : 'AliasBroken',
13 | 'application/x-empty' : 'TextPlain',
14 | 'application/postscript' : 'Postscript',
15 | 'application/vnd.ms-office' : 'MsOffice',
16 | 'application/vnd.ms-word' : 'MsWord',
17 | 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' : 'MsWord',
18 | 'application/vnd.ms-word.document.macroEnabled.12' : 'MsWord',
19 | 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' : 'MsWord',
20 | 'application/vnd.ms-word.template.macroEnabled.12' : 'MsWord',
21 | 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' : 'MsWord',
22 | 'application/vnd.ms-excel' : 'MsExcel',
23 | 'application/vnd.ms-excel.sheet.macroEnabled.12' : 'MsExcel',
24 | 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' : 'MsExcel',
25 | 'application/vnd.ms-excel.template.macroEnabled.12' : 'MsExcel',
26 | 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' : 'MsExcel',
27 | 'application/vnd.ms-excel.addin.macroEnabled.12' : 'MsExcel',
28 | 'application/vnd.ms-powerpoint' : 'MsPP',
29 | 'application/vnd.openxmlformats-officedocument.presentationml.presentation' : 'MsPP',
30 | 'application/vnd.ms-powerpoint.presentation.macroEnabled.12' : 'MsPP',
31 | 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' : 'MsPP',
32 | 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' : 'MsPP',
33 | 'application/vnd.openxmlformats-officedocument.presentationml.template' : 'MsPP',
34 | 'application/vnd.ms-powerpoint.template.macroEnabled.12' : 'MsPP',
35 | 'application/vnd.ms-powerpoint.addin.macroEnabled.12' : 'MsPP',
36 | 'application/vnd.openxmlformats-officedocument.presentationml.slide' : 'MsPP',
37 | 'application/vnd.ms-powerpoint.slide.macroEnabled.12' : 'MsPP',
38 | 'application/pdf' : 'PDF',
39 | 'application/xml' : 'XML',
40 | 'application/vnd.oasis.opendocument.text' : 'OO',
41 | 'application/vnd.oasis.opendocument.text-template' : 'OO',
42 | 'application/vnd.oasis.opendocument.text-web' : 'OO',
43 | 'application/vnd.oasis.opendocument.text-master' : 'OO',
44 | 'application/vnd.oasis.opendocument.graphics' : 'OO',
45 | 'application/vnd.oasis.opendocument.graphics-template' : 'OO',
46 | 'application/vnd.oasis.opendocument.presentation' : 'OO',
47 | 'application/vnd.oasis.opendocument.presentation-template' : 'OO',
48 | 'application/vnd.oasis.opendocument.spreadsheet' : 'OO',
49 | 'application/vnd.oasis.opendocument.spreadsheet-template' : 'OO',
50 | 'application/vnd.oasis.opendocument.chart' : 'OO',
51 | 'application/vnd.oasis.opendocument.formula' : 'OO',
52 | 'application/vnd.oasis.opendocument.database' : 'OO',
53 | 'application/vnd.oasis.opendocument.image' : 'OO',
54 | 'application/vnd.openofficeorg.extension' : 'OO',
55 | 'application/x-shockwave-flash' : 'AppFlash',
56 | 'application/flash-video' : 'Flash video',
57 | 'application/x-bittorrent' : 'Torrent',
58 | 'application/javascript' : 'JS',
59 | 'application/rtf' : 'RTF',
60 | 'application/rtfd' : 'RTF',
61 | 'application/x-font-ttf' : 'TTF',
62 | 'application/x-font-otf' : 'OTF',
63 | 'application/x-rpm' : 'RPM',
64 | 'application/x-web-config' : 'TextPlain',
65 | 'application/xhtml+xml' : 'HTML',
66 | 'application/docbook+xml' : 'DOCBOOK',
67 | 'application/x-awk' : 'AWK',
68 | 'application/x-gzip' : 'GZIP',
69 | 'application/x-bzip2' : 'BZIP',
70 | 'application/zip' : 'ZIP',
71 | 'application/x-zip' : 'ZIP',
72 | 'application/x-rar' : 'RAR',
73 | 'application/x-tar' : 'TAR',
74 | 'application/x-7z-compressed' : '7z',
75 | 'application/x-jar' : 'JAR',
76 | 'text/plain' : 'TextPlain',
77 | 'text/x-php' : 'PHP',
78 | 'text/html' : 'HTML',
79 | 'text/javascript' : 'JS',
80 | 'text/css' : 'CSS',
81 | 'text/rtf' : 'RTF',
82 | 'text/rtfd' : 'RTF',
83 | 'text/x-c' : 'C',
84 | 'text/x-csrc' : 'C',
85 | 'text/x-chdr' : 'CHeader',
86 | 'text/x-c++' : 'CPP',
87 | 'text/x-c++src' : 'CPP',
88 | 'text/x-c++hdr' : 'CPPHeader',
89 | 'text/x-shellscript' : 'Shell',
90 | 'application/x-csh' : 'Shell',
91 | 'text/x-python' : 'Python',
92 | 'text/x-java' : 'Java',
93 | 'text/x-java-source' : 'Java',
94 | 'text/x-ruby' : 'Ruby',
95 | 'text/x-perl' : 'Perl',
96 | 'text/x-sql' : 'SQL',
97 | 'text/xml' : 'XML',
98 | 'text/x-comma-separated-values' : 'CSV',
99 | 'image/x-ms-bmp' : 'BMP',
100 | 'image/jpeg' : 'JPEG',
101 | 'image/gif' : 'GIF',
102 | 'image/png' : 'PNG',
103 | 'image/tiff' : 'TIFF',
104 | 'image/x-targa' : 'TGA',
105 | 'image/vnd.adobe.photoshop' : 'PSD',
106 | 'image/xbm' : 'XBITMAP',
107 | 'image/pxm' : 'PXM',
108 | 'audio/mpeg' : 'AudioMPEG',
109 | 'audio/midi' : 'AudioMIDI',
110 | 'audio/ogg' : 'AudioOGG',
111 | 'audio/mp4' : 'AudioMPEG4',
112 | 'audio/x-m4a' : 'AudioMPEG4',
113 | 'audio/wav' : 'AudioWAV',
114 | 'audio/x-mp3-playlist' : 'AudioPlaylist',
115 | 'video/x-dv' : 'VideoDV',
116 | 'video/mp4' : 'VideoMPEG4',
117 | 'video/mpeg' : 'VideoMPEG',
118 | 'video/x-msvideo' : 'VideoAVI',
119 | 'video/quicktime' : 'VideoMOV',
120 | 'video/x-ms-wmv' : 'VideoWM',
121 | 'video/x-flv' : 'VideoFlash',
122 | 'video/x-matroska' : 'VideoMKV',
123 | 'video/ogg' : 'VideoOGG'
124 | };
125 |
126 |
127 | /**
128 | * Return localized kind of file
129 | *
130 | * @param Object|String file or file mimetype
131 | * @return String
132 | */
133 | Finder.prototype.mime2kind = function(f) {
134 | var mime = typeof(f) == 'object' ? f.mime : f, kind;
135 |
136 | if (f.alias) {
137 | kind = 'Alias';
138 | } else if (this.kinds[mime]) {
139 | kind = this.kinds[mime];
140 | } else {
141 | if (mime.indexOf('text') === 0) {
142 | kind = 'Text';
143 | } else if (mime.indexOf('image') === 0) {
144 | kind = 'Image';
145 | } else if (mime.indexOf('audio') === 0) {
146 | kind = 'Audio';
147 | } else if (mime.indexOf('video') === 0) {
148 | kind = 'Video';
149 | } else if (mime.indexOf('application') === 0) {
150 | kind = 'App';
151 | } else {
152 | kind = mime;
153 | }
154 | }
155 |
156 | return this.messages['kind'+kind] ? this.i18n('kind'+kind) : mime;
157 | };
158 |
159 |
160 | /**
161 | * Convert mimetype into css classes
162 | *
163 | * @param String file mimetype
164 | * @return String
165 | */
166 | Finder.prototype.mime2class = function(mime) {
167 | var prefix = 'finder-cwd-icon-';
168 |
169 | mime = mime.split('/');
170 |
171 | return prefix+mime[0]+(mime[0] != 'image' && mime[1] ? ' '+prefix+mime[1].replace(/(\.|\+)/g, '-') : '');
172 | };
173 |
--------------------------------------------------------------------------------
/js/ui/places.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /**
3 | * @class Finder places/favorites ui
4 | *
5 | * @author Dmitry (dio) Levashov
6 | **/
7 | $.fn.finderplaces = function(fm, opts) {
8 | return this.each(function() {
9 | var dirs = [],
10 | c = 'class',
11 | navdir = fm.res(c, 'navdir'),
12 | collapsed = fm.res(c, 'navcollapse'),
13 | expanded = fm.res(c, 'navexpand'),
14 | hover = fm.res(c, 'hover'),
15 | clroot = fm.res(c, 'treeroot'),
16 | tpl = fm.res('tpl', 'navdir'),
17 | ptpl = fm.res('tpl', 'perms'),
18 | spinner = $(fm.res('tpl', 'navspinner')),
19 | /**
20 | * Convert places dir node into dir hash
21 | *
22 | * @param String directory id
23 | * @return String
24 | **/
25 | id2hash = function(id) { return id.substr(6); },
26 | /**
27 | * Convert places dir node into dir hash
28 | *
29 | * @param String directory id
30 | * @return String
31 | **/
32 | hash2id = function(hash) { return 'place-'+hash; },
33 |
34 | /**
35 | * Save current places state
36 | *
37 | * @return void
38 | **/
39 | save = function() { fm.storage('places', dirs.join(',')); },
40 | /**
41 | * Return node for given dir object
42 | *
43 | * @param Object directory object
44 | * @return jQuery
45 | **/
46 | create = function(dir) {
47 | return $(tpl.replace(/\{id\}/, hash2id(dir.hash))
48 | .replace(/\{name\}/, fm.escape(dir.name))
49 | .replace(/\{cssclass\}/, fm.perms2class(dir))
50 | .replace(/\{permissions\}/, !dir.read || !dir.write ? ptpl : '')
51 | .replace(/\{symlink\}/, ''));
52 | },
53 | /**
54 | * Add new node into places
55 | *
56 | * @param Object directory object
57 | * @return void
58 | **/
59 | add = function(dir) {
60 | var node = create(dir);
61 |
62 | if (subtree.children().length) {
63 | $.each(subtree.children(), function() {
64 | var current = $(this);
65 |
66 | if (dir.name.localeCompare(current.children('.'+navdir).text()) < 0) {
67 | return !node.insertBefore(current);
68 | }
69 | });
70 | }
71 |
72 | dirs.push(dir.hash);
73 | !node.parent().length && subtree.append(node);
74 | root.addClass(collapsed);
75 | node.draggable({
76 | appendTo : 'body',
77 | revert : false,
78 | helper : function() {
79 | var dir = $(this);
80 |
81 | dir.children().removeClass('ui-state-hover');
82 |
83 | return $('
')
84 | .append(dir.clone())
85 | .data('hash', id2hash(dir.children(':first').attr('id')));
86 |
87 | },
88 | start : function() { $(this).hide(); },
89 | stop : function(e, ui) {
90 | var top = places.offset().top,
91 | left = places.offset().left,
92 | width = places.width(),
93 | height = places.height(),
94 | x = e.clientX,
95 | y = e.clientY;
96 |
97 | if (x > left && x < left+width && y > top && y < y+height) {
98 | $(this).show();
99 | } else {
100 | remove(ui.helper.data('hash'));
101 | save();
102 | }
103 | }
104 | });
105 | },
106 | /**
107 | * Remove dir from places
108 | *
109 | * @param String directory id
110 | * @return void
111 | **/
112 | remove = function(hash) {
113 | var ndx = $.inArray(hash, dirs);
114 |
115 | if (ndx !== -1) {
116 | dirs.splice(ndx, 1);
117 | subtree.find('#'+hash2id(hash)).parent().remove();
118 | !subtree.children().length && root.removeClass(collapsed+' '+expanded);
119 | }
120 | },
121 | /**
122 | * Remove all dir from places
123 | *
124 | * @return void
125 | **/
126 | clear = function() {
127 | subtree.empty();
128 | root.removeClass(collapsed+' '+expanded);
129 | },
130 | /**
131 | * Node - wrapper for places root
132 | *
133 | * @type jQuery
134 | **/
135 | wrapper = create({
136 | hash : 'root-'+fm.namespace,
137 | name : fm.i18n(opts.name, 'places'),
138 | read : true,
139 | write : true
140 | }),
141 | /**
142 | * Places root node
143 | *
144 | * @type jQuery
145 | **/
146 | root = wrapper.children('.'+navdir)
147 | .addClass(clroot)
148 | .click(function() {
149 | if (root.is('.'+collapsed)) {
150 | places.toggleClass(expanded);
151 | subtree.slideToggle();
152 | fm.storage('placesState', places.is('.'+expanded)? 1 : 0);
153 | }
154 | }),
155 | /**
156 | * Container for dirs
157 | *
158 | * @type jQuery
159 | **/
160 | subtree = wrapper.children('.'+fm.res(c, 'navsubtree')),
161 | /**
162 | * Main places container
163 | *
164 | * @type jQuery
165 | **/
166 | places = $(this).addClass(fm.res(c, 'tree')+' finder-places ui-corner-all')
167 | .hide()
168 | .append(wrapper)
169 | .appendTo(fm.getUI('navbar'))
170 | .delegate('.'+navdir,{
171 | 'click': function() {
172 | fm.exec('open', $(this).attr('id').substr(6));
173 | },
174 | 'mouseenter': function(){
175 | $(this).addClass('ui-state-hover');
176 | },
177 | 'mouseleave': function(){
178 | $(this).removeClass('ui-state-hover');
179 | }
180 | })
181 | .delegate('.'+navdir+':not(.'+clroot+')', 'contextmenu', function(e) {
182 | var hash = $(this).attr('id').substr(6);
183 |
184 | e.preventDefault();
185 |
186 | fm.trigger('contextmenu', {
187 | raw : [{
188 | label : fm.i18n('rmFromPlaces'),
189 | icon : 'rm',
190 | callback : function() { remove(hash); save(); }
191 | }],
192 | 'x' : e.clientX,
193 | 'y' : e.clientY
194 | })
195 |
196 | })
197 | .droppable({
198 | tolerance : 'pointer',
199 | accept : '.finder-cwd-file-wrapper,.finder-tree-dir,.finder-cwd-file',
200 | hoverClass : fm.res('class', 'adroppable'),
201 | drop : function(e, ui) {
202 | var resolve = true;
203 |
204 | $.each(ui.helper.data('files'), function(i, hash) {
205 | var dir = fm.file(hash);
206 |
207 | if (dir && dir.mime == 'directory' && $.inArray(dir.hash, dirs) === -1) {
208 | add(dir);
209 | } else {
210 | resolve = false;
211 | }
212 | })
213 | save();
214 | resolve && ui.helper.hide();
215 | }
216 | });
217 |
218 |
219 | // on fm load - show places and load files from backend
220 | fm.one('load', function() {
221 |
222 | places.show().parent().show();
223 |
224 | dirs = $.map(fm.storage('places').split(','), function(hash) { return hash || null});
225 |
226 | if (dirs.length) {
227 | root.prepend(spinner);
228 |
229 | fm.request({
230 | data : {cmd : 'info', targets : dirs},
231 | preventDefault : true
232 | })
233 | .done(function(data) {
234 | dirs = [];
235 | $.each(data.files, function(i, file) {
236 | file.mime == 'directory' && add(file);
237 | });
238 | save();
239 | if (fm.storage('placesState') > 0) {
240 | root.click();
241 | }
242 | })
243 | .always(function() {
244 | spinner.remove();
245 | })
246 | }
247 |
248 |
249 | fm.remove(function(e) {
250 | $.each(e.data.removed, function(i, hash) {
251 | remove(hash);
252 | });
253 | save();
254 | })
255 | .change(function(e) {
256 | $.each(e.data.changed, function(i, file) {
257 | if ($.inArray(file.hash, dirs) !== -1) {
258 | remove(file.hash);
259 | file.mime == 'directory' && add(file);
260 | }
261 | });
262 | save();
263 | })
264 | .bind('sync', function() {
265 | if (dirs.length) {
266 | root.prepend(spinner);
267 |
268 | fm.request({
269 | data : {cmd : 'info', targets : dirs},
270 | preventDefault : true
271 | })
272 | .done(function(data) {
273 | $.each(data.files || [], function(i, file) {
274 | if ($.inArray(file.hash, dirs) === -1) {
275 | remove(file.hash);
276 | }
277 | });
278 | save();
279 | })
280 | .always(function() {
281 | spinner.remove();
282 | });
283 | }
284 | })
285 |
286 | })
287 |
288 | });
289 | }
--------------------------------------------------------------------------------
/php/connector.src.php:
--------------------------------------------------------------------------------
1 | $name ){
103 | if( stripos($name,'.php') !== false ){
104 | return false;
105 | }
106 | }
107 | return $args;
108 | }
109 |
110 |
111 | /**
112 | * Simple function to demonstrate how to control file access using "accessControl" callback.
113 | * This method will disable accessing files/folders starting from '.' (dot)
114 | *
115 | * @param string $attr attribute name (read|write|locked|hidden)
116 | * @param string $path file path relative to volume root directory started with directory separator
117 | * @return bool|null
118 | **/
119 | function access($attr, $path, $data, $volume) {
120 | return strpos(basename($path), '.') === 0 // if file/folder begins with '.' (dot)
121 | ? !($attr == 'read' || $attr == 'write') // set read+write to false, other (locked+hidden) set to true
122 | : null; // else Finder decide it itself
123 | }
124 |
125 |
126 |
127 | $opts = array(
128 | 'locale' => 'en_US.UTF-8',
129 | 'bind' => array(
130 | '*' => 'logger',
131 | //'*-before' => 'logger_before'
132 | 'upload-before' => 'upload_check'
133 | // 'mkdir mkfile rename duplicate upload rm paste' => 'logger'
134 | ),
135 | //'debug' => true,
136 | 'saveData' => 'SaveFinderData',
137 | 'returnData' => 'ReturnFinderData',
138 |
139 | 'roots' => array(
140 | array(
141 | 'driver' => 'LocalFileSystem',
142 |
143 | 'path' => dirname(dirname(__FILE__)).'/files',
144 | 'separator' => '/',
145 |
146 | //'path' => '../files/',
147 | //'startPath' => '../files/test/',
148 |
149 |
150 | 'URL' => dirname($_SERVER['PHP_SELF']) . '/../files/',
151 | // 'treeDeep' => 3,
152 | // 'alias' => 'File system',
153 | 'tmbPath' => '.tmb',
154 | 'utf8fix' => true,
155 | 'tmbCrop' => false,
156 | 'tmbBgColor' => 'transparent',
157 | 'accessControl' => 'access',
158 | 'acceptedName' => '/^[^\.].*$/',
159 | // 'tmbSize' => 128,
160 | 'attributes' => array(
161 | array(
162 | 'pattern' => '/\.js$/',
163 | 'read' => true,
164 | 'write' => false
165 | ),
166 | array(
167 | 'pattern' => '/^\/icons$/',
168 | 'read' => true,
169 | 'write' => false
170 | )
171 | )
172 | // 'uploadDeny' => array('application', 'text/xml')
173 | ),
174 | // array(
175 | // 'driver' => 'LocalFileSystem',
176 | // 'path' => '../files2/',
177 | // // 'URL' => dirname($_SERVER['PHP_SELF']) . '/../files2/',
178 | // 'alias' => 'File system',
179 | // 'tmbPath' => '.tmb',
180 | // 'utf8fix' => true,
181 | // 'tmbCrop' => false,
182 | // 'startPath' => '../files/test',
183 | // // 'separator' => ':',
184 | // 'attributes' => array(
185 | // array(
186 | // 'pattern' => '~/\.~',
187 | // // 'pattern' => '/^\/\./',
188 | // 'read' => false,
189 | // 'write' => false,
190 | // 'hidden' => true,
191 | // 'locked' => false
192 | // ),
193 | // array(
194 | // 'pattern' => '~/replace/.+png$~',
195 | // // 'pattern' => '/^\/\./',
196 | // 'read' => false,
197 | // 'write' => false,
198 | // // 'hidden' => true,
199 | // 'locked' => true
200 | // )
201 | // ),
202 | // // 'defaults' => array('read' => false, 'write' => true)
203 | // ),
204 |
205 | // array(
206 | // 'driver' => 'FTP',
207 | // 'host' => '192.168.1.38',
208 | // 'user' => 'dio',
209 | // 'pass' => 'hane',
210 | // 'path' => '/Users/dio/Documents',
211 | // 'tmpPath' => '../files/ftp',
212 | // 'utf8fix' => true,
213 | // 'attributes' => array(
214 | // array(
215 | // 'pattern' => '~/\.~',
216 | // 'read' => false,
217 | // 'write' => false,
218 | // 'hidden' => true,
219 | // 'locked' => false
220 | // ),
221 | //
222 | // )
223 | // ),
224 | // array(
225 | // 'driver' => 'FTP',
226 | // 'host' => 'work.std42.ru',
227 | // 'user' => 'dio',
228 | // 'pass' => 'wallrus',
229 | // 'path' => '/',
230 | // 'tmpPath' => '../files/ftp',
231 | // ),
232 | // array(
233 | // 'driver' => 'FTP',
234 | // 'host' => '192.168.1.35',
235 | // 'user' => 'frontrow',
236 | // 'pass' => 'frontrow',
237 | // 'path' => '/'
238 | // ),
239 |
240 | // array(
241 | // 'driver' => 'LocalFileSystem',
242 | // 'path' => '../files2/',
243 | // 'URL' => dirname($_SERVER['PHP_SELF']) . '/../files2/',
244 | // 'alias' => 'Files',
245 | // 'tmbPath' => '.tmb',
246 | // // 'copyOverwrite' => false,
247 | // 'utf8fix' => true,
248 | // 'attributes' => array(
249 | // array(
250 | // 'pattern' => '~/\.~',
251 | // // 'pattern' => '/^\/\./',
252 | // // 'read' => false,
253 | // // 'write' => false,
254 | // 'hidden' => true,
255 | // 'locked' => false
256 | // ),
257 | // )
258 | // ),
259 |
260 | // array(
261 | // 'driver' => 'MySQL',
262 | // 'path' => 1,
263 | // // 'treeDeep' => 2,
264 | // // 'socket' => '/opt/local/var/run/mysql5/mysqld.sock',
265 | // 'user' => 'root',
266 | // 'pass' => 'hane',
267 | // 'db' => 'finder',
268 | // 'user_id' => 1,
269 | // // 'accessControl' => 'access',
270 | // // 'separator' => ':',
271 | // 'tmbCrop' => true,
272 | // // thumbnails background color (hex #rrggbb or 'transparent')
273 | // 'tmbBgColor' => '#000000',
274 | // 'files_table' => 'finder_file',
275 | // // 'imgLib' => 'imagick',
276 | // // 'uploadOverwrite' => false,
277 | // // 'copyTo' => false,
278 | // // 'URL' => 'http://localhost/git/finder',
279 | // 'tmpPath' => '../filesdb/tmp',
280 | // 'tmbPath' => '../filesdb/tmb',
281 | // 'tmbURL' => dirname($_SERVER['PHP_SELF']) . '/../filesdb/tmb/',
282 | // // 'attributes' => array(
283 | // // array(),
284 | // // array(
285 | // // 'pattern' => '/\.jpg$/',
286 | // // 'read' => false,
287 | // // 'write' => false,
288 | // // 'locked' => true,
289 | // // 'hidden' => true
290 | // // )
291 | // // )
292 | //
293 | // )
294 | )
295 |
296 | );
297 |
298 |
299 | /**
300 | * Functions for saving and returning data used by the finder
301 | *
302 | */
303 | session_start();
304 | //$_SESSION = array();
305 | function SaveFinderData($data){
306 | $_SESSION['finder_data'] = $data;
307 | }
308 | function ReturnFinderData(){
309 | if( isset($_SESSION['finder_data']) ){
310 | return $_SESSION['finder_data'];
311 | }
312 | return false;
313 | }
314 |
315 |
316 |
317 | header('Access-Control-Allow-Origin: *');
318 | $finder = new Finder($opts);
319 | $finder->run();
320 |
321 |
--------------------------------------------------------------------------------
/js/commands/quicklook.plugins.js:
--------------------------------------------------------------------------------
1 |
2 | Finder.prototype.commands.quicklook.plugins = [
3 |
4 | /**
5 | * Images preview plugin
6 | *
7 | * @param Finder.commands.quicklook
8 | **/
9 | function(ql) {
10 | var mimes = ['image/jpeg', 'image/png', 'image/gif'],
11 | preview = ql.preview;
12 |
13 | // what kind of images we can display
14 | $.each(navigator.mimeTypes, function(i, o) {
15 | var mime = o.type;
16 |
17 | if (mime.indexOf('image/') === 0 && $.inArray(mime, mimes)) {
18 | mimes.push(mime);
19 | }
20 | });
21 |
22 | preview.bind('update', function(e) {
23 | var file = e.file,
24 | img;
25 |
26 | if ($.inArray(file.mime, mimes) !== -1) {
27 | // this is our file - stop event propagation
28 | e.stopImmediatePropagation();
29 |
30 | img = $(' ')
31 | .hide()
32 | .appendTo(preview)
33 | .load(function() {
34 | // timeout - because of strange safari bug -
35 | // sometimes cant get image height 0_o
36 | setTimeout(function() {
37 | var prop = (img.width()/img.height()).toFixed(2);
38 | preview.bind('changesize', function() {
39 | var pw = parseInt(preview.width()),
40 | ph = parseInt(preview.height()),
41 | w, h;
42 |
43 | if (prop < (pw/ph).toFixed(2)) {
44 | h = ph;
45 | w = Math.floor(h * prop);
46 | } else {
47 | w = pw;
48 | h = Math.floor(w/prop);
49 | }
50 | img.width(w).height(h).css('margin-top', h < ph ? Math.floor((ph - h)/2) : 0);
51 |
52 | })
53 | .trigger('changesize');
54 |
55 | // hide info/icon
56 | ql.hideinfo();
57 | //show image
58 | img.fadeIn(100);
59 | }, 1)
60 | })
61 | .attr('src', ql.fm.url(file.hash));
62 | }
63 |
64 | });
65 | },
66 |
67 | /**
68 | * HTML preview plugin
69 | *
70 | * @param Finder.commands.quicklook
71 | **/
72 | function(ql) {
73 | var mimes = ['text/html', 'application/xhtml+xml'],
74 | preview = ql.preview,
75 | fm = ql.fm;
76 |
77 | preview.bind('update', function(e) {
78 | var file = e.file, jqxhr;
79 |
80 | if ($.inArray(file.mime, mimes) !== -1) {
81 | e.stopImmediatePropagation();
82 |
83 | // stop loading on change file if not loaded yet
84 | preview.one('change', function() {
85 | if( (jqxhr.state() != 'resolved') && (jqxhr.state() != 'rejected') ){
86 | jqxhr.reject();
87 | }
88 | });
89 |
90 | jqxhr = fm.request({
91 | data : {cmd : 'get', target : file.hash, current : file.phash},
92 | preventDefault : true
93 | })
94 | .done(function(data) {
95 | ql.hideinfo();
96 | doc = $('').appendTo(preview)[0].contentWindow.document;
97 | doc.open();
98 | doc.write(data.content);
99 | doc.close();
100 | });
101 | }
102 | })
103 | },
104 |
105 | /**
106 | * Texts preview plugin
107 | *
108 | * @param Finder.commands.quicklook
109 | **/
110 | function(ql) {
111 | var fm = ql.fm,
112 | mimes = fm.res('mimes', 'text'),
113 | preview = ql.preview;
114 |
115 |
116 | preview.bind('update', function(e) {
117 | var file = e.file,
118 | mime = file.mime,
119 | jqxhr;
120 |
121 | if (mime.indexOf('text/') === 0 || $.inArray(mime, mimes) !== -1) {
122 | e.stopImmediatePropagation();
123 |
124 | // stop loading on change file if not loadin yet
125 | preview.one('change', function() {
126 | if( (jqxhr.state() != 'resolved') && (jqxhr.state() != 'rejected') ){
127 | jqxhr.reject();
128 | }
129 | });
130 |
131 | jqxhr = fm.request({
132 | data : {cmd : 'get', target : file.hash },
133 | preventDefault : true
134 | })
135 | .done(function(data) {
136 | ql.hideinfo();
137 | $(''+fm.escape(data.content)+' ').appendTo(preview);
138 | });
139 | }
140 | });
141 | },
142 |
143 | /**
144 | * PDF preview plugin
145 | *
146 | * @param Finder.commands.quicklook
147 | **/
148 | function(ql) {
149 | var fm = ql.fm,
150 | mime = 'application/pdf',
151 | preview = ql.preview,
152 | active = false;
153 |
154 | if ((fm.UA.Safari && fm.OS == 'mac') || fm.UA.IE) {
155 | active = true;
156 | } else {
157 | $.each(navigator.plugins, function(i, plugins) {
158 | $.each(plugins, function(i, plugin) {
159 | if (plugin.type == mime) {
160 | return !(active = true);
161 | }
162 | });
163 | });
164 | }
165 |
166 | active && preview.bind('update', function(e) {
167 | var file = e.file, node;
168 |
169 | if (file.mime == mime) {
170 | e.stopImmediatePropagation();
171 | preview.one('change', function() {
172 | node.unbind('load').remove();
173 | });
174 |
175 | node = $('')
176 | .hide()
177 | .appendTo(preview)
178 | .load(function() {
179 | ql.hideinfo();
180 | node.show();
181 | })
182 | .attr('src', fm.url(file.hash));
183 | }
184 |
185 | })
186 |
187 |
188 | },
189 |
190 | /**
191 | * Flash preview plugin
192 | *
193 | * @param Finder.commands.quicklook
194 | **/
195 | function(ql) {
196 | var fm = ql.fm,
197 | mime = 'application/x-shockwave-flash',
198 | preview = ql.preview,
199 | active = false;
200 |
201 | $.each(navigator.plugins, function(i, plugins) {
202 | $.each(plugins, function(i, plugin) {
203 | if (plugin.type == mime) {
204 | return !(active = true);
205 | }
206 | });
207 | });
208 |
209 | active && preview.bind('update', function(e) {
210 | var file = e.file,
211 | node;
212 |
213 | if (file.mime == mime) {
214 | e.stopImmediatePropagation();
215 | ql.hideinfo();
216 | preview.append((node = $(' ')));
217 | }
218 | });
219 | },
220 |
221 | /**
222 | * HTML5 audio preview plugin
223 | *
224 | * @param Finder.commands.quicklook
225 | **/
226 | function(ql) {
227 | var preview = ql.preview,
228 | autoplay = !!ql.options['autoplay'],
229 | mimes = {
230 | 'audio/mpeg' : 'mp3',
231 | 'audio/mpeg3' : 'mp3',
232 | 'audio/mp3' : 'mp3',
233 | 'audio/x-mpeg3' : 'mp3',
234 | 'audio/x-mp3' : 'mp3',
235 | 'audio/x-wav' : 'wav',
236 | 'audio/wav' : 'wav',
237 | 'audio/x-m4a' : 'm4a',
238 | 'audio/aac' : 'm4a',
239 | 'audio/mp4' : 'm4a',
240 | 'audio/x-mp4' : 'm4a',
241 | 'audio/ogg' : 'ogg'
242 | },
243 | node;
244 |
245 | preview.bind('update', function(e) {
246 | var file = e.file,
247 | type = mimes[file.mime];
248 |
249 | if (ql.support.audio[type]) {
250 | e.stopImmediatePropagation();
251 |
252 | node = $(' ')
253 | .appendTo(preview);
254 | autoplay && node[0].play();
255 | }
256 | }).bind('change', function() {
257 | if (node && node.parent().length) {
258 | node[0].pause();
259 | node.remove();
260 | node= null;
261 | }
262 | });
263 | },
264 |
265 | /**
266 | * HTML5 video preview plugin
267 | *
268 | * @param Finder.commands.quicklook
269 | **/
270 | function(ql) {
271 | var preview = ql.preview,
272 | autoplay = !!ql.options['autoplay'],
273 | mimes = {
274 | 'video/mp4' : 'mp4',
275 | 'video/x-m4v' : 'mp4',
276 | 'video/ogg' : 'ogg',
277 | 'application/ogg' : 'ogg',
278 | 'video/webm' : 'webm'
279 | },
280 | node;
281 |
282 | preview.bind('update', function(e) {
283 | var file = e.file,
284 | type = mimes[file.mime];
285 |
286 | if (ql.support.video[type]) {
287 | e.stopImmediatePropagation();
288 |
289 | ql.hideinfo();
290 | node = $(' ').appendTo(preview);
291 | autoplay && node[0].play();
292 |
293 | }
294 | }).bind('change', function() {
295 | if (node && node.parent().length) {
296 | node[0].pause();
297 | node.remove();
298 | node= null;
299 | }
300 | });
301 | },
302 |
303 | /**
304 | * Audio/video preview plugin using browser plugins
305 | *
306 | * @param Finder.commands.quicklook
307 | **/
308 | function(ql) {
309 | var preview = ql.preview,
310 | mimes = [],
311 | node;
312 |
313 | $.each(navigator.plugins, function(i, plugins) {
314 | $.each(plugins, function(i, plugin) {
315 | (plugin.type.indexOf('audio/') === 0 || plugin.type.indexOf('video/') === 0) && mimes.push(plugin.type);
316 | });
317 | });
318 |
319 | preview.bind('update', function(e) {
320 | var file = e.file,
321 | mime = file.mime,
322 | video;
323 |
324 | if ($.inArray(file.mime, mimes) !== -1) {
325 | e.stopImmediatePropagation();
326 | (video = mime.indexOf('video/') === 0) && ql.hideinfo();
327 | node = $(' ')
328 | .appendTo(preview);
329 | }
330 | }).bind('change', function() {
331 | if (node && node.parent().length) {
332 | node.remove();
333 | node= null;
334 | }
335 | });
336 |
337 | }
338 |
339 | ]
--------------------------------------------------------------------------------
/css/cwd.css:
--------------------------------------------------------------------------------
1 | /******************************************************************/
2 | /* CURRENT DIRECTORY STYLES */
3 | /******************************************************************/
4 | /* cwd container to avoid selectable on scrollbar */
5 | .finder-cwd-wrapper {
6 | overflow: auto;
7 | position:relative;
8 | padding:2px;
9 | margin:0;
10 | }
11 |
12 | .finder-cwd-wrapper-list { padding:0; }
13 |
14 | /* container */
15 | .finder-cwd {
16 | position:relative;
17 | cursor:default;
18 | padding:0;
19 | margin:0;
20 | -moz-user-select: -moz-none;
21 | -khtml-user-select: none;
22 | -webkit-user-select: none;
23 | user-select: none;
24 | }
25 |
26 | /* container active on dropenter */
27 | .finder .finder-cwd-wrapper.finder-droppable-active {
28 | padding:0;
29 | border:2px solid #8cafed;
30 | }
31 |
32 |
33 | /************************** ICONS VIEW ********************************/
34 |
35 | /* file container */
36 | .finder-cwd-view-icons .finder-cwd-file {
37 | width:120px;
38 | height:80px;
39 | padding-bottom:2px;
40 | cursor:default;
41 | border:none;
42 | /* overflow:hidden; */
43 | /* position:relative;*/
44 | }
45 |
46 | /* ltr/rtl enviroment */
47 | .finder-ltr .finder-cwd-view-icons .finder-cwd-file { float:left; margin:0 3px 12px 0; }
48 | .finder-rtl .finder-cwd-view-icons .finder-cwd-file { float:right; margin:0 0 5px 3px; }
49 |
50 | /* remove ui hover class border */
51 | .finder-cwd-view-icons .finder-cwd-file .ui-state-hover { border:0 solid; }
52 |
53 | /* icon wrapper to create selected highlight around icon */
54 | .finder-cwd-view-icons .finder-cwd-file-wrapper {
55 | width:52px;
56 | height:52px;
57 | margin:1px auto 1px auto;
58 | padding:2px;
59 | position:relative;
60 | }
61 |
62 | /* file name place */
63 | .finder-cwd-view-icons .finder-cwd-filename {
64 | text-align:center;
65 | white-space:pre;
66 | overflow:hidden;
67 | text-overflow:ellipsis;
68 | -o-text-overflow:ellipsis;
69 | margin:3px 1px 0 1px;
70 | padding:1px;
71 | border-radius: 8px;
72 | }
73 |
74 | /* permissions/symlink markers */
75 | .finder-cwd-view-icons .finder-perms { bottom:4px; right:2px; }
76 | .finder-cwd-view-icons .finder-symlink { bottom:6px; left:0px; }
77 |
78 | /* icon/thumbnail */
79 | .finder-cwd-icon {
80 | display:block;
81 | width:48px;
82 | height:48px;
83 | margin:0 auto;
84 | background: url('../img/icons-big.png') 0 0 no-repeat;
85 | -moz-background-clip: padding;
86 | -webkit-background-clip: padding-box;
87 | background-clip: padding-box;
88 | }
89 |
90 | /* "opened folder" icon on dragover */
91 | .finder-cwd .finder-droppable-active .finder-cwd-icon { background-position: 0 -100px; }
92 |
93 | /* mimetypes icons */
94 | .finder-cwd-icon-directory { background-position:0 -50px; }
95 | .finder-cwd-icon-application { background-position:0 -150px; }
96 | .finder-cwd-icon-x-empty,
97 | .finder-cwd-icon-text { background-position:0 -200px; }
98 | .finder-cwd-icon-image,
99 | .finder-cwd-icon-vnd-adobe-photoshop,
100 | .finder-cwd-icon-postscript { background-position:0 -250px; }
101 | .finder-cwd-icon-audio { background-position:0 -300px; }
102 | .finder-cwd-icon-video,
103 | .finder-cwd-icon-flash-video { background-position:0 -350px; }
104 | .finder-cwd-icon-rtf,
105 | .finder-cwd-icon-rtfd { background-position: 0 -401px; }
106 | .finder-cwd-icon-pdf { background-position: 0 -450px; }
107 | .finder-cwd-icon-ms-excel,
108 | .finder-cwd-icon-msword,
109 | .finder-cwd-icon-vnd-ms-excel,
110 | .finder-cwd-icon-vnd-ms-excel-addin-macroEnabled-12,
111 | .finder-cwd-icon-vnd-ms-excel-sheet-binary-macroEnabled-12,
112 | .finder-cwd-icon-vnd-ms-excel-sheet-macroEnabled-12,
113 | .finder-cwd-icon-vnd-ms-excel-template-macroEnabled-12,
114 | .finder-cwd-icon-vnd-ms-office,
115 | .finder-cwd-icon-vnd-ms-powerpoint,
116 | .finder-cwd-icon-vnd-ms-powerpoint-addin-macroEnabled-12,
117 | .finder-cwd-icon-vnd-ms-powerpoint-presentation-macroEnabled-12,
118 | .finder-cwd-icon-vnd-ms-powerpoint-slide-macroEnabled-12,
119 | .finder-cwd-icon-vnd-ms-powerpoint-slideshow-macroEnabled-12,
120 | .finder-cwd-icon-vnd-ms-powerpoint-template-macroEnabled-12,
121 | .finder-cwd-icon-vnd-ms-word,
122 | .finder-cwd-icon-vnd-ms-word-document-macroEnabled-12,
123 | .finder-cwd-icon-vnd-ms-word-template-macroEnabled-12,
124 | .finder-cwd-icon-vnd-oasis-opendocument-chart,
125 | .finder-cwd-icon-vnd-oasis-opendocument-database,
126 | .finder-cwd-icon-vnd-oasis-opendocument-formula,
127 | .finder-cwd-icon-vnd-oasis-opendocument-graphics,
128 | .finder-cwd-icon-vnd-oasis-opendocument-graphics-template,
129 | .finder-cwd-icon-vnd-oasis-opendocument-image,
130 | .finder-cwd-icon-vnd-oasis-opendocument-presentation,
131 | .finder-cwd-icon-vnd-oasis-opendocument-presentation-template,
132 | .finder-cwd-icon-vnd-oasis-opendocument-spreadsheet,
133 | .finder-cwd-icon-vnd-oasis-opendocument-spreadsheet-template,
134 | .finder-cwd-icon-vnd-oasis-opendocument-text,
135 | .finder-cwd-icon-vnd-oasis-opendocument-text-master,
136 | .finder-cwd-icon-vnd-oasis-opendocument-text-template,
137 | .finder-cwd-icon-vnd-oasis-opendocument-text-web,
138 | .finder-cwd-icon-vnd-openofficeorg-extension,
139 | .finder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-presentation,
140 | .finder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-slide,
141 | .finder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-slideshow,
142 | .finder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-template,
143 | .finder-cwd-icon-vnd-openxmlformats-officedocument-spreadsheetml-sheet,
144 | .finder-cwd-icon-vnd-openxmlformats-officedocument-spreadsheetml-template,
145 | .finder-cwd-icon-vnd-openxmlformats-officedocument-wordprocessingml-document,
146 | .finder-cwd-icon-vnd-openxmlformats-officedocument-wordprocessingml-template { background-position: 0 -500px; }
147 | .finder-cwd-icon-html { background-position: 0 -550px; }
148 | .finder-cwd-icon-css { background-position: 0 -600px; }
149 | .finder-cwd-icon-javascript,
150 | .finder-cwd-icon-x-javascript { background-position: 0 -650px; }
151 | .finder-cwd-icon-x-perl { background-position: 0 -700px; }
152 | .finder-cwd-icon-x-python { background-position: 0 -750px; }
153 | .finder-cwd-icon-x-ruby { background-position: 0 -800px; }
154 | .finder-cwd-icon-x-sh,
155 | .finder-cwd-icon-x-shellscript { background-position: 0 -850px; }
156 | .finder-cwd-icon-x-c,
157 | .finder-cwd-icon-x-csrc,
158 | .finder-cwd-icon-x-chdr,
159 | .finder-cwd-icon-x-c--,
160 | .finder-cwd-icon-x-c--src,
161 | .finder-cwd-icon-x-c--hdr,
162 | .finder-cwd-icon-x-java,
163 | .finder-cwd-icon-x-java-source { background-position: 0 -900px; }
164 | .finder-cwd-icon-x-php { background-position: 0 -950px; }
165 | .finder-cwd-icon-xml { background-position: 0 -1000px; }
166 | .finder-cwd-icon-zip,
167 | .finder-cwd-icon-x-zip,
168 | .finder-cwd-icon-x-7z-compressed { background-position: 0 -1050px; }
169 | .finder-cwd-icon-x-gzip,
170 | .finder-cwd-icon-x-tar { background-position: 0 -1100px; }
171 | .finder-cwd-icon-x-bzip,
172 | .finder-cwd-icon-x-bzip2 { background-position: 0 -1150px; }
173 | .finder-cwd-icon-x-rar,
174 | .finder-cwd-icon-x-rar-compressed { background-position: 0 -1200px; }
175 | .finder-cwd-icon-x-shockwave-flash { background-position: 0 -1250px; }
176 | .finder-cwd-icon-group { background-position:0 -1300px;}
177 |
178 | /* textfield inside icon */
179 | .finder-cwd input { width:100% !important; border:0px solid; margin:0; padding:0; }
180 | .finder-cwd-view-icons input {text-align:center; }
181 |
182 | .finder-cwd-view-icons { text-align:center; }
183 |
184 |
185 | /************************************ LIST VIEW ************************************/
186 |
187 | /*.finder-cwd-view-list { padding:0 0 4px 0; }*/
188 |
189 | .finder-cwd table { width:100%; border-collapse:collapse; border:0 solid; margin:0 0 10px 0; }
190 | .finder .finder-cwd table thead tr { border-left:0 solid; border-top:0 solid; border-right:0 solid; }
191 |
192 | .finder .finder-cwd table td {
193 | padding:3px 12px;
194 | white-space:pre;
195 | overflow:hidden;
196 | text-align:right;
197 | cursor:default;
198 | border:0 solid;
199 |
200 | }
201 |
202 | .finder-ltr .finder-cwd table td { text-align:right; }
203 | .finder-ltr .finder-cwd table td:first-child { text-align:left; }
204 | .finder-rtl .finder-cwd table td { text-align:left; }
205 | .finder-rtl .finder-cwd table td:first-child { text-align:right; }
206 |
207 | .finder-odd-row { background:#eee; }
208 |
209 | /* filename container */
210 | .finder-cwd-view-list .finder-cwd-file-wrapper { width:97%; position:relative; }
211 | /* filename container in ltr/rtl enviroment */
212 | .finder-ltr .finder-cwd-view-list .finder-cwd-file-wrapper { padding-left:23px; }
213 | .finder-rtl .finder-cwd-view-list .finder-cwd-file-wrapper { padding-right:23px; }
214 |
215 | /* premissions/symlink marker */
216 | .finder-cwd-view-list .finder-perms,
217 | .finder-cwd-view-list .finder-symlink { top:50%; margin-top:-6px; }
218 | /* markers in ltr/rtl enviroment */
219 | .finder-ltr .finder-cwd-view-list .finder-perms { left:7px; }
220 | .finder-ltr .finder-cwd-view-list .finder-symlink { left:-7px; }
221 |
222 | /* file icon */
223 | .finder-cwd-view-list td .finder-cwd-icon {
224 | width:16px;
225 | height:16px;
226 | position:absolute;
227 | top:50%;
228 | margin-top:-8px;
229 | background-image:url(../img/icons-small.png);
230 | }
231 | /* icon in ltr/rtl enviroment */
232 | .finder-ltr .finder-cwd-view-list .finder-cwd-icon { left:0; }
233 | .finder-rtl .finder-cwd-view-list .finder-cwd-icon { right:0; }
234 |
235 |
236 |
--------------------------------------------------------------------------------