view e2gallerypro/e2upload/Source/FileManager.js @ 20:1038db2374ec judyates

change address
author Robert McIntyre <rlm@mit.edu>
date Sun, 08 Sep 2013 00:47:09 -0400
parents 3f6b44aa6b35
children
line wrap: on
line source
1 /*
2 Script: FileManager.js
3 MooTools FileManager
5 License:
6 MIT-style license.
8 Version:
9 1.0rc1
11 Copyright:
12 Copyright (c) 2009 [Christoph Pojer](http://og5.net/christoph).
14 Dependencies:
15 - MooTools Core 1.2.2
16 - MooTools More 1.2.2.1 or newer: Drag.js, Drag.Move.js, Tips.js, Asset.js
17 - Additions.js
19 Todo:
20 - Add Scroller.js (optional) for Drag&Drop in the Filelist
22 Inspiration:
23 - Loosely based on a Script by [Yannick Croissant](http://dev.k1der.net/dev/brooser-un-browser-de-fichier-pour-mootools/)
25 Options:
26 - url: (string) The base url to the Backend FileManager, without QueryString
27 - assetBasePath: (string) The path to all images and swf files
28 - selectable: (boolean, defaults to *false*) If true, provides a button to select a file
29 - language: (string, defaults to *en*) The language used for the FileManager
30 - hideOnClick: (boolean, defaults to *false*) When true, hides the FileManager when the area outside of it is clicked
31 - directory: (string) Can be used to load a subfolder instead of the base folder
33 Events:
34 - onComplete(path, file): fired when a file gets selected via the "Select file" button
35 - onModify(file): fired when a file gets renamed/deleted or modified in another way
36 - onShow: fired when the FileManager opens
37 - onHide: event fired when FileManager closes
38 */
40 var FileManager = new Class({
42 Implements: [Options, Events],
44 Request: null,
45 Directory: null,
46 Current: null,
48 options: {
49 /*onComplete: $empty,
50 onModify: $empty,
51 onShow: $empty,
52 onHide: $empty,*/
53 directory: '',
54 url: null,
55 assetBasePath: null,
56 selectable: false,
57 hideOnClick: false,
58 language: 'en'
59 },
61 hooks: {
62 show: {},
63 cleanup: {}
64 },
66 initialize: function(options){
67 this.setOptions(options);
68 this.options.assetBasePath = this.options.assetBasePath.replace(/(\/|\\)*$/, '/');
69 this.droppables = [];
70 this.Directory = this.options.directory;
72 this.language = FileManager.Language[this.options.language] || FileManager.Language.en;
73 this.container = new Element('div', {'class': 'filemanager-container filemanager-engine-'+Browser.Engine.name+(Browser.Engine.trident ? Browser.Engine.version : '')});
74 this.el = new Element('div', {'class': 'filemanager'}).inject(this.container);
75 this.menu = new Element('div', {'class': 'filemanager-menu'}).inject(this.el);
76 this.loader = new Element('div', {'class': 'loader', opacity: 0, tween: {duration: 200}}).inject(this.menu);
77 this.browser = new Element('ul', {'class': 'filemanager-browser'}).addEvents({
78 click: (function(e){
79 if(e.target.match('ul')) return this.deselect();
81 if(!e.target || !e.target.getParent('li')) return;
82 var el = e.target.getParent('li').getElement('span');
83 if(!el) return;
85 e.stop();
86 var file = el.retrieve('file');
87 if(el.retrieve('block')){
88 el.eliminate('block');
89 return;
90 }else if(file.mime=='text/directory'){
91 el.addClass('selected');
92 this.load(this.Directory+'/'+file.name);
93 return;
94 }
96 this.fillInfo(file);
97 if(this.Current) this.Current.removeClass('selected');
98 this.Current = el.addClass('selected');
100 this.switchButton();
101 }).bind(this)
102 }).inject(this.el);
105 if(this.options.selectable) this.addMenuButton('open');
106 this.addMenuButton('create');
108 this.info = new Element('div', {'class': 'filemanager-infos', opacity: 0}).inject(this.el);
110 var head = new Element('div', {'class': 'filemanager-head'}).adopt([
111 new Element('img', {'class': 'filemanager-icon'}),
112 new Element('h1')
113 ]);
115 this.info.adopt([head, new Element('h2', {text: this.language.information})]);
117 var list = new Element('dl').adopt([
118 new Element('dt', {text: this.language.modified}),
119 new Element('dd', {'class': 'filemanager-modified'}),
120 new Element('dt', {text: this.language.type}),
121 new Element('dd', {'class': 'filemanager-type'}),
122 new Element('dt', {text: this.language.size}),
123 new Element('dd', {'class': 'filemanager-size'}),
124 new Element('dt', {text: this.language.dir}),
125 new Element('dd', {'class': 'filemanager-dir'})
126 ]).inject(this.info);
128 this.preview = new Element('div', {'class': 'filemanager-preview'});
129 this.info.adopt([
130 new Element('h2', {'class': 'filemanager-headline', text: this.language.preview}),
131 this.preview
132 ]);
134 this.closeIcon = new Element('div', {
135 'class': 'filemanager-close',
136 title: this.language.close,
137 events: {click: this.hide.bind(this)}
138 }).adopt(new Asset.image(this.options.assetBasePath+'destroy.png')).inject(this.el);
139 new FileManager.Tips(this.closeIcon.appearOn(this.closeIcon, [1, 0.8]).appearOn(this.el, 0.8));
141 this.imageadd = new Asset.image(this.options.assetBasePath+'add.png', {
142 'class': 'browser-add'
143 }).set('opacity', 0).inject(this.container);
145 this.container.inject(document.body);
146 this.overlay = new Overlay(this.options.hideOnClick ? {
147 events: {click: this.hide.bind(this)}
148 } : null);
149 this.bound = {
150 keydown: (function(e){
151 if(e.control) this.imageadd.fade(1);
152 }).bind(this),
153 keyup: (function(){
154 this.imageadd.fade(0);
155 }).bind(this),
156 keyesc: (function(e){
157 if(e.key=='esc') this.hide();
158 }).bind(this),
159 scroll: (function(){
160 this.el.center(this.offsets);
161 this.fireEvent('scroll');
162 }).bind(this)
163 };
164 },
166 show: function(e){
167 if(e) e.stop();
169 this.load(this.Directory);
170 this.overlay.show();
172 this.info.set('opacity', 0);
174 (function(){
175 this.container.setStyles({
176 opacity: 0,
177 display: 'block'
178 });
180 this.el.center(this.offsets);
181 this.fireEvent('show');
182 this.container.set('opacity', 1);
183 this.fireHooks('show');
185 window.addEvents({
186 scroll: this.bound.scroll,
187 resize: this.bound.scroll,
188 keyup: this.bound.keyesc
189 });
190 }).delay(500, this);
191 },
193 hide: function(e){
194 if(e) e.stop();
196 this.overlay.hide();
197 this.browser.empty();
198 this.container.setStyle('display', 'none');
200 this.fireHooks('cleanup').fireEvent('hide');
201 window.removeEvent('scroll', this.bound.scroll).removeEvent('resize', this.bound.scroll).removeEvent('keyup', this.bound.keyesc);
202 },
204 open: function(e){
205 e.stop();
207 if(!this.Current) return false;
209 this.fireEvent('complete', [
210 this.normalize(this.Directory+'/'+this.Current.retrieve('file').name),
211 this.Current.retrieve('file')
212 ]);
213 this.hide();
214 },
216 create: function(e){
217 e.stop();
219 var self = this;
220 new Dialog(this.language.createdir, {
221 language: {
222 confirm: this.language.create,
223 decline: this.language.cancel
224 },
225 content: [
226 new Element('input', {'class': 'createDirectory'})
227 ],
228 onOpen: this.onDialogOpen.bind(this),
229 onClose: this.onDialogClose.bind(this),
230 onShow: function(){
231 var self = this;
232 this.el.getElement('input').addEvent('keyup', function(e){
233 if(e.key=='enter') self.el.getElement('button-confirm').fireEvent('click');
234 }).focus();
235 },
236 onConfirm: function(){
237 new FileManager.Request({
238 url: self.options.url+'?event=create',
239 onSuccess: self.fill.bind(self),
240 data: {
241 file: this.el.getElement('input').get('value'),
242 directory: self.Directory
243 }
244 }, self).post();
245 }
246 });
247 },
249 deselect: function(el){
250 if(el && this.Current!=el) return;
252 if(el) this.fillInfo();
253 if(this.Current) this.Current.removeClass('selected');
254 this.Current = null;
256 this.switchButton();
257 },
259 load: function(dir, nofade){
260 this.deselect();
261 if(!nofade) this.info.fade(0);
263 if(this.Request) this.Request.cancel();
265 this.Request = new FileManager.Request({
266 url: this.options.url,
267 onSuccess: (function(j){
268 this.fill(j, nofade);
269 }).bind(this),
270 data: {
271 directory: dir
272 }
273 }, this).post();
274 },
276 destroy: function(e, file){
277 e.stop();
279 var self = this;
280 new Dialog(this.language.destroyfile, {
281 language: {
282 confirm: this.language.destroy,
283 decline: this.language.cancel
284 },
285 onOpen: this.onDialogOpen.bind(this),
286 onClose: this.onDialogClose.bind(this),
287 onConfirm: function(){
288 new FileManager.Request({
289 url: self.options.url+'?event=destroy',
290 data: {
291 file: file.name,
292 directory: self.Directory
293 },
294 onSuccess: function(j){
295 if(!j || j.content!='destroyed'){
296 new Dialog(self.language.nodestroy, {language: {confirm: self.language.ok}, buttons: ['confirm']});
297 return;
298 }
300 self.fireEvent('modify', [$unlink(file)]);
301 file.element.getParent().fade(0).get('tween').chain(function(){
302 self.deselect(file.element);
303 this.element.destroy();
304 });
305 }
306 }, self).post();
307 }
308 });
310 },
312 rename: function(e, file){
313 e.stop();
315 var name = file.name;
316 if(file.mime!='text/directory') name = name.replace(/\..*$/, '');
318 var self = this;
319 new Dialog(this.language.renamefile, {
320 language: {
321 confirm: this.language.rename,
322 decline: this.language.cancel
323 },
324 content: [
325 new Element('input', {'class': 'rename', value: name})
326 ],
327 onOpen: this.onDialogOpen.bind(this),
328 onClose: this.onDialogClose.bind(this),
329 onShow: function(){
330 var self = this;
331 this.el.getElement('input').addEvent('keyup', function(e){
332 if(e.key=='enter') self.el.getElement('button-confirm').fireEvent('click');
333 }).focus();
334 },
335 onConfirm: function(){
336 new FileManager.Request({
337 url: self.options.url+'?event=move',
338 onSuccess: (function(j){
339 if(!j || !j.name) return;
341 self.fireEvent('modify', [$unlink(file)]);
343 file.element.getElement('span').set('text', j.name);
344 file.name = j.name;
345 self.fillInfo(file);
346 }).bind(this),
347 data: {
348 file: file.name,
349 name: this.el.getElement('input').get('value'),
350 directory: self.Directory
351 }
352 }, self).post();
353 }
354 });
355 },
357 fill: function(j, nofade){
358 this.Directory = j.path;
359 this.CurrentDir = j.dir;
360 if(!nofade) this.fillInfo(j.dir);
361 this.browser.empty();
363 if(!j.files) return;
365 var els = [[], []];
366 $each(j.files, function(file){
367 file.dir = j.path;
368 var el = file.element = new Element('span', {'class': 'fi', href: '#'}).adopt(
369 new Asset.image(this.options.assetBasePath+'Icons/'+file.icon+'.png'),
370 new Element('span', {text: file.name})
371 ).store('file', file);
373 var icons = [];
374 if(file.mime!='text/directory')
375 icons.push(new Asset.image(this.options.assetBasePath+'disk.png', {title: this.language.download}).addClass('browser-icon').addEvent('click', (function(e){
376 e.stop();
377 window.open(this.normalize(this.Directory+'/'+file.name));
378 }).bind(this)).inject(el, 'top'));
380 if(file.name!='..')
381 ['rename', 'destroy'].each(function(v){
382 icons.push(new Asset.image(this.options.assetBasePath+v+'.png', {title: this.language[v]}).addClass('browser-icon').addEvent('click', this[v].bindWithEvent(this, [file])).injectTop(el));
383 }, this);
385 els[file.mime=='text/directory' ? 1 : 0].push(el);
386 if(file.name=='..') el.set('opacity', 0.7);
387 el.inject(new Element('li').inject(this.browser));
388 icons = $$(icons.map(function(icon){ return icon.appearOn(icon, [1, 0.7]); })).appearOn(el.getParent('li'), 0.7);
389 }, this);
391 var self = this;
392 $$(els[0]).makeDraggable({
393 droppables: $$(this.droppables, els[1]),
395 onDrag: function(el, e){
396 self.imageadd.setStyles(Hash.getValues(e.page).map(function(v){ return v+15; }).associate(['left', 'top']));
397 },
399 onBeforeStart: function(el){
400 el.setStyles({left: '0', top: '0'});
401 },
403 onStart: function(el){
404 self.onDragStart(el, this);
406 el.set('opacity', 0.7);
407 document.addEvents({
408 keydown: self.bound.keydown,
409 keyup: self.bound.keyup
410 });
411 },
413 onEnter: function(el, droppable){
414 droppable.addClass('droppable');
415 },
417 onLeave: function(el, droppable){
418 droppable.removeClass('droppable');
419 },
421 onDrop: function(el, droppable, e){
422 document.removeEvents('keydown', self.bound.keydown).removeEvents('keyup', self.bound.keydown);
424 self.imageadd.fade(0);
425 el.set('opacity', 1).store('block', true);
426 if(e.control || !droppable)
427 el.setStyles({left: '0', top: '0'});
429 if(!droppable && !e.control)
430 return;
432 var dir;
433 if(droppable){
434 droppable.addClass('selected');
435 (function(){ droppable.removeClass('droppable').removeClass('selected'); }).delay(300);
437 if(self.onDragComplete(el, droppable))
438 return;
440 dir = droppable.retrieve('file');
441 }
442 var file = el.retrieve('file');
444 new FileManager.Request({
445 url: self.options.url+'?event=move',
446 data: {
447 file: file.name,
448 directory: self.Directory,
449 newDirectory: dir ? dir.dir+'/'+dir.name : self.Directory,
450 copy: e.control ? 1 : 0
451 },
452 onSuccess: function(){
453 if(!dir) self.load(self.Directory);
454 }
455 }, self).post();
457 self.fireEvent('modify', [$unlink(file)]);
459 if(!e.control)
460 el.fade(0).get('tween').chain(function(){
461 self.deselect(el);
462 el.getParent().destroy();
463 });
464 }
465 });
466 $$(els).setStyles({left: '0', top: '0'});
467 var tips = new FileManager.Tips(this.browser.getElements('img.browser-icon'));
469 tips.tip.removeClass('tip-base');
470 },
472 fillInfo: function(file, path){
473 if(!file) file = this.CurrentDir;
474 if(!path) path = this.Directory;
476 if(!file) return;
477 var size = this.size(file.size);
479 this.info.fade(1).getElement('img').set({
480 src: this.options.assetBasePath+'Icons/'+file.icon+'.png',
481 alt: file.mime
482 });
484 this.fireHooks('cleanup');
485 this.preview.empty();
487 this.info.getElement('h1').set('text', file.name);
488 this.info.getElement('dd.filemanager-modified').set('text', file.date);
489 this.info.getElement('dd.filemanager-type').set('text', file.mime);
490 this.info.getElement('dd.filemanager-size').set('text', !size[0] && size[1]=='Bytes' ? '-' : (size.join(' ')+(size[1]!='Bytes' ? ' ('+file.size+' Bytes)' : '')));
491 this.info.getElement('h2.filemanager-headline').setStyle('display', file.mime=='text/directory' ? 'none' : 'block');
493 var text = [], pre = [];
495 path.split('/').each(function(v){
496 if(!v) return;
498 pre.push(v);
499 text.push(new Element('a', {
500 'class': 'icon',
501 href: '#',
502 text: v
503 }).addEvent('click', (function(e, dir){
504 e.stop();
506 this.load(dir);
507 }).bindWithEvent(this, [pre.join('/')]))
508 );
509 text.push(new Element('span', {text: ' / '}));
510 }, this);
512 text.pop();
513 text[text.length-1].addClass('selected').removeEvents('click').addEvent('click', function(e){ e.stop(); });
515 this.info.getElement('dd.filemanager-dir').empty().adopt(new Element('span', {text: '/ '}), text);
517 if(file.mime=='text/directory') return;
519 if(this.Request) this.Request.cancel();
521 this.Request = new FileManager.Request({
522 url: this.options.url+'?event=detail',
523 onSuccess: (function(j){
524 var prev = this.preview.removeClass('filemanager-loading').set('html', j && j.content ? j.content.substitute(this.language, /\\?\$\{([^{}]+)\}/g) : '').getElement('img.prev');
525 if(prev) prev.addEvent('load', function(){
526 this.setStyle('background', 'none');
527 });
529 var els = this.preview.getElements('button');
530 if(els) els.addEvent('click', function(e){
531 e.stop();
532 window.open(this.get('value'));
533 });
534 }).bind(this),
535 data: {
536 directory: this.Directory,
537 file: file.name
538 }
539 }, this).post();
540 },
542 size: function(size){
543 var tab = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
544 for(var i = 0; size > 1024; i++)
545 size = size/1024;
547 return [Math.round(size), tab[i]];
548 },
550 normalize: function(str){
551 return str.replace(/\/+/g, '/');
552 },
554 switchButton: function(){
555 var chk = !!this.Current;
556 var el = this.menu.getElement('button.filemanager-open');
557 if(el) el.set('disabled', !chk)[(chk ? 'remove' : 'add')+'Class']('disabled');
558 },
560 addMenuButton: function(name){
561 var el = new Element('button', {
562 'class': 'filemanager-'+name,
563 text: this.language[name]
564 }).inject(this.menu);
565 if(this[name]) el.addEvent('click', this[name].bind(this));
566 return el;
567 },
569 fireHooks: function(hook){
570 var args = Array.slice(arguments, 1);
571 for(var key in this.hooks[hook]) this.hooks[hook][key].apply(this, args);
572 return this;
573 },
575 onRequest: function(){ this.loader.set('opacity', 1); },
576 onComplete: function(){ this.loader.fade(0); },
577 onDialogOpen: $empty,
578 onDialogClose: $empty,
580 onDragStart: $empty,
581 onDragComplete: $lambda(false)
583 });
585 FileManager.Language = {};